AnyEvent-SMTP
view release on metacpan or search on metacpan
lib/AnyEvent/SMTP/Client.pm view on Meta::CPAN
package AnyEvent::SMTP::Client;
=head1 NAME
AnyEvent::SMTP::Client - Simple asyncronous SMTP Client
=cut
use AnyEvent;
use common::sense;
m{# trying to cheat with cpants game ;)
use strict;
use warnings;
}x;
use base 'Object::Event';
use AnyEvent::Handle;
use AnyEvent::Socket;
use AnyEvent::DNS;
use AnyEvent::Util;
use Sys::Hostname;
use Mail::Address;
use AnyEvent::SMTP::Conn;
our $VERSION = $AnyEvent::SMTP::VERSION;use AnyEvent::SMTP ();
# vvv This code was partly derived from AnyEvent::HTTP vvv
our $MAXCON = 10; # Maximum number of connections to any host
our %MAXCON; # Maximum number of connections to concrete host
our $ACTIVE = 0; # Currently active connections
our %ACTIVE;
my %CO_SLOT; # number of open connections, and wait queue, per host
sub _slot_schedule;
sub _slot_schedule($) {
my $host = shift;
my $mc = exists $MAXCON{$host} ? $MAXCON{$host} : $MAXCON;
while (!$mc or ( $mc > 0 and $CO_SLOT{$host}[0] < $mc )) {
if (my $cb = shift @{ $CO_SLOT{$host}[1] }) {
# somebody wants that slot
++$CO_SLOT{$host}[0];
++$ACTIVE;
++$ACTIVE{$host};
$cb->(AnyEvent::Util::guard {
--$ACTIVE;
--$ACTIVE{$host} > 0 or delete $ACTIVE{$host};
--$CO_SLOT{$host}[0];
#warn "Release slot (have $ACTIVE) by @{[ (caller)[1,2] ]}\n";
_slot_schedule $host;
});
} else {
# nobody wants the slot, maybe we can forget about it
delete $CO_SLOT{$host} unless $CO_SLOT{$host}[0];
last;
}
}
}
# wait for a free slot on host, call callback
sub _get_slot($$) {
push @{ $CO_SLOT{$_[0]}[1] }, $_[1];
_slot_schedule $_[0];
}
sub _tcp_connect($$$;$) {
my ($host,$port,$cb,$pr) = @_;
#warn "Need slot $host (have $ACTIVE)";
_get_slot $host, sub {
my $sg = shift;
#warn "Have slot $host (have $ACTIVE)";
tcp_connect($host,$port,sub {
$cb->(@_,$sg);
}, $pr);
}
}
# ^^^ This code was partly derived from AnyEvent::HTTP ^^^
=head1 SYNOPSIS
use AnyEvent::SMTP::Client 'sendmail';
sendmail
from => 'mons@cpan.org',
to => 'mons@cpan.org', # SMTP host will be detected from addres by MX record
data => 'Test message '.time().' '.$$,
cb => sub {
if (my $ok = shift) {
warn "Successfully sent";
}
if (my $err = shift) {
warn "Failed to send: $err";
}
}
;
=head1 DESCRIPTION
Asyncronously connect to SMTP server, resolve MX, if needed, then send HELO => MAIL => RCPT => DATA => QUIT and return responce
=head1 FUNCTIONS
=head2 sendmail ... , cb => $cb->(OK,ERR)
Argument names are case insensitive. So, it may be calles as
sendmail From => ..., To => ..., ...
( run in 2.041 seconds using v1.01-cache-2.11-cpan-0bb4e1dffa6 )