"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "lib/Mail/SpamAssassin/Plugin/HashBL.pm" between
Mail-SpamAssassin-3.4.4.tar.bz2 and Mail-SpamAssassin-3.4.5.tar.bz2

About: SpamAssassin is a mail filter that uses a wide range of heuristic tests on mail headers and body text to identify "spam" (also known as unsolicited commercial email) incl. Bayesian (statistical) spam filter and several internet-based realtime blacklists.

HashBL.pm  (Mail-SpamAssassin-3.4.4.tar.bz2):HashBL.pm  (Mail-SpamAssassin-3.4.5.tar.bz2)
skipping to change at line 26 skipping to change at line 26
# </@LICENSE> # </@LICENSE>
=head1 NAME =head1 NAME
HashBL - query hashed (and unhashed) DNS blocklists HashBL - query hashed (and unhashed) DNS blocklists
=head1 SYNOPSIS =head1 SYNOPSIS
loadplugin Mail::SpamAssassin::Plugin::HashBL loadplugin Mail::SpamAssassin::Plugin::HashBL
header HASHBL_EMAIL eval:check_hashbl_emails('ebl.msbl.org') # NON-WORKING usage examples below, replace xxx.example.invalid with real list
# See documentation below for detailed usage
header HASHBL_EMAIL eval:check_hashbl_emails('ebl.example.invalid')
describe HASHBL_EMAIL Message contains email address found on EBL describe HASHBL_EMAIL Message contains email address found on EBL
priority HASHBL_EMAIL -100 # required priority to launch async lookups early
tflags HASHBL_EMAIL net
hashbl_acl_freemail gmail.com hashbl_acl_freemail gmail.com
header HASHBL_OSENDR eval:check_hashbl_emails('rbl.example.com/A', 'md5/max= 10/shuffle', 'X-Original-Sender', '^127\.', 'freemail') header HASHBL_OSENDR eval:check_hashbl_emails('rbl.example.invalid/A', 'md5/ max=10/shuffle', 'X-Original-Sender', '^127\.', 'freemail')
describe HASHBL_OSENDR Message contains email address found on HASHBL describe HASHBL_OSENDR Message contains email address found on HASHBL
tflags HASHBL_OSENDR net priority HASHBL_OSENDR -100 # required priority to launch async lookups early
tflags HASHBL_OSENDR net
body HASHBL_BTC eval:check_hashbl_bodyre('btcbl.foo.bar', 'sha1/max=10/shu ffle', '\b([13][a-km-zA-HJ-NP-Z1-9]{25,34})\b') body HASHBL_BTC eval:check_hashbl_bodyre('btcbl.example.invalid', 'sha1/ma x=10/shuffle', '\b([13][a-km-zA-HJ-NP-Z1-9]{25,34})\b')
describe HASHBL_BTC Message contains BTC address found on BTCBL describe HASHBL_BTC Message contains BTC address found on BTCBL
priority HASHBL_BTC -100 # required priority to launch async lookups priority HASHBL_BTC -100 # required priority to launch async lookups early
tflags HASHBL_BTC net
header HASHBL_URI eval:check_hashbl_uris('rbl.foo.bar', 'sha1', '127.0.0.32' ) header HASHBL_URI eval:check_hashbl_uris('rbl.example.invalid', 'sha1', '127 .0.0.32')
describe HASHBL_URI Message contains uri found on rbl describe HASHBL_URI Message contains uri found on rbl
priority HASHBL_URI -100 # required priority to launch async lookups early
tflags HASHBL_URI net
=head1 DESCRIPTION =head1 DESCRIPTION
This plugin support multiple types of hashed or unhashed DNS blocklists. This plugin support multiple types of hashed or unhashed DNS blocklists.
OPTS refers to multiple generic options: OPTS refers to multiple generic options:
raw do not hash data, query as is raw do not hash data, query as is
md5 hash query with MD5 md5 hash query with MD5
sha1 hash query with SHA1 sha1 hash query with SHA1
skipping to change at line 68 skipping to change at line 77
ALL all headers ALL all headers
ALLFROM all From headers as returned by $pms->all_from_addrs() ALLFROM all From headers as returned by $pms->all_from_addrs()
EnvelopeFrom message envelope from (Return-Path etc) EnvelopeFrom message envelope from (Return-Path etc)
HeaderName any header as used with $pms->get() HeaderName any header as used with $pms->get()
if HEADERS is empty ('') or missing, default is used. if HEADERS is empty ('') or missing, default is used.
=over 4 =over 4
=item header RULE check_hashbl_emails('bl.example.com/A', 'OPTS', 'HEADERS/body' , '^127\.') =item header RULE check_hashbl_emails('bl.example.invalid/A', 'OPTS', 'HEADERS/b ody', '^127\.')
Check email addresses from DNS list, "body" can be specified along with Check email addresses from DNS list, "body" can be specified along with
headers to search body for emails. Optional subtest regexp to match DNS headers to search body for emails. Optional subtest regexp to match DNS
answer. Note that eval rule type must always be "header". answer. Note that eval rule type must always be "header".
DNS query type can be appended to list with /A (default) or /TXT. DNS query type can be appended to list with /A (default) or /TXT.
Additional supported OPTS: Additional supported OPTS:
nodot strip username dots from email nodot strip username dots from email
notag strip username tags from email notag strip username tags from email
nouri ignore emails inside uris nouri ignore emails inside uris
noquote ignore emails inside < > or possible quotings noquote ignore emails inside < > or possible quotings
Default OPTS: sha1/notag/noquote/max=10/shuffle Default OPTS: sha1/notag/noquote/max=10/shuffle
Default HEADERS: ALLFROM/Reply-To/body Default HEADERS: ALLFROM/Reply-To/body
For existing public email blacklist, see: http://msbl.org/ebl.html For existing public email blacklist, see: http://msbl.org/ebl.html
header HASHBL_EBL check_hashbl_emails('ebl.msbl.org') # Working example, see http://msbl.org/ebl.html before usage
priority HASHBL_EBL -100 # required for async query header HASHBL_EMAIL eval:check_hashbl_emails('ebl.msbl.org')
describe HASHBL_EMAIL Message contains email address found on EBL
priority HASHBL_EMAIL -100 # required priority to launch async lookups early
tflags HASHBL_EMAIL net
=over 4 =over 4
=item header RULE check_hashbl_uris('bl.example.com/A', 'OPTS', '^127\.') =item header RULE check_hashbl_uris('bl.example.invalid/A', 'OPTS', '^127\.')
Check uris from DNS list, optional subtest regexp to match DNS Check uris from DNS list, optional subtest regexp to match DNS
answer. answer.
DNS query type can be appended to list with /A (default) or /TXT. DNS query type can be appended to list with /A (default) or /TXT.
Default OPTS: sha1/max=10/shuffle Default OPTS: sha1/max=10/shuffle
=back =back
=item body RULE check_hashbl_bodyre('bl.example.com/A', 'OPTS', '\b(match)\b', ' ^127\.') =item body RULE check_hashbl_bodyre('bl.example.invalid/A', 'OPTS', '\b(match)\b ', '^127\.')
Search body for matching regexp and query the string captured. Regexp must Search body for matching regexp and query the string captured. Regexp must
have a single capture ( ) for the string ($1). Optional subtest regexp to have a single capture ( ) for the string ($1). Optional subtest regexp to
match DNS answer. Note that eval rule type must be "body" or "rawbody". match DNS answer. Note that eval rule type must be "body" or "rawbody".
=back =back
=cut =cut
package Mail::SpamAssassin::Plugin::HashBL; package Mail::SpamAssassin::Plugin::HashBL;
skipping to change at line 344 skipping to change at line 356
} elsif ($hdr eq 'body') { } elsif ($hdr eq 'body') {
# get all <a href="mailto:", since they don't show up on stripped_body # get all <a href="mailto:", since they don't show up on stripped_body
my $uris = $pms->get_uri_detail_list(); my $uris = $pms->get_uri_detail_list();
while (my($uri, $info) = each %{$uris}) { while (my($uri, $info) = each %{$uris}) {
if (defined $info->{types}->{a} && !defined $info->{types}->{parsed}) { if (defined $info->{types}->{a} && !defined $info->{types}->{parsed}) {
if ($uri =~ /^mailto:(.+)/i) { if ($uri =~ /^mailto:(.+)/i) {
$str .= "$1\n"; $str .= "$1\n";
} }
} }
} }
my $body = join('', $pms->get_decoded_stripped_body_text_array()); my $body = join('', @{$pms->get_decoded_stripped_body_text_array()});
if ($opts =~ /\bnouri\b/) { if ($opts =~ /\bnouri\b/) {
# strip urls with possible emails inside # strip urls with possible emails inside
$body =~ s#<?https?://\S{0,255}(?:\@|%40)\S{0,255}# #gi; $body =~ s#<?https?://\S{0,255}(?:\@|%40)\S{0,255}# #gi;
} }
if ($opts =~ /\bnoquote\b/) { if ($opts =~ /\bnoquote\b/) {
# strip emails contained in <>, not mailto: # strip emails contained in <>, not mailto:
# also strip ones followed by quote-like "wrote:" (but not fax: and tel: e tc) # also strip ones followed by quote-like "wrote:" (but not fax: and tel: e tc)
$body =~ s#<?(?<!mailto:)$self->{email_re}(?:>|\s{1,10}(?!(?:fa(?:x|csi)|t el|phone|e?-?mail))[a-z]{2,11}:)# #gi; $body =~ s#<?(?<!mailto:)$self->{email_re}(?:>|\s{1,10}(?!(?:fa(?:x|csi)|t el|phone|e?-?mail))[a-z]{2,11}:)# #gi;
} }
$str .= $body; $str .= $body;
skipping to change at line 419 skipping to change at line 431
} }
# Filter list # Filter list
my $keep_case = $opts =~ /\bcase\b/i; my $keep_case = $opts =~ /\bcase\b/i;
my $nodot = $opts =~ /\bnodot\b/i; my $nodot = $opts =~ /\bnodot\b/i;
my $notag = $opts =~ /\bnotag\b/i; my $notag = $opts =~ /\bnotag\b/i;
my @filtered_emails; # keep order my @filtered_emails; # keep order
my %seen; my %seen;
foreach my $email (@$emails) { foreach my $email (@$emails) {
next if exists $seen{$email}; next if exists $seen{$email};
next if $email !~ /.*\@.*/;
if (($email =~ $self->{email_whitelist}) or defined ($pms->{hashbl_whitelist }{$email})) { if (($email =~ $self->{email_whitelist}) or defined ($pms->{hashbl_whitelist }{$email})) {
dbg("Address whitelisted: $email"); dbg("Address whitelisted: $email");
next; next;
} }
if ($nodot || $notag) { if ($nodot || $notag) {
my ($username, $domain) = ($email =~ /(.*)(\@.*)/); my ($username, $domain) = ($email =~ /(.*)(\@.*)/);
$username =~ tr/.//d if $nodot; $username =~ tr/.//d if $nodot;
$username =~ s/\+.*// if $notag; $username =~ s/\+.*// if $notag;
$email = $username.$domain; $email = $username.$domain;
} }
skipping to change at line 442 skipping to change at line 455
# Randomize order # Randomize order
if ($opts =~ /\bshuffle\b/) { if ($opts =~ /\bshuffle\b/) {
Mail::SpamAssassin::Util::fisher_yates_shuffle(\@filtered_emails); Mail::SpamAssassin::Util::fisher_yates_shuffle(\@filtered_emails);
} }
# Truncate list # Truncate list
my $max = $opts =~ /\bmax=(\d+)\b/ ? $1 : 10; my $max = $opts =~ /\bmax=(\d+)\b/ ? $1 : 10;
$#filtered_emails = $max-1 if scalar @filtered_emails > $max; $#filtered_emails = $max-1 if scalar @filtered_emails > $max;
$pms->{hashbl_emails_count}{$rulename} = scalar @filtered_emails;
foreach my $email (@filtered_emails) { foreach my $email (@filtered_emails) {
$self->_submit_query($pms, $rulename, $email, $list, $opts, $subtest); $self->_submit_query($pms, $rulename, $email, $list, $opts, $subtest);
} }
return 0; return 0;
} }
sub check_hashbl_uris { sub check_hashbl_uris {
my ($self, $pms, $list, $opts, $subtest) = @_; my ($self, $pms, $list, $opts, $subtest) = @_;
skipping to change at line 656 skipping to change at line 670
$ent = $pms->{async}->bgsend_and_start_lookup($lookup, $type, undef, $ent, $ent = $pms->{async}->bgsend_and_start_lookup($lookup, $type, undef, $ent,
sub { my ($ent, $pkt) = @_; $self->_finish_query($pms, $ent, $pkt); }, sub { my ($ent, $pkt) = @_; $self->_finish_query($pms, $ent, $pkt); },
master_deadline => $pms->{master_deadline} master_deadline => $pms->{master_deadline}
); );
$pms->register_async_rule_start($rulename) if $ent; $pms->register_async_rule_start($rulename) if $ent;
} }
sub _finish_query { sub _finish_query {
my ($self, $pms, $ent, $pkt) = @_; my ($self, $pms, $ent, $pkt) = @_;
my $rulename = $ent->{rulename};
if (!$pkt) { if (!$pkt) {
# $pkt will be undef if the DNS query was aborted (e.g. timed out) # $pkt will be undef if the DNS query was aborted (e.g. timed out)
dbg("lookup was aborted: $ent->{rulename} $ent->{key}"); dbg("lookup was aborted: $rulename $ent->{key}");
return; return;
} }
my $dnsmatch = $ent->{subtest} ? $ent->{subtest} : qr/^127\./; my $dnsmatch = $ent->{subtest} ? $ent->{subtest} : qr/^127\./;
my @answer = $pkt->answer; my @answer = $pkt->answer;
foreach my $rr (@answer) { foreach my $rr (@answer) {
if ($rr->address =~ $dnsmatch) { if ($rr->address =~ $dnsmatch) {
dbg("$ent->{rulename}: $ent->{zone} hit '$ent->{value}'"); dbg("$rulename: $ent->{zone} hit '$ent->{value}'");
$ent->{value} =~ s/\@/[at]/g; $ent->{value} =~ s/\@/[at]/g;
$pms->test_log($ent->{value}); # Hit now if only one query exists, otherwise call hits at scan end
$pms->got_hit($ent->{rulename}, '', ruletype => 'eval'); if ($pms->{hashbl_emails_count}{$rulename} == 1) {
$pms->register_async_rule_finish($ent->{rulename}); $pms->test_log($ent->{value});
$pms->got_hit($rulename, '', ruletype => 'eval');
$pms->register_async_rule_finish($rulename);
} else {
push @{$pms->{hashbl_emails_hits}{$rulename}}, $ent->{value};
}
return; return;
} }
} }
} }
sub check_cleanup {
my ($self, $opts) = @_;
my $pms = $opts->{permsgstatus};
# Call any remaining hits
if (exists $pms->{hashbl_emails_hits}) {
foreach my $rulename (keys %{$pms->{hashbl_emails_hits}}) {
$pms->test_log(join(', ', sort @{$pms->{hashbl_emails_hits}{$rulename}}));
$pms->got_hit($rulename, '', ruletype => 'eval');
}
}
}
# Version features # Version features
sub has_hashbl_bodyre { 1 } sub has_hashbl_bodyre { 1 }
sub has_hashbl_emails { 1 } sub has_hashbl_emails { 1 }
sub has_hashbl_uris { 1 } sub has_hashbl_uris { 1 }
sub has_hashbl_ignore { 1 } sub has_hashbl_ignore { 1 }
1; 1;
 End of changes. 20 change blocks. 
17 lines changed or deleted 52 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)