You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by gb...@apache.org on 2018/06/17 09:41:02 UTC
svn commit: r1833660 - in /spamassassin:
branches/3.4/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm
trunk/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm
Author: gbechis
Date: Sun Jun 17 09:41:02 2018
New Revision: 1833660
URL: http://svn.apache.org/viewvc?rev=1833660&view=rev
Log:
partial fix for bz 7529
starting from 04/01/2018, Geolite legacy databases has been
discontinued and they will be no more updates.
Add a "country_db_type" option that will let the user choose
between GeoIP and IP::Country::Fast databases.
By default GeoIP is enabled and there is still a fallback
on IP::Country::Fast as in previuos implementation.
IP::Country::Fast has no ipv6 support, so a better api
should be adopted sooner or later.
Modified:
spamassassin/branches/3.4/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm
Modified: spamassassin/branches/3.4/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm
URL: http://svn.apache.org/viewvc/spamassassin/branches/3.4/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm?rev=1833660&r1=1833659&r2=1833660&view=diff
==============================================================================
--- spamassassin/branches/3.4/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm (original)
+++ spamassassin/branches/3.4/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm Sun Jun 17 09:41:02 2018
@@ -32,8 +32,9 @@ header markup.
=head1 REQUIREMENT
-This plugin requires the Geo::IP module from CPAN. For backward
-compatibility IP::Country::Fast is used if Geo::IP is not installed.
+This plugin requires the Geo::IP or IP::Country::Fast module from CPAN.
+For backward compatibility IP::Country::Fast is used if Geo::IP is
+not installed.
=cut
@@ -49,51 +50,10 @@ use re 'taint';
our @ISA = qw(Mail::SpamAssassin::Plugin);
-my ($db, $dbv6);
-my $ip_to_cc; # will hold a sub() for the lookup
-my $db_info; # will hold a sub() for database info
-
-# Try to load Geo::IP first
-eval {
- require Geo::IP;
- $db = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION, Geo::IP->GEOIP_STANDARD);
- die "GeoIP.dat not found" unless $db;
- # IPv6 requires version Geo::IP 1.39+ with GeoIP C API 1.4.7+
- if (Geo::IP->VERSION >= 1.39 && Geo::IP->api eq 'CAPI') {
- $dbv6 = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION_V6, Geo::IP->GEOIP_STANDARD);
- if (!$dbv6) {
- dbg("metadata: RelayCountry: IPv6 support not enabled, GeoIPv6.dat not found");
- }
- } else {
- dbg("metadata: RelayCountry: IPv6 support not enabled, versions Geo::IP 1.39, GeoIP C API 1.4.7 required");
- }
- $ip_to_cc = sub {
- if ($dbv6 && $_[0] =~ /:/) {
- return $dbv6->country_code_by_addr_v6($_[0]) || "XX";
- } else {
- return $db->country_code_by_addr($_[0]) || "XX";
- }
- };
- $db_info = sub { return "Geo::IP " . ($db->database_info || '?') };
- 1;
-} or do {
- my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
- dbg("metadata: RelayCountry: failed to load 'Geo::IP', skipping: $eval_stat");
- # Try IP::Country::Fast as backup
- eval {
- require IP::Country::Fast;
- $db = IP::Country::Fast->new();
- $ip_to_cc = sub {
- return $db->inet_atocc($_[0]) || "XX";
- };
- $db_info = sub { return "IP::Country::Fast ".localtime($db->db_time()); };
- 1;
- } or do {
- my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
- dbg("metadata: RelayCountry: failed to load 'IP::Country::Fast', skipping: $eval_stat");
- return 1;
- };
-};
+my $db;
+my $dbv6;
+my $db_info; # will hold database info
+my $db_type; # will hold database type
# constructor: register the eval rule
sub new {
@@ -104,11 +64,91 @@ sub new {
$class = ref($class) || $class;
my $self = $class->SUPER::new($mailsaobject);
bless ($self, $class);
+
+ $self->set_config($mailsaobject->{conf});
return $self;
}
+sub set_config {
+ my ($self, $conf) = @_;
+ my @cmds;
+
+=head1 USER PREFERENCES
+
+The following options can be used in both site-wide (C<local.cf>) and
+user-specific (C<user_prefs>) configuration files to customize how
+SpamAssassin handles incoming email messages.
+
+=over 4
+
+=item country_db_type STRING
+
+This option tells SpamAssassin which type of Geo database to use.
+Valid database types are GeoIP and Fast.
+
+=back
+
+=cut
+
+ push (@cmds, {
+ setting => 'country_db_type',
+ default => "GeoIP",
+ type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING,
+ code => sub {
+ my ($self, $key, $value, $line) = @_;
+ if ( $value !~ /GeoIP|Fast/) {
+ return $Mail::SpamAssassin::Conf::INVALID_VALUE;
+ }
+
+ $self->{country_db_type} = $value;
+ }
+ });
+
+ $conf->{parser}->register_commands(\@cmds);
+}
+
sub extract_metadata {
my ($self, $opts) = @_;
+ my $geo;
+ my $cc;
+
+ my $conf_country_db_type = $self->{'main'}{'resolver'}{'conf'}->{country_db_type};
+
+ if ( $conf_country_db_type eq "GeoIP") {
+ eval {
+ require Geo::IP;
+ $db = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION, Geo::IP->GEOIP_STANDARD);
+ die "GeoIP.dat not found" unless $db;
+ # IPv6 requires version Geo::IP 1.39+ with GeoIP C API 1.4.7+
+ if (Geo::IP->VERSION >= 1.39 && Geo::IP->api eq 'CAPI') {
+ $dbv6 = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION_V6, Geo::IP->GEOIP_STANDARD);
+ if (!$dbv6) {
+ dbg("metadata: RelayCountry: IPv6 support not enabled, GeoIPv6.dat not found");
+ }
+ $db_info = sub { return "Geo::IP " . ($db->database_info || '?') };
+ } else {
+ dbg("metadata: RelayCountry: IPv6 support not enabled, versions Geo::IP 1.39, GeoIP C API 1.4.7 required");
+ }
+ } or do {
+ # Fallback to IP::Country::Fast
+ dbg("metadata: RelayCountry: GeoIP.dat not found, IP::Country::Fast enabled as fallback");
+ $conf_country_db_type = "Fast";
+ }
+ }
+ if( $conf_country_db_type eq "Fast") {
+ my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
+ # Try IP::Country::Fast as backup
+ eval {
+ require IP::Country::Fast;
+ $db = IP::Country::Fast->new();
+ $db_info = sub { return "IP::Country::Fast ".localtime($db->db_time()); };
+ 1;
+ } or do {
+ my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
+ dbg("metadata: RelayCountry: failed to load 'IP::Country::Fast', skipping: $eval_stat");
+ return 1;
+ };
+ };
return 1 unless $db;
@@ -117,10 +157,20 @@ sub extract_metadata {
my $countries = '';
my $IP_PRIVATE = IP_PRIVATE;
+ my $IPV4_ADDRESS = IPV4_ADDRESS;
foreach my $relay (@{$msg->{metadata}->{relays_untrusted}}) {
my $ip = $relay->{ip};
# Private IPs will always be returned as '**'
- my $cc = $ip =~ /^$IP_PRIVATE$/o ? '**' : $ip_to_cc->($ip);
+ if ( $conf_country_db_type eq "GeoIP" ) {
+ if ( $ip !~ /^$IPV4_ADDRESS$/o ) {
+ $geo = $dbv6->country_code_by_addr_v6($ip) || "XX";
+ } else {
+ $geo = $db->country_code_by_addr($ip) || "XX";
+ }
+ } elsif ( $conf_country_db_type eq "Fast" ) {
+ $geo = $db->inet_atocc($ip) || "XX";
+ }
+ $cc = $ip =~ /^$IP_PRIVATE$/o ? '**' : $geo;
$countries .= $cc." ";
}
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm?rev=1833660&r1=1833659&r2=1833660&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm Sun Jun 17 09:41:02 2018
@@ -32,8 +32,9 @@ header markup.
=head1 REQUIREMENT
-This plugin requires the Geo::IP module from CPAN. For backward
-compatibility IP::Country::Fast is used if Geo::IP is not installed.
+This plugin requires the Geo::IP or IP::Country::Fast module from CPAN.
+For backward compatibility IP::Country::Fast is used if Geo::IP is
+not installed.
=cut
@@ -49,51 +50,10 @@ use re 'taint';
our @ISA = qw(Mail::SpamAssassin::Plugin);
-my ($db, $dbv6);
-my $ip_to_cc; # will hold a sub() for the lookup
-my $db_info; # will hold a sub() for database info
-
-# Try to load Geo::IP first
-eval {
- require Geo::IP;
- $db = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION, Geo::IP->GEOIP_STANDARD);
- die "GeoIP.dat not found" unless $db;
- # IPv6 requires version Geo::IP 1.39+ with GeoIP C API 1.4.7+
- if (Geo::IP->VERSION >= 1.39 && Geo::IP->api eq 'CAPI') {
- $dbv6 = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION_V6, Geo::IP->GEOIP_STANDARD);
- if (!$dbv6) {
- dbg("metadata: RelayCountry: IPv6 support not enabled, GeoIPv6.dat not found");
- }
- } else {
- dbg("metadata: RelayCountry: IPv6 support not enabled, versions Geo::IP 1.39, GeoIP C API 1.4.7 required");
- }
- $ip_to_cc = sub {
- if ($dbv6 && $_[0] =~ /:/) {
- return $dbv6->country_code_by_addr_v6($_[0]) || "XX";
- } else {
- return $db->country_code_by_addr($_[0]) || "XX";
- }
- };
- $db_info = sub { return "Geo::IP " . ($db->database_info || '?') };
- 1;
-} or do {
- my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
- dbg("metadata: RelayCountry: failed to load 'Geo::IP', skipping: $eval_stat");
- # Try IP::Country::Fast as backup
- eval {
- require IP::Country::Fast;
- $db = IP::Country::Fast->new();
- $ip_to_cc = sub {
- return $db->inet_atocc($_[0]) || "XX";
- };
- $db_info = sub { return "IP::Country::Fast ".localtime($db->db_time()); };
- 1;
- } or do {
- my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
- dbg("metadata: RelayCountry: failed to load 'IP::Country::Fast', skipping: $eval_stat");
- return 1;
- };
-};
+my $db;
+my $dbv6;
+my $db_info; # will hold database info
+my $db_type; # will hold database type
# constructor: register the eval rule
sub new {
@@ -104,11 +64,91 @@ sub new {
$class = ref($class) || $class;
my $self = $class->SUPER::new($mailsaobject);
bless ($self, $class);
+
+ $self->set_config($mailsaobject->{conf});
return $self;
}
+sub set_config {
+ my ($self, $conf) = @_;
+ my @cmds;
+
+=head1 USER PREFERENCES
+
+The following options can be used in both site-wide (C<local.cf>) and
+user-specific (C<user_prefs>) configuration files to customize how
+SpamAssassin handles incoming email messages.
+
+=over 4
+
+=item country_db_type STRING
+
+This option tells SpamAssassin which type of Geo database to use.
+Valid database types are GeoIP and Fast.
+
+=back
+
+=cut
+
+ push (@cmds, {
+ setting => 'country_db_type',
+ default => "GeoIP",
+ type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING,
+ code => sub {
+ my ($self, $key, $value, $line) = @_;
+ if ( $value !~ /GeoIP|Fast/) {
+ return $Mail::SpamAssassin::Conf::INVALID_VALUE;
+ }
+
+ $self->{country_db_type} = $value;
+ }
+ });
+
+ $conf->{parser}->register_commands(\@cmds);
+}
+
sub extract_metadata {
my ($self, $opts) = @_;
+ my $geo;
+ my $cc;
+
+ my $conf_country_db_type = $self->{'main'}{'resolver'}{'conf'}->{country_db_type};
+
+ if ( $conf_country_db_type eq "GeoIP") {
+ eval {
+ require Geo::IP;
+ $db = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION, Geo::IP->GEOIP_STANDARD);
+ die "GeoIP.dat not found" unless $db;
+ # IPv6 requires version Geo::IP 1.39+ with GeoIP C API 1.4.7+
+ if (Geo::IP->VERSION >= 1.39 && Geo::IP->api eq 'CAPI') {
+ $dbv6 = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION_V6, Geo::IP->GEOIP_STANDARD);
+ if (!$dbv6) {
+ dbg("metadata: RelayCountry: IPv6 support not enabled, GeoIPv6.dat not found");
+ }
+ $db_info = sub { return "Geo::IP " . ($db->database_info || '?') };
+ } else {
+ dbg("metadata: RelayCountry: IPv6 support not enabled, versions Geo::IP 1.39, GeoIP C API 1.4.7 required");
+ }
+ } or do {
+ # Fallback to IP::Country::Fast
+ dbg("metadata: RelayCountry: GeoIP.dat not found, IP::Country::Fast enabled as fallback");
+ $conf_country_db_type = "Fast";
+ }
+ }
+ if( $conf_country_db_type eq "Fast") {
+ my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
+ # Try IP::Country::Fast as backup
+ eval {
+ require IP::Country::Fast;
+ $db = IP::Country::Fast->new();
+ $db_info = sub { return "IP::Country::Fast ".localtime($db->db_time()); };
+ 1;
+ } or do {
+ my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
+ dbg("metadata: RelayCountry: failed to load 'IP::Country::Fast', skipping: $eval_stat");
+ return 1;
+ };
+ };
return 1 unless $db;
@@ -117,10 +157,20 @@ sub extract_metadata {
my $countries = '';
my $IP_PRIVATE = IP_PRIVATE;
+ my $IPV4_ADDRESS = IPV4_ADDRESS;
foreach my $relay (@{$msg->{metadata}->{relays_untrusted}}) {
my $ip = $relay->{ip};
# Private IPs will always be returned as '**'
- my $cc = $ip =~ /^$IP_PRIVATE$/o ? '**' : $ip_to_cc->($ip);
+ if ( $conf_country_db_type eq "GeoIP" ) {
+ if ( $ip !~ /^$IPV4_ADDRESS$/o ) {
+ $geo = $dbv6->country_code_by_addr_v6($ip) || "XX";
+ } else {
+ $geo = $db->country_code_by_addr($ip) || "XX";
+ }
+ } elsif ( $conf_country_db_type eq "Fast" ) {
+ $geo = $db->inet_atocc($ip) || "XX";
+ }
+ $cc = $ip =~ /^$IP_PRIVATE$/o ? '**' : $geo;
$countries .= $cc." ";
}