move the queue code to a plugin; document the queue plugin hook.

git-svn-id: https://svn.perl.org/qpsmtpd/trunk@80 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
Ask Bjørn Hansen 2002-10-10 01:49:34 +00:00
parent 9c38313d06
commit 253eeee879
4 changed files with 90 additions and 49 deletions

View File

@ -84,6 +84,17 @@ Hook after receiving all data; just before the message is queued.
All other codes and the message will be queued normally All other codes and the message will be queued normally
=head2 queue
Called on completion of the DATA command.
DONE - skip further processing (plugin gave response code)
OK - Return success message
DENY - Return hard failure code
DENYSOFT - Return soft failure code
Any other code will return a soft failure code.
=head2 connect =head2 connect
@ -93,6 +104,7 @@ Allowed return codes:
DECLINED - Process the next plugin DECLINED - Process the next plugin
DONE - Stop processing plugins and don't give the default response DONE - Stop processing plugins and don't give the default response
=head2 quit =head2 quit
Called on the "quit" command. Called on the "quit" command.

View File

@ -8,7 +8,9 @@ check_badrcptto
# this plugin needs to run after all other "rcpt" plugins # this plugin needs to run after all other "rcpt" plugins
check_relay check_relay
# content filters
klez_filter klez_filter
spamassassin spamassassin
queue/qmail-queue

View File

@ -300,6 +300,8 @@ sub data {
# way a Received: line that is already in the header. # way a Received: line that is already in the header.
$header->extract(\@header); $header->extract(\@header);
$header->add("X-SMTPD", "qpsmtpd/".$self->version.", http://develooper.com/code/qpsmtpd/");
$buffer = ""; $buffer = "";
# FIXME - call plugins to work on just the header here; can # FIXME - call plugins to work on just the header here; can
@ -360,55 +362,23 @@ sub data {
sub queue { sub queue {
my ($self, $transaction) = @_; my ($self, $transaction) = @_;
# these bits inspired by Peter Samuels "qmail-queue wrapper" my ($rc, $msg) = $self->run_hooks("queue");
pipe(MESSAGE_READER, MESSAGE_WRITER) or fault("Could not create message pipe"), exit; if ($rc == DONE) {
pipe(ENVELOPE_READER, ENVELOPE_WRITER) or fault("Could not create envelope pipe"), exit; return 1;
my $child = fork();
not defined $child and fault(451, "Could not fork"), exit;
if ($child) {
# Parent
my $oldfh = select(MESSAGE_WRITER); $| = 1;
select(ENVELOPE_WRITER); $| = 1;
select($oldfh);
close MESSAGE_READER or fault("close msg reader fault"),exit;
close ENVELOPE_READER or fault("close envelope reader fault"), exit;
$transaction->header->add("X-SMTPD", "qpsmtpd/".$self->version.", http://develooper.com/code/qpsmtpd/");
$transaction->header->print(\*MESSAGE_WRITER);
$transaction->body_resetpos;
while (my $line = $transaction->body_getline) {
print MESSAGE_WRITER $line;
} }
close MESSAGE_WRITER; elsif ($rc == OK) {
$self->respond(250, ($msg || 'Queued'));
my @rcpt = map { "T" . $_->address } $transaction->recipients;
my $from = "F".($transaction->sender->address|| "" );
print ENVELOPE_WRITER "$from\0", join("\0",@rcpt), "\0\0"
or respond(451,"Could not print addresses to queue"),exit;
close ENVELOPE_WRITER;
waitpid($child, 0);
my $exit_code = $? >> 8;
$exit_code and respond(451, "Unable to queue message ($exit_code)"), exit;
$self->respond(250, "Queued.");
} }
elsif (defined $child) { elsif ($rc == DENY) {
# Child $self->respond(552, $msg || "Message denied");
close MESSAGE_WRITER or die "could not close message writer in parent";
close ENVELOPE_WRITER or die "could not close envelope writer in parent";
open(STDIN, "<&MESSAGE_READER") or die "b1";
open(STDOUT, "<&ENVELOPE_READER") or die "b2";
unless (exec '/var/qmail/bin/qmail-queue') {
die "should never be here!";
} }
elsif ($rc == DENYSOFT) {
$self->respond(452, $msg || "Message denied temporarily");
} }
else {
$self->respond(451, $msg || "Queuing declined or disabled; try again later" );
}
} }

57
plugins/queue/qmail-queue Normal file
View File

@ -0,0 +1,57 @@
sub register {
my ($self, $qp) = @_;
$self->register_hook("queue", "queue_handler");
}
sub queue_handler {
my ($self, $transaction) = @_;
# these bits inspired by Peter Samuels "qmail-queue wrapper"
pipe(MESSAGE_READER, MESSAGE_WRITER) or fault("Could not create message pipe"), exit;
pipe(ENVELOPE_READER, ENVELOPE_WRITER) or fault("Could not create envelope pipe"), exit;
my $child = fork();
not defined $child and fault(451, "Could not fork"), exit;
if ($child) {
# Parent
my $oldfh = select(MESSAGE_WRITER); $| = 1;
select(ENVELOPE_WRITER); $| = 1;
select($oldfh);
close MESSAGE_READER or fault("close msg reader fault"),exit;
close ENVELOPE_READER or fault("close envelope reader fault"), exit;
$transaction->header->print(\*MESSAGE_WRITER);
$transaction->body_resetpos;
while (my $line = $transaction->body_getline) {
print MESSAGE_WRITER $line;
}
close MESSAGE_WRITER;
my @rcpt = map { "T" . $_->address } $transaction->recipients;
my $from = "F".($transaction->sender->address|| "" );
print ENVELOPE_WRITER "$from\0", join("\0",@rcpt), "\0\0"
or return(DECLINED,"Could not print addresses to queue");
close ENVELOPE_WRITER;
waitpid($child, 0);
my $exit_code = $? >> 8;
$exit_code and return(DECLINED, "Unable to queue message ($exit_code)");
return (OK, "Queued!");
}
elsif (defined $child) {
# Child
close MESSAGE_WRITER or die "could not close message writer in parent";
close ENVELOPE_WRITER or die "could not close envelope writer in parent";
open(STDIN, "<&MESSAGE_READER") or die "b1";
open(STDOUT, "<&ENVELOPE_READER") or die "b2";
unless (exec '/var/qmail/bin/qmail-queue') {
return (DECLINED, "fatal error spawning qmail-queue");
}
}
}