[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