File Coverage

blib/lib/Mail/MtPolicyd/Plugin/CtIpRep.pm
Criterion Covered Total %
statement 15 64 23.4
branch 0 26 0.0
condition 0 9 0.0
subroutine 5 9 55.5
pod 1 1 100.0
total 21 109 19.2


line stmt bran cond sub pod time code
1             package Mail::MtPolicyd::Plugin::CtIpRep;
2              
3 2     2   2397 use Moose;
  2         5  
  2         18  
4 2     2   13329 use namespace::autoclean;
  2         6  
  2         23  
5              
6             our $VERSION = '1.23'; # VERSION
7             # ABSTRACT: mtpolicyd plugin for the Commtouch IP reputation service (ctipd)
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', 'tempfail_mode', 'permfail_mode' ],
14             };
15              
16 2     2   253 use Mail::MtPolicyd::Plugin::Result;
  2         3  
  2         47  
17              
18 2     2   2158 use LWP::UserAgent;
  2         86644  
  2         70  
19 2     2   1584 use HTTP::Request::Common;
  2         4662  
  2         1900  
20              
21              
22             has 'enabled' => ( is => 'rw', isa => 'Str', default => 'on' );
23              
24             has '_agent' => (
25             is => 'ro', isa => 'LWP::UserAgent', lazy => 1,
26             default => sub { LWP::UserAgent->new }
27             );
28             has 'url' => (
29             is => 'ro', isa => 'Str', default => 'http://localhost:8080/ctipd/iprep',
30             );
31             has 'key' => ( is => 'ro', isa => 'Maybe[Str]' );
32              
33             has 'reject_message' => (
34             is => 'rw', isa => 'Str', default => '550 delivery from %IP% is rejected. Check at http://www.commtouch.com/Site/Resources/Check_IP_Reputation.asp. Reference code: %REFID%',
35             );
36             has 'defer_message' => (
37             is => 'rw', isa => 'Str', default => '450 delivery from %IP% is deferred,repeatedly. Send again or check at http://www.commtouch.com/Site/Resources/Check_IP_Reputation.asp. Reference code: %REFID%',
38             );
39              
40             has 'permfail_score' => ( is => 'rw', isa => 'Maybe[Num]' );
41             has 'permfail_mode' => ( is => 'rw', isa => 'Str', default => 'reject' );
42              
43             has 'tempfail_score' => ( is => 'rw', isa => 'Maybe[Num]' );
44             has 'tempfail_mode' => ( is => 'rw', isa => 'Str', default => 'defer' );
45              
46             sub _scan_ip {
47 0     0     my ( $self, $ip ) = @_;
48 0           my $request = "x-ctch-request-type: classifyip\r\n".
49             "x-ctch-pver: 1.0\r\n";
50 0 0         if( defined $self->key ) {
51 0           $request .= 'x-ctch-key: '.$self->key."\r\n";
52             }
53 0           $request .= "\r\n";
54 0           $request .= 'x-ctch-ip: '.$ip."\r\n";
55              
56 0           my $response = $self->_agent->request(POST $self->url, Content => $request );
57 0 0         if( $response->code ne 200 ) {
58 0           die('error while accessing Commtouch ctipd: '.$response->status_line);
59             }
60 0           my $content = $response->content;
61 0           my ( $action ) = $content =~ m/^x-ctch-dm-action:(.*)\r$/m;
62 0           my ( $refid ) = $content =~ m/^x-ctch-refid:(.*)\r$/m;
63 0 0         if( ! defined $action ) {
64 0           die('could not find action in response: '.$content);
65             }
66              
67 0           return( $action, $refid );
68             }
69              
70             sub run {
71 0     0 1   my ( $self, $r ) = @_;
72 0           my $ip = $r->attr('client_address');
73 0           my $session = $r->session;
74 0           my $mode;
75              
76 0 0         if( ! defined $ip ) {
77 0           die('no client_address in request!');
78             }
79              
80 0           my $enabled = $self->get_uc($session, 'enabled');
81 0 0         if( $enabled eq 'off' ) {
82 0           return;
83             }
84            
85             my ( $result, $refid ) = $r->do_cached( $self->name.'-result',
86 0     0     sub{ $self->_scan_ip( $ip ) } );
  0            
87              
88 0 0         if( $result eq 'accept') {
    0          
    0          
89 0           $self->log( $r, 'CtIpRep: sender IP is ok' );
90 0           return; # do nothing
91             } elsif( $result eq 'permfail' ) {
92 0           $mode = $self->get_uc( $session, 'permfail_mode' );
93 0 0 0       if( $self->permfail_score
94             && ! $r->is_already_done($self->name.'-score') ) {
95 0           $self->add_score($r, $self->name => $self->permfail_score);
96             }
97             } elsif ($result eq 'tempfail' ) {
98 0           $mode = $self->get_uc( $session, 'tempfail_mode' );
99 0 0 0       if( $self->tempfail_score
100             && ! $r->is_already_done($self->name.'-score') ) {
101 0           $self->add_score($r, $self->name => $self->tempfail_score);
102             }
103             } else {
104 0           die('unknown ctiprep action: '.$result);
105             }
106 0           $self->log($r, 'CtIpRep: result='.$result.', mode='.$mode);
107              
108 0 0 0       if ( $mode eq 'reject' || $mode eq 'defer' ) {
109 0           return Mail::MtPolicyd::Plugin::Result->new(
110             action => $self->_build_action($mode, $ip, $refid),
111             abort => 1,
112             );
113             }
114 0           return;
115             }
116              
117             sub _build_action {
118 0     0     my ( $self, $action, $ip, $refid ) = @_;
119 0           my $message;
120 0 0         if( $action eq 'reject' ) {
    0          
121 0           $message = $self->reject_message;
122             } elsif ( $action eq 'defer' ) {
123 0           $message = $self->defer_message;
124             } else {
125 0           die('unknown action: '.$action);
126             }
127 0           $message =~ s/%IP%/$ip/;
128 0           $message =~ s/%REFID%/$refid/;
129              
130 0           return($action.' '.$message);
131             }
132              
133             __PACKAGE__->meta->make_immutable;
134              
135             1;
136              
137             __END__
138              
139             =pod
140              
141             =encoding UTF-8
142              
143             =head1 NAME
144              
145             Mail::MtPolicyd::Plugin::CtIpRep - mtpolicyd plugin for the Commtouch IP reputation service (ctipd)
146              
147             =head1 VERSION
148              
149             version 1.23
150              
151             =head1 DESCRIPTION
152              
153             This plugin will query the Commtouch IP Reputation service (ctipd).
154              
155             The used protocol is HTTP.
156              
157             The services will return a status permfail or tempfail.
158              
159             =head1 PARAMETERS
160              
161             =over
162              
163             =item (uc_)enabled (default: on)
164              
165             Enable/disable the plugin.
166              
167             =item url (default: http://localhost:8080/ctipd/iprep)
168              
169             The URL to access the ctipd daemon.
170              
171             =item key (default: empty)
172              
173             If an authentication key is required by the ctipd.
174              
175             =item reject_message (default: 550 delivery from %IP% is rejected. Check at http://www.commtouch.com/Site/Resources/Check_IP_Reputation.asp. Reference code: %REFID%)
176              
177             This parameter could be used to specifiy a custom reject message if message is rejected.
178              
179             =item defer_message (default: 450 delivery from %IP% is deferred,repeatedly. Send again or check at http://www.commtouch.com/Site/Resources/Check_IP_Reputation.asp. Reference code: %REFID%)
180              
181             This parameter could be used to specifiy a custom message is a message is to be defered.
182              
183             =item (uc_)permfail_mode, (uc_)tempfail_mode (default: reject, defer)
184              
185             Action to take when the service return permfail/tempfail status:
186              
187             =over
188              
189             =item reject
190              
191             =item defer
192              
193             =item passive
194              
195             =back
196              
197             =item permfail_score, tempfail_score (default: empty)
198              
199             Apply the specified score.
200              
201             =back
202              
203             =head1 AUTHOR
204              
205             Markus Benning <ich@markusbenning.de>
206              
207             =head1 COPYRIGHT AND LICENSE
208              
209             This software is Copyright (c) 2014 by Markus Benning <ich@markusbenning.de>.
210              
211             This is free software, licensed under:
212              
213             The GNU General Public License, Version 2, June 1991
214              
215             =cut