/[smecontribs]/rpms/smeserver-mailstats/contribs7/smeserver-mailstats-0.0.2_spamfilter-stats.patch
ViewVC logotype

Contents of /rpms/smeserver-mailstats/contribs7/smeserver-mailstats-0.0.2_spamfilter-stats.patch

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download)
Fri Feb 15 18:37:14 2008 UTC (16 years, 3 months ago) by slords
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -0 lines
FILE REMOVED
Import on branch contribs7 of package smeserver-mailstats-0.0.3-1.el4.sme.src.rpm

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

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed