← Index
NYTProf Performance Profile   « line view »
For /usr/local/bin/sa-learn
  Run on Sun Nov 5 02:36:06 2017
Reported on Sun Nov 5 02:56:22 2017

Filename/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/VBounce.pm
StatementsExecuted 25 statements in 1.86ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
111108µs320µsMail::SpamAssassin::Plugin::VBounce::::newMail::SpamAssassin::Plugin::VBounce::new
11142µs42µsMail::SpamAssassin::Plugin::VBounce::::BEGIN@30Mail::SpamAssassin::Plugin::VBounce::BEGIN@30
11130µs248µsMail::SpamAssassin::Plugin::VBounce::::BEGIN@31Mail::SpamAssassin::Plugin::VBounce::BEGIN@31
11127µs113µsMail::SpamAssassin::Plugin::VBounce::::BEGIN@34Mail::SpamAssassin::Plugin::VBounce::BEGIN@34
11126µs129µsMail::SpamAssassin::Plugin::VBounce::::set_configMail::SpamAssassin::Plugin::VBounce::set_config
11122µs30µsMail::SpamAssassin::Plugin::VBounce::::BEGIN@32Mail::SpamAssassin::Plugin::VBounce::BEGIN@32
11121µs54µsMail::SpamAssassin::Plugin::VBounce::::BEGIN@33Mail::SpamAssassin::Plugin::VBounce::BEGIN@33
0000s0sMail::SpamAssassin::Plugin::VBounce::::_relay_is_in_listMail::SpamAssassin::Plugin::VBounce::_relay_is_in_list
0000s0sMail::SpamAssassin::Plugin::VBounce::::_relay_is_in_whitelist_bounce_relaysMail::SpamAssassin::Plugin::VBounce::_relay_is_in_whitelist_bounce_relays
0000s0sMail::SpamAssassin::Plugin::VBounce::::check_whitelist_bounce_relaysMail::SpamAssassin::Plugin::VBounce::check_whitelist_bounce_relays
0000s0sMail::SpamAssassin::Plugin::VBounce::::have_any_bounce_relaysMail::SpamAssassin::Plugin::VBounce::have_any_bounce_relays
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
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
20Mail::SpamAssassin::Plugin::VBounce - aid in rescuing genuine bounces
21
22=head1 SYNOPSIS
23
24 loadplugin Mail::SpamAssassin::Plugin::VBounce [/path/to/VBounce.pm]
25
26=cut
27
28package Mail::SpamAssassin::Plugin::VBounce;
29
30284µs142µs
# spent 42µs within Mail::SpamAssassin::Plugin::VBounce::BEGIN@30 which was called: # once (42µs+0s) by Mail::SpamAssassin::PluginHandler::load_plugin at line 30
use Mail::SpamAssassin::Plugin;
# spent 42µs making 1 call to Mail::SpamAssassin::Plugin::VBounce::BEGIN@30
31270µs2466µs
# spent 248µs (30+218) within Mail::SpamAssassin::Plugin::VBounce::BEGIN@31 which was called: # once (30µs+218µs) by Mail::SpamAssassin::PluginHandler::load_plugin at line 31
use Mail::SpamAssassin::Logger;
# spent 248µs making 1 call to Mail::SpamAssassin::Plugin::VBounce::BEGIN@31 # spent 218µs making 1 call to Exporter::import
32278µs239µs
# spent 30µs (22+8) within Mail::SpamAssassin::Plugin::VBounce::BEGIN@32 which was called: # once (22µs+8µs) by Mail::SpamAssassin::PluginHandler::load_plugin at line 32
use strict;
# spent 30µs making 1 call to Mail::SpamAssassin::Plugin::VBounce::BEGIN@32 # spent 8µs making 1 call to strict::import
33275µs288µs
# spent 54µs (21+33) within Mail::SpamAssassin::Plugin::VBounce::BEGIN@33 which was called: # once (21µs+33µs) by Mail::SpamAssassin::PluginHandler::load_plugin at line 33
use warnings;
# spent 54µs making 1 call to Mail::SpamAssassin::Plugin::VBounce::BEGIN@33 # spent 33µs making 1 call to warnings::import
3421.43ms2199µs
# spent 113µs (27+86) within Mail::SpamAssassin::Plugin::VBounce::BEGIN@34 which was called: # once (27µs+86µs) by Mail::SpamAssassin::PluginHandler::load_plugin at line 34
use re 'taint';
# spent 113µs making 1 call to Mail::SpamAssassin::Plugin::VBounce::BEGIN@34 # spent 86µs making 1 call to re::import
35
36113µsour @ISA = qw(Mail::SpamAssassin::Plugin);
37
38
# spent 320µs (108+211) within Mail::SpamAssassin::Plugin::VBounce::new which was called: # once (108µs+211µs) by Mail::SpamAssassin::PluginHandler::load_plugin at line 1 of (eval 107)[Mail/SpamAssassin/PluginHandler.pm:129]
sub new {
3912µs my $class = shift;
4012µs my $mailsaobject = shift;
41
4212µs $class = ref($class) || $class;
43120µs118µs my $self = $class->SUPER::new($mailsaobject);
# spent 18µs making 1 call to Mail::SpamAssassin::Plugin::new
4412µs bless ($self, $class);
45
46117µs135µs $self->register_eval_rule("have_any_bounce_relays");
# spent 35µs making 1 call to Mail::SpamAssassin::Plugin::register_eval_rule
4716µs129µs $self->register_eval_rule("check_whitelist_bounce_relays");
# spent 29µs making 1 call to Mail::SpamAssassin::Plugin::register_eval_rule
48
4917µs1129µs $self->set_config($mailsaobject->{conf});
# spent 129µs making 1 call to Mail::SpamAssassin::Plugin::VBounce::set_config
50
51116µs return $self;
52}
53
54
# spent 129µs (26+103) within Mail::SpamAssassin::Plugin::VBounce::set_config which was called: # once (26µs+103µs) by Mail::SpamAssassin::Plugin::VBounce::new at line 49
sub set_config {
5512µs my($self, $conf) = @_;
5612µs my @cmds;
57
58=head1 USER PREFERENCES
59
60The following options can be used in both site-wide (C<local.cf>) and
61user-specific (C<user_prefs>) configuration files to customize how
62SpamAssassin handles incoming email messages.
63
64=over 4
65
66=item whitelist_bounce_relays hostname [hostname2 ...]
67
68This is used to 'rescue' legitimate bounce messages that were generated in
69response to mail you really *did* send. List the MTA relays that your outbound
70mail is delivered through. If a bounce message is found, and it contains one
71of these hostnames in a 'Received' header, it will not be marked as a blowback
72virus-bounce.
73
74The hostnames can be file-glob-style patterns, so C<relay*.isp.com> will work.
75Specifically, C<*> and C<?> are allowed, but all other metacharacters are not.
76Regular expressions are not used for security reasons.
77
78Multiple addresses per line, separated by spaces, is OK. Multiple
79C<whitelist_bounce_relays> lines are also OK.
80
81=back
82
83=cut
84
8515µs push (@cmds, {
86 setting => 'whitelist_bounce_relays',
87 type => $Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST
88 });
89
90118µs1103µs $conf->{parser}->register_commands(\@cmds);
91}
92
93sub have_any_bounce_relays {
94 my ($self, $pms) = @_;
95 return $pms->{conf}->{whitelist_bounce_relays} &&
96 %{$pms->{conf}->{whitelist_bounce_relays}} ? 1 : 0;
97}
98
99sub check_whitelist_bounce_relays {
100 my ($self, $pms) = @_;
101
102 return 0 if !$self->have_any_bounce_relays($pms);
103
104 my $body = $pms->get_decoded_stripped_body_text_array();
105 my $res;
106
107 # catch lines like:
108 # Received: by dogma.boxhost.net (Postfix, from userid 1007)
109
110 # check the plain-text body, first
111 foreach my $line (@{$body}) {
112 next unless ($line =~ /^[> ]*Received:/i);
113 while ($line =~ / (\S+\.\S+) /g) {
114 return 1 if $self->_relay_is_in_whitelist_bounce_relays($pms, $1);
115 }
116 }
117
118 # now check any "message/anything" attachment MIME parts, too.
119 # don't use the more efficient find_parts() method until bug 5331 is
120 # fixed, otherwise we'll miss some messages due to their MIME structure
121
122 my $pristine = $pms->{msg}->get_pristine_body();
123
124 # triage, avoids expensive loop through large mail with attachments
125 return 0 if $pristine !~ /Received:/i;
126
127 my $found_received = 0;
128 my $fullhdr = '';
129 foreach my $line ($pristine =~ /^(.*)$/gm) {
130 if (!defined $line) { return 0; }
131
132 # don't bother until we see a line with "Received:" in it
133 if (!$found_received) {
134 next unless ($line =~ /^[> ]*Received:/i);
135 $found_received = 1;
136 }
137
138 if ($line =~ /^\s/) { # bug 5912, deal with multiline
139 $fullhdr .= $line;
140 } else {
141 $fullhdr = $line;
142 }
143
144 next unless ($fullhdr =~ /^[> ]*Received:/i);
145 while ($fullhdr =~ /\s(\S+\.\S+)\s/gs) {
146 return 1 if $self->_relay_is_in_whitelist_bounce_relays($pms, $1);
147 }
148 }
149
150 return 0;
151}
152
153sub _relay_is_in_whitelist_bounce_relays {
154 my ($self, $pms, $relay) = @_;
155 return 1 if $self->_relay_is_in_list(
156 $pms->{conf}->{whitelist_bounce_relays}, $pms, $relay);
157 dbg("rules: relay $relay doesn't match any whitelist");
158
159 return 0;
160}
161
162sub _relay_is_in_list {
163 my ($self, $list, $pms, $relay) = @_;
164 $relay = lc $relay;
165
166 if (defined $list->{$relay}) { return 1; }
167
168 foreach my $regexp (values %{$list}) {
169 if ($relay =~ qr/$regexp/i) {
170 dbg("rules: relay $relay matches regexp: $regexp");
171 return 1;
172 }
173 }
174
175 return 0;
176}
177
17818µs1;