EoText
- print $htm_col_headers;
+ print $htm_fh $htm_col_headers
}
if ($xls_fh) {
@@ -1470,7 +1493,7 @@ EoText
EoText
- print $htm_col_headers;
+ print $htm_fh $htm_col_headers;
}
if ($xls_fh) {
$spreadsheet->write(${$row_sref}++, 0, $title, $f_header2);
@@ -1627,7 +1650,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};
@@ -1771,6 +1794,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
@@ -1816,7 +1840,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>) {
@@ -1902,13 +1926,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");
@@ -1930,16 +1964,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) {
@@ -2081,7 +2124,17 @@ sub generate_parser {
#ENDIF ($include_original_destination)
#my($parent) = $_ =~ /(<[^@]+@?[^>]*>)/;
my($parent) = $_ =~ / (<.+?>) /; #DT 1.54
- $user = "$user $parent" if defined $parent;
+ 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};
@@ -2290,9 +2343,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 [^ ]+)/ ||
@@ -2304,6 +2369,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)/ ||
@@ -2319,18 +2385,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)/ ||
@@ -2358,9 +2426,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;
}
}
@@ -2437,9 +2515,9 @@ sub print_header {
if ($htm_fh) {
print $htm_fh html_header($title);
print $htm_fh "\n";
- print $htm_fh "- Grand total summary\n";
- print $htm_fh "
- User Specified Patterns\n" if @user_patterns;
- print $htm_fh "
- Deliveries by Transport\n" if $show_transport;
+ print $htm_fh "
- Grand total summary\n";
+ print $htm_fh "
- User Specified Patterns\n" if @user_patterns;
+ print $htm_fh "
- Deliveries by Transport\n" if $show_transport;
if ($hist_opt) {
print $htm_fh "
- Messages received per hour\n";
print $htm_fh "
- Deliveries per hour\n";
@@ -2461,28 +2539,33 @@ sub print_header {
print $htm_fh "
- Relayed messages\n" if $show_relay;
if ($topcount) {
- print $htm_fh "
- Top $topcount mail rejection reasons by message count\n" if %rejected_count_by_reason;
+ print $htm_fh "
- Top $topcount mail rejection reasons by message count\n" if %rejected_count_by_reason;
foreach ('Host','Domain','Email','Edomain') {
next unless $do_sender{$_};
- print $htm_fh "
- Top $topcount sending \l${_}s by message count\n";
- print $htm_fh "
- Top $topcount sending \l${_}s by volume\n";
+ print $htm_fh "
- Top $topcount sending \l${_}s by message count\n";
+ print $htm_fh "
- Top $topcount sending \l${_}s by volume\n";
}
if (($local_league_table || $include_remote_users) && %received_count_user) {
- print $htm_fh "
- Top $topcount local senders by message count\n";
- print $htm_fh "
- Top $topcount local senders by volume\n";
+ print $htm_fh "
- Top $topcount local senders by message count\n";
+ print $htm_fh "
- Top $topcount local senders by volume\n";
}
foreach ('Host','Domain','Email','Edomain') {
next unless $do_sender{$_};
- print $htm_fh "
- Top $topcount \l$_ destinations by message count\n";
- print $htm_fh "
- Top $topcount \l$_ destinations by volume\n";
+ print $htm_fh "
- Top $topcount \l$_ destinations by message count\n";
+ print $htm_fh "
- Top $topcount \l$_ destinations by volume\n";
}
if (($local_league_table || $include_remote_users) && %delivered_messages_user) {
- print $htm_fh "
- Top $topcount local destinations by message count\n";
- print $htm_fh "
- Top $topcount local destinations by volume\n";
+ print $htm_fh "
- Top $topcount local destinations by message count\n";
+ print $htm_fh "
- Top $topcount local destinations by volume\n";
+ }
+ if (($local_league_table || $include_remote_users) && %delivered_messages_local_domain) {
+ print $htm_fh "
- Top $topcount local domain destinations by message count\n";
+ print $htm_fh "
- Top $topcount local domain destinations by volume\n";
}
- print $htm_fh "
- Top $topcount rejected ips by message count\n" if %rejected_count_by_ip;
- print $htm_fh "
- Top $topcount non-rejected spamming ips by message count\n" if %spam_count_by_ip;
+ print $htm_fh "
- Top $topcount rejected ips by message count\n" if %rejected_count_by_ip;
+ print $htm_fh "
- Top $topcount temporarily rejected ips by message count\n" if %temporarily_rejected_count_by_ip;
+ print $htm_fh "
- Top $topcount non-rejected spamming ips by message count\n" if %spam_count_by_ip;
}
print $htm_fh "
- List of errors\n" if %errors_count;
@@ -2524,8 +2607,8 @@ sub print_grandtotals {
push(@delivered_totals,scalar(keys %{$delivered_data{$_}}));
}
$sender_txt_header .= " " x ($COLUMN_WIDTHS - length($_)) . $_ . 's';
- $sender_html_format .= "
%d | ";
- $sender_txt_format .= " " x ($COLUMN_WIDTHS - 5) . "%6d";
+ $sender_html_format .= "%s | ";
+ $sender_txt_format .= " " x ($COLUMN_WIDTHS - 5) . "%6s";
push(@col_headers,"${_}s");
}
@@ -2543,7 +2626,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 "\n";
print $htm_fh "" . join(' | ',@col_headers) . " | At least one addr Delayed | At least one addr Failed | \n";
@@ -2617,12 +2700,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;
@@ -2631,15 +2719,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;
@@ -2670,7 +2767,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 "\n";
print $htm_fh "\n";
print $htm_fh "\n";
@@ -2817,7 +2914,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 " | Volume | Messages | \n";
}
@@ -3143,7 +3240,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);
}
@@ -3263,8 +3360,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');
@@ -3355,6 +3452,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
@@ -3363,12 +3466,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;
}
@@ -3567,7 +3676,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
@@ -3597,7 +3706,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 {
@@ -3663,7 +3772,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.
#######################################################################
@@ -3705,7 +3814,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.
@@ -3814,6 +3923,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) }
@@ -3964,7 +4074,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;
}
@@ -4056,14 +4166,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{$_};
@@ -4077,8 +4189,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;
}
---|
|
|
---|
| |