File Coverage

blib/lib/Mail/MtPolicyd/Plugin/SaAwlLookup.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Mail::MtPolicyd::Plugin::SaAwlLookup;
2              
3 3     3   2288 use Moose;
  3         3  
  3         20  
4 3     3   13536 use namespace::autoclean;
  3         5  
  3         26  
5              
6             our $VERSION = '2.01'; # VERSION
7             # ABSTRACT: mtpolicyd plugin for querying a spamassassin AWL database for reputation
8              
9             extends 'Mail::MtPolicyd::Plugin';
10              
11 3     3   255 use Mail::MtPolicyd::Plugin::Result;
  3         4  
  3         49  
12              
13 3     3   555 use BerkeleyDB;
  0            
  0            
14             use BerkeleyDB::Hash;
15              
16             use NetAddr::IP;
17              
18              
19             has 'db_file' => ( is => 'rw', isa => 'Str',
20             default => '/var/lib/amamvis/.spamassassin/auto-whitelist'
21             );
22              
23             has '_awl' => (
24             is => 'ro', isa => 'HashRef', lazy => 1,
25             default => sub {
26             my $self = shift;
27             my %map;
28             my $db = tie %map, 'BerkeleyDB::Hash',
29             -Filename => $self->db_file,
30             -Flags => DB_RDONLY
31             or die "Cannot open ".$self->db_file.": $!\n" ;
32             return(\%map);
33             },
34             );
35              
36             sub truncate_ip_v4 {
37             my ( $self, $ip ) = @_;
38             if( $ip =~ m/^(\d+\.\d+).\d+.\d+$/ ) {
39             return( $1 );
40             }
41             return;
42             }
43              
44             sub truncate_ip_v6 {
45             my ( $self, $ip ) = @_;
46             my $addr = NetAddr::IP->new6( $ip.'/48' );
47             if( ! defined $addr ) {
48             return;
49             }
50             my $result = $addr->network->full6;
51             $result =~ s/(:0000)+/::/;
52             return $result;
53             }
54              
55             sub truncate_ip {
56             my ( $self, $ip ) = @_;
57              
58             if( $ip =~ /:/) {
59             return $self->truncate_ip_v6($ip);
60             }
61             return $self->truncate_ip_v4($ip);
62             }
63              
64             sub query_awl {
65             my ( $self, $addr, $ip ) = @_;
66             my $ip_key = $self->truncate_ip( $ip );
67             if( ! defined $ip_key ) {
68             return;
69             }
70             my $count = $self->_awl->{$addr.'|ip='.$ip_key};
71             if( ! defined $count ) { return; }
72              
73             my $total = $self->_awl->{$addr.'|ip='.$ip_key.'|totscore'};
74             if( ! defined $total ) { return; }
75              
76             my $score = $total / $count;
77              
78             return( $count, $score );
79             }
80              
81             sub run {
82             my ( $self, $r ) = @_;
83             my $addr = $r->attr('sender');
84             my $ip = $r->attr('client_address');
85             my $session = $r->session;
86              
87             if( ! defined $addr || ! defined $ip ) {
88             return;
89             }
90              
91             my ( $count, $score ) = $r->do_cached('sa-awl-'.$self->name.'-result',
92             sub { $self->query_awl( $addr, $ip ) } );
93              
94             if( ! defined $count || ! defined $score ) {
95             $self->log($r, 'no AWL record for '.$addr.'/'.$ip.' found');
96             return;
97             }
98              
99             $self->log($r, 'AWL record for '.$addr.'/'.$ip.' count='.$count.', score='.$score);
100              
101             return;
102             }
103              
104             __PACKAGE__->meta->make_immutable;
105              
106             1;
107              
108             __END__
109              
110             =pod
111              
112             =encoding UTF-8
113              
114             =head1 NAME
115              
116             Mail::MtPolicyd::Plugin::SaAwlLookup - mtpolicyd plugin for querying a spamassassin AWL database for reputation
117              
118             =head1 VERSION
119              
120             version 2.01
121              
122             =head1 DESCRIPTION
123              
124             This plugin queries the auto_whitelist database used by spamassassins AWL
125             plugin for the reputation of sender ip/address combination.
126              
127             Based on the AWL score a score or action in mtpolicyd can be applied in combination
128             with the SaAwlAction plugin.
129              
130             =head1 PARAMETERS
131              
132             =over
133              
134             =item db_file (default: /var/lib/amavis/.spamassassin/auto-whitelist)
135              
136             The path to the auto-whitelist database file.
137              
138             =back
139              
140             =head1 EXAMPLE
141              
142             To read reputation from amavis/spamassassin AWL use:
143              
144             <Plugin amavis-awl>
145             module = "SaAwlLookup"
146             db_file = "/var/lib/amamvis/.spamassassin/auto-whitelist"
147             </Plugin>
148              
149             The location of auto-whitelist may be different on your system.
150             Make sure mtpolicyd is allowed to read the db_file.
151              
152             =head1 AUTHOR
153              
154             Markus Benning <ich@markusbenning.de>
155              
156             =head1 COPYRIGHT AND LICENSE
157              
158             This software is Copyright (c) 2014 by Markus Benning <ich@markusbenning.de>.
159              
160             This is free software, licensed under:
161              
162             The GNU General Public License, Version 2, June 1991
163              
164             =cut