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:
parent
e561b69696
commit
8ce8427bf9
@ -5,3 +5,5 @@ dnsbl
|
|||||||
|
|
||||||
# this plugin needs to run after all other "rcpt" plugins
|
# this plugin needs to run after all other "rcpt" plugins
|
||||||
check_relay
|
check_relay
|
||||||
|
|
||||||
|
spamassassin
|
@ -335,7 +335,8 @@ sub data {
|
|||||||
#. ..
|
#. ..
|
||||||
}
|
}
|
||||||
|
|
||||||
$buffer .= $_;
|
$self->transaction->body_write($_);
|
||||||
|
|
||||||
$size += length $_;
|
$size += length $_;
|
||||||
}
|
}
|
||||||
$self->log(5, "size is at $size\n") unless ($i % 300);
|
$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->log(6, "max_size: $max_size / size: $size");
|
||||||
|
|
||||||
$self->transaction->header($header);
|
$self->transaction->header($header);
|
||||||
$self->transaction->body(\$buffer);
|
|
||||||
|
|
||||||
# if we get here without seeing a terminator, the connection is
|
# if we get here without seeing a terminator, the connection is
|
||||||
# probably dead.
|
# probably dead.
|
||||||
$self->respond(451, "Incomplete DATA"), return 1 unless $complete;
|
$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(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;
|
$self->respond(552, "Message too big!"),return 1 if $max_size and $size > $max_size;
|
||||||
|
|
||||||
return $self->queue($self->transaction);
|
my ($rc, $msg) = $self->run_hooks("data_post");
|
||||||
|
if ($rc != DONE) {
|
||||||
|
warn "QPSM100";
|
||||||
|
return $self->queue($self->transaction);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub queue {
|
sub queue {
|
||||||
my ($self, $transaction) = @_;
|
my ($self, $transaction) = @_;
|
||||||
|
|
||||||
|
warn "QPSM2000";
|
||||||
|
|
||||||
# these bits inspired by Peter Samuels "qmail-queue wrapper"
|
# these bits inspired by Peter Samuels "qmail-queue wrapper"
|
||||||
pipe(MESSAGE_READER, MESSAGE_WRITER) or fault("Could not create message pipe"), exit;
|
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;
|
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";
|
print MESSAGE_WRITER "X-smtpd: qpsmtpd/",$self->version,", http://develooper.com/code/qpsmtpd/\n";
|
||||||
|
|
||||||
$transaction->header->print(\*MESSAGE_WRITER);
|
$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;
|
close MESSAGE_WRITER;
|
||||||
|
|
||||||
my @rcpt = map { "T" . $_->address } $transaction->recipients;
|
my @rcpt = map { "T" . $_->address } $transaction->recipients;
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
package Qpsmtpd::Transaction;
|
package Qpsmtpd::Transaction;
|
||||||
use strict;
|
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(@_) }
|
sub new { start(@_) }
|
||||||
|
|
||||||
@ -33,11 +38,11 @@ sub header {
|
|||||||
$self->{_header};
|
$self->{_header};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub body {
|
#sub body {
|
||||||
my $self = shift;
|
# my $self = shift;
|
||||||
@_ and $self->{_body} = shift;
|
# @_ and $self->{_body} = shift;
|
||||||
$self->{_body};
|
# $self->{_body};
|
||||||
}
|
#}
|
||||||
|
|
||||||
sub blocked {
|
sub blocked {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
@ -52,10 +57,45 @@ sub notes {
|
|||||||
$self->{_notes}->{$key};
|
$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;
|
1;
|
||||||
|
55
plugins/spamassassin
Normal file
55
plugins/spamassassin
Normal 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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user