Author: jpeacock
Date: Wed Mar 1 08:46:55 2006
New Revision: 626
Modified:
branches/0.3x/lib/Qpsmtpd.pm
branches/0.3x/lib/Qpsmtpd/Plugin.pm
branches/0.3x/lib/Qpsmtpd/SMTP.pm
Log:
Automatically disconnect DENY'd server if it doesn't go willingly.
Implement queue_pre and queue_post hooks.
Modified: branches/0.3x/lib/Qpsmtpd.pm
==============================================================================
--- branches/0.3x/lib/Qpsmtpd.pm (original)
+++ branches/0.3x/lib/Qpsmtpd.pm Wed Mar 1 08:46:55 2006
@@ -433,6 +433,14 @@
my $self = shift;
return (defined $self->{_auth_mechanism} ? $self->{_auth_mechanism} : "" );
}
+
+sub denied {
+ my ($self, $value) = @_;
+ $self->transaction->{_denied} = $value if defined $value;
+ return (defined $self->transaction->{_denied}
+ ? $self->transaction->{_denied}
+ : "" );
+}
1;
Modified: branches/0.3x/lib/Qpsmtpd/Plugin.pm
==============================================================================
--- branches/0.3x/lib/Qpsmtpd/Plugin.pm (original)
+++ branches/0.3x/lib/Qpsmtpd/Plugin.pm Wed Mar 1 08:46:55 2006
@@ -2,11 +2,13 @@
use Qpsmtpd::Constants;
use strict;
+# more or less in the order they will fire
our @hooks = qw(
- logging config queue data data_post quit rcpt mail ehlo helo
+ logging config pre-connection connect ehlo helo
auth auth-plain auth-login auth-cram-md5
- connect reset_transaction unrecognized_command disconnect
- deny ok pre-connection post-connection
+ rcpt mail data data_post queue_pre queue queue_post
+ quit reset_transaction disconnect post-connection
+ unrecognized_command deny ok
);
our %hooks = map { $_ => 1 } @hooks;
Modified: branches/0.3x/lib/Qpsmtpd/SMTP.pm
==============================================================================
--- branches/0.3x/lib/Qpsmtpd/SMTP.pm (original)
+++ branches/0.3x/lib/Qpsmtpd/SMTP.pm Wed Mar 1 08:46:55 2006
@@ -50,6 +50,12 @@
$self->{_counter}++;
+ if ( $cmd !~ /^(rset|quit)$/ and $self->denied ) { # RFC non-compliant
+ $self->log(LOGWARN, "non-RFC compliant MTA disconnected");
+ $self->respond(521, "non-RFC compliant MTA disconnected (#5.7.0)");
+ $self->disconnect;
+ }
+
if ($cmd !~ /^(\w{1,12})$/ or !exists $self->{_commands}->{$1}) {
my ($rc, $msg) = $self->run_hooks("unrecognized_command", $cmd, @_);
if ($rc == DENY_DISCONNECT) {
@@ -150,8 +156,10 @@
if ($rc == DONE) {
# do nothing
} elsif ($rc == DENY) {
+ $self->denied(1);
$self->respond(550, $msg);
} elsif ($rc == DENYSOFT) {
+ $self->denied(1);
$self->respond(450, $msg);
} elsif ($rc == DENY_DISCONNECT) {
$self->respond(550, $msg);
@@ -178,8 +186,10 @@
if ($rc == DONE) {
# do nothing
} elsif ($rc == DENY) {
+ $self->denied(1);
$self->respond(550, $msg);
} elsif ($rc == DENYSOFT) {
+ $self->denied(1);
$self->respond(450, $msg);
} elsif ($rc == DENY_DISCONNECT) {
$self->respond(550, $msg);
@@ -290,11 +300,13 @@
return 1;
}
elsif ($rc == DENY) {
+ $self->denied(1);
$msg ||= $from->format . ', denied';
$self->log(LOGINFO, "deny mail from " . $from->format . " ($msg)");
$self->respond(550, $msg);
}
elsif ($rc == DENYSOFT) {
+ $self->denied(1);
$msg ||= $from->format . ', temporarily denied';
$self->log(LOGINFO, "denysoft mail from " . $from->format . " ($msg)");
$self->respond(450, $msg);
@@ -336,10 +348,12 @@
return 1;
}
elsif ($rc == DENY) {
+ $self->denied(1);
$msg ||= 'relaying denied';
$self->respond(550, $msg);
}
elsif ($rc == DENYSOFT) {
+ $self->denied(1);
$msg ||= 'relaying denied';
return $self->respond(450, $msg);
}
@@ -558,7 +572,7 @@
$self->respond(452, $msg || "Message denied temporarily");
}
else {
- $self->queue($self->transaction);
+ $self->queue($self->transaction);
}
# DATA is always the end of a "transaction"
@@ -578,7 +592,18 @@
sub queue {
my ($self, $transaction) = @_;
- my ($rc, $msg) = $self->run_hooks("queue");
+ # First fire any queue_pre hooks
+ my ($rc, $msg) = $self->run_hooks("queue_pre");
+ if ($rc == DONE) {
+ return 1;
+ }
+ elsif ($rc != OK and $rc != DECLINED) {
+ return $self->log(LOGERROR, "pre plugin returned illegal value");
+ return 0;
+ }
+
+ # If we got this far, run the queue hooks
+ ($rc, $msg) = $self->run_hooks("queue");
if ($rc == DONE) {
return 1;
}
@@ -586,16 +611,20 @@
$self->respond(250, ($msg || 'Queued'));
}
elsif ($rc == DENY) {
+ $self->denied(1);
$self->respond(552, $msg || "Message denied");
}
elsif ($rc == DENYSOFT) {
+ $self->denied(1);
$self->respond(452, $msg || "Message denied temporarily");
}
else {
$self->respond(451, $msg || "Queuing declined or disabled; try again
later" );
}
-
-
+
+ # And finally run any queue_post hooks
+ ($rc, $msg) = $self->run_hooks("queue_post");
+ $self->log(LOGERROR, $msg) unless $rc == OK;
}