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
38             blacklisting particular strings in the Subject header. String will match
39             anywhere in the subject. The value for whitelist_subject or blacklist_subject
40             are strings which may contain file -glob -style patterns, similar to the
41             other whitelist_* config options. Note that each subject/string must be a
42             separate *_subject command, all whitespace is included in the string.
43              
44             =cut
45              
46             package Mail::SpamAssassin::Plugin::WhiteListSubject;
47              
48 21     21   179 use Mail::SpamAssassin::Plugin;
  21         58  
  21         695  
49 21     21   132 use strict;
  21         64  
  21         609  
50 21     21   176 use warnings;
  21         53  
  21         701  
51             # use bytes;
52 21     21   140 use re 'taint';
  21         61  
  21         15138  
53              
54             our @ISA = qw(Mail::SpamAssassin::Plugin);
55              
56             # constructor: register the eval rule
57             sub new {
58 62     62 1 275 my $class = shift;
59 62         169 my $mailsaobject = shift;
60              
61 62   33     436 $class = ref($class) || $class;
62 62         386 my $self = $class->SUPER::new($mailsaobject);
63 62         250 bless ($self, $class);
64              
65 62         367 $self->register_eval_rule ("check_subject_in_whitelist");
66 62         237 $self->register_eval_rule ("check_subject_in_blacklist");
67              
68 62         355 $self->set_config($mailsaobject->{conf});
69              
70 62         633 return $self;
71             }
72              
73             sub set_config {
74 62     62 0 184 my ($self, $conf) = @_;
75              
76 62         143 my @cmds;
77              
78             push(@cmds, {
79             setting => 'whitelist_subject',
80             default => {},
81             type => $Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST,
82             code => sub {
83 0     0   0 my ($self, $key, $value, $line) = @_;
84              
85 0         0 $value = lc $value;
86 0         0 my $re = $value;
87 0         0 $re =~ s/[\000\\\(]/_/gs; # paranoia
88 0         0 $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars
89 0         0 $re =~ tr/?/./; # "?" -> "."
90 0         0 $re =~ s/\*+/\.\*/g; # "*" -> "any string"
91 0         0 $conf->{$key}->{$value} = ${re};
92 62         691 }});
93              
94             push(@cmds, {
95             setting => 'blacklist_subject',
96             default => {},
97             type => $Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST,
98             code => sub {
99 0     0   0 my ($self, $key, $value, $line) = @_;
100              
101 0         0 $value = lc $value;
102 0         0 my $re = $value;
103 0         0 $re =~ s/[\000\\\(]/_/gs; # paranoia
104 0         0 $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars
105 0         0 $re =~ tr/?/./; # "?" -> "."
106 0         0 $re =~ s/\*+/\.\*/g; # "*" -> "any string"
107 0         0 $conf->{$key}->{$value} = ${re};
108 62         501 }});
109              
110 62         344 $conf->{parser}->register_commands(\@cmds);
111             }
112              
113             sub check_subject_in_whitelist {
114 81     81 0 258 my ($self, $permsgstatus) = @_;
115              
116 81         295 my $subject = $permsgstatus->get('Subject');
117              
118 81 100       1001 return 0 unless $subject ne '';
119              
120 42         208 return $self->_check_subject($permsgstatus->{conf}->{whitelist_subject}, $subject);
121             }
122              
123             sub check_subject_in_blacklist {
124 81     81 0 241 my ($self, $permsgstatus) = @_;
125              
126 81         333 my $subject = $permsgstatus->get('Subject');
127              
128 81 100       1048 return 0 unless $subject ne '';
129              
130 42         179 return $self->_check_subject($permsgstatus->{conf}->{blacklist_subject}, $subject);
131             }
132              
133             sub _check_subject {
134 84     84   246 my ($self, $list, $subject) = @_;
135              
136 84         194 $subject = lc $subject;
137              
138 84 50       294 return 1 if defined($list->{$subject});
139              
140 84         167 study $subject; # study is a no-op since perl 5.16.0, eliminating bugs
141 84         167 foreach my $regexp (values %{$list}) {
  84         277  
142 0 0       0 if ($subject =~ qr/$regexp/i) {
143 0         0 return 1;
144             }
145             }
146              
147 84         1663 return 0;
148             }
149              
150             1;