NetServer-SMTP
view release on metacpan or search on metacpan
"250" => "OK: %s",
"251" => "User not local; will forward to <forward-path>",
"354" => "%s",
"421" => "%s Service not available, closing connection",
"450" => "Requested mail action not taken: mailbox unavailable",
"451" => "Requested action aborted: error in processing",
"452" => "Requested action not taken: insufficient system storage",
"500" => "Syntax error, command unrecognized",
"501" => "Syntax error in parameter or arguments: %s",
"502" => "Command not implemented %s",
"503" => "Bad sequence of commands",
"504" => "Command parameter not implemented",
"550" => "Requested action not taken: %s",
"551" => "User not local; please try %s",
"552" => "Requested mail action aborted: exceeded storage allocation",
"553" => "Requested action not taken: mailbox name not allowed",
"554" => "Transaction failed: %s"
};
# legal SMTP state transitions -- each state is followed by an arrayref
# to its legal predecessors. To determine if a new state is legal, check
# to see if it's predecessor is in the array in NFA.
$NetServer::SMTP::NFA = {
"HELO" => [ "undef" ],
"EHELO" => [ "undef" ],
"MAIL" => [ qw(HELO RSET NOOP DATA) ],
"RCPT" => [ qw(MAIL NOOP RCPT RSET) ],
"MAIL" => [ qw(HELO NOOP DATA RSET) ],
"DATA" => [ qw(RCPT NOOP) ],
"TURN" => [ @$NetServer::SMTP::States ],
"NOOP" => [ @$NetServer::SMTP::States ],
"QUIT" => [ @$NetServer::SMTP::States ],
"HELP" => [ @$NetServer::SMTP::States ],
"DUMP" => [ @$NetServer::SMTP::States ],
"RSET" => [ @$NetServer::SMTP::States ],
};
sub new {
# create a new NetServer::SMTP
my ($class) = shift;
my ($self) = bless {}, $class;
if (@_) {
$self = $self->initialise(@_);
}
if (! defined($self->{silent})) {
$self->respond(220, "leafmail $NetServer::SMTP::VERSION is ready");
}
return $self;
}
sub initialise {
=pod
=item initialise()
Called by B<new()> to initialise the new object. Initialisation keys
may be specified as a hash, supplied as a parameter to the new
object, or as a filename or file handle containing a frozen
B<NetServer::SMTP> object which is users to overlay the object.
Recognized keys are:
=over 4
=item myhost
My host name (FQDN)
=item allowed
array of aliases for hosts users allowed to send mail
=item silent
If silent, dont say hello when creating a new server (we have other
reasons for creating NetServer::SMTP objects, once in a while :)
=item relay
Relay hostname (FQDN)
=item ERROR
If this flag goes non-zero, Something Bad has happened and the session
should either terminate or refuse to proceed further
=item spooldir
Directory where spooled transactions are waiting
=back
=cut
my ($self) = shift ;
my (@junk);
if (scalar(@_) == 1) {
# it's a filehandle or filename -- open it and load the contents
my ($file);
my ($fn) = shift;
if (ref($fn) !~ /file/i) {
$file = new IO::File($fn, "r") or croak "Could not open $fn\n";
}
my ($frozen) = join( "", $file->getlines() );
$file->close();
($self, @junk) = thaw($frozen);
$self->{spooledfile} = $fn;
return $self;
} elsif (scalar(@_) % 2 == 0) {
# it's an initialisation hash -- overlay it on $self
%$self = (@_);
return $self;
} else {
croak "Don't know how to initialise from [", join("][", @_), "]\n";
}
}
sub respond ($$;@) {
# issue a response code and the corresponding message
# NOTE: SMTP response messages are printf() format strings and
# positional substitution may occur if additional respond() parameters
# are available
my ($self) = shift;
my ($resp) = shift;
my (@args) = @_;
print STDOUT "$resp ", sprintf($NetServer::SMTP::Err->{$resp}, @args),
"\r\n";
}
sub EHLO {
my $self = shift;
$self->respond(550, "I don't talk ESMTP");
return;
}
sub HELP {
my $self = shift;
my $resp = "<<%%"
NetServer::SMTP $NetServer::SMTP::VERSION
Known Commands:
HELO MAIL RCPT DATA RSET NOOP QUIT HELP DUMP TURN
%%
$self->respond("214", $resp);
return;
}
sub HELO {
# say hello -- start a session
my ($self) = shift;
my ($next) = join(" ", @_);
$next =~ s/\r\n//;;
my ($f, $snd) = "";
if ($next =~ /^from:/i) {
$next =~ /(from:*)\s+(.*)/i;
($f, $snd) = ($1, $2);
$snd =~ s/[><]//g;
} else {
$snd = $next;
}
if (grep(/$snd/i, @{ $self->{allowed} }) != 0) {
$self->{host} = $snd;
my ($s) = $self->serv();
my ($peer) = $s->peer();
if ($self->{host} ne $peer->[0]) {
$self->respond(554, " lie to me at your peril!" );
$self->{ERROR} = 1;
return;
( run in 3.268 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )