X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/f3f065bbe8b7d7fdc4d46dbfa063ae4dfb05bfd7..428cdca73df1791fcba048d0f1093725d8288bd6:/src/src/eximstats.src diff --git a/src/src/eximstats.src b/src/src/eximstats.src index 88eb69fe8..5e1a0847b 100644 --- a/src/src/eximstats.src +++ b/src/src/eximstats.src @@ -1,7 +1,6 @@ -#!PERL_COMMAND -w -# $Cambridge: exim/src/src/eximstats.src,v 1.13 2007/01/31 16:52:12 ph10 Exp $ +#!PERL_COMMAND -# Copyright (c) 2001 University of Cambridge. +# Copyright (c) 2001-2017 University of Cambridge. # See the file NOTICE for conditions of use and distribution. # Perl script to generate statistics from one or more Exim log files. @@ -74,7 +73,7 @@ # 2001-10-21 Removed -domain flag and added -bydomain, -byhost, and -byemail. # We now generate our main parsing subroutine as an eval statement # which improves performance dramatically when not all the results -# are required. We also cache the last timestamp to time convertion. +# are required. We also cache the last timestamp to time conversion. # # NOTE: 'Top 50 destinations by (message count|volume)' lines are # now 'Top N (host|email|domain) destinations by (message count|volume)' @@ -143,7 +142,7 @@ # in HTML output. Also added code to convert them back with -merge. # Fixed timestamp offsets to convert to seconds rather than minutes. # Updated -merge to work with output files using timezones. -# Added cacheing to speed up the calculation of timezone offsets. +# Added caching to speed up the calculation of timezone offsets. # # 2003-02-07 V1.25 Steve Campbell # Optimised the usage of mktime() in the seconds subroutine. @@ -163,7 +162,7 @@ # Bernard Massot. # # 2003-06-03 V1.28 John Newman -# Added in the ability to skip over the parsing and evaulation of +# Added in the ability to skip over the parsing and evaluation of # specific transports as passed to eximstats via the new "-nt/.../" # command line argument. This new switch allows the viewing of # not more accurate statistics but more applicable statistics when @@ -201,7 +200,7 @@ # Added -xls and the ability to specify output files. # # 2005-04-29 V1.38 Steve Campbell -# Use FileHandles for outputing results. +# Use FileHandles for outputting results. # Allow any combination of xls, txt, and html output. # Fixed display of large numbers with -nvr option # Fixed merging of reports with empty tables. @@ -263,6 +262,30 @@ # 2007-01-31 V1.53 Philip Hazel # Allow for [pid] after date in log lines # +# 2007-02-14 V1.54 Daniel Tiefnig +# Improved the '($parent) =' pattern match. +# +# 2007-03-19 V1.55 Steve Campbell +# Differentiate between permanent and temporary rejects. +# +# 2007-03-29 V1.56 Jez Hancock +# Fixed some broken HTML links and added missing column headers. +# +# 2007-03-30 V1.57 Steve Campbell +# Fixed Grand Total Summary Domains, Edomains, and Email columns +# for Rejects, Temp Rejects, Ham, and Spam rows. +# +# 2007-04-11 V1.58 Steve Campbell +# Fix to get <> and blackhole to show in edomain tables. +# +# 2007-09-20 V1.59 Steve Campbell +# Added the -bylocaldomain option +# +# 2007-09-20 V1.60 Heiko Schlittermann +# Fix for misinterpreted log lines +# +# 2013-01-14 V1.61 Steve Campbell +# Watch out for senders sending "HELO [IpAddr]" # # # For documentation on the logfile format, see @@ -367,7 +390,7 @@ Useful for finding out which of your mailing lists are receiving mail. Show the delivery times (B
)for all the messages. -Exim must have been configured to use the +delivery_time logging option +Exim must have been configured to use the +deliver_time logging option for this option to work. I is an optional list of times. Eg -show_dt1,2,4,8 will show @@ -510,7 +533,7 @@ about how to create charts from the tables. =head1 AUTHOR -There is a web site at http://www.exim.org - this contains details of the +There is a website at https://www.exim.org - this contains details of the mailing list exim-users@exim.org. =head1 TO DO @@ -518,19 +541,29 @@ mailing list exim-users@exim.org. This program does not perfectly handle messages whose received and delivered log lines are in different files, which can happen when you have multiple mail servers and a message cannot be -immeadiately delivered. Fixing this could be tricky... +immediately delivered. Fixing this could be tricky... Merging of xls files is not (yet) possible. Be free to implement :) =cut +use warnings; use integer; +BEGIN { pop @INC if $INC[-1] eq '.' }; use strict; use IO::File; +use File::Basename; # use Time::Local; # PH/FANF use POSIX; +if (@ARGV and $ARGV[0] eq '--version') { + print basename($0) . ": $0\n", + "build: EXIM_RELEASE_VERSIONEXIM_VARIANT_VERSION\n", + "perl(runtime): $]\n"; + exit 0; +} + use vars qw($HAVE_GD_Graph_pie $HAVE_GD_Graph_linespoints $HAVE_Spreadsheet_WriteExcel); eval { require GD::Graph::pie; }; $HAVE_GD_Graph_pie = $@ ? 0 : 1; @@ -561,7 +594,7 @@ use vars qw($WEEK $DAY $HOUR $MINUTE); @days_per_month = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334); $gig = 1024 * 1024 * 1024; -$VERSION = '1.53'; +$VERSION = '1.61'; # How much space do we allow for the Hosts/Domains/Emails/Edomains column headers? $COLUMN_WIDTHS = 8; @@ -575,9 +608,9 @@ $WEEK = 7 * $DAY; use vars qw($total_received_data $total_received_data_gigs $total_received_count); use vars qw($total_delivered_data $total_delivered_data_gigs $total_delivered_messages $total_delivered_addresses); use vars qw(%timestamp2time); #Hash of timestamp => time. -use vars qw($last_timestamp $last_time); #The last time convertion done. -use vars qw($last_date $date_seconds); #The last date convertion done. -use vars qw($last_offset $offset_seconds); #The last time offset convertion done. +use vars qw($last_timestamp $last_time); #The last time conversion done. +use vars qw($last_date $date_seconds); #The last date conversion done. +use vars qw($last_offset $offset_seconds); #The last time offset conversion done. use vars qw($localtime_offset); use vars qw($i); #General loop counter. use vars qw($debug); #Debug mode? @@ -589,8 +622,9 @@ use vars qw($spam_score $spam_score_gigs); use vars qw($ham_score $ham_score_gigs); use vars qw(%ham_count_by_ip %spam_count_by_ip); use vars qw(%rejected_count_by_ip %rejected_count_by_reason); +use vars qw(%temporarily_rejected_count_by_ip %temporarily_rejected_count_by_reason); -#For use in Speadsheed::WriteExcel +#For use in Spreadsheet::WriteExcel use vars qw($workbook $ws_global $ws_relayed $ws_errors); use vars qw($row $col $row_hist $col_hist); use vars qw($run_hist); @@ -604,7 +638,7 @@ $ntopchart = 5; # The following are parameters whose values are # set by command line switches: use vars qw($show_errors $show_relay $show_transport $transport_pattern); -use vars qw($topcount $local_league_table $include_remote_users); +use vars qw($topcount $local_league_table $include_remote_users $do_local_domain); use vars qw($hist_opt $hist_interval $hist_number $volume_rounding $emptyOK); use vars qw($relay_pattern @queue_times @user_patterns @user_descriptions); use vars qw(@rcpt_times @delivery_times); @@ -623,6 +657,7 @@ use vars qw(%received_count %received_data %received_data_gigs); use vars qw(%delivered_messages %delivered_data %delivered_data_gigs %delivered_addresses); use vars qw(%received_count_user %received_data_user %received_data_gigs_user); use vars qw(%delivered_messages_user %delivered_addresses_user %delivered_data_user %delivered_data_gigs_user); +use vars qw(%delivered_messages_local_domain %delivered_addresses_local_domain %delivered_data_local_domain %delivered_data_gigs_local_domain); use vars qw(%transported_count %transported_data %transported_data_gigs); use vars qw(%relayed %errors_count $message_errors); use vars qw(@qt_all_bin @qt_remote_bin); @@ -732,8 +767,8 @@ sub volume_rounded { } else { # We don't want any rounding to be done. - # and we don't need broken formated output which on one hand avoids numbers from - # being interpreted as string by Spreadsheed Calculators, on the other hand + # and we don't need broken formatted output which on one hand avoids numbers from + # being interpreted as string by Spreadsheet Calculators, on the other hand # breaks if more than 4 digits! -> flexible length instead of fixed length # Format the return value at the output routine! -fh #$rounded = sprintf("%d", ($g * $gig) + $x); @@ -846,10 +881,10 @@ $p; # Eg 3h20m5s => 12005 ####################################################################### sub unformat_time { - my($formated_time) = pop @_; + my($formatted_time) = pop @_; my $time = 0; - while ($formated_time =~ s/^(\d+)([wdhms]?)//) { + while ($formatted_time =~ s/^(\d+)([wdhms]?)//) { $time += $1 if ($2 eq '' || $2 eq 's'); $time += $1 * 60 if ($2 eq 'm'); $time += $1 * 60 * 60 if ($2 eq 'h'); @@ -869,6 +904,7 @@ sub unformat_time { # POSIX::mktime. We expect the timestamp to be of the form # "$year-$mon-$day $hour:$min:$sec", with month going from 1 to 12, # and the year to be absolute (we do the necessary conversions). The +# seconds value can be followed by decimals, which we ignore. The # timestamp may be followed with an offset from UTC like "+$hh$mm"; if the # offset is not present, and we have not been told that the log is in UTC # (with the -utc option), then we adjust the time by the current local @@ -892,7 +928,7 @@ sub seconds { # Is the timestamp the same as the last one? return $last_time if ($last_timestamp eq $timestamp); - return 0 unless ($timestamp =~ /^((\d{4})\-(\d\d)-(\d\d))\s(\d\d):(\d\d):(\d\d)( ([+-])(\d\d)(\d\d))?/o); + return 0 unless ($timestamp =~ /^((\d{4})\-(\d\d)-(\d\d))\s(\d\d):(\d\d):(\d\d)(?:\.\d+)?( ([+-])(\d\d)(\d\d))?/o); unless ($last_date eq $1) { $last_date = $1; @@ -903,8 +939,8 @@ sub seconds { } my $time = $date_seconds + ($5 * 3600) + ($6 * 60) + $7; - # SC. Use cacheing. Also note we want seconds not minutes. - #my($this_offset) = ($10 * 60 + $11) * ($9 . "1") if defined $8; + # SC. Use caching. Also note we want seconds not minutes. + #my($this_offset) = ($10 * 60 + $12) * ($9 . "1") if defined $8; if (defined $8 && ($8 ne $last_offset)) { $last_offset = $8; $offset_seconds = ($10 * 60 + $11) * 60; @@ -912,7 +948,7 @@ sub seconds { } - if (defined $7) { + if (defined $8) { #$time -= $this_offset; $time -= $offset_seconds; } elsif (defined $localtime_offset) { @@ -1346,7 +1382,8 @@ sub print_league_table { # Generate the printf formats and table headers. ################################################ my(@headers) = ('Messages'); - push(@headers,'Addresses') if defined $a_count; + #push(@headers,'Addresses') if defined $a_count; + push(@headers,'Addresses') if defined $a_count && %$a_count; push(@headers,'Bytes','Average') if defined $m_data; my $txt_format = "%10s " x @headers . " %s\n"; @@ -1368,7 +1405,7 @@ sub print_league_table { EoText - print $htm_col_headers; + print $htm_fh $htm_col_headers } if ($xls_fh) { @@ -1467,7 +1504,7 @@ EoText
EoText - print $htm_col_headers; + print $htm_fh $htm_col_headers; } if ($xls_fh) { $spreadsheet->write(${$row_sref}++, 0, $title, $f_header2); @@ -1624,7 +1661,7 @@ sub top_n_sort { # Create a dummy hash entry for the key if required. # Note that setting the dummy_hash value sets it for both href2 & - # href3. Also note that currently we are guarenteed to have a real + # href3. Also note that currently we are guaranteed to have a real # value for href3 if a real value for href2 exists so don't need to # test for it as well. $dummy_hash{$key} = 0 unless exists $href2->{$key}; @@ -1768,6 +1805,7 @@ Valid options are: -bydomain show results by sending domain. -byemail show results by sender's email address -byedomain show results by sender's email domain +-bylocaldomain show results by local domain -pattern "Description" /pattern/ Count lines matching specified patterns and show them in @@ -1813,7 +1851,7 @@ sub generate_parser { my $parser = ' my($ip,$host,$email,$edomain,$domain,$thissize,$size,$old,$new); my($tod,$m_hour,$m_min,$id,$flag,$extra,$length); - my($seconds,$queued,$rcpt_time); + my($seconds,$queued,$rcpt_time,$local_domain); my $rej_id = 0; while (<$fh>) { @@ -1824,12 +1862,23 @@ sub generate_parser { $length = length($_); next if ($length < 38); - next unless /^(\\d{4}\\-\\d\\d-\\d\\d\\s(\\d\\d):(\\d\\d):\\d\\d( [-+]\\d\\d\\d\\d)?)( \\[\\d+\\])?/o; - - ($tod,$m_hour,$m_min) = ($1,$2,$3); + next unless /^ + (\\d{4}\\-\\d\\d-\\d\\d\\s # 1: YYYYMMDD HHMMSS + (\\d\\d) # 2: HH + : + (\\d\\d) # 3: MM + :\\d\\d + ) + (\\.\\d+)? # 4: subseconds + (\s[-+]\\d\\d\\d\\d)? # 5: tz-offset + (\s\\[\\d+\\])? # 6: pid + /ox; + + $tod = defined($5) ? $1 . $5 : $1; + ($m_hour,$m_min) = ($2,$3); # PH - watch for GMT offsets in the timestamp. - if (defined($4)) { + if (defined($5)) { $extra = 6; next if ($length < 44); } @@ -1837,9 +1886,15 @@ sub generate_parser { $extra = 0; } + # watch for subsecond precision + if (defined($4)) { + $extra += length($4); + next if ($length < 38 + $extra); + } + # PH - watch for PID added after the timestamp. - if (defined($5)) { - $extra += length($5); + if (defined($6)) { + $extra += length($6); next if ($length < 38 + $extra); } @@ -1899,13 +1954,23 @@ sub generate_parser { # "H=Host (UnverifiedHost) [IpAddr]" or "H=(UnverifiedHost) [IpAddr]". # We do 2 separate matches to keep the matches simple and fast. # Host is local unless otherwise specified. - $ip = (/\\bH=.*?(\\[[^]]+\\])/) ? $1 : "local"; + # Watch out for "H=([IpAddr])" in case they send "[IpAddr]" as their HELO! + $ip = (/\\bH=(?:|.*? )(\\[[^]]+\\])/) ? $1 + # 2008-03-31 06:25:22 Connection from [213.246.33.217]:39456 refused: too many connections from that IP address // .hs + : (/Connection from (\[\S+\])/) ? $1 + # 2008-03-31 06:52:40 SMTP call from mail.cacoshrf.com (ccsd02.ccsd.local) [69.24.118.229]:4511 dropped: too many nonmail commands (last was "RSET") // .hs + : (/SMTP call from .*?(\[\S+\])/) ? $1 + : "local"; $host = (/\\bH=(\\S+)/) ? $1 : "local"; $domain = "localdomain"; #Domain is localdomain unless otherwise specified. #IFDEF ($do_sender{Domain}) - if ($host !~ /^\\[/ && $host =~ /^(\\(?)[^\\.]+\\.([^\\.]+\\..*)/) { + if ($host =~ /^\\[/ || $host =~ /^[\\d\\.]+$/) { + # Host is just an IP address. + $domain = $host; + } + elsif ($host =~ /^(\\(?)[^\\.]+\\.([^\\.]+\\..*)/) { # Remove the host portion from the DNS name. We ensure that we end up # with at least xxx.yyy. $host can be "(x.y.z)" or "x.y.z". $domain = lc("$1.$2"); @@ -1927,16 +1992,25 @@ sub generate_parser { #ENDIF ($do_sender{Email}) #IFDEF ($do_sender{Edomain}) + if (/^(<>|blackhole)/) { + $edomain = $1; + } #IFDEF ($include_original_destination) - #$edomain = (/^(\S+) (<\S*?\\@(\S+)>)?/) ? $3 || $1 : ""; - $edomain = (/^(\S+ (<\S*?\\@(\S+?)>)?)/) ? $1 : ""; - chomp($edomain); - lc($edomain); + elsif (/^(\S+ (<\S*?\\@(\S+?)>)?)/) { + $edomain = $1; + chomp($edomain); + $edomain =~ s/@(\S+?)>/"@" . lc($1) . ">"/e; + } #ENDIF ($include_original_destination) - #IFNDEF ($include_original_destination) - $edomain = (/^\S*?\\@(\S+)/) ? lc($1) : ""; + elsif (/^\S*?\\@(\S+)/) { + $edomain = lc($1); + } #ENDIF ($include_original_destination) + else { + $edomain = ""; + } + #ENDIF ($do_sender{Edomain}) if ($tod lt $begin) { @@ -2076,8 +2150,19 @@ sub generate_parser { #IFNDEF ($include_original_destination) if ($user =~ /^[\\/|]/) { #ENDIF ($include_original_destination) - my($parent) = $_ =~ /(<[^@]+@?[^>]*>)/; - $user = "$user $parent" if defined $parent; + #my($parent) = $_ =~ /(<[^@]+@?[^>]*>)/; + my($parent) = $_ =~ / (<.+?>) /; #DT 1.54 + if (defined $parent) { + $user = "$user $parent"; + #IFDEF ($do_local_domain) + if ($parent =~ /\\@(.+)>/) { + $local_domain = lc($1); + ++$delivered_messages_local_domain{$local_domain}; + ++$delivered_addresses_local_domain{$local_domain}; + add_volume(\\$delivered_data_local_domain{$local_domain},\\$delivered_data_gigs_local_domain{$local_domain},$size); + } + #ENDIF ($do_local_domain) + } } ++$delivered_messages_user{$user}; ++$delivered_addresses_user{$user}; @@ -2164,7 +2249,8 @@ sub generate_parser { #IFNDEF ($include_original_destination) if ($user =~ /^[\\/|]/) { #ENDIF ($include_original_destination) - my($parent) = $_ =~ /(<[^@]+@?[^>]*>)/; + #my($parent) = $_ =~ /(<[^@]+@?[^>]*>)/; + my($parent) = $_ =~ / (<.+?>) /; #DT 1.54 $user = "$user $parent" if defined $parent; } ++$delivered_addresses_user{$user}; @@ -2285,9 +2371,21 @@ sub generate_parser { # rejected EHLO from my.test.net [10.0.0.5]: syntactically invalid argument(s): # rejected EHLO from [10.0.0.6]: syntactically invalid argument(s): $ip = $1 if ($ip eq "local" && /^rejected [HE][HE]LO from .*?(\[.+?\]):/); - ++$rejected_count_by_ip{$ip}; if (/SpamAssassin/) { ++$rejected_count_by_reason{"Rejected by SpamAssassin"}; + ++$rejected_count_by_ip{$ip}; + } + elsif ( + /(temporarily rejected [A-Z]*) .*?(: .*?)(:|\s*$)/ + ) { + ++$temporarily_rejected_count_by_reason{"\u$1$2"}; + ++$temporarily_rejected_count_by_ip{$ip}; + } + elsif ( + /(temporarily refused connection)/ + ) { + ++$temporarily_rejected_count_by_reason{"\u$1"}; + ++$temporarily_rejected_count_by_ip{$ip}; } elsif ( /(listed at [^ ]+)/ || @@ -2299,6 +2397,7 @@ sub generate_parser { # 2005-09-23 15:07:49 1EInHJ-0007Ex-Au H=(a.b.c) [10.0.0.1] F=<> rejected after DATA: This message contains a virus: (Eicar-Test-Signature) please scan your system. # 2005-10-06 10:50:07 1ENRS3-0000Nr-Kt => blackhole (DATA ACL discarded recipients): This message contains a virus: (Worm.SomeFool.P) please scan your system. / rejected after DATA: (.*)/ || + / (rejected DATA: .*)/ || /.DATA ACL discarded recipients.: (.*)/ || /rejected after DATA: (unqualified address not permitted)/ || /(VRFY rejected)/ || @@ -2314,18 +2413,20 @@ sub generate_parser { # local_scan() function crashed with signal %d - message temporarily rejected # local_scan() function timed out - message temporarily rejected /(local_scan.. function .* - message temporarily rejected)/ || - /(temporarily refused connection)/ || # SMTP protocol synchronization error (input sent without waiting for greeting): rejected connection from %s /(SMTP protocol .*?(error|violation))/ || /(message too big)/ ) { ++$rejected_count_by_reason{"\u$1"}; + ++$rejected_count_by_ip{$ip}; } elsif (/rejected [HE][HE]LO from [^:]*: syntactically invalid argument/) { ++$rejected_count_by_reason{"Rejected HELO/EHLO: syntactically invalid argument"}; + ++$rejected_count_by_ip{$ip}; } elsif (/response to "RCPT TO.*? was: (.*)/) { ++$rejected_count_by_reason{"Response to RCPT TO was: $1"}; + ++$rejected_count_by_ip{$ip}; } elsif ( /(lookup of host )\S+ (failed)/ || @@ -2353,9 +2454,19 @@ sub generate_parser { /: (Connection refused)()/ ) { ++$rejected_count_by_reason{"\u$1$2"}; + ++$rejected_count_by_ip{$ip}; + } + elsif ( + # 2008-03-31 06:25:22 H=mail.densitron.com [216.70.140.224]:45386 temporarily rejected connection in "connect" ACL: too fast reconnects // .hs + # 2008-03-31 06:25:22 H=mail.densitron.com [216.70.140.224]:45386 temporarily rejected connection in "connect" ACL // .hs + /(temporarily rejected connection in .*?ACL:?.*)/ + ) { + ++$temporarily_rejected_count_by_ip{$ip}; + ++$temporarily_rejected_count_by_reason{"\u$1"}; } else { ++$rejected_count_by_reason{Unknown}; + ++$rejected_count_by_ip{$ip}; print STDERR "Unknown rejection: $_" if $debug; } } @@ -2432,9 +2543,9 @@ sub print_header { if ($htm_fh) { print $htm_fh html_header($title); print $htm_fh ""; - $sender_txt_format .= " " x ($COLUMN_WIDTHS - 5) . "%6d"; + $sender_html_format .= ""; + $sender_txt_format .= " " x ($COLUMN_WIDTHS - 5) . "%6s"; push(@col_headers,"${_}s"); } @@ -2538,7 +2654,7 @@ sub print_grandtotals { print $txt_fh " TOTAL Volume Messages Addresses $sender_txt_header Delayed Failed\n"; } if ($htm_fh) { - print $htm_fh "\n"; + print $htm_fh "\n"; print $htm_fh "

Grand total summary

\n"; print $htm_fh "
%d%s
\n"; print $htm_fh "\n"; @@ -2612,12 +2728,17 @@ sub print_grandtotals { } if ($merge_reports) { - foreach ('Rejects', 'Ham', 'Spam') { + foreach ('Rejects', 'Temp Rejects', 'Ham', 'Spam') { my $messages = get_report_total($report_totals{$_},'Messages'); my $addresses = get_report_total($report_totals{$_},'Addresses'); if ($messages) { @content = ($_, '', $messages, ''); push(@content,get_report_total($report_totals{$_},'Hosts')) if $do_sender{Host}; + #These rows do not have entries for the following columns (if specified) + foreach ('Domain','Email','Edomain') { + push(@content,'') if $do_sender{$_}; + } + printf $txt_fh ("$txt_format1\n", @content) if $txt_fh; printf $htm_fh ("$htm_format1\n", @content) if $htm_fh; $ws_global->write(++$row, 0, \@content) if $xls_fh; @@ -2626,15 +2747,24 @@ sub print_grandtotals { } else { foreach my $total_aref (['Rejects',\%rejected_count_by_ip], + ['Temp Rejects',\%temporarily_rejected_count_by_ip], ['Ham',\%ham_count_by_ip], ['Spam',\%spam_count_by_ip]) { + #Count the number of messages of this type. my $messages = 0; map {$messages += $_} values %{$total_aref->[1]}; if ($messages > 0) { @content = ($total_aref->[0], '', $messages, ''); + + #Count the number of distinct IPs for the Hosts column. push(@content,scalar(keys %{$total_aref->[1]})) if $do_sender{Host}; + #These rows do not have entries for the following columns (if specified) + foreach ('Domain','Email','Edomain') { + push(@content,'') if $do_sender{$_}; + } + printf $txt_fh ("$txt_format1\n", @content) if $txt_fh; printf $htm_fh ("$htm_format1\n", @content) if $htm_fh; $ws_global->write(++$row, 0, \@content) if $xls_fh; @@ -2665,7 +2795,7 @@ sub print_user_patterns { print $txt_fh "\n Total\n"; } if ($htm_fh) { - print $htm_fh "

User Specified Patterns

\n"; + print $htm_fh "

User Specified Patterns

\n"; print $htm_fh "
" . join('',@col_headers) . "At least one addr
Delayed
At least one addr
Failed
\n"; print $htm_fh "
\n"; print $htm_fh "\n"; @@ -2812,7 +2942,7 @@ sub print_transport { print $txt_fh "\n Volume Messages\n"; } if ($htm_fh) { - print $htm_fh "

Deliveries by Transport

\n"; + print $htm_fh "

Deliveries by Transport

\n"; print $htm_fh "
\n"; print $htm_fh "\n"; } @@ -3138,7 +3268,7 @@ sub parse_old_eximstat_reports { add_to_totals($report_totals{Delivered},['Addresses'],$tmp{Messages}); } } - elsif (/(Rejects|Ham|Spam)\s+(.*?)\s*$/) { + elsif (/(Temp Rejects|Rejects|Ham|Spam)\s+(.*?)\s*$/) { print STDERR "Parsing $_" if $debug; add_to_totals($report_totals{$1},['Messages','Hosts'],$2); } @@ -3258,8 +3388,8 @@ sub parse_old_eximstat_reports { my $previous_seconds_on_queue = 0; if (/^\s*(Under|Over|)\s+(\d+[smhdw])\s+(\d+)/) { print STDERR "Parsing $_" if $debug; - my($modifier,$formated_time,$count) = ($1,$2,$3); - my $seconds = unformat_time($formated_time); + my($modifier,$formatted_time,$count) = ($1,$2,$3); + my $seconds = unformat_time($formatted_time); my $time_on_queue = ($seconds + $previous_seconds_on_queue) / 2; $previous_seconds_on_queue = $seconds; $time_on_queue = $seconds * 2 if ($modifier eq 'Over'); @@ -3350,6 +3480,12 @@ sub parse_old_eximstat_reports { $data_href = \%delivered_data_user; $data_gigs_href = \%delivered_data_gigs_user; } + elsif ($category =~ /local domain destination/) { + $messages_href = \%delivered_messages_local_domain; + $addresses_href = \%delivered_addresses_local_domain; + $data_href = \%delivered_data_local_domain; + $data_gigs_href = \%delivered_data_gigs_local_domain; + } elsif ($category =~ /(\S+) destination/) { #Top 50 (host|domain|email|edomain) destinations #Top (host|domain|email|edomain) destination @@ -3358,12 +3494,18 @@ sub parse_old_eximstat_reports { $data_href = \%{$delivered_data{"\u$1"}}; $data_gigs_href = \%{$delivered_data_gigs{"\u$1"}}; } + elsif ($category =~ /temporarily rejected ips/) { + $messages_href = \%temporarily_rejected_count_by_ip; + } elsif ($category =~ /rejected ips/) { $messages_href = \%rejected_count_by_ip; } elsif ($category =~ /non-rejected spamming ips/) { $messages_href = \%spam_count_by_ip; } + elsif ($category =~ /mail temporary rejection reasons/) { + $messages_href = \%temporarily_rejected_count_by_reason; + } elsif ($category =~ /mail rejection reasons/) { $messages_href = \%rejected_count_by_reason; } @@ -3562,7 +3704,7 @@ sub update_relayed { # # add_to_totals(\%totals,\@keys,$values); # -# Given a line of space seperated values, add them into the provided hash using @keys +# Given a line of space separated values, add them into the provided hash using @keys # as the hash keys. # # If the value contains a '%', then the value is set rather than added. Otherwise, we @@ -3592,7 +3734,7 @@ sub add_to_totals { # # line_to_hash(\%hash,\@keys,$line); # -# Given a line of space seperated values, set them into the provided hash +# Given a line of space separated values, set them into the provided hash # using @keys as the hash keys. ####################################################################### sub line_to_hash { @@ -3658,7 +3800,7 @@ sub html2txt { # until we've got all of the argument. # # This isn't perfect as all white space gets reduced to one space, -# but it's as good as we can get! If it's esential that spacing +# but it's as good as we can get! If it's essential that spacing # be preserved precisely, then you get that by not using shell # variables. ####################################################################### @@ -3700,7 +3842,7 @@ sub set_worksheet_line { ####################################################################### # @rcpt_times = parse_time_list($string); # -# Parse a comma seperated list of time values in seconds given by +# Parse a comma separated list of time values in seconds given by # the user and fill an array. # # Return a default list if $string is undefined. @@ -3809,6 +3951,7 @@ while (@ARGV > 0 && substr($ARGV[0], 0, 1) eq '-') { elsif ($ARGV[0] =~ /^-byemail$/) { $do_sender{Email} = 1 } elsif ($ARGV[0] =~ /^-byemaildomain$/) { $do_sender{Edomain} = 1 } elsif ($ARGV[0] =~ /^-byedomain$/) { $do_sender{Edomain} = 1 } + elsif ($ARGV[0] =~ /^-bylocaldomain$/) { $do_local_domain = 1 } elsif ($ARGV[0] =~ /^-emptyok$/) { $emptyOK = 1 } elsif ($ARGV[0] =~ /^-nvr$/) { $volume_rounding = 0 } elsif ($ARGV[0] =~ /^-show_rt([,\d\+\-\*\/]+)?$/) { @rcpt_times = parse_time_list($1) } @@ -3959,7 +4102,7 @@ $message_errors = 0; $begin = "9999-99-99 99:99:99"; $end = "0000-00-00 00:00:00"; my($section,$type); -foreach $section ('Received','Delivered','Rejects','Ham','Spam') { +foreach $section ('Received','Delivered','Temp Rejects', 'Rejects','Ham','Spam') { foreach $type ('Volume','Messages','Delayed','Failed','Hosts','Domains','Emails','Edomains') { $report_totals{$section}{$type} = 0; } @@ -4051,14 +4194,16 @@ print_relay() if $show_relay; # Print the league tables, if topcount isn't zero. if ($topcount > 0) { - my($ws_rej, $ws_top50, $ws_rej_row, $ws_top50_row); - $ws_rej_row = $ws_top50_row = 0; + my($ws_rej, $ws_top50, $ws_rej_row, $ws_top50_row, $ws_temp_rej, $ws_temp_rej_row); + $ws_rej_row = $ws_temp_rej_row = $ws_top50_row = 0; if ($xls_fh) { $ws_top50 = $workbook->addworksheet('Deliveries'); $ws_rej = $workbook->addworksheet('Rejections') if (%rejected_count_by_reason || %rejected_count_by_ip || %spam_count_by_ip); + $ws_temp_rej = $workbook->addworksheet('Temporary Rejections') if (%temporarily_rejected_count_by_reason || %temporarily_rejected_count_by_ip); } print_league_table("mail rejection reason", \%rejected_count_by_reason, undef, undef, undef, $ws_rej, \$ws_rej_row) if %rejected_count_by_reason; + print_league_table("mail temporary rejection reason", \%temporarily_rejected_count_by_reason, undef, undef, undef, $ws_temp_rej, \$ws_temp_rej_row) if %temporarily_rejected_count_by_reason; foreach ('Host','Domain','Email','Edomain') { next unless $do_sender{$_}; @@ -4072,8 +4217,10 @@ if ($topcount > 0) { print_league_table("\l$_ destination", $delivered_messages{$_}, $delivered_addresses{$_}, $delivered_data{$_},$delivered_data_gigs{$_}, $ws_top50, \$ws_top50_row); } print_league_table("local destination", \%delivered_messages_user, \%delivered_addresses_user, \%delivered_data_user,\%delivered_data_gigs_user, $ws_top50, \$ws_top50_row) if (($local_league_table || $include_remote_users) && %delivered_messages_user); + print_league_table("local domain destination", \%delivered_messages_local_domain, \%delivered_addresses_local_domain, \%delivered_data_local_domain,\%delivered_data_gigs_local_domain, $ws_top50, \$ws_top50_row) if (($local_league_table || $include_remote_users) && %delivered_messages_local_domain); print_league_table("rejected ip", \%rejected_count_by_ip, undef, undef, undef, $ws_rej, \$ws_rej_row) if %rejected_count_by_ip; + print_league_table("temporarily rejected ip", \%temporarily_rejected_count_by_ip, undef, undef, undef, $ws_rej, \$ws_rej_row) if %temporarily_rejected_count_by_ip; print_league_table("non-rejected spamming ip", \%spam_count_by_ip, undef, undef, undef, $ws_rej, \$ws_rej_row) if %spam_count_by_ip; }
 VolumeMessages