Skip to content

Commit

Permalink
move the queue code to a plugin; document the queue plugin hook.
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.perl.org/qpsmtpd/trunk@80 958fd67b-6ff1-0310-b445-bb7760255be9
  • Loading branch information
abh committed Oct 10, 2002
1 parent 9c38313 commit 253eeee
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 49 deletions.
12 changes: 12 additions & 0 deletions README.plugins
Original file line number Diff line number Diff line change
Expand Up @@ -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

=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

Expand All @@ -93,6 +104,7 @@ Allowed return codes:
DECLINED - Process the next plugin
DONE - Stop processing plugins and don't give the default response


=head2 quit

Called on the "quit" command.
Expand Down
6 changes: 4 additions & 2 deletions config.sample/plugins
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ check_badrcptto
# this plugin needs to run after all other "rcpt" plugins
check_relay


# content filters
klez_filter
spamassassin

queue/qmail-queue

spamassassin
64 changes: 17 additions & 47 deletions lib/Qpsmtpd/SMTP.pm
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ sub data {
# way a Received: line that is already in the header.

$header->extract(\@header);
$header->add("X-SMTPD", "qpsmtpd/".$self->version.", http://develooper.com/code/qpsmtpd/");

$buffer = "";

# FIXME - call plugins to work on just the header here; can
Expand Down Expand Up @@ -360,56 +362,24 @@ sub data {
sub queue {
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->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;

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.");
my ($rc, $msg) = $self->run_hooks("queue");
if ($rc == DONE) {
return 1;
}
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') {
die "should never be here!";
}
elsif ($rc == OK) {
$self->respond(250, ($msg || 'Queued'));
}
elsif ($rc == DENY) {
$self->respond(552, $msg || "Message denied");
}
elsif ($rc == DENYSOFT) {
$self->respond(452, $msg || "Message denied temporarily");
}
else {
$self->respond(451, $msg || "Queuing declined or disabled; try again later" );
}


}


Expand Down
57 changes: 57 additions & 0 deletions plugins/queue/qmail-queue
Original file line number Diff line number Diff line change
@@ -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");
}
}
}

0 comments on commit 253eeee

Please sign in to comment.