File Coverage

blib/lib/Mail/MtPolicyd/Plugin/SaAwlAction.pm
Criterion Covered Total %
statement 9 51 17.6
branch 0 24 0.0
condition 0 12 0.0
subroutine 3 6 50.0
pod 1 2 50.0
total 13 95 13.6


line stmt bran cond sub pod time code
1             package Mail::MtPolicyd::Plugin::SaAwlAction;
2              
3 1     1   1093 use Moose;
  1         3  
  1         6  
4 1     1   4179 use namespace::autoclean;
  1         1  
  1         9  
5              
6             our $VERSION = '2.01'; # VERSION
7             # ABSTRACT: mtpolicyd plugin for checking spamassassin AWL reputation
8              
9              
10             extends 'Mail::MtPolicyd::Plugin';
11             with 'Mail::MtPolicyd::Plugin::Role::Scoring';
12             with 'Mail::MtPolicyd::Plugin::Role::UserConfig' => {
13             'uc_attributes' => [ 'enabled', 'mode' ],
14             };
15              
16 1     1   94 use Mail::MtPolicyd::Plugin::Result;
  1         2  
  1         475  
17              
18             has 'result_from' => ( is => 'rw', isa => 'Str', required => 1 );
19             has 'enabled' => ( is => 'rw', isa => 'Str', default => 'on' );
20             has 'mode' => ( is => 'rw', isa => 'Str', default => 'reject' );
21              
22             has 'reject_message' => (
23             is => 'ro', isa => 'Str', default => 'sender address/ip has bad reputation',
24             );
25              
26             has 'score' => ( is => 'rw', isa => 'Maybe[Num]' );
27             has 'score_factor' => ( is => 'rw', isa => 'Maybe[Num]' );
28              
29             has 'min_count' => ( is => 'rw', isa => 'Int', default => 10 );
30              
31             has 'threshold' => ( is => 'rw', isa => 'Num', default => 5 );
32             has 'match' => ( is => 'rw', isa => 'Str', default => 'gt');
33              
34             sub matches {
35 0     0 0   my ( $self, $score ) = @_;
36              
37 0 0 0       if( $self->match eq 'gt' && $score >= $self->threshold ) {
    0 0        
38 0           return 1;
39             } elsif ( $self->match eq 'lt' && $score <= $self->threshold ) {
40 0           return 1;
41             }
42              
43 0           return 0;
44             }
45              
46             sub run {
47 0     0 1   my ( $self, $r ) = @_;
48 0           my $addr = $r->attr('sender');
49 0           my $ip = $r->attr('client_address');
50 0           my $session = $r->session;
51              
52 0           my $enabled = $self->get_uc( $session, 'enabled' );
53 0 0         if( $enabled eq 'off' ) {
54 0           return;
55             }
56              
57 0           my $result_key = 'sa-awl-'.$self->result_from.'-result';
58 0 0         if( ! defined $session->{$result_key} ) {
59 0           $self->log( $r, 'no SaAwlLookup result for '.$self->result_from.' found!');
60 0           return;
61             }
62 0           my ( $count, $score ) = @{$session->{$result_key}};
  0            
63 0 0 0       if( ! defined $count || ! defined $score) {
64 0           return; # there was no entry in AWL
65             }
66            
67 0 0         if( $count < $self->min_count ) {
68 0           $self->log( $r, 'sender awl reputation below min_count' );
69 0           return;
70             }
71              
72 0 0         if( ! $self->matches( $score ) ) {
73 0           return;
74             }
75              
76 0           $self->log( $r, 'matched SA AWL threshold action '.$self->name );
77 0 0         if( ! $r->is_already_done('sa-awl-'.$self->name.'-score') ) {
78 0 0         if( $self->score ) {
    0          
79 0           $self->add_score($r, $self->name => $self->score);
80             } elsif( $self->score_factor ) {
81 0           $self->add_score($r, $self->name => $score * $self->score_factor);
82             }
83             }
84              
85 0           my $mode = $self->get_uc( $session, 'mode' );
86 0 0         if( $mode eq 'reject' ) {
87 0           return Mail::MtPolicyd::Plugin::Result->new(
88             action => $self->_get_reject_action( $addr, $ip, $score ),
89             abort => 1,
90             );
91             }
92 0 0 0       if( $mode eq 'accept' || $mode eq 'dunno' ) {
93 0           return Mail::MtPolicyd::Plugin::Result->new_dunno;
94             }
95              
96 0           return;
97             }
98              
99             sub _get_reject_action {
100 0     0     my ( $self, $sender, $ip, $score ) = @_;
101 0           my $message = $self->reject_message;
102 0           $message =~ s/%IP%/$ip/;
103 0           $message =~ s/%SENDER%/$sender/;
104 0           $message =~ s/%SCORE%/$score/;
105 0           return('reject '.$message);
106             }
107              
108             __PACKAGE__->meta->make_immutable;
109              
110             1;
111              
112             __END__
113              
114             =pod
115              
116             =encoding UTF-8
117              
118             =head1 NAME
119              
120             Mail::MtPolicyd::Plugin::SaAwlAction - mtpolicyd plugin for checking spamassassin AWL reputation
121              
122             =head1 VERSION
123              
124             version 2.01
125              
126             =head1 DESCRIPTION
127              
128             This plugin will execute an action or score based on a previous lookup
129             done with SaAwlLookup plugin.
130              
131             =head1 PARAMETERS
132              
133             =over
134              
135             =item result_from (required)
136              
137             Take the AWL information from the result of this plugin.
138              
139             The plugin in must be executed before this plugin.
140              
141             =item (uc_)enabled (default: on)
142              
143             Enable/disable this plugin.
144              
145             =item (uc_)mode (default: reject)
146              
147             If set to 'passive' no action will be returned.
148              
149             =item reject_message (default: 'sender address/ip has bad reputation')
150              
151             Could be used to specify an custom reject message.
152              
153             =item score (default: empty)
154              
155             A score to apply to the message.
156              
157             =item score_factor (default: empty)
158              
159             A factor to apply the SA score to the message.
160              
161             Do not configure a score if you want to use the factor.
162              
163             =item min_count (default: 10)
164              
165             The minimum count of mails/scores spamassassin must have
166             done on this sender/ip before the AWL entry is used.
167              
168             If the count in AWLs auto-whitelist table is below this
169             count the test will be skipped.
170              
171             =item threshold (default: 5)
172              
173             At this threshold the action or score will be applied.
174              
175             =item match (default: gt)
176              
177             The default is to match values greater("gt") than the threshold.
178              
179             When configured with 'lt' AWL scores less than the threshold will
180             be matched.
181              
182             =back
183              
184             =head1 EXAMPLE
185              
186             Check that AWL is active in your SA/amavis configuration:
187              
188             loadplugin Mail::SpamAssassin::Plugin::AWL
189             use_auto_whitelist 1
190              
191             Make sure that mtpolicyd has permissions to read the auto-whitelist db:
192              
193             $ usermod -G amavis mtpolicyd
194             $ chmod g+rx /var/lib/amavis/.spamassassin
195             $ chmod g+r /var/lib/amavis/.spamassassin/auto-whitelist
196              
197             Make sure it stays like this when its recreated in your SA local.cf:
198              
199             auto_whitelist_file_mode 0770
200              
201             Net::Server does not automatically set supplementary groups.
202             You have to do that in mtpolicyd.conf:
203              
204             group="mtpolicyd amavis"
205              
206             Permissions may be different on your system.
207              
208             To check that mtpolicyd can access the file try:
209              
210             $ sudo -u mtpolicyd -- head -n0 /var/lib/amavis/.spamassassin/auto-whitelist
211              
212             Now use it in mtpolicyd.conf:
213              
214             <Plugin amavis-reputation>
215             module = "SaAwlLookup"
216             db_file = "/var/lib/amavis/.spamassassin/auto-whitelist"
217             </Plugin>
218              
219             For whitelisting you may configure it like:
220              
221             <Plugin awl-whitelist>
222             module = "SaAwlAction"
223             result_from = "amavis-reputation"
224             mode = "accept"
225             match = "lt"
226             threshold = "0"
227             </Plugin>
228              
229             Or apply a score based for bad AWL reputation (score > 5):
230              
231             <Plugin awl-score-bad>
232             module = "SaAwlAction"
233             result_from = "amavis-reputation"
234             mode = "passive"
235             match = "gt"
236             threshold = 6
237             score = 5
238             </Plugin>
239              
240             Or apply the score value from AWL with an factor:
241              
242             <Plugin awl-score-bad>
243             module = "SaAwlAction"
244             result_from = "amavis-reputation"
245             mode = "passive"
246             match = "gt"
247             threshold = 5
248             score_factor = 0.5
249             </Plugin>
250              
251             If the score in AWL is >5 it will apply the score with an factor of 0.5.
252             When the score in AWL is 8 it will apply a score of 4.
253              
254             Or just reject all mail with a bad reputation:
255              
256             <Plugin awl-reject>
257             module = "SaAwlAction"
258             result_from = "amavis-reputation"
259             mode = "reject"
260             match = "gt"
261             threshold = 5
262             reject_message = "bye bye..."
263             </Plugin>
264              
265             =head1 Troubleshooting
266              
267             =head2 Check content of spamassassin AWL auto-whitelist
268              
269             To check the content of the auto-whitelist database use the sa-awl command:
270              
271             $ sa-awl /var/lib/amavis/.spamassassin/auto-whitelist | grep <user>
272              
273             =head1 SEE ALSO
274              
275             =over
276              
277             =item Spamassassin AutoWhitelist manual
278              
279             L<http://wiki.apache.org/spamassassin/AutoWhitelist>
280              
281             =item Spamassassin AWL plugin reference
282              
283             L<http://spamassassin.apache.org/full/3.1.x/doc/Mail_SpamAssassin_Plugin_AWL.html>
284              
285             =back
286              
287             =head1 AUTHOR
288              
289             Markus Benning <ich@markusbenning.de>
290              
291             =head1 COPYRIGHT AND LICENSE
292              
293             This software is Copyright (c) 2014 by Markus Benning <ich@markusbenning.de>.
294              
295             This is free software, licensed under:
296              
297             The GNU General Public License, Version 2, June 1991
298              
299             =cut