File Coverage

blib/lib/Mail/Exim/Blacklist/GeoIP.pm
Criterion Covered Total %
statement 21 21 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod 1 1 100.0
total 29 29 100.0


line stmt bran cond sub pod time code
1             package Mail::Exim::Blacklist::GeoIP;
2              
3             # SPDX-License-Identifier: Artistic-1.0-Perl OR GPL-1.0-or-later
4              
5 1     1   114700 use 5.016;
  1         16  
6 1     1   6 use warnings;
  1         2  
  1         57  
7 1     1   8 use utf8;
  1         2  
  1         7  
8              
9             our $VERSION = 1.001;
10              
11 1     1   60 use Exporter qw(import);
  1         2  
  1         32  
12 1     1   994 use MaxMind::DB::Reader;
  1         375069  
  1         74  
13 1     1   11 use List::Util qw(first);
  1         3  
  1         438  
14              
15             our @EXPORT_OK = qw(geoip_country_code);
16              
17             our @DIRECTORIES = qw(
18             /var/lib/GeoIP
19             /usr/share/GeoIP
20             );
21              
22             our @DATABASES = qw(
23             dbip-country.mmdb
24             GeoIP2-Country.mmdb
25             dbip-country-lite.mmdb
26             GeoLite2-Country.mmdb
27             );
28              
29             our $DATABASE = $ENV{GEOIP_COUNTRY} || first {-r} map {
30             my $dir = $_;
31             map {"$dir/$_"} @DATABASES
32             } @DIRECTORIES;
33              
34             our $GEOIP_READER = eval { MaxMind::DB::Reader->new(file => $DATABASE) };
35              
36             sub geoip_country_code {
37 2     2 1 141 my $ip_address = shift;
38              
39 2         5 my $code = eval {
40 2         20 $GEOIP_READER->record_for_address($ip_address)->{country}->{iso_code};
41             };
42              
43 2         54079 return $code;
44             }
45              
46             1;
47             __END__
48              
49             =encoding UTF-8
50              
51             =head1 NAME
52              
53             Mail::Exim::Blacklist::GeoIP - Map IP addresses to country codes
54              
55             =head1 VERSION
56              
57             version 1.001
58              
59             =head1 SYNOPSIS
60              
61             acl_check_rcpt:
62              
63             warn
64             domains = +local_domains : +relay_to_domains
65             set acl_m_country_code = ${perl{geoip_country_code}{$sender_host_address}}
66             add_header = X-Sender-Host-Country: $acl_m_country_code
67              
68             accept
69              
70             =head1 DESCRIPTION
71              
72             A Perl module for the Exim mailer that maps IP addresses to two-letter country
73             codes such as "DE", "FR" and "US". SpamAssassin can use these country codes
74             to filter junk e-mail.
75              
76             =head1 SUBROUTINES/METHODS
77              
78             =head2 geoip_country_code
79              
80             my $country_code = geoip_country_code($ip_address);
81              
82             Maps an IP address to a country. Returns the country code or the undefined
83             value.
84              
85             =head1 DIAGNOSTICS
86              
87             None.
88              
89             =head1 CONFIGURATION AND ENVIRONMENT
90              
91             Create a file such as F</etc/exim/exim.pl>. Add the following Perl code.
92              
93             use Mail::Exim::Blacklist::GeoIP qw(geoip_country_code);
94              
95             Edit Exim's configuration file. Enable Perl in the main section.
96              
97             perl_startup = do '/etc/exim/exim.pl'
98             perl_taintmode = yes
99              
100             Get the sending host's country code in the RCPT ACL. Add the country code to
101             the message header.
102              
103             acl_check_rcpt:
104              
105             warn
106             domains = +local_domains : +relay_to_domains
107             set acl_m_country_code = ${perl{geoip_country_code}{$sender_host_address}}
108             add_header = X-Sender-Host-Country: $acl_m_country_code
109              
110             accept
111              
112             Add a rule to your SpamAssassin configuration that increases the spam score if
113             the message is sent from a country that is not whitelisted.
114              
115             bayes_ignore_header X-Sender-Host-Country
116              
117             header UNCOMMON_COUNTRY X-Sender-Host-Country !~ /^(?:DE|FR|US)/ [if-unset: US]
118             describe UNCOMMON_COUNTRY Message is sent from non-whitelisted country
119             tflags UNCOMMON_COUNTRY noautolearn
120             score UNCOMMON_COUNTRY 0.1
121              
122             See L<https://en.wikipedia.org/wiki/ISO_3166-2> for a list of two-letter
123             country codes. A useful list for businesses with contacts in Western Europe
124             and North America is:
125              
126             (?:AT|BE|CA|CH|DE|DK|ES|EU|FI|FR|GB|IE|IS|IT|LU|NL|NO|PT|SE|US)
127              
128             Combine your new rule with other rules.
129              
130             meta SUSPICIOUS_BULKMAIL UNCOMMON_COUNTRY && (DCC_CHECK || RAZOR2_CHECK)
131             describe SUSPICIOUS_BULKMAIL Fuzzy checksum and from non-whitelisted country
132             tflags SUSPICIOUS_BULKMAIL net
133             score SUSPICIOUS_BULKMAIL 1.5
134              
135             =head1 DEPENDENCIES
136              
137             Requires the Perl module MaxMind::DB::Reader from CPAN and the modules
138             Exporter and List::Util, which are distributed with Perl.
139              
140             Requires an IP to country database in the MMDB format from
141             L<https://db-ip.com/> or L<https://www.maxmind.com/>. The module searches the
142             directories F</var/lib/GeoIP> and F</usr/share/GeoIP> for one of the following
143             database files:
144              
145             dbip-country.mmdb
146             GeoIP2-Country.mmdb
147             dbip-country-lite.mmdb
148             GeoLite2-Country.mmdb
149              
150             =head1 INCOMPATIBILITIES
151              
152             None.
153              
154             =head1 SEE ALSO
155              
156             L<Mail::SpamAssassin::Conf>
157              
158             =head1 AUTHOR
159              
160             Andreas Vögele E<lt>voegelas@cpan.orgE<gt>
161              
162             =head1 BUGS AND LIMITATIONS
163              
164             None known.
165              
166             =head1 LICENSE AND COPYRIGHT
167              
168             Copyright 2021 Andreas Vögele
169              
170             This module is free software; you can redistribute it and/or modify it under
171             the same terms as Perl itself.
172              
173             =cut