File Coverage

blib/lib/Mail/SpamAssassin/Plugin/WhiteListSubject.pm
Criterion Covered Total %
statement 41 59 69.4
branch 5 8 62.5
condition 1 3 33.3
subroutine 9 11 81.8
pod 1 4 25.0
total 57 85 67.0


line stmt bran cond sub pod time code
1             # <@LICENSE>
2             # Licensed to the Apache Software Foundation (ASF) under one or more
3             # contributor license agreements. See the NOTICE file distributed with
4             # this work for additional information regarding copyright ownership.
5             # The ASF licenses this file to you under the Apache License, Version 2.0
6             # (the "License"); you may not use this file except in compliance with
7             # the License. You may obtain a copy of the License at:
8             #
9             # http://www.apache.org/licenses/LICENSE-2.0
10             #
11             # Unless required by applicable law or agreed to in writing, software
12             # distributed under the License is distributed on an "AS IS" BASIS,
13             # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14             # See the License for the specific language governing permissions and
15             # limitations under the License.
16             # </@LICENSE>
17              
18             =head1 NAME
19              
20             Mail::SpamAssassin::Plugin::WhiteListSubject - whitelist by Subject header
21              
22             =head1 SYNOPSIS
23              
24             loadplugin Mail::SpamAssassin::Plugin::WhiteListSubject
25              
26             header SUBJECT_IN_WHITELIST eval:check_subject_in_whitelist()
27             header SUBJECT_IN_BLACKLIST eval:check_subject_in_blacklist()
28              
29             score SUBJECT_IN_WHITELIST -100
30             score SUBJECT_IN_BLACKLIST 100
31              
32             whitelist_subject [Bug *]
33             blacklist_subject Make Money Fast
34              
35             =head1 DESCRIPTION
36              
37             This SpamAssassin plugin module provides eval tests for whitelisting and blacklisting
38             particular strings in the Subject header. The value for whitelist_subject or
39             blacklist_subject are strings which may contain file -glob -style patterns,
40             similar to the other whitelist_* config options.
41              
42             =cut
43              
44             package Mail::SpamAssassin::Plugin::WhiteListSubject;
45              
46 22     22   163 use Mail::SpamAssassin::Plugin;
  22         60  
  22         715  
47 22     22   121 use strict;
  22         66  
  22         551  
48 22     22   125 use warnings;
  22         56  
  22         760  
49             # use bytes;
50 22     22   134 use re 'taint';
  22         42  
  22         14981  
51              
52             our @ISA = qw(Mail::SpamAssassin::Plugin);
53              
54             # constructor: register the eval rule
55             sub new {
56 63     63 1 226 my $class = shift;
57 63         131 my $mailsaobject = shift;
58              
59 63   33     493 $class = ref($class) || $class;
60 63         338 my $self = $class->SUPER::new($mailsaobject);
61 63         214 bless ($self, $class);
62              
63 63         351 $self->register_eval_rule ("check_subject_in_whitelist");
64 63         243 $self->register_eval_rule ("check_subject_in_blacklist");
65              
66 63         288 $self->set_config($mailsaobject->{conf});
67              
68 63         794 return $self;
69             }
70              
71             sub set_config {
72 63     63 0 183 my ($self, $conf) = @_;
73              
74 63         121 my @cmds;
75              
76             push(@cmds, {
77             setting => 'whitelist_subject',
78             default => {},
79             type => $Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST,
80             code => sub {
81 0     0   0 my ($self, $key, $value, $line) = @_;
82              
83 0         0 $value = lc $value;
84 0         0 my $re = $value;
85 0         0 $re =~ s/[\000\\\(]/_/gs; # paranoia
86 0         0 $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars
87 0         0 $re =~ tr/?/./; # "?" -> "."
88 0         0 $re =~ s/\*+/\.\*/g; # "*" -> "any string"
89 0         0 $conf->{$key}->{$value} = ${re};
90 63         665 }});
91              
92             push(@cmds, {
93             setting => 'blacklist_subject',
94             default => {},
95             type => $Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST,
96             code => sub {
97 0     0   0 my ($self, $key, $value, $line) = @_;
98              
99 0         0 $value = lc $value;
100 0         0 my $re = $value;
101 0         0 $re =~ s/[\000\\\(]/_/gs; # paranoia
102 0         0 $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars
103 0         0 $re =~ tr/?/./; # "?" -> "."
104 0         0 $re =~ s/\*+/\.\*/g; # "*" -> "any string"
105 0         0 $conf->{$key}->{$value} = ${re};
106 63         554 }});
107              
108 63         331 $conf->{parser}->register_commands(\@cmds);
109             }
110              
111             sub check_subject_in_whitelist {
112 77     77 0 232 my ($self, $permsgstatus) = @_;
113              
114 77         316 my $subject = $permsgstatus->get('Subject');
115              
116 77 100       868 return 0 unless $subject ne '';
117              
118 39         203 return $self->_check_subject($permsgstatus->{conf}->{whitelist_subject}, $subject);
119             }
120              
121             sub check_subject_in_blacklist {
122 77     77 0 255 my ($self, $permsgstatus) = @_;
123              
124 77         290 my $subject = $permsgstatus->get('Subject');
125              
126 77 100       891 return 0 unless $subject ne '';
127              
128 39         189 return $self->_check_subject($permsgstatus->{conf}->{blacklist_subject}, $subject);
129             }
130              
131             sub _check_subject {
132 78     78   224 my ($self, $list, $subject) = @_;
133              
134 78         153 $subject = lc $subject;
135              
136 78 50       219 return 1 if defined($list->{$subject});
137              
138 78         145 study $subject; # study is a no-op since perl 5.16.0, eliminating bugs
139 78         177 foreach my $regexp (values %{$list}) {
  78         283  
140 0 0       0 if ($subject =~ qr/$regexp/i) {
141 0         0 return 1;
142             }
143             }
144              
145 78         1360 return 0;
146             }
147              
148             1;