-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
awesome! any chance you could put this on the wiki, linked from CustomPlugins? - --j. Derek Harding writes: > On Mon, 2005-08-08 at 15:53 -0500, [EMAIL PROTECTED] wrote: > > > > > > It allows rules such as: > > > uricountry URICOUNTRY_CN CN > > > header URICOUNTRY_CN eval:check_uricountry('URICOUNTRY_CN') > > > describe URICOUNTRY_CN Contains a URI hosted in China > > > tflags URICOUNTRY_CN net > > > score URICOUNTRY_CN 2.0 > > > > > > Derek > > > > > > Oh yes, that type code would be very nice to have indeed for people like > > me who can't outright RBL them. Do you also have code for Korea even? But > > dare I ask too much. :-) I could give it a score of 4 or so... and up it > > even more when spammer simpletons start thinking they are on to the latest > > greatest China spam idea. :-) > > The code will work for any country. Just write a rule for that country. > > Here's what's needed in your local.cf > > loadplugin Mail::SpamAssassin::Plugin::URICountry > > uricountry URICOUNTRY_CN CN > header URICOUNTRY_CN eval:check_uricountry('URICOUNTRY_CN') > describe URICOUNTRY_CN Contains a URI hosted in China > tflags URICOUNTRY_CN net > score URICOUNTRY_CN 2.0 > > uricountry URICOUNTRY_KR KR > header URICOUNTRY_KR eval:check_uricountry('URICOUNTRY_KR') > describe URICOUNTRY_KR Contains a URI hosted in Korea > tflags URICOUNTRY_KR net > score URICOUNTRY_KR 2.0 > > uricountry URICOUNTRY_BR BR > header URICOUNTRY_BR eval:check_uricountry('URICOUNTRY_BR') > describe URICOUNTRY_BR Contains a URI hosted in Brazil > tflags URICOUNTRY_BR net > score URICOUNTRY_BR 2.0 > > Derek > > -- code for the plugin follows -- > =head1 NAME > > URICountry - add message metadata indicating the country code of each > relay > > =head1 SYNOPSIS > > loadplugin Mail::SpamAssassin::Plugin::URICountry > > =head1 REQUIREMENT > > This plugin requires the IP::Country::Fast module from CPAN. > > =cut > > package Mail::SpamAssassin::Plugin::URICountry; > > use Mail::SpamAssassin::Plugin; > use strict; > use bytes; > > use vars qw(@ISA); > @ISA = qw(Mail::SpamAssassin::Plugin); > > # constructor: register the eval rule > sub new { > my $class = shift; > my $mailsaobject = shift; > > # some boilerplate... > $class = ref($class) || $class; > my $self = $class->SUPER::new($mailsaobject); > bless ($self, $class); > > $self->register_eval_rule ("check_uricountry"); > > return $self; > } > > # this is just a placeholder; in fact the results are dealt with later > sub check_uricountry { > my ($self, $permsgstatus, $rulename) = @_; > return 0; > } > > # and the eval rule itself > sub parsed_metadata { > my ($self, $opts) = @_; > my $scanner = $opts->{permsgstatus}; > > my $reg; > > eval { > require IP::Country::Fast; > $reg = IP::Country::Fast->new(); > }; > if ($@) { > dbg ("failed to load 'IP::Country::Fast', skipping"); > return 1; > } > > my %domlist = (); > foreach my $uri ($scanner->get_uri_list()) { > my $dom = my_uri_to_domain($uri); > dbg("debug: URICountry $uri in $dom"); > if ($dom) { > $domlist{$dom} = 1; > } > } > > # Build a list of the countries for URIs in the message. > my %countries = (); > foreach my $dom (keys(%domlist)) { > my $cc = $reg->inet_atocc($dom) || "XX"; > dbg("debug: URICountry $dom in $cc"); > $countries{lc($cc)} = 1; > } > > # Now check if any match any defined rules. > foreach my $rule (keys(%{$scanner->{conf}->{uricountry}})) { > my $country = lc($scanner->{conf}->{uricountry}->{$rule}); > if($countries{$country}) { > dbg ("debug: URICountry hit rule: $country"); > $scanner->got_hit($rule, ""); > } > } > > return 1; > } > > sub parse_config { > my ($self, $opts) = @_; > > my $key = $opts->{key}; > > if ($key eq 'uricountry') { > if ($opts->{value} =~ /^(\S+)\s+(\S+)\s*$/) { > my $rulename = $1; > my $country = $2; > > dbg("debug: URICountry: registering $rulename"); > $opts->{conf}->{uricountry}->{$rulename} = $country; > $self->inhibit_further_callbacks(); return 1; > } > } > > return 0; > } > > # Taken from the one in Util.pm but we don't want to drop the hostname > doing so > # often leaves us with no A record. > sub my_uri_to_domain { > my ($uri) = @_; > > # Javascript is not going to help us, so return. > return if ($uri =~ /^javascript:/i); > > $uri =~ s,#.*$,,gs; # drop fragment > $uri =~ s#^[a-z]+:/{0,2}##gsi; # drop the protocol > $uri =~ s,^[^/]*\@,,gs; # username/passwd > $uri =~ s,[/\?\&].*$,,gs; # path/cgi params > $uri =~ s,:\d+$,,gs; # port > > return if $uri =~ /\%/; # skip undecoded URIs. > # we'll see the decoded version as well > > # keep IPs intact > if ($uri !~ /^\d+\.\d+\.\d+\.\d+$/) { > # get rid of hostname part of domain, understanding delegation > #$uri Mail::SpamAssassin::Util::RegistrarBoundaries::trim_domain($uri); > > # ignore invalid domains > return unless > > (Mail::SpamAssassin::Util::RegistrarBoundaries::is_domain_valid($uri)); > } > > # $uri is now the domain only > return lc $uri; > } > > sub dbg { Mail::SpamAssassin::dbg (@_); } > > 1; > -- end code -- -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.5 (GNU/Linux) Comment: Exmh CVS iD8DBQFC98tnMJF5cimLx9ARAopMAJwPUfRwleBHQAJlNDpHLaJOyPpuHACfQ3Sy JiuVQJF2cDbW8JrjhfcZRFU= =K+Sc -----END PGP SIGNATURE-----