[rt-users] SpamAssassin filter for RT 3.0.10
Larry Stone
lcs at MIT.EDU
Mon May 3 22:51:17 EDT 2004
I got SpamAssassin working via the mail filter in
RT::Interface::Email::Filter::SpamAssassin. The filter needed a
complete renovation; perhaps it came from some much earlier RT version?
The appended patch works with SpamAssassin 2.63, only tested on RT 3.0.10/
Solaris 9/MySQL/Perl5.8.3/FastCGI/etc.
There was another tricky bug: apparently SpamAssassin munges the $_
global variable when a message rings the spam bell, such that its value
in the Gateway function's loop around @RT::MailPlugins gets unset. This
clears the plugin entry so it breaks on the next incoming email. I know
the functions/operators that set $_ are supposed have local effects but
apparently something doesn't. Switching to an explicit loop variable
fixed the symptom, so that patch is included.
I also added a couple of new features:
- It logs the message-id header of a message it drops on the floor at
the "info" level so you can match it with MTA logs to diagnose cases
of vanished mail.
- Adds the "X-RT-SpamAssassin-Score" header so a scrip can sort the
spammiest messages into a separate queue.
I know the spam filter could be implemented in the MTA or in procmail
driving the rt-mailgate, but this looked easier to maintain. If there aren't
any objections I'll submit it as a patch.
-- Larry
*** lib/RT/Interface/Email.pm.orig Fri Jan 2 17:55:55 2004
--- lib/RT/Interface/Email.pm Mon May 3 19:52:05 2004
***************
*** 500,521 ****
# Since this needs loading, no matter what
! for (@RT::MailPlugins) {
my $Code;
my $NewAuthStat;
! if ( ref($_) eq "CODE" ) {
! $Code = $_;
}
else {
! $_ = "RT::Interface::Email::$_" unless /^RT::Interface::Email::/;
! eval "require $_;";
if ($@) {
! die ("Couldn't load module $_: $@");
next;
}
no strict 'refs';
! if ( !defined( $Code = *{ $_ . "::GetCurrentUser" }{CODE} ) ) {
! die ("No GetCurrentUser code found in $_ module");
next;
}
}
--- 500,522 ----
# Since this needs loading, no matter what
! my $pi;
! foreach $pi (@RT::MailPlugins) {
my $Code;
my $NewAuthStat;
! if ( ref($pi) eq "CODE" ) {
! $Code = $pi;
}
else {
! $pi = "RT::Interface::Email::$pi" unless $pi =~ m/^RT::Interface::Email::/;
! eval "require $pi;";
if ($@) {
! die ("Couldn't load module $pi: $@");
next;
}
no strict 'refs';
! if ( !defined( $Code = *{ $pi . "::GetCurrentUser" }{CODE} ) ) {
! die ("No GetCurrentUser code found in $pi module");
next;
}
}
*** lib/RT/Interface/Email/Filter/SpamAssassin.pm.orig Fri Jan 2 17:55:55 2004
--- lib/RT/Interface/Email/Filter/SpamAssassin.pm Mon May 3 20:15:40 2004
***************
*** 27,41 ****
my $spamtest = Mail::SpamAssassin->new();
sub GetCurrentUser {
! my $item = shift;
! my $status = $spamtest->check ($item);
! return (undef, 0) unless $status->is_spam();
! eval { $status->rewrite_mail() };
! if ($status->get_hits > $status->get_required_hits()*1.5) {
# Spammy indeed
! return (undef, -1);
}
! return (undef, 0);
}
=head1 NAME
--- 27,48 ----
my $spamtest = Mail::SpamAssassin->new();
sub GetCurrentUser {
! my $result = 0;
! my %args = ( Message => undef,
! @_ );
! my $status = $spamtest->check_message_text($args{'Message'}->as_string());
! if ($status->is_spam() &&
! $status->get_hits() > $status->get_required_hits()*1.5) {
# Spammy indeed
! my $mid = $args{'Message'}->head()->get('Message-Id');
! my $hits = $status->get_hits();
! $RT::Logger->info("Filter::SpamAssassin: Dropping message $mid because spam score = $hits");
! $result = -1;
! } else {
! $args{'Message'}->head()->replace('X-RT-SpamAssassin-Score', sprintf("%.3f", $status->get_hits()));
}
! $status->finish();
! return (undef, $result);
}
=head1 NAME
More information about the rt-users
mailing list