End of headers hook: data_headers_end

Hook after receiving all headers lines. Defaults to nothing,
just continue processing. At this step, sender does not wait for a reply,
but we can stop him from sending remaining data by disconnecting.

(Cleaned up by Robert for english and coding style.)

Signed-off-by: Ask Bjørn Hansen <ask@develooper.com>
Signed-off-by: Robert Spier <robert@perl.org>
This commit is contained in:
Karl Y. Pradene 2009-02-09 22:25:51 +01:00 committed by Ask Bjørn Hansen
parent ea86b9fdb2
commit 059771d31d
3 changed files with 34 additions and 7 deletions

View File

@ -150,6 +150,24 @@ Hook for the "data" command. Defaults to '354, "go ahead"'.
recommended) recommended)
=head2 data_headers_end
Hook fires after all header lines of the message data has been received.
Defaults to doing nothing, just continue processing. At this step,
the sender is not waiting for a reply, but we can try and prevent him from
sending the entire message by disconnecting immediately. (Although it is
likely the packets are already in flight due to buffering and pipelining).
BE CAREFUL! If you drop the connection legal MTAs will retry again and again,
spammers will probably not. This is not RFC compliant and can lead to
an unpredictable mess. Use with caution.
Allowed return codes:
DENY_DISCONNECT - Return '554 Message denied' and disconnect
DENYSOFT_DISCONNECT - Return '421 Message denied temporarily' and disconnect
DECLINED - Do nothing
=head2 data_post =head2 data_post
Hook after receiving all data; just before the message is queued. Hook after receiving all data; just before the message is queued.
@ -305,6 +323,7 @@ routine is: C< s/\W/_/g; >
config hook_config config hook_config
queue hook_queue queue hook_queue
data hook_data data hook_data
data_headers_end hook_data_headers_end
data_post hook_data_post data_post hook_data_post
quit hook_quit quit hook_quit
rcpt hook_rcpt rcpt hook_rcpt

View File

@ -7,7 +7,7 @@ our @hooks = qw(
logging config post-fork pre-connection connect ehlo_parse ehlo logging config post-fork pre-connection connect ehlo_parse ehlo
helo_parse helo auth_parse auth auth-plain auth-login auth-cram-md5 helo_parse helo auth_parse auth auth-plain auth-login auth-cram-md5
rcpt_parse rcpt_pre rcpt mail_parse mail mail_pre rcpt_parse rcpt_pre rcpt mail_parse mail mail_pre
data data_post queue_pre queue queue_post vrfy noop data data_headers_end data_post queue_pre queue queue_post vrfy noop
quit reset_transaction disconnect post-connection quit reset_transaction disconnect post-connection
unrecognized_command deny ok received_line help unrecognized_command deny ok received_line help
); );

View File

@ -664,8 +664,18 @@ sub data_respond {
$buffer = ""; $buffer = "";
# FIXME - call plugins to work on just the header here; can $self->transaction->header($header);
# save us buffering the mail content.
my ($rc, $msg) = $self->run_hooks('data_headers_end');
if ($rc == DENY_DISCONNECT) {
$self->respond(554, $msg || "Message denied");
$self->disconnect;
return 1;
} elsif ($rc == DENYSOFT_DISCONNECT) {
$self->respond(421, $msg || "Message denied temporarily");
$self->disconnect;
return 1;
}
# Save the start of just the body itself # Save the start of just the body itself
$self->transaction->set_body_start(); $self->transaction->set_body_start();
@ -687,8 +697,6 @@ sub data_respond {
$self->log(LOGDEBUG, "max_size: $max_size / size: $size"); $self->log(LOGDEBUG, "max_size: $max_size / size: $size");
$self->transaction->header($header);
my $smtp = $self->connection->hello eq "ehlo" ? "ESMTP" : "SMTP"; my $smtp = $self->connection->hello eq "ehlo" ? "ESMTP" : "SMTP";
my $esmtp = substr($smtp,0,1) eq "E"; my $esmtp = substr($smtp,0,1) eq "E";
my $authheader = ''; my $authheader = '';