Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 537464
Collapse All | Expand All

(-)file_not_specified_in_diff (-21 / +68 lines)
Line  Link Here
0
-- init.pre-orig       2015-01-23 09:39:49.000000000 -0800
0
++ init.pre    2015-01-23 09:42:13.000000000 -0800
Lines 17-23 Link Here
17
# RelayCountry - add metadata for Bayes learning, marking the countries
17
# RelayCountry - add metadata for Bayes learning, marking the countries
18
# a message was relayed through
18
# a message was relayed through
19
#
19
#
20
# Note: This requires the IP::Country::Fast Perl module
20
# Note: This requires the Geo::IP Perl module
21
#
21
#
22
loadplugin Mail::SpamAssassin::Plugin::RelayCountry
22
loadplugin Mail::SpamAssassin::Plugin::RelayCountry
23
23
24
-- RelayCountry.pm-orig        2015-01-23 09:38:49.000000000 -0800
24
++ RelayCountry.pm     2015-01-23 09:41:15.000000000 -0800
Lines 25-38 Link Here
25
25
26
=head1 DESCRIPTION
26
=head1 DESCRIPTION
27
27
28
By the RelayCountry plugin attempts to determine the domain country
28
The RelayCountry plugin attempts to determine the domain country codes
29
codes of each relay used in the delivery path of messages and add that
29
of each relay used in the delivery path of messages and add that information
30
information to the message metadata as "X-Relay-Countries", or 
30
to the message metadata as "X-Relay-Countries", or the C<_RELAYCOUNTRY_>
31
the C<_RELAYCOUNTRY_> header markup.
31
header markup.
32
32
33
=head1 REQUIREMENT
33
=head1 REQUIREMENT
34
34
35
This plugin requires the IP::Country module from CPAN.
35
This plugin requires the Geo::IP module from CPAN. For backward
36
compatibility IP::Country::Fast is used if Geo::IP is not installed.
36
37
37
=cut
38
=cut
38
39
Lines 40-45 Link Here
40
41
41
use Mail::SpamAssassin::Plugin;
42
use Mail::SpamAssassin::Plugin;
42
use Mail::SpamAssassin::Logger;
43
use Mail::SpamAssassin::Logger;
44
use Mail::SpamAssassin::Constants qw(:ip);
43
use strict;
45
use strict;
44
use warnings;
46
use warnings;
45
use bytes;
47
use bytes;
Lines 48-53 Link Here
48
use vars qw(@ISA);
50
use vars qw(@ISA);
49
@ISA = qw(Mail::SpamAssassin::Plugin);
51
@ISA = qw(Mail::SpamAssassin::Plugin);
50
52
53
my ($db, $dbv6);
54
my $ip_to_cc; # will hold a sub() for the lookup
55
my $db_info;  # will hold a sub() for database info
56
57
# Try to load Geo::IP first
58
eval {
59
  require Geo::IP;
60
  $db = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION, Geo::IP->GEOIP_STANDARD);
61
  die "GeoIP.dat not found" unless $db;
62
  # IPv6 requires version Geo::IP 1.39+ with GeoIP C API 1.4.7+
63
  if (Geo::IP->VERSION >= 1.39 && Geo::IP->api eq 'CAPI') {
64
    $dbv6 = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION_V6, Geo::IP->GEOIP_STANDARD);
65
    if (!$dbv6) {
66
      dbg("metadata: RelayCountry: IPv6 support not enabled, GeoIPv6.dat not found");
67
    }
68
  } else {
69
    dbg("metadata: RelayCountry: IPv6 support not enabled, versions Geo::IP 1.39, GeoIP C API 1.4.7 required");
70
  }
71
  $ip_to_cc = sub {
72
    if ($dbv6 && $_[0] =~ /:/) {
73
      return $dbv6->country_code_by_addr_v6($_[0]) || "XX";
74
    } else {
75
      return $db->country_code_by_addr($_[0]) || "XX";
76
    }
77
  };
78
  $db_info = sub { return "Geo::IP " . ($db->database_info || '?') };
79
  1;
80
} or do {
81
  my $eval_stat = $@ ne '' ? $@ : "errno=$!";  chomp $eval_stat;
82
  dbg("metadata: RelayCountry: failed to load 'Geo::IP', skipping: $eval_stat");
83
  # Try IP::Country::Fast as backup
84
  eval {
85
    require IP::Country::Fast;
86
    $db = IP::Country::Fast->new();
87
    $ip_to_cc = sub {
88
      return $db->inet_atocc($_[0]) || "XX";
89
    };
90
    $db_info = sub { return "IP::Country::Fast ".localtime($db->db_time()); };
91
    1;
92
  } or do {
93
    my $eval_stat = $@ ne '' ? $@ : "errno=$!";  chomp $eval_stat;
94
    dbg("metadata: RelayCountry: failed to load 'IP::Country::Fast', skipping: $eval_stat");
95
    return 1;
96
  };
97
};
98
51
# constructor: register the eval rule
99
# constructor: register the eval rule
52
sub new {
100
sub new {
53
  my $class = shift;
101
  my $class = shift;
Lines 63-86 Link Here
63
sub extract_metadata {
111
sub extract_metadata {
64
  my ($self, $opts) = @_;
112
  my ($self, $opts) = @_;
65
113
66
  my $reg;
114
  return 1 unless $db;
67
68
  eval {
69
    require IP::Country::Fast;
70
    $reg = IP::Country::Fast->new();
71
    1;
72
  } or do {
73
    my $eval_stat = $@ ne '' ? $@ : "errno=$!";  chomp $eval_stat;
74
    dbg("metadata: failed to load 'IP::Country::Fast', skipping: $eval_stat");
75
    return 1;
76
  };
77
115
116
  dbg("metadata: RelayCountry: Using database: ".$db_info->());
78
  my $msg = $opts->{msg};
117
  my $msg = $opts->{msg};
79
118
80
  my $countries = '';
119
  my $countries = '';
120
  my $IP_PRIVATE = IP_PRIVATE;
81
  foreach my $relay (@{$msg->{metadata}->{relays_untrusted}}) {
121
  foreach my $relay (@{$msg->{metadata}->{relays_untrusted}}) {
82
    my $ip = $relay->{ip};
122
    my $ip = $relay->{ip};
83
    my $cc = $reg->inet_atocc($ip) || "XX";
123
    # Private IPs will always be returned as '**'
124
    my $cc = $ip =~ /^$IP_PRIVATE$/o ? '**' : $ip_to_cc->($ip);
84
    $countries .= $cc." ";
125
    $countries .= $cc." ";
85
  }
126
  }
86
127
Lines 93-100 Link Here
93
134
94
sub parsed_metadata {
135
sub parsed_metadata {
95
  my ($self, $opts) = @_;
136
  my ($self, $opts) = @_;
137
138
  return 1 unless $db;
139
140
  my $countries =
141
    $opts->{permsgstatus}->get_message->get_metadata('X-Relay-Countries');
142
  my @c_list = split(' ', $countries);
96
  $opts->{permsgstatus}->set_tag ("RELAYCOUNTRY",
143
  $opts->{permsgstatus}->set_tag ("RELAYCOUNTRY",
97
          $opts->{permsgstatus}->get_message->get_metadata('X-Relay-Countries'));
144
                                 @c_list == 1 ? $c_list[0] : \@c_list);
98
  return 1;
145
  return 1;
99
}
146
}
100
147

Return to bug 537464