1 |
slords |
1.1 |
diff -Nur -x '*.orig' -x '*.rej' smeserver-mailstats-0.0.2/root/usr/bin/spamfilter-stats-7.pl mezzanine_patched_smeserver-mailstats-0.0.2/root/usr/bin/spamfilter-stats-7.pl |
2 |
|
|
--- smeserver-mailstats-0.0.2/root/usr/bin/spamfilter-stats-7.pl 2007-04-11 16:48:31.000000000 -0400 |
3 |
|
|
+++ mezzanine_patched_smeserver-mailstats-0.0.2/root/usr/bin/spamfilter-stats-7.pl 2007-09-10 17:06:26.000000000 -0400 |
4 |
|
|
@@ -1,774 +1,831 @@ |
5 |
|
|
-#!/usr/bin/perl -w |
6 |
|
|
- |
7 |
|
|
-############################################################################# |
8 |
|
|
-# |
9 |
|
|
-# This script provides daily SpamFilter statistics and deletes all users |
10 |
|
|
-# junkmails. Configuration of the script is done by the Spam Filter |
11 |
|
|
-# Server-Manager module |
12 |
|
|
-# |
13 |
|
|
-# April 2006 - no longer controlled by server manager, and does not delete files |
14 |
|
|
-# |
15 |
|
|
-# This script has been developed |
16 |
|
|
-# by Jesper Knudsen at http://sme.swerts-knudsen.dk |
17 |
|
|
-# |
18 |
|
|
-# Revision History: |
19 |
|
|
-# |
20 |
|
|
-# August 13, 2003: Initial version |
21 |
|
|
-# August 25, 2004: fixed problem when hostname had no-ASCII chars |
22 |
|
|
-# March 23, 2006 Revised for sme7 RM |
23 |
|
|
-# March 27, 2006 ditto BJR (http://www.abandonmicrosoft.co.uk) |
24 |
|
|
-# - Merged Clamav and SA stats |
25 |
|
|
-# - Moved all analysis to qsmtpd log |
26 |
|
|
-# - Removed parameterised interval (for simplicity - not sure of format anyway) |
27 |
|
|
-# - add in archived log files for people who have high turnover |
28 |
|
|
-# - Alter labels to be more accurate |
29 |
|
|
-# - Detect deleted spam (over threshold) without using spam score |
30 |
|
|
-# - Detect RBL rejections |
31 |
|
|
-# - Detect pattern (executible) rejections |
32 |
|
|
-# - Look for the DENY labels - add in Miscellaneous category |
33 |
|
|
-# April 6, 2006 - check qpsmtp log level and also DNS enable properties |
34 |
|
|
-# - Average spam scores for under and over threshold seperatly |
35 |
|
|
-# - Log tag and Reject levels |
36 |
|
|
-# - TBD - check that RBL DENY are being detected (I have no date to check this) |
37 |
|
|
-# April 7, 2007 - re-written by Charlie Brady totally in Perl |
38 |
|
|
-# April 16, 2006 - move warnings to report |
39 |
|
|
-# - Spot fetchmail deliveries |
40 |
|
|
-# - Spot Internal connections from client PCs |
41 |
|
|
-# - TBD check that RBL DENY are being detected (I have no data to check this) |
42 |
|
|
-# April 30, 2006 - Pascal Schirrmann Start Time and End Time to noon - should be a param |
43 |
|
|
-# so the script can be run at any time in the day. |
44 |
|
|
-# - adds 'by recipients domains' stats Useful for MX-Backup or multi domains hosts |
45 |
|
|
-# - Add a 'recipients per mail' stat. Useful : until now the sums are correct :-) |
46 |
|
|
-# - Correct some messages about rbl who can led to wrong entry in the config database |
47 |
|
|
-# ( and without expected results, of course !) |
48 |
|
|
-# - improve a regexp in the SPAM detection |
49 |
|
|
-# May 1, 2006 - BJR - Fix situation where mxbackup prop is not defined |
50 |
|
|
-# - fix a spelling and minor format of domain report |
51 |
|
|
-# May 9, 2006 - bjr - Make RBL percentage a percentage of total connections (else it >100%) |
52 |
|
|
-# May 9, 2006 - ps - some 'sanity check' in the 'per domains part of the stats (to avoid / 0) |
53 |
|
|
-# May 12, 2006 - ps - some cleanup in the 'per domains' stats |
54 |
|
|
-# - Add a version number, logged in the mail |
55 |
|
|
-# June 20, 2006 - bjr - Minor change to RBL instructions, and adjust domain table format |
56 |
|
|
-# Feb 19, 2007 - bjr - Adjust table lines oin a couple of places |
57 |
|
|
-# - bjr - and add documentation details about percentages etc |
58 |
|
|
-# - bjr - Alter misc to "non conforming" anmd accumulated these hourly |
59 |
|
|
-# - bjr - Express change over tag count to exclude spam rejected over threshold |
60 |
|
|
-# - bjr - Change "processsed" to "fully downloaded" |
61 |
|
|
-# - bjr - Change percentages so that they are all a percetnage of the total emails received |
62 |
|
|
-# 0.6.1 - bjr - Change to use output from the logterse qpsmtpd plugin |
63 |
|
|
-# 0.6.2 - bjr - Fix fetchmail tests |
64 |
|
|
-# 0.6.3 - bjr - adjust for log-items change in order |
65 |
|
|
-# 0.6.4&5 - bjr - Adjust table formatting |
66 |
|
|
-# 0.6.6 - bjr - Take outgoing emails out of "others", add "Outgoing" and "Internal" |
67 |
|
|
-# 0.6.7 - bjr - Fix missing plugins/wrong names. pull invalid recipient out of deny msg for goodrcptto |
68 |
|
|
-# 0.6.8 - bjr - catch a few more plugin name failures |
69 |
|
|
-############################################################################# |
70 |
|
|
- |
71 |
|
|
- |
72 |
|
|
-# internal modules (part of core perl distribution) |
73 |
|
|
-use strict; |
74 |
|
|
-use warnings; |
75 |
|
|
-use Getopt::Long; |
76 |
|
|
-use Pod::Usage; |
77 |
|
|
-use POSIX qw/strftime floor/; |
78 |
|
|
-use Time::Local; |
79 |
|
|
-use Date::Manip; |
80 |
|
|
-use Time::TAI64; |
81 |
|
|
-use esmith::ConfigDB; |
82 |
|
|
-use esmith::DomainsDB; |
83 |
|
|
-use Sys::Hostname; |
84 |
|
|
-use Switch; |
85 |
|
|
- |
86 |
|
|
-my $hostname = hostname(); |
87 |
|
|
- |
88 |
|
|
-#Configuration section |
89 |
|
|
-my %opt = (); |
90 |
|
|
- |
91 |
|
|
-$opt{'version'} = '0.6.8'; # please update at each change. |
92 |
|
|
-$opt{'debug'} = 0; # guess what ? |
93 |
|
|
-$opt{'sendmail'} = '/usr/sbin/sendmail'; # Path to sendmail stub |
94 |
|
|
-$opt{'from'} = 'spamfilter-stats'; # Who is the mail from |
95 |
|
|
-$opt{'end'} = `date --iso-8601`; # midnight today |
96 |
|
|
-my $yesterday = $opt{ 'end' }; |
97 |
|
|
-$yesterday =~ s/\-//g ; |
98 |
|
|
-$yesterday--; |
99 |
|
|
-$opt{'start'} = `date --iso-8601 -d $yesterday`; # midnight yesterday |
100 |
|
|
-$opt{'mail'} = "admin"; |
101 |
|
|
-$opt{'timezone'} = `date +%z`; |
102 |
|
|
-Date_Init("TZ=$opt{'timezone'}"); |
103 |
|
|
-my $FetchmailIP = '127.0.0.200'; #Apparent Ip address of fetchmail deliveries |
104 |
|
|
- |
105 |
|
|
-my $disabled = 0; |
106 |
|
|
- |
107 |
|
|
-my $tstart = time; |
108 |
|
|
- |
109 |
|
|
-#Local variables |
110 |
|
|
-my $YEAR = ( localtime(time) )[5]; # this is years since 1900 |
111 |
|
|
- |
112 |
|
|
-my $total = 0; |
113 |
|
|
-my $spamcount = 0; |
114 |
|
|
-my $spamavg = 0; |
115 |
|
|
-my $hamcount = 0; |
116 |
|
|
-my $hamavg = 0; |
117 |
|
|
-my $rejectspamavg = 0; |
118 |
|
|
- |
119 |
|
|
-my $Accepttotal = 0; |
120 |
|
|
-my $localAccepttotal = 0; #Fetchmail connections |
121 |
|
|
-my $localsendtotal = 0; #Connections from local PCs |
122 |
|
|
-my $totalexamined = 0; #total download + RBL etc |
123 |
|
|
-my %sendtotalbyhour = (); |
124 |
|
|
-my %localLANbyhour = (); |
125 |
|
|
-my %localacceptbyhour = (); |
126 |
|
|
- |
127 |
|
|
-my $above15 = 0; |
128 |
|
|
-my %above15byhour = (); |
129 |
|
|
- |
130 |
|
|
-my $RBLcount = 0; |
131 |
|
|
-my %RBLbyhour = (); |
132 |
|
|
- |
133 |
|
|
-my $MiscDenyCount = 0; |
134 |
|
|
-my %MiscDenybyhour = (); |
135 |
|
|
- |
136 |
|
|
-my $PatternFilterCount = 0; |
137 |
|
|
-my %patternfilterbyhour = (); |
138 |
|
|
- |
139 |
|
|
-my $noninfectedcount = 0; |
140 |
|
|
-my $okemailcount = 0; |
141 |
|
|
- |
142 |
|
|
-my $infectedcount = 0; |
143 |
|
|
-my %infectedbyhour = (); |
144 |
|
|
-my %found_viruses = (); |
145 |
|
|
- |
146 |
|
|
-my %spambyhour = (); |
147 |
|
|
-my %hambyhour = (); |
148 |
|
|
- |
149 |
|
|
-my $warnnoreject = " "; |
150 |
|
|
-my $rblnotset = ' '; |
151 |
|
|
- |
152 |
|
|
-my $FS = "\t"; # field separator used by logterse plugin |
153 |
|
|
-my %log_items = (); |
154 |
|
|
-my $score; |
155 |
|
|
-my %timestamp_items = (); |
156 |
|
|
-my $localflag = 0; #indicate if current email is local or not |
157 |
|
|
- |
158 |
|
|
-# some storage for by recipient domains stats (PS) |
159 |
|
|
-# my bad : I have to deal with multiple simoultaneous connections |
160 |
|
|
-# will play with the process number. |
161 |
|
|
-# my $currentrcptdomain = '' ; |
162 |
|
|
-my %currentrcptdomain ; # temporay store the recipient domain until end of mail processing |
163 |
|
|
-my %byrcptdomain ; # Store 'by domains stats' |
164 |
|
|
-my @extdomain ; # only useful in some MX-Backup case, when any subdomains are allowed |
165 |
|
|
-my $morethanonercpt = 0 ; # count every 'second' recipients for a mail. |
166 |
|
|
- |
167 |
|
|
-# store the domain of interest. Every other records are stored in a 'Other' zone |
168 |
|
|
-my $ddb = esmith::DomainsDB->open_ro or die "Couldn't open DomainsDB : $!\n"; |
169 |
|
|
-foreach my $domain( $ddb->get_all_by_prop( type => "domain" ) ) { |
170 |
|
|
- $byrcptdomain{ $domain->key }{ 'type' }='local'; |
171 |
|
|
-} |
172 |
|
|
-$byrcptdomain{ esmith::ConfigDB->open_ro->get('SystemName')->value . "." |
173 |
|
|
- . esmith::ConfigDB->open_ro->get('DomainName')->value }{ 'type' } = 'local'; |
174 |
|
|
- |
175 |
|
|
-# is this system a MX-Backup ? |
176 |
|
|
-if (esmith::ConfigDB->open_ro->get('mxbackup')){ |
177 |
|
|
- if ( ( esmith::ConfigDB->open_ro->get('mxbackup')->prop('status') || 'disabled' ) eq 'enabled' ) { |
178 |
|
|
- my %MXValues = split( /,/, ( esmith::ConfigDB->open_ro->get('mxbackup')->prop('name') || '' ) ) ; |
179 |
|
|
- foreach my $data ( keys %MXValues ) { |
180 |
|
|
- $byrcptdomain{ $data }{ 'type' } = "mxbackup-$MXValues{ $data }" ; |
181 |
|
|
- if ( $MXValues{ $data } == 1 ) { # subdomains allowed, must take care of this |
182 |
|
|
- push @extdomain, $data ; |
183 |
|
|
- } |
184 |
|
|
- } |
185 |
|
|
- } |
186 |
|
|
-} |
187 |
|
|
- |
188 |
|
|
-my ( $start, $end ) = parse_arg( $opt{'start'}, $opt{'end'} ); |
189 |
|
|
- |
190 |
|
|
-# |
191 |
|
|
-# First check current configuration for logging, DNS enable and Max threshold for spamassassin |
192 |
|
|
-# |
193 |
|
|
- |
194 |
|
|
-#my $LogLevel = esmith::ConfigDB->open_ro->get('qpsmtpd')->prop('LogLevel'); |
195 |
|
|
-#my $LowLogLevel = ( $LogLevel < 8 ); |
196 |
|
|
- |
197 |
|
|
-my $RHSenabled = |
198 |
|
|
- ( esmith::ConfigDB->open_ro->get('qpsmtpd')->prop('RHSBL') eq 'enabled' ); |
199 |
|
|
-my $DNSenabled = |
200 |
|
|
- ( esmith::ConfigDB->open_ro->get('qpsmtpd')->prop('DNSBL') eq 'enabled' ); |
201 |
|
|
-my $SARejectLevel = |
202 |
|
|
- esmith::ConfigDB->open_ro->get('spamassassin')->prop('RejectLevel'); |
203 |
|
|
-my $SATagLevel = |
204 |
|
|
- esmith::ConfigDB->open_ro->get('spamassassin')->prop('TagLevel'); |
205 |
|
|
-my $DomainName = |
206 |
|
|
- esmith::ConfigDB->open_ro->get('DomainName')->value; |
207 |
|
|
- |
208 |
|
|
-# check that logterse is in use |
209 |
|
|
-#my pluginfile = '/var/service/qpsmtpd/config/peers/0'; |
210 |
|
|
- |
211 |
|
|
- |
212 |
|
|
- |
213 |
|
|
-if ( !$RHSenabled || !$DNSenabled ) { |
214 |
|
|
- $rblnotset = '*'; |
215 |
|
|
-} |
216 |
|
|
- |
217 |
|
|
-if ( $SARejectLevel == 0 ) { |
218 |
|
|
- |
219 |
|
|
- $warnnoreject = "(*Warning* 0 = no reject)"; |
220 |
|
|
- |
221 |
|
|
-} |
222 |
|
|
- |
223 |
|
|
-# |
224 |
|
|
-#--------------------------------------- |
225 |
|
|
-# Scan the qpsmtpd log file |
226 |
|
|
-#--------------------------------------- |
227 |
|
|
- |
228 |
|
|
- |
229 |
|
|
-# Init the hashes |
230 |
|
|
-my $nhour = floor( $start / 3600 ); |
231 |
|
|
-while ( $nhour < $end / 3600 ) { |
232 |
|
|
- $MiscDenybyhour{$nhour}=0; |
233 |
|
|
- $RBLbyhour{$nhour}=0; |
234 |
|
|
- $above15byhour{$nhour}=0; |
235 |
|
|
- $patternfilterbyhour{$nhour}=0; |
236 |
|
|
- $nhour++; |
237 |
|
|
-} |
238 |
|
|
- |
239 |
|
|
-my $starttai = Time::TAI64::unixtai64n($start); |
240 |
|
|
-my $endtai = Time::TAI64::unixtai64n($end); |
241 |
|
|
- |
242 |
|
|
-LINE: while (<>) { |
243 |
|
|
- my($tai,$log) = split(' ',$_,2); |
244 |
|
|
- |
245 |
|
|
- |
246 |
|
|
- #If date specified, only process lines matching date |
247 |
|
|
- next LINE if ( $tai lt $starttai ); |
248 |
|
|
- last if ( $tai gt $endtai ); |
249 |
|
|
- |
250 |
|
|
- #only select Logterse output |
251 |
|
|
- next LINE unless m/terse plugin/; |
252 |
|
|
- |
253 |
|
|
- |
254 |
|
|
- my $abstime = Time::TAI64::tai2unix($tai); |
255 |
|
|
- my $abshour = floor( $abstime / 3600 ); # Hours since the epoch |
256 |
|
|
- |
257 |
|
|
- |
258 |
|
|
- my ($timestamp_part, $log_part) = split '`'; |
259 |
|
|
- my (@log_items) = split $FS, $log_part; |
260 |
|
|
- |
261 |
|
|
- my (@timestamp_items) = split(' ',$timestamp_part); |
262 |
|
|
- |
263 |
|
|
- # we store the more recent recipient domain, for domain statistics |
264 |
|
|
- # in fact, we only store the first recipient. Could be sort of headhache |
265 |
|
|
- # to obtain precise stats with many recipients on more than one domain ! |
266 |
|
|
- my $proc = $timestamp_items[1] ; #numeric Id for the email |
267 |
|
|
- |
268 |
|
|
- $totalexamined++; |
269 |
|
|
- |
270 |
|
|
- # first spot the fetchmail and local deliveries. |
271 |
|
|
- |
272 |
|
|
- # print '<'.$log_items[1].'><'.$log_items[5].'><'.$log_items[8].">\n"; |
273 |
|
|
- |
274 |
|
|
- if ($log_items[1] =~ m/.*$DomainName.*/) {$localsendtotal++;$localLANbyhour{$abshour}++;$localflag=1} |
275 |
|
|
- else {$localflag=0} |
276 |
|
|
- |
277 |
|
|
- if ($log_items[0] =~ m/.*$FetchmailIP.*/) {$localAccepttotal++;$localacceptbyhour{$abshour}++} |
278 |
|
|
- |
279 |
|
|
- |
280 |
|
|
- # and adjust for recipient field if not set-up by denying plugin - extract from deny msg |
281 |
|
|
- |
282 |
|
|
- if (length($log_items[4])==0) { |
283 |
|
|
- if ($log_items[5] eq 'check_goodrcptto') { |
284 |
|
|
- if ($log_items[7] gt "invalid recipient") { |
285 |
|
|
- $log_items[4] = substr($log_items[7],18) #Leave only email address |
286 |
|
|
- } |
287 |
|
|
- } |
288 |
|
|
- } |
289 |
|
|
- |
290 |
|
|
- |
291 |
|
|
- |
292 |
|
|
- if ( ( $currentrcptdomain{ $proc } || '' ) eq '' ) { |
293 |
|
|
- $currentrcptdomain{ $proc } = lc($log_items[4]) ; |
294 |
|
|
- $currentrcptdomain{ $proc } =~ s/.*@//; |
295 |
|
|
- |
296 |
|
|
- |
297 |
|
|
- |
298 |
|
|
-# print $proc,$log_items[4]."\n"; |
299 |
|
|
- |
300 |
|
|
- $currentrcptdomain{ $proc } =~ s/[^\w\-\.]//g ; |
301 |
|
|
- |
302 |
|
|
-# print $currentrcptdomain{ $proc }."\n"; |
303 |
|
|
- |
304 |
|
|
- my $NotableDomain = 0 ; |
305 |
|
|
- if ( defined ( $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'type' } ) ) { |
306 |
|
|
- $NotableDomain = 1 ; |
307 |
|
|
- } else { |
308 |
|
|
- foreach ( @extdomain ) { |
309 |
|
|
- if ( $currentrcptdomain{ $proc } =~ m/$_$/ ) { |
310 |
|
|
- $NotableDomain = 1 ; |
311 |
|
|
- last ; |
312 |
|
|
- } |
313 |
|
|
- } |
314 |
|
|
- } |
315 |
|
|
- if ( !$NotableDomain ) { |
316 |
|
|
- # check for outgoing email |
317 |
|
|
- if ($localflag==1) {$currentrcptdomain{ $proc } = 'Outgoing'} |
318 |
|
|
- else {$currentrcptdomain{ $proc } = 'Others'} |
319 |
|
|
- } else { |
320 |
|
|
- if ($localflag==1) {$currentrcptdomain{ $proc } = 'Internal'} |
321 |
|
|
- } |
322 |
|
|
- $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'total' }++ ; |
323 |
|
|
- } else { |
324 |
|
|
- # there more than a recipient for a mail, how many daily ? |
325 |
|
|
- $morethanonercpt++; |
326 |
|
|
- } |
327 |
|
|
- |
328 |
|
|
- # then categorise the result |
329 |
|
|
- if (exists $log_items[5]) { |
330 |
|
|
- #Check for badly formed lines (from earlier testing) |
331 |
|
|
- |
332 |
|
|
- if ($log_items[5] eq 'check_earlytalker') {$MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
333 |
|
|
- |
334 |
|
|
- if ($log_items[5] eq 'check_relay') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
335 |
|
|
- |
336 |
|
|
- if ($log_items[5] eq 'check_norelay') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
337 |
|
|
- |
338 |
|
|
- if ($log_items[5] eq 'require_resolvable_fromhost') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
339 |
|
|
- |
340 |
|
|
- if ($log_items[5] eq 'check_basicheaders') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
341 |
|
|
- |
342 |
|
|
- if ($log_items[5] eq 'rhsbl') { $RBLcount++;$RBLbyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
343 |
|
|
- |
344 |
|
|
- if ($log_items[5] eq 'dnsbl') { $RBLcount++;$RBLbyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
345 |
|
|
- |
346 |
|
|
- if ($log_items[5] eq 'check_badmailfrom') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
347 |
|
|
- |
348 |
|
|
- if ($log_items[5] eq 'check_badrcptto_patterns') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
349 |
|
|
- |
350 |
|
|
- if ($log_items[5] eq 'check_badrcptto') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
351 |
|
|
- |
352 |
|
|
- if ($log_items[5] eq 'check_spamhelo') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
353 |
|
|
- |
354 |
|
|
- if ($log_items[5] eq 'check_goodrcptto extn') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
355 |
|
|
- |
356 |
|
|
- if ($log_items[5] eq 'rcpt_ok') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
357 |
|
|
- |
358 |
|
|
- if ($log_items[5] eq 'pattern_filter') { $PatternFilterCount++;$patternfilterbyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
359 |
|
|
- |
360 |
|
|
- if ($log_items[5] eq 'virus::pattern_filter') { $PatternFilterCount++;$patternfilterbyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
361 |
|
|
- |
362 |
|
|
- if ($log_items[5] eq 'check_goodrcptto') {$MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
363 |
|
|
- |
364 |
|
|
- if ($log_items[5] eq 'check_smtp_forward') {$MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
365 |
|
|
- |
366 |
|
|
- if ($log_items[5] eq 'count_unrecognized_commands') {$MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
367 |
|
|
- |
368 |
|
|
- if ($log_items[5] eq 'tnef2mime') { next LINE} #Not expecting this one. |
369 |
|
|
- |
370 |
|
|
- if ($log_items[5] eq 'spamassassin') { $above15++;$above15byhour{$abshour}++; |
371 |
|
|
- # and extract the spam score |
372 |
|
|
- if ($log_items[8] =~ "Yes, hits=(.*) required=([0-9\.]+)") {$rejectspamavg += $1} |
373 |
|
|
- mark_domain_rejected($proc); |
374 |
|
|
- next LINE |
375 |
|
|
- } |
376 |
|
|
- |
377 |
|
|
- if ($log_items[5] eq 'virus::clamav') { $infectedcount++;$infectedbyhour{$abshour}++; |
378 |
|
|
- #extract the virus name |
379 |
|
|
- if ($log_items[7] =~ "Virus Found: (.*)" ) {$found_viruses{$1}++;} |
380 |
|
|
- mark_domain_rejected($proc); |
381 |
|
|
- next LINE |
382 |
|
|
- } |
383 |
|
|
- |
384 |
|
|
- if ($log_items[5] eq 'queued') { $Accepttotal++; |
385 |
|
|
- #extract the spam score |
386 |
|
|
- if ($log_items[8] =~ ".*hits=(.*) required=([0-9\.]+)") { |
387 |
|
|
- $score = $1; |
388 |
|
|
- if ($score < $SATagLevel) { $hamcount++;$hamavg += $score} |
389 |
|
|
- else {$spamcount++;$spamavg += $score} |
390 |
|
|
- } |
391 |
|
|
- if ( ( $currentrcptdomain{ $proc } || '' ) ne '' ) { |
392 |
|
|
- $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'accept' }++ ; |
393 |
|
|
- $currentrcptdomain{ $proc } = '' ; |
394 |
|
|
- } |
395 |
|
|
- next LINE |
396 |
|
|
- } |
397 |
|
|
- |
398 |
|
|
- print $log_items[5]."\n"; #Not detected |
399 |
|
|
- |
400 |
|
|
- } |
401 |
|
|
- |
402 |
|
|
- |
403 |
|
|
- |
404 |
|
|
-} |
405 |
|
|
- |
406 |
|
|
-my $QueryNoLogTerse = ($totalexamined==0); #might indicate logterse not installed in qpsmtpd plugins |
407 |
|
|
- |
408 |
|
|
-#Calculate some numbers |
409 |
|
|
- |
410 |
|
|
-$spamavg = $spamavg / $spamcount if $spamcount; |
411 |
|
|
-$rejectspamavg = $rejectspamavg / $above15 if $above15; |
412 |
|
|
-$hamavg = $hamavg / $hamcount if $hamcount; |
413 |
|
|
- |
414 |
|
|
-# RBL etc percent of total SMTP sessions |
415 |
|
|
- |
416 |
|
|
-my $rblpercent = ( ( $RBLcount / $totalexamined ) * 100 ) if $totalexamined; |
417 |
|
|
-my $PatternFilterpercent = ( ( $PatternFilterCount / $totalexamined ) * 100 ) if $totalexamined; |
418 |
|
|
-my $Miscpercent = ( ( $MiscDenyCount / $totalexamined ) * 100 ) if $totalexamined; |
419 |
|
|
- |
420 |
|
|
-#Spam and virus percent of total email downloaded |
421 |
|
|
-#Expressed as a % of total examined |
422 |
|
|
-my $spampercent = ( ( $spamcount / $totalexamined ) * 100 ) if $totalexamined; |
423 |
|
|
-my $hampercent = ( ( $hamcount / $totalexamined ) * 100 ) if $totalexamined; |
424 |
|
|
-my $hrsinperiod = ( ( $end - $start ) / 3600 ); |
425 |
|
|
-my $emailperhour = ( $totalexamined / $hrsinperiod ) if $totalexamined; |
426 |
|
|
-my $above15percent = ( $above15 / $totalexamined * 100 ) if $totalexamined; |
427 |
|
|
-my $infectedpercent = ( ( $infectedcount / ($totalexamined) ) * 100 ) if $totalexamined; |
428 |
|
|
-my $AcceptPercent = ( ( $Accepttotal / ($totalexamined) ) * 100 ) if $totalexamined; |
429 |
|
|
- |
430 |
|
|
-my $oldfh; |
431 |
|
|
-#Open Sendmail if we are mailing it |
432 |
|
|
-if ( $opt{'mail'} && !$disabled ) { |
433 |
|
|
- open( SENDMAIL, "|$opt{'sendmail'} -oi -t -odq" ) |
434 |
|
|
- or die "Can't open sendmail: $!\n"; |
435 |
|
|
- print SENDMAIL "From: $opt{'from'}\n"; |
436 |
|
|
- print SENDMAIL "To: $opt{'mail'}\n"; |
437 |
|
|
- print SENDMAIL "Subject: Spam Filter Statistics from $hostname - ", |
438 |
|
|
- strftime( "%F", localtime($start) ), "\n\n"; |
439 |
|
|
- $oldfh = select SENDMAIL; |
440 |
|
|
-} |
441 |
|
|
- |
442 |
|
|
-my $telapsed = time - $tstart; |
443 |
|
|
- |
444 |
|
|
-if ( !$disabled ) { |
445 |
|
|
- |
446 |
|
|
- #Output results |
447 |
|
|
- print "SMEServer daily Anti-Virus and Spamfilter statistics", "\n"; |
448 |
|
|
- print "----------------------------------------------------", "\n\n"; |
449 |
|
|
- |
450 |
|
|
- print "$0 Version : $opt{'version'}", "\n\n"; |
451 |
|
|
- print "Period Beginning : ", strftime( "%c", localtime($start) ), "\n"; |
452 |
|
|
- print "Period Ending : ", strftime( "%c", localtime($end) ), "\n"; |
453 |
|
|
- print "\n"; |
454 |
|
|
- |
455 |
|
|
- print "Clam Version : ", `freshclam -V`; |
456 |
|
|
- print "SpamAssassin Version : ", `spamassassin -V`; |
457 |
|
|
- printf "Tag level: %3d; Reject level: %3d $warnnoreject\n", $SATagLevel, |
458 |
|
|
- $SARejectLevel; |
459 |
|
|
- |
460 |
|
|
- print "\n"; |
461 |
|
|
- printf "Reporting Period : %.2f hrs\n", $hrsinperiod; |
462 |
|
|
- print "----------------------------\n"; |
463 |
|
|
- print "\n"; |
464 |
|
|
- |
465 |
|
|
- printf "All SMTP connections accepted : %8d \n", $totalexamined; |
466 |
|
|
- |
467 |
|
|
- if ($localAccepttotal>0) { |
468 |
|
|
- printf "Connections from Fetchmail : %8d \n", |
469 |
|
|
- $localAccepttotal; |
470 |
|
|
- } |
471 |
|
|
- printf "SMTP from local workstations : %8d \n\n", $localsendtotal; |
472 |
|
|
- |
473 |
|
|
- |
474 |
|
|
- printf "RBL rejected : %8d (%6.2f%%)\n", $RBLcount, |
475 |
|
|
- $rblpercent || 0; |
476 |
|
|
- printf "Pattern filter rejected : %8d (%6.2f%%)\n", |
477 |
|
|
- $PatternFilterCount, $PatternFilterpercent || 0; |
478 |
|
|
- printf "Rejected due to non conformance : %8d (%6.2f%%)\n", $MiscDenyCount, |
479 |
|
|
- $Miscpercent || 0; |
480 |
|
|
- |
481 |
|
|
- printf "Infected by Virus : %8d (%6.2f%%)\n", $infectedcount, |
482 |
|
|
- $infectedpercent || 0; |
483 |
|
|
- |
484 |
|
|
- printf "Spam rejected (over reject level): %8d (%6.2f%%)\n", $above15, |
485 |
|
|
- $above15percent || 0; |
486 |
|
|
- printf "Spam detected (over tag level) : %8d (%6.2f%%)\n", $spamcount, |
487 |
|
|
- $spampercent || 0; |
488 |
|
|
- printf "Ham detected (under tag level) : %8d (%6.2f%%)\n", $hamcount, |
489 |
|
|
- $hampercent || 0; |
490 |
|
|
- print " --------------------\n"; |
491 |
|
|
- printf "Total emails accepted : %8d (%6.2f%%)\n", $Accepttotal, |
492 |
|
|
- $AcceptPercent || 0; |
493 |
|
|
- |
494 |
|
|
- printf "Emails per hour : (%8.1f/hr)\n", $emailperhour || 0; |
495 |
|
|
- print "\n"; |
496 |
|
|
- printf "Average spam score (accepted): %11.2f\n", $spamavg || 0; |
497 |
|
|
- printf "Average spam score (rejected): %11.2f\n", $rejectspamavg || 0; |
498 |
|
|
- printf "Average ham score : %11.2f\n", $hamavg || 0; |
499 |
|
|
- print "\n"; |
500 |
|
|
- print "Statistics by Hour\n"; |
501 |
|
|
- if ($localAccepttotal>0) { |
502 |
|
|
- print "---------------------------------------------------------------------------------------- \n"; |
503 |
|
|
- print |
504 |
|
|
- "Hour Fetchml Local Virus Spam Ham RBL/DNS$rblnotset Execut. Non.Conf.\n"; |
505 |
|
|
- print "-------------- -------- -------- -------- -------- -------- -------- -------- ---------\n"; |
506 |
|
|
- |
507 |
|
|
- my $hour = floor( $start / 3600 ); |
508 |
|
|
- while ( $hour < $end / 3600 ) { |
509 |
|
|
- printf( |
510 |
|
|
- "%s %8d %8d %8d %8d %8d %8d %8d %8d\n", |
511 |
|
|
- strftime( "%F, %H", localtime( $hour * 3600 ) ), |
512 |
|
|
- $localacceptbyhour{$hour} || 0, |
513 |
|
|
- $localLANbyhour{$hour} || 0, |
514 |
|
|
- $infectedbyhour{$hour} || 0, |
515 |
|
|
- $spambyhour{$hour} || 0, |
516 |
|
|
- $hambyhour{$hour} || 0, |
517 |
|
|
- $RBLbyhour{$hour} || 0, |
518 |
|
|
- $patternfilterbyhour{$hour} || 0, |
519 |
|
|
- $MiscDenybyhour{$hour} || 0 |
520 |
|
|
- ); |
521 |
|
|
- $hour++; |
522 |
|
|
- } |
523 |
|
|
- print "---------------------------------------------------------------------------------------- \n"; |
524 |
|
|
- |
525 |
|
|
- } else { |
526 |
|
|
- print "------------------------------------------------------------------------------- \n"; |
527 |
|
|
- print |
528 |
|
|
- "Hour Local Virus Spam Ham RBL/DNS$rblnotset Execut. Non.Conf.\n"; |
529 |
|
|
- print "--------------- -------- -------- -------- -------- -------- -------- --------- \n"; |
530 |
|
|
- |
531 |
|
|
- my $hour = floor( $start / 3600 ); |
532 |
|
|
- while ( $hour < $end / 3600 ) { |
533 |
|
|
- printf( |
534 |
|
|
- "%s %8d %8d %8d %8d %8d %8d %8d\n", |
535 |
|
|
- strftime( "%F, %H", localtime( $hour * 3600 ) ), |
536 |
|
|
- $localLANbyhour{$hour} || 0, |
537 |
|
|
- $infectedbyhour{$hour} || 0, |
538 |
|
|
- $spambyhour{$hour} || 0, |
539 |
|
|
- $hambyhour{$hour} || 0, |
540 |
|
|
- $RBLbyhour{$hour} || 0, |
541 |
|
|
- $patternfilterbyhour{$hour} || 0, |
542 |
|
|
- $MiscDenybyhour{$hour} || 0 |
543 |
|
|
- ); |
544 |
|
|
- $hour++; |
545 |
|
|
- } |
546 |
|
|
- |
547 |
|
|
- print "------------------------------------------------------------------------------ \n"; |
548 |
|
|
- |
549 |
|
|
- } |
550 |
|
|
- if ($localAccepttotal>0) { |
551 |
|
|
- print "*Fetchml* means connections from Fetchmail delivering email\n"; |
552 |
|
|
- } |
553 |
|
|
- print "*Local* means connections from workstations on local LAN.\n"; |
554 |
|
|
- print "*Non\.Conf\.* means sending mailserver did not conform to correct protocol.\n"; |
555 |
|
|
- print " or email was to non existant address.\n"; |
556 |
|
|
- print "\n"; |
557 |
|
|
- |
558 |
|
|
- if ($QueryNoLogTerse) { |
559 |
|
|
- print "* - as no records where found, it looks as though you may not have the *logterse* \nplugin running as part of qpsmtpd \n"; |
560 |
|
|
- print " to enable it follow the instructions at .............................\n"; |
561 |
|
|
- } |
562 |
|
|
- |
563 |
|
|
- |
564 |
|
|
- if ( !$RHSenabled || !$DNSenabled ) { |
565 |
|
|
- |
566 |
|
|
- # comment about RBL not set |
567 |
|
|
- print |
568 |
|
|
-"* - This means that one or more of the possible spam black listing services\n that are available have not been enabled.\n"; |
569 |
|
|
- print " You have not enabled:\n"; |
570 |
|
|
- |
571 |
|
|
- if ( !$RHSenabled ) { |
572 |
|
|
- print " RHSBL\n"; |
573 |
|
|
- } |
574 |
|
|
- |
575 |
|
|
- if ( !$DNSenabled ) { |
576 |
|
|
- print " DNSBL\n"; |
577 |
|
|
- } |
578 |
|
|
- |
579 |
|
|
- |
580 |
|
|
- print " To enable these you can use the following commands:\n"; |
581 |
|
|
- if ( !$RHSenabled ) { |
582 |
|
|
- print " config setprop qpsmtpd RHSBL enabled\n"; |
583 |
|
|
- } |
584 |
|
|
- |
585 |
|
|
- if ( !$DNSenabled ) { |
586 |
|
|
- print " config setprop qpsmtpd DNSBL enabled\n"; |
587 |
|
|
- } |
588 |
|
|
- |
589 |
|
|
- # there so much templates to expand... (PS) |
590 |
|
|
- print " Followed by:\n signal-event email-update and\n svc -t /service/qpsmtpd\n\n"; |
591 |
|
|
- } |
592 |
|
|
- |
593 |
|
|
- |
594 |
|
|
- # time to do a 'by recipient domain' report |
595 |
|
|
- print "\nIncoming mails by recipient domains usage\n"; |
596 |
|
|
- print "-----------------------------------------\n"; |
597 |
|
|
- print |
598 |
|
|
- "Domains Type Total Denied XferErr Accept \%accept\n"; |
599 |
|
|
- print |
600 |
|
|
- "---------------------------- ---------- ------ ------ ------- ------ -------\n"; |
601 |
|
|
- my %total = ( |
602 |
|
|
- total => 0, |
603 |
|
|
- deny => 0, |
604 |
|
|
- xfer => 0, |
605 |
|
|
- accept => 0, |
606 |
|
|
- ); |
607 |
|
|
- foreach my $domain ( |
608 |
|
|
- sort { |
609 |
|
|
- join( "\.", reverse( split /\./, $a ) ) cmp |
610 |
|
|
- join( "\.", reverse( split /\./, $b ) ) |
611 |
|
|
- } keys %byrcptdomain |
612 |
|
|
- ) |
613 |
|
|
- { |
614 |
|
|
- next if ( ( $byrcptdomain{$domain}{'total'} || 0 ) == 0 ); |
615 |
|
|
- my $tp = $byrcptdomain{$domain}{'type'} || 'other'; |
616 |
|
|
- my $to = $byrcptdomain{$domain}{'total'} || 0; |
617 |
|
|
- my $de = $byrcptdomain{$domain}{'deny'} || 0; |
618 |
|
|
- my $xr = $byrcptdomain{$domain}{'xfer'} || 0; |
619 |
|
|
- my $ac = $byrcptdomain{$domain}{'accept'} || 0; |
620 |
|
|
- printf "%-28s %-10s %6d %6d %7d %6d %6.2f%%\n", $domain, $tp, $to, |
621 |
|
|
- $de, $xr, $ac, $ac * 100 / $to; |
622 |
|
|
- $total{'total'} += $to; |
623 |
|
|
- $total{'deny'} += $de; |
624 |
|
|
- $total{'xfer'} += $xr; |
625 |
|
|
- $total{'accept'} += $ac; |
626 |
|
|
- } |
627 |
|
|
- print |
628 |
|
|
- "---------------------------- ---------- ------ ------- ------ ------ -------\n"; |
629 |
|
|
- |
630 |
|
|
- # $total{ 'total' } can be equal to 0, bad for divisions... |
631 |
|
|
- my $perc1 = 0; |
632 |
|
|
- my $perc2 = 0; |
633 |
|
|
- if ( $total{'total'} != 0 ) { |
634 |
|
|
- $perc1 = $total{'accept'} * 100 / $total{'total'}; |
635 |
|
|
- $perc2 = ( ( $total{'total'} + $morethanonercpt ) / $total{'total'} ); |
636 |
|
|
- } |
637 |
|
|
- printf |
638 |
|
|
- "Total %6d %6d %7d %6d %6.2f%%\n\n", |
639 |
|
|
- $total{'total'}, $total{'deny'}, $total{'xfer'}, $total{'accept'}, |
640 |
|
|
- $perc1; |
641 |
|
|
- printf |
642 |
|
|
- "%d mails were processed for %d Recipients\nThe average recipients by mail is %4.2f\n\n", |
643 |
|
|
- $total{'total'}, ( $total{'total'} + $morethanonercpt ), $perc2; |
644 |
|
|
- |
645 |
|
|
- if ( $infectedcount > 0 ) { |
646 |
|
|
- show_virus_variants(); |
647 |
|
|
- } |
648 |
|
|
- |
649 |
|
|
-} # not disabled |
650 |
|
|
- |
651 |
|
|
-List_Junkmail(); |
652 |
|
|
- |
653 |
|
|
-if ( !$disabled ) { |
654 |
|
|
- |
655 |
|
|
- print "\nDone. Report generated in $telapsed sec.\n\n"; |
656 |
|
|
- |
657 |
|
|
- #Close Senmdmail if it was opened |
658 |
|
|
- if ( $opt{'mail'} ) { |
659 |
|
|
- select $oldfh; |
660 |
|
|
- close(SENDMAIL); |
661 |
|
|
- } |
662 |
|
|
- |
663 |
|
|
-} |
664 |
|
|
- |
665 |
|
|
-#All done |
666 |
|
|
-exit 0; |
667 |
|
|
- |
668 |
|
|
-############################################################################# |
669 |
|
|
-# Subroutines ############################################################### |
670 |
|
|
-############################################################################# |
671 |
|
|
- |
672 |
|
|
- |
673 |
|
|
-######################################## |
674 |
|
|
-# Process parms # |
675 |
|
|
-######################################## |
676 |
|
|
-sub parse_arg { |
677 |
|
|
- my $startdate = shift; |
678 |
|
|
- my $enddate = shift; |
679 |
|
|
- |
680 |
|
|
- my $secsinday = 86400; |
681 |
|
|
- my $time = 0; |
682 |
|
|
- |
683 |
|
|
- my $start = UnixDate( $startdate, "%s" ); |
684 |
|
|
- my $end = UnixDate( $enddate, "%s" ); |
685 |
|
|
- |
686 |
|
|
- if ( !$start && !$end ) { |
687 |
|
|
- $end = time; |
688 |
|
|
- $start = $end - $secsinday; |
689 |
|
|
- return ( $start, $end ); |
690 |
|
|
- } |
691 |
|
|
- |
692 |
|
|
- if ( !$start ) { |
693 |
|
|
- $start = $end - $secsinday; |
694 |
|
|
- return ( $start, $end ); |
695 |
|
|
- } |
696 |
|
|
- |
697 |
|
|
- if ( !$end ) { |
698 |
|
|
- $end = $start + $secsinday; |
699 |
|
|
- return ( $start, $end ); |
700 |
|
|
- } |
701 |
|
|
- |
702 |
|
|
- if ( $start > $end ) { |
703 |
|
|
- return ( $end, $start ); |
704 |
|
|
- } |
705 |
|
|
- |
706 |
|
|
- return ( $start, $end ); |
707 |
|
|
- |
708 |
|
|
-} |
709 |
|
|
- |
710 |
|
|
-sub dbg { |
711 |
|
|
- my $msg = shift; |
712 |
|
|
- |
713 |
|
|
- if ( $opt{debug} ) { |
714 |
|
|
- print STDERR $msg; |
715 |
|
|
- } |
716 |
|
|
-} |
717 |
|
|
- |
718 |
|
|
-sub List_Junkmail { |
719 |
|
|
- |
720 |
|
|
- # |
721 |
|
|
- # Show how many junkmails in each user's junkmail folder. |
722 |
|
|
- # |
723 |
|
|
- use esmith::AccountsDB; |
724 |
|
|
- my $adb = esmith::AccountsDB->open_ro; |
725 |
|
|
- my $entry; |
726 |
|
|
- foreach my $user ($adb->users) { |
727 |
|
|
- my $found = 0; |
728 |
|
|
- my $junkmail_dir = "/home/e-smith/files/users/" . |
729 |
|
|
- $user->key . "/Maildir/.junkmail"; |
730 |
|
|
-# print $user->key; |
731 |
|
|
- foreach my $dir (qw(new cur)) { |
732 |
|
|
- # Now get the content list for the directory. |
733 |
|
|
- if (opendir( QDIR, "$junkmail_dir/$dir" )) { |
734 |
|
|
- while ($entry=readdir(QDIR) ) { |
735 |
|
|
- next if $entry =~ /^\./; |
736 |
|
|
- $found++; |
737 |
|
|
- } |
738 |
|
|
- |
739 |
|
|
- closedir(QDIR); |
740 |
|
|
- } |
741 |
|
|
- } |
742 |
|
|
- if ( !$disabled ) { |
743 |
|
|
- printf "User \"%s\" ", $user->key; |
744 |
|
|
- printf "- %d email(s) left in junkmail folder\n", $found; |
745 |
|
|
- } |
746 |
|
|
- } |
747 |
|
|
-} |
748 |
|
|
- |
749 |
|
|
-sub show_virus_variants |
750 |
|
|
- |
751 |
|
|
-# |
752 |
|
|
-# Show a league table of the different virus types found today |
753 |
|
|
-# |
754 |
|
|
- |
755 |
|
|
-{ |
756 |
|
|
- |
757 |
|
|
- print("Virus Statistics by name:\n"); |
758 |
|
|
- print("---------------------------------------------\n"); |
759 |
|
|
- foreach my $virus (sort { $found_viruses{$b} <=> $found_viruses{$a} } |
760 |
|
|
- keys %found_viruses) |
761 |
|
|
- { |
762 |
|
|
- print "Rejected $found_viruses{$virus}\t$virus\n"; |
763 |
|
|
- } |
764 |
|
|
- print("---------------------------------------------\n"); |
765 |
|
|
-} |
766 |
|
|
- |
767 |
|
|
-sub mark_domain_rejected |
768 |
|
|
- |
769 |
|
|
-# |
770 |
|
|
-# Tag domain as having a rejected email |
771 |
|
|
-# |
772 |
|
|
-{ |
773 |
|
|
-my ($proc) = @_; |
774 |
|
|
-if ( ( $currentrcptdomain{ $proc } || '' ) ne '' ) { |
775 |
|
|
- $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'deny' }++ ; |
776 |
|
|
- $currentrcptdomain{ $proc } = '' ; |
777 |
|
|
- } |
778 |
|
|
+#!/usr/bin/perl -w |
779 |
|
|
+ |
780 |
|
|
+############################################################################# |
781 |
|
|
+# |
782 |
|
|
+# This script provides daily SpamFilter statistics and deletes all users |
783 |
|
|
+# junkmails. Configuration of the script is done by the Spam Filter |
784 |
|
|
+# Server-Manager module |
785 |
|
|
+# |
786 |
|
|
+# April 2006 - no longer controlled by server manager, and does not delete files |
787 |
|
|
+# |
788 |
|
|
+# This script has been developed |
789 |
|
|
+# by Jesper Knudsen at http://sme.swerts-knudsen.dk |
790 |
|
|
+# |
791 |
|
|
+# Revision History: |
792 |
|
|
+# |
793 |
|
|
+# August 13, 2003: Initial version |
794 |
|
|
+# August 25, 2004: fixed problem when hostname had no-ASCII chars |
795 |
|
|
+# March 23, 2006 Revised for sme7 RM |
796 |
|
|
+# March 27, 2006 ditto BJR (http://www.abandonmicrosoft.co.uk) |
797 |
|
|
+# - Merged Clamav and SA stats |
798 |
|
|
+# - Moved all analysis to qsmtpd log |
799 |
|
|
+# - Removed parameterised interval (for simplicity - not sure of format anyway) |
800 |
|
|
+# - add in archived log files for people who have high turnover |
801 |
|
|
+# - Alter labels to be more accurate |
802 |
|
|
+# - Detect deleted spam (over threshold) without using spam score |
803 |
|
|
+# - Detect RBL rejections |
804 |
|
|
+# - Detect pattern (executible) rejections |
805 |
|
|
+# - Look for the DENY labels - add in Miscellaneous category |
806 |
|
|
+# April 6, 2006 - check qpsmtp log level and also DNS enable properties |
807 |
|
|
+# - Average spam scores for under and over threshold seperatly |
808 |
|
|
+# - Log tag and Reject levels |
809 |
|
|
+# - TBD - check that RBL DENY are being detected (I have no date to check this) |
810 |
|
|
+# April 7, 2007 - re-written by Charlie Brady totally in Perl |
811 |
|
|
+# April 16, 2006 - move warnings to report |
812 |
|
|
+# - Spot fetchmail deliveries |
813 |
|
|
+# - Spot Internal connections from client PCs |
814 |
|
|
+# - TBD check that RBL DENY are being detected (I have no data to check this) |
815 |
|
|
+# April 30, 2006 - Pascal Schirrmann Start Time and End Time to noon - should be a param |
816 |
|
|
+# so the script can be run at any time in the day. |
817 |
|
|
+# - adds 'by recipients domains' stats Useful for MX-Backup or multi domains hosts |
818 |
|
|
+# - Add a 'recipients per mail' stat. Useful : until now the sums are correct :-) |
819 |
|
|
+# - Correct some messages about rbl who can led to wrong entry in the config database |
820 |
|
|
+# ( and without expected results, of course !) |
821 |
|
|
+# - improve a regexp in the SPAM detection |
822 |
|
|
+# May 1, 2006 - BJR - Fix situation where mxbackup prop is not defined |
823 |
|
|
+# - fix a spelling and minor format of domain report |
824 |
|
|
+# May 9, 2006 - bjr - Make RBL percentage a percentage of total connections (else it >100%) |
825 |
|
|
+# May 9, 2006 - ps - some 'sanity check' in the 'per domains part of the stats (to avoid / 0) |
826 |
|
|
+# May 12, 2006 - ps - some cleanup in the 'per domains' stats |
827 |
|
|
+# - Add a version number, logged in the mail |
828 |
|
|
+# June 20, 2006 - bjr - Minor change to RBL instructions, and adjust domain table format |
829 |
|
|
+# Feb 19, 2007 - bjr - Adjust table lines oin a couple of places |
830 |
|
|
+# - bjr - and add documentation details about percentages etc |
831 |
|
|
+# - bjr - Alter misc to "non conforming" anmd accumulated these hourly |
832 |
|
|
+# - bjr - Express change over tag count to exclude spam rejected over threshold |
833 |
|
|
+# - bjr - Change "processsed" to "fully downloaded" |
834 |
|
|
+# - bjr - Change percentages so that they are all a percetnage of the total emails received |
835 |
|
|
+# 0.6.1 - bjr - Change to use output from the logterse qpsmtpd plugin |
836 |
|
|
+# 0.6.2 - bjr - Fix fetchmail tests |
837 |
|
|
+# 0.6.3 - bjr - adjust for log-items change in order |
838 |
|
|
+# 0.6.4&5 - bjr - Adjust table formatting |
839 |
|
|
+# 0.6.6 - bjr - Take outgoing emails out of "others", add "Outgoing" and "Internal" |
840 |
|
|
+# 0.6.7 - bjr - Fix missing plugins/wrong names. pull invalid recipient out of deny msg for goodrcptto |
841 |
|
|
+# 0.6.8 - bjr - catch a few more plugin name failures |
842 |
|
|
+# 0.6.9 - bjr - Catch webmail and mailman |
843 |
|
|
+# 0.6.10 - bjr - Refine Webmail identification |
844 |
|
|
+# 0.6.11 - bjr - Fix Webmail identification |
845 |
|
|
+# |
846 |
|
|
+# |
847 |
|
|
+# |
848 |
|
|
+# TODO |
849 |
|
|
+# ---- |
850 |
|
|
+# |
851 |
|
|
+# 1. Re-Write the table so that it does not show certain columns if they are zero, this will allow EXTRA |
852 |
|
|
+# columns to be shown (e.g Mailman, fetchmail, webmail) only if there is some activity |
853 |
|
|
+# |
854 |
|
|
+############################################################################# |
855 |
|
|
+ |
856 |
|
|
+ |
857 |
|
|
+# internal modules (part of core perl distribution) |
858 |
|
|
+use strict; |
859 |
|
|
+use warnings; |
860 |
|
|
+use Getopt::Long; |
861 |
|
|
+use Pod::Usage; |
862 |
|
|
+use POSIX qw/strftime floor/; |
863 |
|
|
+use Time::Local; |
864 |
|
|
+use Date::Manip; |
865 |
|
|
+use Time::TAI64; |
866 |
|
|
+use esmith::ConfigDB; |
867 |
|
|
+use esmith::DomainsDB; |
868 |
|
|
+use Sys::Hostname; |
869 |
|
|
+use Switch; |
870 |
|
|
+ |
871 |
|
|
+my $hostname = hostname(); |
872 |
|
|
+ |
873 |
|
|
+#Configuration section |
874 |
|
|
+my %opt = (); |
875 |
|
|
+ |
876 |
|
|
+$opt{'version'} = '0.6.11'; # please update at each change. |
877 |
|
|
+$opt{'debug'} = 0; # guess what ? |
878 |
|
|
+$opt{'sendmail'} = '/usr/sbin/sendmail'; # Path to sendmail stub |
879 |
|
|
+$opt{'from'} = 'spamfilter-stats'; # Who is the mail from |
880 |
|
|
+$opt{'end'} = `date --iso-8601`; # midnight today |
881 |
|
|
+my $yesterday = $opt{ 'end' }; |
882 |
|
|
+$yesterday =~ s/\-//g ; |
883 |
|
|
+$yesterday--; |
884 |
|
|
+$opt{'start'} = `date --iso-8601 -d $yesterday`; # midnight yesterday |
885 |
|
|
+$opt{'mail'} = "admin"; |
886 |
|
|
+$opt{'timezone'} = `date +%z`; |
887 |
|
|
+Date_Init("TZ=$opt{'timezone'}"); |
888 |
|
|
+my $FetchmailIP = '127.0.0.200'; #Apparent Ip address of fetchmail deliveries |
889 |
|
|
+my $WebmailIP = '127.0.0.1'; #Apparent Ip of Webmail sender |
890 |
|
|
+my $localhost = 'localhost'; #Apparent sender for webmail |
891 |
|
|
+my $FETCHMAIL = 'FETCHMAIL'; #Sender from fetchmail when Ip address not 127.0.0.200 - when qpsmtpd denies the email |
892 |
|
|
+my $MAILMAN = "bounces"; #sender when mailman sending when orig is localhost |
893 |
|
|
+ |
894 |
|
|
+my $disabled = 0; |
895 |
|
|
+ |
896 |
|
|
+my $tstart = time; |
897 |
|
|
+ |
898 |
|
|
+#Local variables |
899 |
|
|
+my $YEAR = ( localtime(time) )[5]; # this is years since 1900 |
900 |
|
|
+ |
901 |
|
|
+my $total = 0; |
902 |
|
|
+my $spamcount = 0; |
903 |
|
|
+my $spamavg = 0; |
904 |
|
|
+my $hamcount = 0; |
905 |
|
|
+my $hamavg = 0; |
906 |
|
|
+my $rejectspamavg = 0; |
907 |
|
|
+ |
908 |
|
|
+my $Accepttotal = 0; |
909 |
|
|
+my $localAccepttotal = 0; #Fetchmail connections |
910 |
|
|
+my $localsendtotal = 0; #Connections from local PCs |
911 |
|
|
+my $totalexamined = 0; #total download + RBL etc |
912 |
|
|
+my $WebMailsendtotal = 0; #total from Webmail |
913 |
|
|
+my $mailmansendcount = 0; #total from mailman |
914 |
|
|
+my %sendtotalbyhour = (); |
915 |
|
|
+my %localLANbyhour = (); |
916 |
|
|
+my %localacceptbyhour = (); |
917 |
|
|
+my %WebMailbyhour = (); |
918 |
|
|
+ |
919 |
|
|
+my $above15 = 0; |
920 |
|
|
+my %above15byhour = (); |
921 |
|
|
+ |
922 |
|
|
+my $RBLcount = 0; |
923 |
|
|
+my %RBLbyhour = (); |
924 |
|
|
+ |
925 |
|
|
+my $MiscDenyCount = 0; |
926 |
|
|
+my %MiscDenybyhour = (); |
927 |
|
|
+ |
928 |
|
|
+my $PatternFilterCount = 0; |
929 |
|
|
+my %patternfilterbyhour = (); |
930 |
|
|
+ |
931 |
|
|
+my $noninfectedcount = 0; |
932 |
|
|
+my $okemailcount = 0; |
933 |
|
|
+ |
934 |
|
|
+my $infectedcount = 0; |
935 |
|
|
+my %infectedbyhour = (); |
936 |
|
|
+my %found_viruses = (); |
937 |
|
|
+ |
938 |
|
|
+my %spambyhour = (); |
939 |
|
|
+my %hambyhour = (); |
940 |
|
|
+ |
941 |
|
|
+my $warnnoreject = " "; |
942 |
|
|
+my $rblnotset = ' '; |
943 |
|
|
+ |
944 |
|
|
+my $FS = "\t"; # field separator used by logterse plugin |
945 |
|
|
+my %log_items = (); |
946 |
|
|
+my $score; |
947 |
|
|
+my %timestamp_items = (); |
948 |
|
|
+my $localflag = 0; #indicate if current email is local or not |
949 |
|
|
+my $WebMailflag = 0; #indicate if current mail is send from webmail |
950 |
|
|
+ |
951 |
|
|
+# some storage for by recipient domains stats (PS) |
952 |
|
|
+# my bad : I have to deal with multiple simoultaneous connections |
953 |
|
|
+# will play with the process number. |
954 |
|
|
+# my $currentrcptdomain = '' ; |
955 |
|
|
+my %currentrcptdomain ; # temporay store the recipient domain until end of mail processing |
956 |
|
|
+my %byrcptdomain ; # Store 'by domains stats' |
957 |
|
|
+my @extdomain ; # only useful in some MX-Backup case, when any subdomains are allowed |
958 |
|
|
+my $morethanonercpt = 0 ; # count every 'second' recipients for a mail. |
959 |
|
|
+ |
960 |
|
|
+# store the domain of interest. Every other records are stored in a 'Other' zone |
961 |
|
|
+my $ddb = esmith::DomainsDB->open_ro or die "Couldn't open DomainsDB : $!\n"; |
962 |
|
|
+foreach my $domain( $ddb->get_all_by_prop( type => "domain" ) ) { |
963 |
|
|
+ $byrcptdomain{ $domain->key }{ 'type' }='local'; |
964 |
|
|
+} |
965 |
|
|
+$byrcptdomain{ esmith::ConfigDB->open_ro->get('SystemName')->value . "." |
966 |
|
|
+ . esmith::ConfigDB->open_ro->get('DomainName')->value }{ 'type' } = 'local'; |
967 |
|
|
+ |
968 |
|
|
+# is this system a MX-Backup ? |
969 |
|
|
+if (esmith::ConfigDB->open_ro->get('mxbackup')){ |
970 |
|
|
+ if ( ( esmith::ConfigDB->open_ro->get('mxbackup')->prop('status') || 'disabled' ) eq 'enabled' ) { |
971 |
|
|
+ my %MXValues = split( /,/, ( esmith::ConfigDB->open_ro->get('mxbackup')->prop('name') || '' ) ) ; |
972 |
|
|
+ foreach my $data ( keys %MXValues ) { |
973 |
|
|
+ $byrcptdomain{ $data }{ 'type' } = "mxbackup-$MXValues{ $data }" ; |
974 |
|
|
+ if ( $MXValues{ $data } == 1 ) { # subdomains allowed, must take care of this |
975 |
|
|
+ push @extdomain, $data ; |
976 |
|
|
+ } |
977 |
|
|
+ } |
978 |
|
|
+ } |
979 |
|
|
+} |
980 |
|
|
+ |
981 |
|
|
+my ( $start, $end ) = parse_arg( $opt{'start'}, $opt{'end'} ); |
982 |
|
|
+ |
983 |
|
|
+# |
984 |
|
|
+# First check current configuration for logging, DNS enable and Max threshold for spamassassin |
985 |
|
|
+# |
986 |
|
|
+ |
987 |
|
|
+#my $LogLevel = esmith::ConfigDB->open_ro->get('qpsmtpd')->prop('LogLevel'); |
988 |
|
|
+#my $LowLogLevel = ( $LogLevel < 8 ); |
989 |
|
|
+ |
990 |
|
|
+my $RHSenabled = |
991 |
|
|
+ ( esmith::ConfigDB->open_ro->get('qpsmtpd')->prop('RHSBL') eq 'enabled' ); |
992 |
|
|
+my $DNSenabled = |
993 |
|
|
+ ( esmith::ConfigDB->open_ro->get('qpsmtpd')->prop('DNSBL') eq 'enabled' ); |
994 |
|
|
+my $SARejectLevel = |
995 |
|
|
+ esmith::ConfigDB->open_ro->get('spamassassin')->prop('RejectLevel'); |
996 |
|
|
+my $SATagLevel = |
997 |
|
|
+ esmith::ConfigDB->open_ro->get('spamassassin')->prop('TagLevel'); |
998 |
|
|
+my $DomainName = |
999 |
|
|
+ esmith::ConfigDB->open_ro->get('DomainName')->value; |
1000 |
|
|
+ |
1001 |
|
|
+# check that logterse is in use |
1002 |
|
|
+#my pluginfile = '/var/service/qpsmtpd/config/peers/0'; |
1003 |
|
|
+ |
1004 |
|
|
+ |
1005 |
|
|
+ |
1006 |
|
|
+if ( !$RHSenabled || !$DNSenabled ) { |
1007 |
|
|
+ $rblnotset = '*'; |
1008 |
|
|
+} |
1009 |
|
|
+ |
1010 |
|
|
+if ( $SARejectLevel == 0 ) { |
1011 |
|
|
+ |
1012 |
|
|
+ $warnnoreject = "(*Warning* 0 = no reject)"; |
1013 |
|
|
+ |
1014 |
|
|
+} |
1015 |
|
|
+ |
1016 |
|
|
+# |
1017 |
|
|
+#--------------------------------------- |
1018 |
|
|
+# Scan the qpsmtpd log file |
1019 |
|
|
+#--------------------------------------- |
1020 |
|
|
+ |
1021 |
|
|
+ |
1022 |
|
|
+# Init the hashes |
1023 |
|
|
+my $nhour = floor( $start / 3600 ); |
1024 |
|
|
+while ( $nhour < $end / 3600 ) { |
1025 |
|
|
+ $MiscDenybyhour{$nhour}=0; |
1026 |
|
|
+ $RBLbyhour{$nhour}=0; |
1027 |
|
|
+ $above15byhour{$nhour}=0; |
1028 |
|
|
+ $patternfilterbyhour{$nhour}=0; |
1029 |
|
|
+ $WebMailbyhour{$nhour}=0; |
1030 |
|
|
+ $nhour++; |
1031 |
|
|
+} |
1032 |
|
|
+ |
1033 |
|
|
+my $starttai = Time::TAI64::unixtai64n($start); |
1034 |
|
|
+my $endtai = Time::TAI64::unixtai64n($end); |
1035 |
|
|
+ |
1036 |
|
|
+LINE: while (<>) { |
1037 |
|
|
+ my($tai,$log) = split(' ',$_,2); |
1038 |
|
|
+ |
1039 |
|
|
+ |
1040 |
|
|
+ #If date specified, only process lines matching date |
1041 |
|
|
+ next LINE if ( $tai lt $starttai ); |
1042 |
|
|
+ last if ( $tai gt $endtai ); |
1043 |
|
|
+ |
1044 |
|
|
+ #only select Logterse output |
1045 |
|
|
+ next LINE unless m/terse plugin/; |
1046 |
|
|
+ |
1047 |
|
|
+ |
1048 |
|
|
+ my $abstime = Time::TAI64::tai2unix($tai); |
1049 |
|
|
+ my $abshour = floor( $abstime / 3600 ); # Hours since the epoch |
1050 |
|
|
+ |
1051 |
|
|
+ |
1052 |
|
|
+ my ($timestamp_part, $log_part) = split '`'; |
1053 |
|
|
+ my (@log_items) = split $FS, $log_part; |
1054 |
|
|
+ |
1055 |
|
|
+ my (@timestamp_items) = split(' ',$timestamp_part); |
1056 |
|
|
+ |
1057 |
|
|
+ # we store the more recent recipient domain, for domain statistics |
1058 |
|
|
+ # in fact, we only store the first recipient. Could be sort of headhache |
1059 |
|
|
+ # to obtain precise stats with many recipients on more than one domain ! |
1060 |
|
|
+ my $proc = $timestamp_items[1] ; #numeric Id for the email |
1061 |
|
|
+ |
1062 |
|
|
+ $totalexamined++; |
1063 |
|
|
+ |
1064 |
|
|
+ # first spot the fetchmail and local deliveries. |
1065 |
|
|
+ |
1066 |
|
|
+ # print '<'.$log_items[1].'><'.$log_items[5].'><'.$log_items[8].">\n"; |
1067 |
|
|
+ |
1068 |
|
|
+ # Spot from local workstation |
1069 |
|
|
+ $localflag = 0; |
1070 |
|
|
+ $WebMailflag=0; |
1071 |
|
|
+ if ($log_items[1] =~ m/.*$DomainName.*/) {$localsendtotal++;$localLANbyhour{$abshour}++;$localflag=1} |
1072 |
|
|
+ # see if from localhost |
1073 |
|
|
+ elsif ($log_items[1] =~ m/.*$localhost.*/){ |
1074 |
|
|
+ # but not if it comes from fetchmail |
1075 |
|
|
+# print $log_items[3]."\n"; |
1076 |
|
|
+ if ($log_items[3] =~ m/.*$FETCHMAIL.*/){} |
1077 |
|
|
+ else { |
1078 |
|
|
+ # might still be from mailman here |
1079 |
|
|
+# print "got webmail\n"; |
1080 |
|
|
+ if ($log_items[3] =~ m/.*$MAILMAN.*/){$mailmansendcount++;$localsendtotal++;$localLANbyhour{$abshour}++;$localflag=1} |
1081 |
|
|
+ else { |
1082 |
|
|
+ # eliminate incoming localhost spoofs |
1083 |
|
|
+ if ($log_items[8] =~ m/.*msg denied before queued.*/){} |
1084 |
|
|
+ else {$localflag = 1;$WebMailsendtotal++;$WebMailbyhour{$abshour}++;$WebMailflag=1} |
1085 |
|
|
+ } |
1086 |
|
|
+ } |
1087 |
|
|
+ } |
1088 |
|
|
+ |
1089 |
|
|
+ # try to spot fetchmail emails |
1090 |
|
|
+ if ($log_items[0] =~ m/.*$FetchmailIP.*/) {$localAccepttotal++;$localacceptbyhour{$abshour}++} |
1091 |
|
|
+ elsif ($log_items[3] =~ m/.*$FETCHMAIL.*/) {$localAccepttotal++;$localacceptbyhour{$abshour}++} |
1092 |
|
|
+ |
1093 |
|
|
+ |
1094 |
|
|
+ # and adjust for recipient field if not set-up by denying plugin - extract from deny msg |
1095 |
|
|
+ |
1096 |
|
|
+ if (length($log_items[4])==0) { |
1097 |
|
|
+ if ($log_items[5] eq 'check_goodrcptto') { |
1098 |
|
|
+ if ($log_items[7] gt "invalid recipient") { |
1099 |
|
|
+ $log_items[4] = substr($log_items[7],18) #Leave only email address |
1100 |
|
|
+ } |
1101 |
|
|
+ } |
1102 |
|
|
+ } |
1103 |
|
|
+ |
1104 |
|
|
+ |
1105 |
|
|
+ |
1106 |
|
|
+ if ( ( $currentrcptdomain{ $proc } || '' ) eq '' ) { |
1107 |
|
|
+ $currentrcptdomain{ $proc } = lc($log_items[4]) ; |
1108 |
|
|
+ $currentrcptdomain{ $proc } =~ s/.*@//; |
1109 |
|
|
+ |
1110 |
|
|
+ |
1111 |
|
|
+ |
1112 |
|
|
+# print $proc,$log_items[4]."\n"; |
1113 |
|
|
+ |
1114 |
|
|
+ $currentrcptdomain{ $proc } =~ s/[^\w\-\.]//g ; |
1115 |
|
|
+ |
1116 |
|
|
+# print $currentrcptdomain{ $proc }."\n"; |
1117 |
|
|
+ |
1118 |
|
|
+ my $NotableDomain = 0 ; |
1119 |
|
|
+ if ( defined ( $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'type' } ) ) { |
1120 |
|
|
+ $NotableDomain = 1 ; |
1121 |
|
|
+ } else { |
1122 |
|
|
+ foreach ( @extdomain ) { |
1123 |
|
|
+ if ( $currentrcptdomain{ $proc } =~ m/$_$/ ) { |
1124 |
|
|
+ $NotableDomain = 1 ; |
1125 |
|
|
+ last ; |
1126 |
|
|
+ } |
1127 |
|
|
+ } |
1128 |
|
|
+ } |
1129 |
|
|
+ if ( !$NotableDomain ) { |
1130 |
|
|
+ # check for outgoing email |
1131 |
|
|
+ if ($localflag==1) {$currentrcptdomain{ $proc } = 'Outgoing'} |
1132 |
|
|
+ else {$currentrcptdomain{ $proc } = 'Others'} |
1133 |
|
|
+ } else { |
1134 |
|
|
+ if ($localflag==1) {$currentrcptdomain{ $proc } = 'Internal'} |
1135 |
|
|
+ } |
1136 |
|
|
+ $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'total' }++ ; |
1137 |
|
|
+ } else { |
1138 |
|
|
+ # there more than a recipient for a mail, how many daily ? |
1139 |
|
|
+ $morethanonercpt++; |
1140 |
|
|
+ } |
1141 |
|
|
+ |
1142 |
|
|
+ # then categorise the result |
1143 |
|
|
+ if (exists $log_items[5]) { |
1144 |
|
|
+ #Check for badly formed lines (from earlier testing) |
1145 |
|
|
+ |
1146 |
|
|
+ if ($log_items[5] eq 'check_earlytalker') {$MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1147 |
|
|
+ |
1148 |
|
|
+ if ($log_items[5] eq 'check_relay') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1149 |
|
|
+ |
1150 |
|
|
+ if ($log_items[5] eq 'check_norelay') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1151 |
|
|
+ |
1152 |
|
|
+ if ($log_items[5] eq 'require_resolvable_fromhost') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1153 |
|
|
+ |
1154 |
|
|
+ if ($log_items[5] eq 'check_basicheaders') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1155 |
|
|
+ |
1156 |
|
|
+ if ($log_items[5] eq 'rhsbl') { $RBLcount++;$RBLbyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1157 |
|
|
+ |
1158 |
|
|
+ if ($log_items[5] eq 'dnsbl') { $RBLcount++;$RBLbyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1159 |
|
|
+ |
1160 |
|
|
+ if ($log_items[5] eq 'check_badmailfrom') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1161 |
|
|
+ |
1162 |
|
|
+ if ($log_items[5] eq 'check_badrcptto_patterns') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1163 |
|
|
+ |
1164 |
|
|
+ if ($log_items[5] eq 'check_badrcptto') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1165 |
|
|
+ |
1166 |
|
|
+ if ($log_items[5] eq 'check_spamhelo') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1167 |
|
|
+ |
1168 |
|
|
+ if ($log_items[5] eq 'check_goodrcptto extn') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1169 |
|
|
+ |
1170 |
|
|
+ if ($log_items[5] eq 'rcpt_ok') { $MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1171 |
|
|
+ |
1172 |
|
|
+ if ($log_items[5] eq 'pattern_filter') { $PatternFilterCount++;$patternfilterbyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1173 |
|
|
+ |
1174 |
|
|
+ if ($log_items[5] eq 'virus::pattern_filter') { $PatternFilterCount++;$patternfilterbyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1175 |
|
|
+ |
1176 |
|
|
+ if ($log_items[5] eq 'check_goodrcptto') {$MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1177 |
|
|
+ |
1178 |
|
|
+ if ($log_items[5] eq 'check_smtp_forward') {$MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1179 |
|
|
+ |
1180 |
|
|
+ if ($log_items[5] eq 'count_unrecognized_commands') {$MiscDenyCount++;$MiscDenybyhour{$abshour}++;mark_domain_rejected($proc);next LINE} |
1181 |
|
|
+ |
1182 |
|
|
+ if ($log_items[5] eq 'tnef2mime') { next LINE} #Not expecting this one. |
1183 |
|
|
+ |
1184 |
|
|
+ if ($log_items[5] eq 'spamassassin') { $above15++;$above15byhour{$abshour}++; |
1185 |
|
|
+ # and extract the spam score |
1186 |
|
|
+ if ($log_items[8] =~ "Yes, hits=(.*) required=([0-9\.]+)") {$rejectspamavg += $1} |
1187 |
|
|
+ mark_domain_rejected($proc); |
1188 |
|
|
+ next LINE |
1189 |
|
|
+ } |
1190 |
|
|
+ |
1191 |
|
|
+ if ($log_items[5] eq 'virus::clamav') { $infectedcount++;$infectedbyhour{$abshour}++; |
1192 |
|
|
+ #extract the virus name |
1193 |
|
|
+ if ($log_items[7] =~ "Virus Found: (.*)" ) {$found_viruses{$1}++;} |
1194 |
|
|
+ mark_domain_rejected($proc); |
1195 |
|
|
+ next LINE |
1196 |
|
|
+ } |
1197 |
|
|
+ |
1198 |
|
|
+ if ($log_items[5] eq 'queued') { $Accepttotal++; |
1199 |
|
|
+ #extract the spam score |
1200 |
|
|
+ if ($log_items[8] =~ ".*hits=(.*) required=([0-9\.]+)") { |
1201 |
|
|
+ $score = $1; |
1202 |
|
|
+# print $log_items[8]."<".$score.">\n"; |
1203 |
|
|
+ if ($score < $SATagLevel) { $hamcount++;$hambyhour{$abshour}++;$hamavg += $score} |
1204 |
|
|
+ else {$spamcount++;$spambyhour{$abshour}++;$spamavg += $score} |
1205 |
|
|
+ } |
1206 |
|
|
+ if ( ( $currentrcptdomain{ $proc } || '' ) ne '' ) { |
1207 |
|
|
+ $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'accept' }++ ; |
1208 |
|
|
+ $currentrcptdomain{ $proc } = '' ; |
1209 |
|
|
+ } |
1210 |
|
|
+ next LINE |
1211 |
|
|
+ } |
1212 |
|
|
+ |
1213 |
|
|
+ print $log_items[5]."\n"; #Not detected |
1214 |
|
|
+ |
1215 |
|
|
+ } |
1216 |
|
|
+ |
1217 |
|
|
+ |
1218 |
|
|
+ |
1219 |
|
|
+} |
1220 |
|
|
+ |
1221 |
|
|
+my $QueryNoLogTerse = ($totalexamined==0); #might indicate logterse not installed in qpsmtpd plugins |
1222 |
|
|
+ |
1223 |
|
|
+#Calculate some numbers |
1224 |
|
|
+ |
1225 |
|
|
+$spamavg = $spamavg / $spamcount if $spamcount; |
1226 |
|
|
+$rejectspamavg = $rejectspamavg / $above15 if $above15; |
1227 |
|
|
+$hamavg = $hamavg / $hamcount if $hamcount; |
1228 |
|
|
+ |
1229 |
|
|
+# RBL etc percent of total SMTP sessions |
1230 |
|
|
+ |
1231 |
|
|
+my $rblpercent = ( ( $RBLcount / $totalexamined ) * 100 ) if $totalexamined; |
1232 |
|
|
+my $PatternFilterpercent = ( ( $PatternFilterCount / $totalexamined ) * 100 ) if $totalexamined; |
1233 |
|
|
+my $Miscpercent = ( ( $MiscDenyCount / $totalexamined ) * 100 ) if $totalexamined; |
1234 |
|
|
+ |
1235 |
|
|
+#Spam and virus percent of total email downloaded |
1236 |
|
|
+#Expressed as a % of total examined |
1237 |
|
|
+my $spampercent = ( ( $spamcount / $totalexamined ) * 100 ) if $totalexamined; |
1238 |
|
|
+my $hampercent = ( ( $hamcount / $totalexamined ) * 100 ) if $totalexamined; |
1239 |
|
|
+my $hrsinperiod = ( ( $end - $start ) / 3600 ); |
1240 |
|
|
+my $emailperhour = ( $totalexamined / $hrsinperiod ) if $totalexamined; |
1241 |
|
|
+my $above15percent = ( $above15 / $totalexamined * 100 ) if $totalexamined; |
1242 |
|
|
+my $infectedpercent = ( ( $infectedcount / ($totalexamined) ) * 100 ) if $totalexamined; |
1243 |
|
|
+my $AcceptPercent = ( ( $Accepttotal / ($totalexamined) ) * 100 ) if $totalexamined; |
1244 |
|
|
+ |
1245 |
|
|
+my $oldfh; |
1246 |
|
|
+ |
1247 |
|
|
+#Open Sendmail if we are mailing it |
1248 |
|
|
+if ( $opt{'mail'} && !$disabled ) { |
1249 |
|
|
+ open( SENDMAIL, "|$opt{'sendmail'} -oi -t -odq" ) |
1250 |
|
|
+ or die "Can't open sendmail: $!\n"; |
1251 |
|
|
+ print SENDMAIL "From: $opt{'from'}\n"; |
1252 |
|
|
+ print SENDMAIL "To: $opt{'mail'}\n"; |
1253 |
|
|
+ print SENDMAIL "Subject: Spam Filter Statistics from $hostname - ", |
1254 |
|
|
+ strftime( "%F", localtime($start) ), "\n\n"; |
1255 |
|
|
+ $oldfh = select SENDMAIL; |
1256 |
|
|
+} |
1257 |
|
|
+ |
1258 |
|
|
+my $telapsed = time - $tstart; |
1259 |
|
|
+ |
1260 |
|
|
+if ( !$disabled ) { |
1261 |
|
|
+ |
1262 |
|
|
+ #Output results |
1263 |
|
|
+ print "SMEServer daily Anti-Virus and Spamfilter statistics", "\n"; |
1264 |
|
|
+ print "----------------------------------------------------", "\n\n"; |
1265 |
|
|
+ |
1266 |
|
|
+ print "$0 Version : $opt{'version'}", "\n\n"; |
1267 |
|
|
+ print "Period Beginning : ", strftime( "%c", localtime($start) ), "\n"; |
1268 |
|
|
+ print "Period Ending : ", strftime( "%c", localtime($end) ), "\n"; |
1269 |
|
|
+ print "\n"; |
1270 |
|
|
+ |
1271 |
|
|
+ print "Clam Version : ", `freshclam -V`; |
1272 |
|
|
+ print "SpamAssassin Version : ", `spamassassin -V`; |
1273 |
|
|
+ printf "Tag level: %3d; Reject level: %3d $warnnoreject\n", $SATagLevel, |
1274 |
|
|
+ $SARejectLevel; |
1275 |
|
|
+ |
1276 |
|
|
+ print "\n"; |
1277 |
|
|
+ printf "Reporting Period : %.2f hrs\n", $hrsinperiod; |
1278 |
|
|
+ print "----------------------------\n"; |
1279 |
|
|
+ print "\n"; |
1280 |
|
|
+ |
1281 |
|
|
+ printf "All SMTP connections accepted : %8d \n", $totalexamined; |
1282 |
|
|
+ |
1283 |
|
|
+ if ($localAccepttotal>0) { |
1284 |
|
|
+ printf "Connections from Fetchmail : %8d \n", |
1285 |
|
|
+ $localAccepttotal; |
1286 |
|
|
+ } |
1287 |
|
|
+ |
1288 |
|
|
+ if ($WebMailsendtotal>0) { |
1289 |
|
|
+ printf "Emails sent from WebMail : %8d \n", |
1290 |
|
|
+ $WebMailsendtotal; |
1291 |
|
|
+ } |
1292 |
|
|
+ |
1293 |
|
|
+ if ($mailmansendcount > 0) { |
1294 |
|
|
+ printf "Emails sent from Mailman : %8d \n", |
1295 |
|
|
+ $mailmansendcount; |
1296 |
|
|
+ } |
1297 |
|
|
+ |
1298 |
|
|
+ printf "SMTP from local workstations : %8d \n\n", $localsendtotal; |
1299 |
|
|
+ |
1300 |
|
|
+ |
1301 |
|
|
+ printf "RBL rejected : %8d (%6.2f%%)\n", $RBLcount, |
1302 |
|
|
+ $rblpercent || 0; |
1303 |
|
|
+ printf "Pattern filter rejected : %8d (%6.2f%%)\n", |
1304 |
|
|
+ $PatternFilterCount, $PatternFilterpercent || 0; |
1305 |
|
|
+ printf "Rejected due to non conformance : %8d (%6.2f%%)\n", $MiscDenyCount, |
1306 |
|
|
+ $Miscpercent || 0; |
1307 |
|
|
+ |
1308 |
|
|
+ printf "Infected by Virus : %8d (%6.2f%%)\n", $infectedcount, |
1309 |
|
|
+ $infectedpercent || 0; |
1310 |
|
|
+ |
1311 |
|
|
+ printf "Spam rejected (over reject level): %8d (%6.2f%%)\n", $above15, |
1312 |
|
|
+ $above15percent || 0; |
1313 |
|
|
+ printf "Spam detected (over tag level) : %8d (%6.2f%%)\n", $spamcount, |
1314 |
|
|
+ $spampercent || 0; |
1315 |
|
|
+ printf "Ham detected (under tag level) : %8d (%6.2f%%)\n", $hamcount, |
1316 |
|
|
+ $hampercent || 0; |
1317 |
|
|
+ print " --------------------\n"; |
1318 |
|
|
+ printf "Total emails accepted : %8d (%6.2f%%)\n", $Accepttotal, |
1319 |
|
|
+ $AcceptPercent || 0; |
1320 |
|
|
+ |
1321 |
|
|
+ printf "Emails per hour : (%8.1f/hr)\n", $emailperhour || 0; |
1322 |
|
|
+ print "\n"; |
1323 |
|
|
+ printf "Average spam score (accepted): %11.2f\n", $spamavg || 0; |
1324 |
|
|
+ printf "Average spam score (rejected): %11.2f\n", $rejectspamavg || 0; |
1325 |
|
|
+ printf "Average ham score : %11.2f\n", $hamavg || 0; |
1326 |
|
|
+ print "\n"; |
1327 |
|
|
+ print "Statistics by Hour\n"; |
1328 |
|
|
+ if ($localAccepttotal>0) { |
1329 |
|
|
+ print "------------------------------------------------------------------------------------------------- \n"; |
1330 |
|
|
+ print |
1331 |
|
|
+ "Hour Fetchml Local WebMail Virus Spam Ham RBL/DNS$rblnotset Execut. Non.Conf.\n"; |
1332 |
|
|
+ print "-------------- -------- -------- -------- -------- -------- -------- -------- -------- ---------\n"; |
1333 |
|
|
+ |
1334 |
|
|
+ my $hour = floor( $start / 3600 ); |
1335 |
|
|
+ while ( $hour < $end / 3600 ) { |
1336 |
|
|
+ printf( |
1337 |
|
|
+ "%s %8d %8d %8d %8d %8d %8d %8d %8d %8d\n", |
1338 |
|
|
+ strftime( "%F, %H", localtime( $hour * 3600 ) ), |
1339 |
|
|
+ $localacceptbyhour{$hour} || 0, |
1340 |
|
|
+ $localLANbyhour{$hour} || 0, |
1341 |
|
|
+ $WebMailbyhour{$hour} || 0, |
1342 |
|
|
+ $infectedbyhour{$hour} || 0, |
1343 |
|
|
+ $spambyhour{$hour} || 0, |
1344 |
|
|
+ $hambyhour{$hour} || 0, |
1345 |
|
|
+ $RBLbyhour{$hour} || 0, |
1346 |
|
|
+ $patternfilterbyhour{$hour} || 0, |
1347 |
|
|
+ $MiscDenybyhour{$hour} || 0 |
1348 |
|
|
+ ); |
1349 |
|
|
+ $hour++; |
1350 |
|
|
+ } |
1351 |
|
|
+ print "------------------------------------------------------------------------------------------------- \n"; |
1352 |
|
|
+ |
1353 |
|
|
+ } else { |
1354 |
|
|
+ print "---------------------------------------------------------------------------------------- \n"; |
1355 |
|
|
+ print |
1356 |
|
|
+ "Hour Local WebMail Virus Spam Ham RBL/DNS$rblnotset Execut. Non.Conf.\n"; |
1357 |
|
|
+ print "--------------- -------- -------- -------- -------- -------- -------- -------- --------- \n"; |
1358 |
|
|
+ |
1359 |
|
|
+ my $hour = floor( $start / 3600 ); |
1360 |
|
|
+ while ( $hour < $end / 3600 ) { |
1361 |
|
|
+ printf( |
1362 |
|
|
+ "%s %8d %8d %8d %8d %8d %8d %8d %8d\n", |
1363 |
|
|
+ strftime( "%F, %H", localtime( $hour * 3600 ) ), |
1364 |
|
|
+ $localLANbyhour{$hour} || 0, |
1365 |
|
|
+ $WebMailbyhour{$hour} || 0, |
1366 |
|
|
+ $infectedbyhour{$hour} || 0, |
1367 |
|
|
+ $spambyhour{$hour} || 0, |
1368 |
|
|
+ $hambyhour{$hour} || 0, |
1369 |
|
|
+ $RBLbyhour{$hour} || 0, |
1370 |
|
|
+ $patternfilterbyhour{$hour} || 0, |
1371 |
|
|
+ $MiscDenybyhour{$hour} || 0 |
1372 |
|
|
+ ); |
1373 |
|
|
+ $hour++; |
1374 |
|
|
+ } |
1375 |
|
|
+ |
1376 |
|
|
+ print "---------------------------------------------------------------------------------------- \n"; |
1377 |
|
|
+ |
1378 |
|
|
+ } |
1379 |
|
|
+ if ($localAccepttotal>0) { |
1380 |
|
|
+ print "*Fetchml* means connections from Fetchmail delivering email\n"; |
1381 |
|
|
+ } |
1382 |
|
|
+ print "*Local* means connections from workstations on local LAN.\n"; |
1383 |
|
|
+ print "*Non\.Conf\.* means sending mailserver did not conform to correct protocol.\n"; |
1384 |
|
|
+ print " or email was to non existant address.\n"; |
1385 |
|
|
+ print "\n"; |
1386 |
|
|
+ |
1387 |
|
|
+ if ($QueryNoLogTerse) { |
1388 |
|
|
+ print "* - as no records where found, it looks as though you may not have the *logterse* \nplugin running as part of qpsmtpd \n"; |
1389 |
|
|
+# print " to enable it follow the instructions at .............................\n"; |
1390 |
|
|
+ } |
1391 |
|
|
+ |
1392 |
|
|
+ |
1393 |
|
|
+ if ( !$RHSenabled || !$DNSenabled ) { |
1394 |
|
|
+ |
1395 |
|
|
+ # comment about RBL not set |
1396 |
|
|
+ print |
1397 |
|
|
+"* - This means that one or more of the possible spam black listing services\n that are available have not been enabled.\n"; |
1398 |
|
|
+ print " You have not enabled:\n"; |
1399 |
|
|
+ |
1400 |
|
|
+ if ( !$RHSenabled ) { |
1401 |
|
|
+ print " RHSBL\n"; |
1402 |
|
|
+ } |
1403 |
|
|
+ |
1404 |
|
|
+ if ( !$DNSenabled ) { |
1405 |
|
|
+ print " DNSBL\n"; |
1406 |
|
|
+ } |
1407 |
|
|
+ |
1408 |
|
|
+ |
1409 |
|
|
+ print " To enable these you can use the following commands:\n"; |
1410 |
|
|
+ if ( !$RHSenabled ) { |
1411 |
|
|
+ print " config setprop qpsmtpd RHSBL enabled\n"; |
1412 |
|
|
+ } |
1413 |
|
|
+ |
1414 |
|
|
+ if ( !$DNSenabled ) { |
1415 |
|
|
+ print " config setprop qpsmtpd DNSBL enabled\n"; |
1416 |
|
|
+ } |
1417 |
|
|
+ |
1418 |
|
|
+ # there so much templates to expand... (PS) |
1419 |
|
|
+ print " Followed by:\n signal-event email-update and\n svc -t /service/qpsmtpd\n\n"; |
1420 |
|
|
+ } |
1421 |
|
|
+ |
1422 |
|
|
+# if ($Webmailsendtotal > 0) {print "If you have the mailman contrib installed, then the webmail totals might include some mailman emails\n"} |
1423 |
|
|
+ |
1424 |
|
|
+ # time to do a 'by recipient domain' report |
1425 |
|
|
+ print "\nIncoming mails by recipient domains usage\n"; |
1426 |
|
|
+ print "-----------------------------------------\n"; |
1427 |
|
|
+ print |
1428 |
|
|
+ "Domains Type Total Denied XferErr Accept \%accept\n"; |
1429 |
|
|
+ print |
1430 |
|
|
+ "---------------------------- ---------- ------ ------ ------- ------ -------\n"; |
1431 |
|
|
+ my %total = ( |
1432 |
|
|
+ total => 0, |
1433 |
|
|
+ deny => 0, |
1434 |
|
|
+ xfer => 0, |
1435 |
|
|
+ accept => 0, |
1436 |
|
|
+ ); |
1437 |
|
|
+ foreach my $domain ( |
1438 |
|
|
+ sort { |
1439 |
|
|
+ join( "\.", reverse( split /\./, $a ) ) cmp |
1440 |
|
|
+ join( "\.", reverse( split /\./, $b ) ) |
1441 |
|
|
+ } keys %byrcptdomain |
1442 |
|
|
+ ) |
1443 |
|
|
+ { |
1444 |
|
|
+ next if ( ( $byrcptdomain{$domain}{'total'} || 0 ) == 0 ); |
1445 |
|
|
+ my $tp = $byrcptdomain{$domain}{'type'} || 'other'; |
1446 |
|
|
+ my $to = $byrcptdomain{$domain}{'total'} || 0; |
1447 |
|
|
+ my $de = $byrcptdomain{$domain}{'deny'} || 0; |
1448 |
|
|
+ my $xr = $byrcptdomain{$domain}{'xfer'} || 0; |
1449 |
|
|
+ my $ac = $byrcptdomain{$domain}{'accept'} || 0; |
1450 |
|
|
+ printf "%-28s %-10s %6d %6d %7d %6d %6.2f%%\n", $domain, $tp, $to, |
1451 |
|
|
+ $de, $xr, $ac, $ac * 100 / $to; |
1452 |
|
|
+ $total{'total'} += $to; |
1453 |
|
|
+ $total{'deny'} += $de; |
1454 |
|
|
+ $total{'xfer'} += $xr; |
1455 |
|
|
+ $total{'accept'} += $ac; |
1456 |
|
|
+ } |
1457 |
|
|
+ print |
1458 |
|
|
+ "---------------------------- ---------- ------ ------- ------ ------ -------\n"; |
1459 |
|
|
+ |
1460 |
|
|
+ # $total{ 'total' } can be equal to 0, bad for divisions... |
1461 |
|
|
+ my $perc1 = 0; |
1462 |
|
|
+ my $perc2 = 0; |
1463 |
|
|
+ if ( $total{'total'} != 0 ) { |
1464 |
|
|
+ $perc1 = $total{'accept'} * 100 / $total{'total'}; |
1465 |
|
|
+ $perc2 = ( ( $total{'total'} + $morethanonercpt ) / $total{'total'} ); |
1466 |
|
|
+ } |
1467 |
|
|
+ printf |
1468 |
|
|
+ "Total %6d %6d %7d %6d %6.2f%%\n\n", |
1469 |
|
|
+ $total{'total'}, $total{'deny'}, $total{'xfer'}, $total{'accept'}, |
1470 |
|
|
+ $perc1; |
1471 |
|
|
+ printf |
1472 |
|
|
+ "%d mails were processed for %d Recipients\nThe average recipients by mail is %4.2f\n\n", |
1473 |
|
|
+ $total{'total'}, ( $total{'total'} + $morethanonercpt ), $perc2; |
1474 |
|
|
+ |
1475 |
|
|
+ if ( $infectedcount > 0 ) { |
1476 |
|
|
+ show_virus_variants(); |
1477 |
|
|
+ } |
1478 |
|
|
+ |
1479 |
|
|
+} # not disabled |
1480 |
|
|
+ |
1481 |
|
|
+List_Junkmail(); |
1482 |
|
|
+ |
1483 |
|
|
+if ( !$disabled ) { |
1484 |
|
|
+ |
1485 |
|
|
+ print "\nDone. Report generated in $telapsed sec.\n\n"; |
1486 |
|
|
+ |
1487 |
|
|
+ #Close Senmdmail if it was opened |
1488 |
|
|
+ if ( $opt{'mail'} ) { |
1489 |
|
|
+ select $oldfh; |
1490 |
|
|
+ close(SENDMAIL); |
1491 |
|
|
+ } |
1492 |
|
|
+ |
1493 |
|
|
+} |
1494 |
|
|
+ |
1495 |
|
|
+#All done |
1496 |
|
|
+exit 0; |
1497 |
|
|
+ |
1498 |
|
|
+############################################################################# |
1499 |
|
|
+# Subroutines ############################################################### |
1500 |
|
|
+############################################################################# |
1501 |
|
|
+ |
1502 |
|
|
+ |
1503 |
|
|
+######################################## |
1504 |
|
|
+# Process parms # |
1505 |
|
|
+######################################## |
1506 |
|
|
+sub parse_arg { |
1507 |
|
|
+ my $startdate = shift; |
1508 |
|
|
+ my $enddate = shift; |
1509 |
|
|
+ |
1510 |
|
|
+ my $secsinday = 86400; |
1511 |
|
|
+ my $time = 0; |
1512 |
|
|
+ |
1513 |
|
|
+ my $start = UnixDate( $startdate, "%s" ); |
1514 |
|
|
+ my $end = UnixDate( $enddate, "%s" ); |
1515 |
|
|
+ |
1516 |
|
|
+ if ( !$start && !$end ) { |
1517 |
|
|
+ $end = time; |
1518 |
|
|
+ $start = $end - $secsinday; |
1519 |
|
|
+ return ( $start, $end ); |
1520 |
|
|
+ } |
1521 |
|
|
+ |
1522 |
|
|
+ if ( !$start ) { |
1523 |
|
|
+ $start = $end - $secsinday; |
1524 |
|
|
+ return ( $start, $end ); |
1525 |
|
|
+ } |
1526 |
|
|
+ |
1527 |
|
|
+ if ( !$end ) { |
1528 |
|
|
+ $end = $start + $secsinday; |
1529 |
|
|
+ return ( $start, $end ); |
1530 |
|
|
+ } |
1531 |
|
|
+ |
1532 |
|
|
+ if ( $start > $end ) { |
1533 |
|
|
+ return ( $end, $start ); |
1534 |
|
|
+ } |
1535 |
|
|
+ |
1536 |
|
|
+ return ( $start, $end ); |
1537 |
|
|
+ |
1538 |
|
|
+} |
1539 |
|
|
+ |
1540 |
|
|
+sub dbg { |
1541 |
|
|
+ my $msg = shift; |
1542 |
|
|
+ |
1543 |
|
|
+ if ( $opt{debug} ) { |
1544 |
|
|
+ print STDERR $msg; |
1545 |
|
|
+ } |
1546 |
|
|
+} |
1547 |
|
|
+ |
1548 |
|
|
+sub List_Junkmail { |
1549 |
|
|
+ |
1550 |
|
|
+ # |
1551 |
|
|
+ # Show how many junkmails in each user's junkmail folder. |
1552 |
|
|
+ # |
1553 |
|
|
+ use esmith::AccountsDB; |
1554 |
|
|
+ my $adb = esmith::AccountsDB->open_ro; |
1555 |
|
|
+ my $entry; |
1556 |
|
|
+ foreach my $user ($adb->users) { |
1557 |
|
|
+ my $found = 0; |
1558 |
|
|
+ my $junkmail_dir = "/home/e-smith/files/users/" . |
1559 |
|
|
+ $user->key . "/Maildir/.junkmail"; |
1560 |
|
|
+# print $user->key; |
1561 |
|
|
+ foreach my $dir (qw(new cur)) { |
1562 |
|
|
+ # Now get the content list for the directory. |
1563 |
|
|
+ if (opendir( QDIR, "$junkmail_dir/$dir" )) { |
1564 |
|
|
+ while ($entry=readdir(QDIR) ) { |
1565 |
|
|
+ next if $entry =~ /^\./; |
1566 |
|
|
+ $found++; |
1567 |
|
|
+ } |
1568 |
|
|
+ |
1569 |
|
|
+ closedir(QDIR); |
1570 |
|
|
+ } |
1571 |
|
|
+ } |
1572 |
|
|
+ if ( !$disabled ) { |
1573 |
|
|
+ printf "User \"%s\" ", $user->key; |
1574 |
|
|
+ printf "- %d email(s) left in junkmail folder\n", $found; |
1575 |
|
|
+ } |
1576 |
|
|
+ } |
1577 |
|
|
+} |
1578 |
|
|
+ |
1579 |
|
|
+sub show_virus_variants |
1580 |
|
|
+ |
1581 |
|
|
+# |
1582 |
|
|
+# Show a league table of the different virus types found today |
1583 |
|
|
+# |
1584 |
|
|
+ |
1585 |
|
|
+{ |
1586 |
|
|
+ |
1587 |
|
|
+ print("Virus Statistics by name:\n"); |
1588 |
|
|
+ print("---------------------------------------------\n"); |
1589 |
|
|
+ foreach my $virus (sort { $found_viruses{$b} <=> $found_viruses{$a} } |
1590 |
|
|
+ keys %found_viruses) |
1591 |
|
|
+ { |
1592 |
|
|
+ print "Rejected $found_viruses{$virus}\t$virus\n"; |
1593 |
|
|
+ } |
1594 |
|
|
+ print("---------------------------------------------\n"); |
1595 |
|
|
+} |
1596 |
|
|
+ |
1597 |
|
|
+sub mark_domain_rejected |
1598 |
|
|
+ |
1599 |
|
|
+# |
1600 |
|
|
+# Tag domain as having a rejected email |
1601 |
|
|
+# |
1602 |
|
|
+{ |
1603 |
|
|
+my ($proc) = @_; |
1604 |
|
|
+if ( ( $currentrcptdomain{ $proc } || '' ) ne '' ) { |
1605 |
|
|
+ $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'deny' }++ ; |
1606 |
|
|
+ $currentrcptdomain{ $proc } = '' ; |
1607 |
|
|
+ } |
1608 |
|
|
} |
1609 |
|
|
\ No newline at end of file |