codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
package RT::Interface::Email::Filter::SpamAssassin; our $VERSION = .95; our $statERR; BEGIN{ if( $RT::SpamAssassinClient == 0 ){ require Mail::Field; require Mail::Header; $statERR = 'There were no X-Spam fields.'; *_score = sub { my $msg = Mail::Header->new( [split(/\n/, $_[0])] ); #Make long headers like X-Spam-Status approx. single-lines. $msg->fold(1024); my $status; my $report = Mail::Field->extract('X-Spam-Status', $msg); $report &&= $report->stringify; $status->{score} = $1 if $report =~ /score=(\d+(?:\.\d+)?)/; $status->{threshold} = $1 if $report =~ /required=(\d+(?:\.\d+)?)/; local $_ = Mail::Field->extract('X-Spam-Flag', $msg); $status->{isspam} = $_->stringify if $_; return $status; }; } elsif( $RT::SpamAssassinClient > 0 ){ require Mail::SpamAssassin::Client; $statERR = 'Is spamd running?'; *_score = sub{ my $client = Mail::SpamAssassin::Client->new({ host=>($RT::SpamAssassinClient eq '1' ? 'localhost' : $RT::SpamAssassinClient), port=>($RT::SpamAssassinPort || 783) }); $client->check( $_[0] ); }; } else{ require Mail::SpamAssassin; $statERR = 'A problem doing it ourselves'; *_score = sub{ my $spamcheck = Mail::SpamAssassin->new(); my $return = $spamcheck->check( $spamcheck->parse($_[0]) ); # make a compatible return value my $status; $status->{isspam} = 'True' if $return->is_spam(); $status->{score} = $return->get_score(); $status->{threshold} = $return->get_required_score(); return $status; }; } } sub GetCurrentUser { my %args = @_; my $status = _score( ${$args{RawMessageRef}} ); unless( $status ){ $RT::Logger && $RT::Logger->error("SpamAssassin returned undef. $statERR"); return ( $args{'CurrentUser'}, $args{'AuthLevel'} ); } my $msgfrom = $args{'Message'}->head->get('From'); $msgfrom =~ s/\s{2,}|\n//; my $msginfo = "score " . $status->{score} . " from [$msgfrom]"; $RT::Logger && $RT::Logger->debug("SpamAssassin returned $msginfo"); # add the new header... so a scrip can deal with it later if( $RT::SpamAssassinClient != 0 ){ $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}); # punt especially spammy messages if( $status->{score} > $status->{threshold}*($RT::SpamAssassinMax||1.5) ){ $RT::Logger && $RT::Logger->info("SpamAssassin thinks $msginfo is very spammy, punting"); return ( $args{'CurrentUser'}, -1 ); } if( $RT::SpamAssassinQueue ){ $RT::Logger && $RT::Logger->info("SpamAssassin rerouting $msginfo to queue " . $RT::SpamAssassinQueue); $args{'Queue'}->Load( $RT::SpamAssassinQueue ); } else{ $RT::Logger && $RT::Logger->debug("SpamAssassin ignoring $msginfo, because SpamAssassinQueue not set."); } return ( $args{'CurrentUser'}, $args{'AuthLevel'} ); } sub _spamdbool { my ($bool) = @_; # in case someone changes things, as they always seem to return ($bool eq 'True' || $bool eq 'YES' || $bool eq '1' || $bool eq 'T'); } =head1 NAME RT::Interface::Email::Filter::SpamAssassin - Spamassassin filter for RT =head1 SYNOPSIS F<RT_SiteConfig.pm> #Enable spam filtering, but make sure you authenticate users first! Set(@MailPlugins, 'Filter::SpamAssassin', ... 'Auth::MailFrom'); #Enable per-message calls to SpamAssassin on localhost Set($RT::SpamAssassinClient, 'mail.example.org') #Refile suspect messages #Set($RT::SpamAssassinQueue, 'SPAM'); #Conservative punting of messages Set($RT::SpamAssassinMax, 4); =head1 DESCRIPTION This plugin checks to see if an incoming mail is spam, optionally running it through SpamAssassin. If the mail is very definitely spam, then it is punted. Otherwise, it may be passed on as normal or directed to a special queue if suspect. =over =item B<$RT:SpamAssassinClient> Whether or not to (re)check messages. =over =item I<hostname> Connect to I<hostname> with L<Mail::SpamAssassin::Client> to process messsage. =item I<-1> Process message with L<Mail::SpamAssassin::PerMsgStatus>. This is very slow. =item I<0> Rely on existing headers. This is very fast. =item I<1> Equivalent to I<localhost>. =back =item B<$RT::SpamAssassinPort> The port to connect to if B<$RT::SpamAssassinClient> is true. Default is 783. =item B<$RT::SpamAssassinMax> If the message's score is at least this many times greather than SpamAssassin's threshold, discard the message. The default is 1.5, so messages scoring > 1.5*threshold are discarded. =item B<$RT::SpamAssassinQueue> If set, messages meeting the local threshold will be shunted to the queue specified in the variable. This can be a safe way to avoid excess notifications to your AdminCCs, without dropping messages. =back =head1 AUTHOR =over =item Jerrad Pierce VERSION 0.95 (20081110) =item Erik Aronesty VERSION: 0.9 (20080807) =item Best Practical =back =head1 LICENSE GPL 2 =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;
Private
[
?
]
Run code
Submit