#### # COPYRIGHT: # # 2008 Erik Aronesty, GPL # # This software was based on the original Filter::SpamAssassin.pm # by BestPractical # # LICENSE: # # This work is made available to you under the terms of Version 2 of # the GNU General Public License. A copy of that license should have # been provided with this software, but in any event can be snarfed # from www.gnu.org. # # This work is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # A current copy of the GPL referenced above is available here: # http://creativecommons.org/licenses/GPL/2.0 # # VERSION: 0.9 (20080807) # # Current source release can be downloaded form # http://www.documentroot.com/SpamAssassin.pm #### package RT::Interface::Email::Filter::SpamAssassin; use Mail::SpamAssassin; use Mail::SpamAssassin::Client; my $spamcheck = Mail::SpamAssassin->new(); my $spamclient = Mail::SpamAssassin::Client->new({ host=>((!$RT::SpamAssassinClient || ($RT::SpamAssassinClient eq '1')) ? 'localhost' : $RT::SpamAssassinClient), port=>($RT::SpamAssassinPort > 0 ? $RT::SpamAssassinPort : 783)}); sub GetCurrentUser { my %args = ( @_ ); # spamassasin doesn't work with mime::entity my $status; if ($RT::SpamAssassinClient) { $status = $spamclient->check( $args{'Message'}->as_string() ); } else { my $parsed = $spamcheck->parse($args{'Message'}->as_string()); my $return = $spamcheck->check($parsed); # make a compatible return value $status->{isspam} = 'True' if $return->is_spam(); $status->{score} = $return->get_score(); $status->{threshold} = $return->get_required_score(); } if (!$status) { $RT::Logger && $RT::Logger->error("SpamAssassin returned undef, probably spamd isn't running?"); return ( $args{'CurrentUser'}, $args{'AuthLevel'} ); } my $msgfrom = $args{'Message'}->head->get('From'); $msgfrom =~ s/\s+//; my $msginfo = "score " . $status->{score} . " from [$msgfrom]"; $RT::Logger && $RT::Logger->debug("SpamAssassin returned $msginfo"); # add the header... so a scrip can deal with it later $args{'Message'}->head->delete('X-Spam-Score'); $args{'Message'}->head->add('X-Spam-Score', $status->{score}); return ( $args{'CurrentUser'}, $args{'AuthLevel'} ) unless $status && _spamdbool($status->{isspam}); if ( $status->{score} > $status->{threshold}*1.5 ) { # drop very spammy ones $RT::Logger && $RT::Logger->info("SpamAssassin thinks $msginfo is very spammy, dropping"); return ( $args{'CurrentUser'}, -1 ); } if ($RT::SpamAssassinQueue) { $RT::Logger && $RT::Logger->debug("SpamAssassin rerouting $msginfo to queue " . $RT::SpamAssassinQueue); $args{'Queue'}->Load( $RT::SpamAssassinQueue ); } else { $RT::Logger && $RT::Logger->info("SpamAssassin ignoring $msginfo, because SpamAssassinQueue not set."); } return ( $args{'CurrentUser'}, $args{'AuthLevel'} ); } sub _spamdbool { my ($bool) = @_; # in case someone changes things, as they always eem to return ($bool eq 'True' || $bool eq '1' || $bool eq 'T'); } =head1 NAME RT::Interface::Email::Filter::SpamAssassin - Spamassassin filter for RT =head1 SYNOPSIS @RT::MailPlugins = ("Filter::SpamAssassin", ...); =head1 DESCRIPTION This plugin checks to see if an incoming mail is spam (using C) and rewrites its headers. If the mail is very definitely spam - 1.5x more hits than required - then it is dropped on the floor; otherwise, it is passed on as normal. You must start the spamd server for this to work (possibly in /etc/init.d/spamassassin). You can set the config variable Set($RT:SpamAssassinQueue, ...) to configure the queue that "possible spam" goes to. You can set the config variable Set($RT:SpamAssassinClient, 'localhost') to enable spamd support. =cut eval "require RT::Interface::Email::Filter::SpamAssassin_Vendor"; die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email/Filter/SpamAssassin_Vendor.pm}); eval "require RT::Interface::Email::Filter::SpamAssassin_Local"; die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email/Filter/SpamAssassin_Local.pm}); 1;