AnyEvent-SMTP
view release on metacpan or search on metacpan
lib/AnyEvent/SMTP/Server.pm view on Meta::CPAN
host => 'remote addr',
port => 'remote port',
helo => 'HELO/EHLO string',
};
=back
=cut
sub import {
my $me = shift;
my $pkg = caller;
@_ or return;
for (@_) {
if ( $_ eq 'smtp_server') {
*{$pkg.'::'.$_} = \&$_;
} else {
croak "$_ is not exported by $me";
}
}
}
sub smtp_server {
my ($host,$port,$cb) = @_;
my $server = AnyEvent::SMTP::Server->new(
host => $host,
port => $port,
);
$server->reg_cb(
mail => sub {
$cb->($_[1]);
},
);
$server->start;
defined wantarray
? AnyEvent::Util::guard { $server->stop; %$server = (); }
: ()
}
sub new {
my $pkg = shift;
my $self = bless { @_ }, $pkg;
$self->{hostname} = hostname() unless defined $self->{hostname};
$self->set_exception_cb( sub {
my ($e, $event, @args) = @_;
my $ex = $@;
if (exists $self->{event_failed}) {
$self->{event_failed} = $ex;
return;
}
#warn "exception: $self, $self->{current_con} (@args) [$@]";
my $con = $self->{current_con};
if (!$con) {
local $::self = $self;
local $::con;
local $::event = $event;
{
package DB;
my $i = 0;
while (my @c = caller(++$i)) {
warn "$i. [@DB::args]";
next if @DB::args < 2;
last if $DB::args[0] == $::self and $DB::args[1] eq $::event and UNIVERSAL::isa($DB::args[2], 'AnyEvent::SMTP::Conn');
}
$::con = $DB::args[2];
}
$con = $::con;
}
if ($con) {
my $msg = "500 INTERNAL ERROR";
if ($self->{devel}) {
$ex =~ s{(?:\r?\n)+}{ }sg;
$ex =~ s{\s+$}{}s;
$msg .= ": ".$ex;
}
$con->reply($msg);
}
warn "exception during $event : $ex";
} );
$self->reg_cb(
command => sub {
my ($s,$con,$com) = @_;
my ($cmd, @args);
for ($com) {
s/^\s+//;s/\s+$//;
length or last;
($cmd, @args) = split /\s+/;
$cmd = uc $cmd;
}
if (exists $CMD{$cmd}) {
$s->handle( $con, $cmd, @args );
} else {
warn "$cmd @args";
$con->reply("500 Learn to type!");
}
#warn "Got command @_";
},
HELO => sub {
my ($s,$con,@args) = @_;
$con->{helo} = "@args";
$con->new_m();
$con->ok("I'm ready.");
},
EHLO => sub {
my ($s,$con,@args) = @_;
$con->{helo} = "@args";
$con->new_m();
$con->ok("Go on.");
},
RSET => sub {
my ($s,$con,@args) = @_;
$con->new_m();
$con->ok;
},
MAIL => sub {
my ($s,$con,@args) = @_;
my $from = join ' ',@args;
$from =~ s{^from:}{}i or return $con->reply('501 Usage: MAIL FROM:<mail addr>');
$con->{helo} or return $con->reply("503 Error: send HELO/EHLO first");
my @addrs;
( run in 1.998 second using v1.01-cache-2.11-cpan-437f7b0c052 )