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 --- smeserver-mailstats-0.0.2/root/usr/bin/spamfilter-stats-7.pl 2007-10-11 16:39:34.000000000 -0400 +++ mezzanine_patched_smeserver-mailstats-0.0.2/root/usr/bin/spamfilter-stats-7.pl 2007-10-11 16:39:19.000000000 -0400 @@ -73,7 +73,8 @@ # - Add in loglevel check # - parameterise email address for report # 0.6.15 - bjr - fix columns included in totals -# - sort out domains when more that one email address in recipient field +# - sort out domains when more that one email address in recipient field +# 0.6.16 - cb - fix date range bug (http://bugs.contribs.org/show_bug.cgi?id=3366) # # TODO # ---- @@ -123,15 +124,10 @@ #Configuration section my %opt = (); -$opt{'version'} = '0.6.15'; # please update at each change. +$opt{'version'} = '0.6.16'; # please update at each change. $opt{'debug'} = 0; # guess what ? $opt{'sendmail'} = '/usr/sbin/sendmail'; # Path to sendmail stub $opt{'from'} = 'spamfilter-stats'; # Who is the mail from -$opt{'end'} = `date --iso-8601`; # midnight today -my $yesterday = $opt{ 'end' }; -$yesterday =~ s/\-//g ; -$yesterday--; -$opt{'start'} = `date --iso-8601 -d $yesterday`; # midnight yesterday #$opt{'mail'} = "admin"; - set from db now... $opt{'timezone'} = `date +%z`; Date_Init("TZ=$opt{'timezone'}"); @@ -143,7 +139,7 @@ my $MAILMAN = "bounces"; #sender when mailman sending when orig is localhost my $MinCol = 8; #Minimum column width -my $HourColWidth = 16; #Date and time column width +my $HourColWidth = 16; #Date and time column width my $SARulethresholdPercent = 10; #If Sa rules less than this of total emails, then cutoff reduced my $maxcutoff = 1; #max percent cutoff applied @@ -176,10 +172,10 @@ my %found_SARules = (); # replaced by... -my %counts = (); #Hold all counts in 2-D matrix -my @display = (); #used to switch on and off columns - yes, no or auto for each category +my %counts = (); #Hold all counts in 2-D matrix +my @display = (); #used to switch on and off columns - yes, no or auto for each category my @colwidth = (); #width of each column - #(auto means only if non zero) - populated from possible db entries + #(auto means only if non zero) - populated from possible db entries my @finaldisplay = (); #final decision on display or not - true or false my $disabled; @@ -202,7 +198,7 @@ my $CATTOTALS='TOTALS'; my $CATPERCENT='PERCENT'; my @categs = ($CATHOUR,$CATFETCHMAIL,$CATWEBMAIL,$CATMAILMAN,$CATLOCAL,$CATVIRUS,$CATRBLDNS,$CATEXECUT,$CATNONCONF,$CATSPAMDEL,$CATSPAM,$CATHAM,$CATTOTALS,$CATPERCENT); -my $GRANDTOTAL = '99'; #subs for count arrays, for grand total +my $GRANDTOTAL = '99'; #subs for count arrays, for grand total my $PERCENT = '98'; # for column percentages my $categlen = @categs-2; #-2 to avoid the total and percent column @@ -217,7 +213,7 @@ my $warnnoreject = " "; my $rblnotset = ' '; -my $FS = "\t"; # field separator used by logterse plugin +my $FS = "\t"; # field separator used by logterse plugin my %log_items = (); my $score; my %timestamp_items = (); @@ -246,15 +242,15 @@ if ( ( esmith::ConfigDB->open_ro->get('mxbackup')->prop('status') || 'disabled' ) eq 'enabled' ) { my %MXValues = split( /,/, ( esmith::ConfigDB->open_ro->get('mxbackup')->prop('name') || '' ) ) ; foreach my $data ( keys %MXValues ) { - $byrcptdomain{ $data }{ 'type' } = "mxbackup-$MXValues{ $data }" ; + $byrcptdomain{ $data }{ 'type' } = "mxbackup-$MXValues{ $data }" ; if ( $MXValues{ $data } == 1 ) { # subdomains allowed, must take care of this - push @extdomain, $data ; + push @extdomain, $data ; } } } } -my ( $start, $end ) = parse_arg( $opt{'start'}, $opt{'end'} ); +my ( $start, $end ) = parse_arg(); # # First check current configuration for logging, DNS enable and Max threshold for spamassassin @@ -309,13 +305,13 @@ my $nhour = floor( $start / 3600 ); my $ncateg; while ( $nhour < $end / 3600 ) { - $counts{$nhour}=(); + $counts{$nhour}=(); $ncateg = 0; - while ( $ncateg < @categs) { - $counts{$nhour}{$categs[$ncateg-1]} = 0; - $ncateg++ - } - $nhour++; + while ( $ncateg < @categs) { + $counts{$nhour}{$categs[$ncateg-1]} = 0; + $ncateg++ + } + $nhour++; } # and grand totals and display status from db entries, and column widths $ncateg = 0; @@ -374,11 +370,11 @@ # we store the more recent recipient domain, for domain statistics # in fact, we only store the first recipient. Could be sort of headhache # to obtain precise stats with many recipients on more than one domain ! - my $proc = $timestamp_items[1] ; #numeric Id for the email + my $proc = $timestamp_items[1] ; #numeric Id for the email - $totalexamined++; + $totalexamined++; - # first spot the fetchmail and local deliveries. + # first spot the fetchmail and local deliveries. # print '<'.$log_items[1].'><'.$log_items[5].'><'.$log_items[8].">\n"; @@ -411,54 +407,54 @@ # and adjust for recipient field if not set-up by denying plugin - extract from deny msg if (length($log_items[4])==0) { - if ($log_items[5] eq 'check_goodrcptto') { - if ($log_items[7] gt "invalid recipient") { - $log_items[4] = substr($log_items[7],18) #Leave only email address - } - } - } - - if ( ( $currentrcptdomain{ $proc } || '' ) eq '' ) { - # reduce to lc and only take first email address in a list - my $recipientmail = lc($log_items[4]); - if ($recipientmail =~ m/.*,/) { - #comma - $recipientmail =~ m/(.*),/; - $currentrcptdomain{ $proc } = $1; - } else { - $currentrcptdomain{ $proc } = lc($log_items[4]) - } - #split to just domain bit. - $currentrcptdomain{ $proc } =~ s/.*@//; - $currentrcptdomain{ $proc } =~ s/[^\w\-\.]//g ; - $currentrcptdomain{ $proc } =~ s/>//g ; - -# print $currentrcptdomain{ $proc }."\n"; - - my $NotableDomain = 0 ; - if ( defined ( $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'type' } ) ) { - $NotableDomain = 1 ; - } else { - foreach ( @extdomain ) { - if ( $currentrcptdomain{ $proc } =~ m/$_$/ ) { - $NotableDomain = 1 ; - last ; - } - } - } - if ( !$NotableDomain ) { - # check for outgoing email - if ($localflag==1) {$currentrcptdomain{ $proc } = 'Outgoing'} - else {$currentrcptdomain{ $proc } = 'Others'} - } else { - if ($localflag==1) {$currentrcptdomain{ $proc } = 'Internal'} - } - $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'total' }++ ; - } else { - # there more than a recipient for a mail, how many daily ? - $morethanonercpt++; - } - + if ($log_items[5] eq 'check_goodrcptto') { + if ($log_items[7] gt "invalid recipient") { + $log_items[4] = substr($log_items[7],18) #Leave only email address + } + } + } + + if ( ( $currentrcptdomain{ $proc } || '' ) eq '' ) { + # reduce to lc and only take first email address in a list + my $recipientmail = lc($log_items[4]); + if ($recipientmail =~ m/.*,/) { + #comma + $recipientmail =~ m/(.*),/; + $currentrcptdomain{ $proc } = $1; + } else { + $currentrcptdomain{ $proc } = lc($log_items[4]) + } + #split to just domain bit. + $currentrcptdomain{ $proc } =~ s/.*@//; + $currentrcptdomain{ $proc } =~ s/[^\w\-\.]//g ; + $currentrcptdomain{ $proc } =~ s/>//g ; + +# print $currentrcptdomain{ $proc }."\n"; + + my $NotableDomain = 0 ; + if ( defined ( $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'type' } ) ) { + $NotableDomain = 1 ; + } else { + foreach ( @extdomain ) { + if ( $currentrcptdomain{ $proc } =~ m/$_$/ ) { + $NotableDomain = 1 ; + last ; + } + } + } + if ( !$NotableDomain ) { + # check for outgoing email + if ($localflag==1) {$currentrcptdomain{ $proc } = 'Outgoing'} + else {$currentrcptdomain{ $proc } = 'Others'} + } else { + if ($localflag==1) {$currentrcptdomain{ $proc } = 'Internal'} + } + $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'total' }++ ; + } else { + # there more than a recipient for a mail, how many daily ? + $morethanonercpt++; + } + # then categorise the result @@ -532,8 +528,8 @@ $hamcount++;$counts{$abshour}{$CATHAM}++; } if ( ( $currentrcptdomain{ $proc } || '' ) ne '' ) { - $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'accept' }++ ; - $currentrcptdomain{ $proc } = '' ; + $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'accept' }++ ; + $currentrcptdomain{ $proc } = '' ; } next LINE } @@ -547,20 +543,20 @@ #total up grand total Columns $nhour = floor( $start / 3600 ); while ( $nhour < $end / 3600 ) { - $ncateg = 0; #past the where it came from columns - while ( $ncateg < @categs) { - #total columns - $counts{$GRANDTOTAL}{$categs[$ncateg]} += $counts{$nhour}{$categs[$ncateg]}; + $ncateg = 0; #past the where it came from columns + while ( $ncateg < @categs) { + #total columns + $counts{$GRANDTOTAL}{$categs[$ncateg]} += $counts{$nhour}{$categs[$ncateg]}; # and total rows if ( $ncateg < $categlen && $ncateg>=$countfromhere) {#skip initial columns of non final reasons $counts{$nhour}{$categs[@categs-2]} += $counts{$nhour}{$categs[$ncateg]}; } - $ncateg++ - } - - $nhour++; -} + $ncateg++ + } + + $nhour++; +} @@ -573,15 +569,15 @@ } #compute column percentages - $ncateg = 0; - while ( $ncateg < @categs) { - if ($ncateg == @categs-1) { - $counts{$PERCENT}{$categs[$ncateg]} = $counts{$GRANDTOTAL}{$categs[$ncateg-1]}*100/$totalexamined if $totalexamined; - } else { - $counts{$PERCENT}{$categs[$ncateg]} = $counts{$GRANDTOTAL}{$categs[$ncateg]}*100/$totalexamined if $totalexamined; + $ncateg = 0; + while ( $ncateg < @categs) { + if ($ncateg == @categs-1) { + $counts{$PERCENT}{$categs[$ncateg]} = $counts{$GRANDTOTAL}{$categs[$ncateg-1]}*100/$totalexamined if $totalexamined; + } else { + $counts{$PERCENT}{$categs[$ncateg]} = $counts{$GRANDTOTAL}{$categs[$ncateg]}*100/$totalexamined if $totalexamined; } - $ncateg++ - } + $ncateg++ + } #compute sum of row percentages $nhour = floor( $start / 3600 ); @@ -657,7 +653,7 @@ print "----------------------------\n"; print "\n"; - printf "All SMTP connections accepted:%8d \n", $totalexamined; + printf "All SMTP connections accepted:%8d \n", $totalexamined; # # if ($localAccepttotal>0) { # printf "Connections from Fetchmail : %8d \n", @@ -666,13 +662,13 @@ # # if ($WebMailsendtotal>0) { # printf "Emails sent from WebMail : %8d \n", -# $WebMailsendtotal; +# $WebMailsendtotal; # } # # if ($mailmansendcount > 0) { # printf "Emails sent from Mailman : %8d \n", -# $mailmansendcount; -# } +# $mailmansendcount; +# } # # printf "SMTP from local workstations : %8d \n\n", $localsendtotal; # @@ -706,12 +702,12 @@ print "\n"; print "Statistics by Hour\n"; - # - # start by working out which colunns to show - tag the display array - # - $ncateg = 1; ##skip the first column - $finaldisplay[0] = $true; - while ( $ncateg < $categlen) { + # + # start by working out which colunns to show - tag the display array + # + $ncateg = 1; ##skip the first column + $finaldisplay[0] = $true; + while ( $ncateg < $categlen) { if ($display[$ncateg] eq 'yes') { $finaldisplay[$ncateg] = $true } elsif ($display[$ncateg] eq 'no') { $finaldisplay[$ncateg] = $false } else { @@ -722,77 +718,77 @@ } } - $ncateg++ - } + $ncateg++ + } #make sure total and percentages are shown $finaldisplay[@categs-2] = $true; $finaldisplay[@categs-1] = $true; - + # and put together the print lines # - my $Line1; #Full Line across the page - my $Line2; #Broken Line across the page - my $Titles; #Column headers - my $Values; #Values - my $Totals; #Corresponding totals + my $Line1; #Full Line across the page + my $Line2; #Broken Line across the page + my $Titles; #Column headers + my $Values; #Values + my $Totals; #Corresponding totals my $Percent; # and column percentages my $hour = floor( $start / 3600 ); - $Line1 = ''; - $Line2 = ''; - $Titles = ''; - $Values = ''; - $Totals = ''; - $Percent = ''; + $Line1 = ''; + $Line2 = ''; + $Titles = ''; + $Values = ''; + $Totals = ''; + $Percent = ''; while ( $hour < $end / 3600 ) { - if ($hour == floor( $start / 3600 )){ - #Do all the once only things - $ncateg = 0; - while ( $ncateg < @categs) { + if ($hour == floor( $start / 3600 )){ + #Do all the once only things + $ncateg = 0; + while ( $ncateg < @categs) { if ($finaldisplay[$ncateg]){ - $Line1 .= substr('---------------------',0,$colwidth[$ncateg]); - $Line2 .= substr('---------------------',0,$colwidth[$ncateg]-1); - $Line2 .= " "; - $Titles .= sprintf('%'.($colwidth[$ncateg]-1).'s',$categs[$ncateg])." "; + $Line1 .= substr('---------------------',0,$colwidth[$ncateg]); + $Line2 .= substr('---------------------',0,$colwidth[$ncateg]-1); + $Line2 .= " "; + $Titles .= sprintf('%'.($colwidth[$ncateg]-1).'s',$categs[$ncateg])." "; if ($ncateg == 0) { $Totals .= substr('TOTALS ',0,$colwidth[$ncateg]-2); $Percent .= substr('PERCENTAGES ',0,$colwidth[$ncateg]-1); } else { # identify bottom right group and supress unless db->ShowGranPerc set if ($ncateg==@categs-1){ - $Totals .= sprintf('%'.$colwidth[$ncateg].'.1f',$counts{$GRANDTOTAL}{$categs[$ncateg]}).'%'; - } else { - $Totals .= sprintf('%'.$colwidth[$ncateg].'d',$counts{$GRANDTOTAL}{$categs[$ncateg]}); - } - $Percent .= sprintf('%'.($colwidth[$ncateg]-1).'.1f',$counts{$PERCENT}{$categs[$ncateg]}).'%'; - } + $Totals .= sprintf('%'.$colwidth[$ncateg].'.1f',$counts{$GRANDTOTAL}{$categs[$ncateg]}).'%'; + } else { + $Totals .= sprintf('%'.$colwidth[$ncateg].'d',$counts{$GRANDTOTAL}{$categs[$ncateg]}); + } + $Percent .= sprintf('%'.($colwidth[$ncateg]-1).'.1f',$counts{$PERCENT}{$categs[$ncateg]}).'%'; + } } - $ncateg++ - } - } - - $ncateg = 0; - while ( $ncateg < @categs) { - if ($finaldisplay[$ncateg]){ - if ($ncateg == 0) { - $Values .= strftime( "%F, %H", localtime( $hour * 3600 ) )." " - } elsif ($ncateg == @categs-1) { - #percentages in last column - $Values .= sprintf('%'.($colwidth[$ncateg]-2).'.1f',$counts{$hour}{$categs[$ncateg]})."%"; - } else { - #body numbers - $Values .= sprintf('%'.($colwidth[$ncateg]-1).'d',$counts{$hour}{$categs[$ncateg]})." "; - } - if (($ncateg == @categs-1)){$Values=$Values."\n"} #&& ($hour == floor($end / 3600)-1) - } - $ncateg++ - } - - $hour++; - } + $ncateg++ + } + } - # print it. + $ncateg = 0; + while ( $ncateg < @categs) { + if ($finaldisplay[$ncateg]){ + if ($ncateg == 0) { + $Values .= strftime( "%F, %H", localtime( $hour * 3600 ) )." " + } elsif ($ncateg == @categs-1) { + #percentages in last column + $Values .= sprintf('%'.($colwidth[$ncateg]-2).'.1f',$counts{$hour}{$categs[$ncateg]})."%"; + } else { + #body numbers + $Values .= sprintf('%'.($colwidth[$ncateg]-1).'d',$counts{$hour}{$categs[$ncateg]})." "; + } + if (($ncateg == @categs-1)){$Values=$Values."\n"} #&& ($hour == floor($end / 3600)-1) + } + $ncateg++ + } + + $hour++; + } + + # print it. print $Line1."\n"; print $Titles."\n"; print $Line2."\n"; @@ -906,24 +902,24 @@ } # get enable/disable subsections - my $enableqpsmtpdcodes; - my $enableSARules; - my $enablejunkMailList; + my $enableqpsmtpdcodes; + my $enableSARules; + my $enablejunkMailList; if (esmith::ConfigDB->open_ro->get('mailstats')){ - $enableqpsmtpdcodes = esmith::ConfigDB->open_ro->get('mailstats')->prop("QpsmtpdCodes") || "enabled" eq "enabled" || $true; - $enableSARules = esmith::ConfigDB->open_ro->get('mailstats')->prop("SARules") || "enabled" eq "enabled" || $true; - $enablejunkMailList = esmith::ConfigDB->open_ro->get('mailstats')->prop("JunkMailList") || "enabled" eq "enabled" || $true; - } else { - $enableqpsmtpdcodes = $true; - $enableSARules = $true; - $enablejunkMailList = $true; - } + $enableqpsmtpdcodes = esmith::ConfigDB->open_ro->get('mailstats')->prop("QpsmtpdCodes") || "enabled" eq "enabled" || $true; + $enableSARules = esmith::ConfigDB->open_ro->get('mailstats')->prop("SARules") || "enabled" eq "enabled" || $true; + $enablejunkMailList = esmith::ConfigDB->open_ro->get('mailstats')->prop("JunkMailList") || "enabled" eq "enabled" || $true; + } else { + $enableqpsmtpdcodes = $true; + $enableSARules = $true; + $enablejunkMailList = $true; + } if ($enableqpsmtpdcodes) {show_qpsmtpd_codes();} if ($enableSARules) {show_SARules_codes();} - if ($enablejunkMailList) {List_Junkmail();} + if ($enablejunkMailList) {List_Junkmail();} print "\nDone. Report generated in $telapsed sec.\n\n"; @@ -997,25 +993,25 @@ my $adb = esmith::AccountsDB->open_ro; my $entry; foreach my $user ($adb->users) { - my $found = 0; - my $junkmail_dir = "/home/e-smith/files/users/" . - $user->key . "/Maildir/.junkmail"; + my $found = 0; + my $junkmail_dir = "/home/e-smith/files/users/" . + $user->key . "/Maildir/.junkmail"; # print $user->key; - foreach my $dir (qw(new cur)) { + foreach my $dir (qw(new cur)) { # Now get the content list for the directory. if (opendir( QDIR, "$junkmail_dir/$dir" )) { - while ($entry=readdir(QDIR) ) { - next if $entry =~ /^\./; - $found++; - } - - closedir(QDIR); - } - } - if ( !$disabled ) { - printf "User \"%s\" ", $user->key; - printf "- %d email(s) left in junkmail folder\n", $found; - } + while ($entry=readdir(QDIR) ) { + next if $entry =~ /^\./; + $found++; + } + + closedir(QDIR); + } + } + if ( !$disabled ) { + printf "User \"%s\" ", $user->key; + printf "- %d email(s) left in junkmail folder\n", $found; + } } } @@ -1030,9 +1026,9 @@ print("Virus Statistics by name:\n"); print("---------------------------------------------\n"); foreach my $virus (sort { $found_viruses{$b} <=> $found_viruses{$a} } - keys %found_viruses) + keys %found_viruses) { - print "Rejected $found_viruses{$virus}\t$virus\n"; + print "Rejected $found_viruses{$virus}\t$virus\n"; } print("---------------------------------------------\n\n"); } @@ -1050,9 +1046,9 @@ print("Count\tPercent\tReason\t\n"); print("---------------------------------------------\n"); foreach my $qpcode (sort { $found_qpcodes{$b} <=> $found_qpcodes{$a} } - keys %found_qpcodes) + keys %found_qpcodes) { - print "$found_qpcodes{$qpcode}\t".sprintf('%4.1f',$found_qpcodes{$qpcode}*100/$totalexamined)."%\t$qpcode\n" if $totalexamined; + print "$found_qpcodes{$qpcode}\t".sprintf('%4.1f',$found_qpcodes{$qpcode}*100/$totalexamined)."%\t$qpcode\n" if $totalexamined; } print("---------------------------------------------\n\n"); } @@ -1075,21 +1071,21 @@ $defaultpercentthreshold = $mincutoff } if (esmith::ConfigDB->open_ro->get('mailstats')){ - $percentthreshold = esmith::ConfigDB->open_ro->get('mailstats')->prop("SARulePercentThreshold") || $defaultpercentthreshold; - } else { - $percentthreshold = $defaultpercentthreshold - } + $percentthreshold = esmith::ConfigDB->open_ro->get('mailstats')->prop("SARulePercentThreshold") || $defaultpercentthreshold; + } else { + $percentthreshold = $defaultpercentthreshold + } print("Spamassassin Rules:\n"); print("---------------------------------------------\n"); print("Count\tPercent\tRule\t\n"); print("---------------------------------------------\n"); foreach my $SARule (sort { $found_SARules{$b} <=> $found_SARules{$a} } - keys %found_SARules) + keys %found_SARules) { - my $percent = $found_SARules{$SARule}*100/$totalexamined if $totalexamined; - if ($percent > $percentthreshold) { - print "$found_SARules{$SARule}\t".sprintf('%4.1f',$percent)."%\t$SARule\n" if $totalexamined; - } + my $percent = $found_SARules{$SARule}*100/$totalexamined if $totalexamined; + if ($percent > $percentthreshold) { + print "$found_SARules{$SARule}\t".sprintf('%4.1f',$percent)."%\t$SARule\n" if $totalexamined; + } } print("---------------------------------------------\n\n"); } @@ -1106,4 +1102,4 @@ $byrcptdomain{ $currentrcptdomain{ $proc } }{ 'deny' }++ ; $currentrcptdomain{ $proc } = '' ; } -} \ No newline at end of file +}