data_post hook

spamassassin plugin


git-svn-id: https://svn.perl.org/qpsmtpd/branches/v010@38 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
Ask Bjørn Hansen 2002-08-06 12:01:22 +00:00
parent e561b69696
commit 8ce8427bf9
4 changed files with 120 additions and 19 deletions

View File

@ -5,3 +5,5 @@ dnsbl
# this plugin needs to run after all other "rcpt" plugins
check_relay
spamassassin

View File

@ -335,7 +335,8 @@ sub data {
#. ..
}
$buffer .= $_;
$self->transaction->body_write($_);
$size += length $_;
}
$self->log(5, "size is at $size\n") unless ($i % 300);
@ -346,27 +347,27 @@ sub data {
$self->log(6, "max_size: $max_size / size: $size");
$self->transaction->header($header);
$self->transaction->body(\$buffer);
# if we get here without seeing a terminator, the connection is
# probably dead.
$self->respond(451, "Incomplete DATA"), return 1 unless $complete;
#
# FIXME - Call plugins to work on the body here
#
$self->respond(550, $self->transaction->blocked),return 1 if ($self->transaction->blocked);
$self->respond(552, "Message too big!"),return 1 if $max_size and $size > $max_size;
my ($rc, $msg) = $self->run_hooks("data_post");
if ($rc != DONE) {
warn "QPSM100";
return $self->queue($self->transaction);
}
}
sub queue {
my ($self, $transaction) = @_;
warn "QPSM2000";
# 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;
@ -391,7 +392,10 @@ sub queue {
print MESSAGE_WRITER "X-smtpd: qpsmtpd/",$self->version,", http://develooper.com/code/qpsmtpd/\n";
$transaction->header->print(\*MESSAGE_WRITER);
print MESSAGE_WRITER ${$transaction->body};
$transaction->body_resetpos;
while (my $line = $transaction->body_getline) {
print MESSAGE_WRITER $line;
}
close MESSAGE_WRITER;
my @rcpt = map { "T" . $_->address } $transaction->recipients;

View File

@ -1,5 +1,10 @@
package Qpsmtpd::Transaction;
use strict;
use IO::File qw(O_RDWR O_CREAT);
# For unique filenames. We write to a local tmp dir so we don't need
# to make them unpredictable.
my $transaction_counter = 0;
sub new { start(@_) }
@ -33,11 +38,11 @@ sub header {
$self->{_header};
}
sub body {
my $self = shift;
@_ and $self->{_body} = shift;
$self->{_body};
}
#sub body {
# my $self = shift;
# @_ and $self->{_body} = shift;
# $self->{_body};
#}
sub blocked {
my $self = shift;
@ -52,10 +57,45 @@ sub notes {
$self->{_notes}->{$key};
}
#sub add_header_line {
#}
sub add_header_line {
my $self = shift;
$self->{_header} .= shift;
}
#sub add_body_line {
#}
sub body_write {
my $self = shift;
my $data = shift;
#$self->{_body} .= shift;
unless ($self->{_body_file}) {
-d "tmp" or mkdir("tmp", 0700) or die "Could not create dir tmp: $!";
$self->{_filename} = "/home/smtpd/qpsmtpd/tmp/" . join(":", time, $$, $transaction_counter++);
$self->{_body_file} = IO::File->new($self->{_filename}, O_RDWR|O_CREAT)
or die "Could not open file $self->{_filename} - $! "; # . $self->{_body_file}->error;
}
# go to the end of the file
seek($self->{_body_file},0,2)
unless $self->{_body_file_writing};
$self->{_body_file_writing} = 1;
$self->{_body_file}->print(ref $data eq "SCALAR" ? $$data : $data);
}
sub body_resetpos {
my $self = shift;
return unless $self->{_body_file};
seek($self->{_body_file}, 0,0);
$self->{_body_file_writing} = 0;
1;
}
sub body_getline {
my $self = shift;
return unless $self->{_body_file};
seek($self->{_body_file}, 0,0)
if $self->{_body_file_writing};
$self->{_body_file_writing} = 0;
my $line = $self->{_body_file}->getline;
return $line;
}
1;

55
plugins/spamassassin Normal file
View File

@ -0,0 +1,55 @@
use Socket qw(:DEFAULT :crlf);
use IO::Handle;
sub register {
my ($self, $qp) = @_;
$self->register_hook("data_post", "check_spam");
}
#my $rv = check_spam();
#die "failure!" unless defined $rv;
#print "rv: $rv\n";
sub check_spam {
my ($self, $transaction) = @_;
my $remote = 'localhost';
my $port = 783;
if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
die "No port" unless $port;
my $iaddr = inet_aton($remote) || die "no host: $remote";
my $paddr = sockaddr_in($port, $iaddr);
my $proto = getprotobyname('tcp');
socket(SPAMD, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
connect(SPAMD, $paddr) || warn "SA: connect: $!", return undef;
SPAMD->autoflush(1);
$transaction->body_resetpos;
print SPAMD "REPORT SPAMC/1.0" . CRLF;
# or CHECK or REPORT or SYMBOLS
while (my $line = $transaction->body_getline) {
chomp $line;
print SPAMD $line, CRLF;
}
print SPAMD CRLF;
shutdown(SPAMD, 1);
my $line0 = <SPAMD>; # get the first protocol lines out
if ($line0) {
$transaction->header->add("X-Spam-Check-By", $self->qp->config('me'));
}
while (<SPAMD>) {
warn "GOT FROM SPAMD1: $_";
next unless m/\S/;
s/\r?\n$/\n/;
my @h = split /: /, $_, 2;
$transaction->header->add(@h);
last if $h[0] eq "Spam" and $h[1] =~ m/^False/;
}
return (OK);
}