X-Git-Url: http://git.sven.stormbind.net/?p=sven%2Fpflogsumm.git;a=blobdiff_plain;f=pflogsumm.pl;h=31de5bd550faf93fa4a798beeb51a775dd2b5728;hp=12b703de1f201ab0bac1ec7bd5ac2932476bf274;hb=refs%2Fheads%2Fupstream;hpb=80016b92950431352612eb3f713acd5f5a7a0e81 diff --git a/pflogsumm.pl b/pflogsumm.pl index 12b703d..31de5bd 100755 --- a/pflogsumm.pl +++ b/pflogsumm.pl @@ -6,20 +6,18 @@ eval 'exec perl -S $0 "$@"' pflogsumm.pl - Produce Postfix MTA logfile summary -Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. +Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.5 =head1 SYNOPSIS pflogsumm.pl -[eq] [-d ] [--detail ] - [--bounce_detail ] [--deferral_detail ] - [-h ] [-i|--ignore_case] [--iso_date_time] [--mailq] - [-m|--uucp_mung] [--no_bounce_detail] [--no_deferral_detail] - [--no_no_msg_size] [--no_reject_detail] [--no_smtpd_warnings] - [--problems_first] [--rej_add_from] [--reject_detail ] - [--smtp_detail ] [--smtpd_stats] - [--smtpd_warning_detail ] [--syslog_name=string] - [-u ] [--verbose_msg_detail] [--verp_mung[=]] - [--zero_fill] [file1 [filen]] + [--bounce-detail ] [--deferral-detail ] + [-h ] [-i|--ignore-case] [--iso-date-time] [--mailq] + [-m|--uucp-mung] [--no-no-msg-size] [--problems-first] + [--rej-add-from] [--reject-detail ] [--smtp-detail ] + [--smtpd-stats] [--smtpd-warning-detail ] + [--syslog-name=string] [-u ] [--verbose-msg-detail] + [--verp-mung[=]] [--zero-fill] [file1 [filen]] pflogsumm.pl -[help|version] @@ -38,7 +36,7 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. =head1 OPTIONS - --bounce_detail + --bounce-detail Limit detailed bounce reports to the top . 0 to suppress entirely. @@ -46,14 +44,14 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. -d today generate report for just today -d yesterday generate report for just "yesterday" - --deferral_detail + --deferral-detail Limit detailed deferral reports to the top . 0 to suppress entirely. --detail - Sets all --*_detail, -h and -u to . Is + Sets all --*-detail, -h and -u to . Is over-ridden by individual settings. --detail 0 suppresses *all* detail. @@ -71,7 +69,7 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. 0 = none. - See also: "-u" and "--*_detail" options for further + See also: "-u" and "--*-detail" options for further report-limiting options. --help Emit short usage message and bail out. @@ -81,7 +79,7 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. know: lame.) -i - --ignore_case Handle complete email address in a case-insensitive + --ignore-case Handle complete email address in a case-insensitive manner. Normally pflogsumm lower-cases only the host and @@ -89,14 +87,14 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. option causes the entire email address to be lower- cased. - --iso_date_time + --iso-date-time For summaries that contain date or time information, use ISO 8601 standard formats (CCYY-MM-DD and HH:MM), rather than "Mon DD CCYY" and "HHMM". -m modify (mung?) UUCP-style bang-paths - --uucp_mung + --uucp-mung This is for use when you have a mix of Internet-style domain addresses and UUCP-style bang-paths in the log. @@ -120,9 +118,9 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. --no_deferral_detail --no_reject_detail - These switches are depreciated in favour of - --bounce_detail, --deferral_detail and - --reject_detail, respectively. + These switches are deprecated in favour of + --bounce-detail, --deferral-detail and + --reject-detail, respectively. Suppresses the printing of the following detailed reports, respectively: @@ -134,7 +132,7 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. See also: "-u" and "-h" for further report-limiting options. - --no_no_msg_size + --no-no-msg-size Do not emit report on "Messages with no size data". @@ -147,21 +145,21 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. normally reported by pflogsumm as "Messages with no size data." - --no_smtpd_warnings + --no-smtpd-warnings - This switch is depreciated in favour of - smtpd_warning_detail + This switch is deprecated in favour of + smtpd-warning-detail On a busy mail server, say at an ISP, SMTPD warnings can result in a rather sizeable report. This option turns reporting them off. - --problems_first + --problems-first Emit "problems" reports (bounces, defers, warnings, etc.) before "normal" stats. - --rej_add_from + --rej-add-from For those reject reports that list IP addresses or host/domain names: append the email from address to each listing. (Does not apply to "Improper use of @@ -172,17 +170,17 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. note: headings for warning, fatal, and "master" messages will always be printed. - --reject_detail + --reject-detail Limit detailed smtpd reject, warn, hold and discard reports to the top . 0 to suppress entirely. - --smtp_detail + --smtp-detail Limit detailed smtp delivery reports to the top . 0 to suppress entirely. - --smtpd_stats + --smtpd-stats Generate smtpd connection statistics. @@ -190,14 +188,14 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. reports. For multiple-day reports: "per-hour" numbers are daily averages (reflected in the report heading). - --smtpd_warning_detail + --smtpd-warning-detail Limit detailed smtpd warnings reports to the top . 0 to suppress entirely. - --syslog_name=name + --syslog-name=name - Set syslog_name to look for for Postfix log entries. + Set syslog-name to look for for Postfix log entries. By default, pflogsumm looks for entries in logfiles with a syslog name of "postfix," the default. @@ -210,18 +208,18 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. -u top to display in user reports. 0 == none. - See also: "-h" and "--*_detail" options for further + See also: "-h" and "--*-detail" options for further report-limiting options. - --verbose_msg_detail + --verbose-msg-detail For the message deferral, bounce and reject summaries: display the full "reason", rather than a truncated one. Note: this can result in quite long lines in the report. - --verp_mung do "VERP" generated address (?) munging. Convert - --verp_mung=2 sender addresses of the form + --verp-mung do "VERP" generated address (?) munging. Convert + --verp-mung=2 sender addresses of the form "list-return-NN-someuser=some.dom@host.sender.dom" to "list-return-ID-someuser=some.dom@host.sender.dom" @@ -242,7 +240,7 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. --version Print program name and version and bail out. - --zero_fill "Zero-fill" certain arrays so reports come out with + --zero-fill "Zero-fill" certain arrays so reports come out with data in columns that that might otherwise be blank. =head1 RETURN VALUE @@ -336,9 +334,9 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. (rejected / (delivered + rejected + discarded)) * 100 - There are some issues with the use of --syslog_name. The problem is - that, even with $syslog_name set, Postfix will sometimes still log - things with "postfix" as the syslog_name. This is noted in + There are some issues with the use of --syslog-name. The problem is + that, even with Postfix' $syslog_name set, it will sometimes still + log things with "postfix" as the syslog_name. This is noted in /etc/postfix/sample-misc.cf: # Beware: a non-default syslog_name setting takes effect only @@ -367,7 +365,7 @@ Copyright (C) 1998-2010 by James S. Seymour, Release 1.1.3. =head1 REQUIREMENTS - For certain options (e.g.: --smtpd_stats), Pflogsumm requires the + For certain options (e.g.: --smtpd-stats), Pflogsumm requires the Date::Calc module, which can be obtained from CPAN at http://www.perl.com. @@ -404,7 +402,7 @@ eval { require Date::Calc }; my $hasDateCalc = $@ ? 0 : 1; my $mailqCmd = "mailq"; -my $release = "1.1.3"; +my $release = "1.1.5"; # Variables and constants used throughout pflogsumm use vars qw( @@ -451,7 +449,7 @@ $msgDlyMaxI = 4; # max delay my ( $cmd, $qid, $addr, $size, $relay, $status, $delay, - $dateStr, + $dateStr, $dateStrRFC3339, %panics, %fatals, %warnings, %masterMsgs, %msgSizes, %deferred, %bounced, @@ -488,55 +486,60 @@ for (0 .. 23) { $smtpdPerHr[$_] = [0,0,0]; } -$progName = "pflogsumm.pl"; +($progName = $0) =~ s/^.*\///; + $usageMsg = "usage: $progName -[eq] [-d ] [--detail ] - [--bounce_detail ] [--deferral_detail ] - [-h ] [-i|--ignore_case] [--iso_date_time] [--mailq] - [-m|--uucp_mung] [--no_bounce_detail] [--no_deferral_detail] - [--no_no_msg_size] [--no_reject_detail] [--no_smtpd_warnings] - [--problems_first] [--rej_add_from] [--reject_detail ] - [--smtp_detail ] [--smtpd_stats] - [--smtpd_warning_detail ] [--syslog_name=string] - [-u ] [--verbose_msg_detail] [--verp_mung[=]] - [--zero_fill] [file1 [filen]] + [--bounce-detail ] [--deferral-detail ] + [-h ] [-i|--ignore-case] [--iso-date-time] [--mailq] + [-m|--uucp-mung] [--no-no-msg-size] [--problems-first] + [--rej-add-from] [--reject-detail ] [--smtp-detail ] + [--smtpd-stats] [--smtpd-warning-detail ] + [--syslog-name=string] [-u ] [--verbose-msg-detail] + [--verp-mung[=]] [--zero-fill] [file1 [filen]] $progName --[version|help]"; +# Accept either "_"s or "-"s in --switches +foreach (@ARGV) { + last if($_ eq "--"); + tr/_/-/ if(/^--\w/); +} + # Some pre-inits for convenience $isoDateTime = 0; # Don't use ISO date/time formats GetOptions( - "bounce_detail=i" => \$opts{'bounceDetail'}, + "bounce-detail=i" => \$opts{'bounceDetail'}, "d=s" => \$opts{'d'}, - "deferral_detail=i" => \$opts{'deferralDetail'}, + "deferral-detail=i" => \$opts{'deferralDetail'}, "detail=i" => \$opts{'detail'}, "e" => \$opts{'e'}, "help" => \$opts{'help'}, "h=i" => \$opts{'h'}, - "ignore_case" => \$opts{'i'}, + "ignore-case" => \$opts{'i'}, "i" => \$opts{'i'}, - "iso_date_time" => \$isoDateTime, + "iso-date-time" => \$isoDateTime, "mailq" => \$opts{'mailq'}, "m" => \$opts{'m'}, - "no_bounce_detail" => \$opts{'noBounceDetail'}, - "no_deferral_detail" => \$opts{'noDeferralDetail'}, - "no_no_msg_size" => \$opts{'noNoMsgSize'}, - "no_reject_detail" => \$opts{'noRejectDetail'}, - "no_smtpd_warnings" => \$opts{'noSMTPDWarnings'}, - "problems_first" => \$opts{'pf'}, + "no-bounce-detail" => \$opts{'noBounceDetail'}, + "no-deferral-detail" => \$opts{'noDeferralDetail'}, + "no-no-msg-size" => \$opts{'noNoMsgSize'}, + "no-reject-detail" => \$opts{'noRejectDetail'}, + "no-smtpd-warnings" => \$opts{'noSMTPDWarnings'}, + "problems-first" => \$opts{'pf'}, "q" => \$opts{'q'}, - "rej_add_from" => \$opts{'rejAddFrom'}, - "reject_detail=i" => \$opts{'rejectDetail'}, - "smtp_detail=i" => \$opts{'smtpDetail'}, - "smtpd_stats" => \$opts{'smtpdStats'}, - "smtpd_warning_detail=i" => \$opts{'smtpdWarnDetail'}, - "syslog_name=s" => \$opts{'syslogName'}, + "rej-add-from" => \$opts{'rejAddFrom'}, + "reject-detail=i" => \$opts{'rejectDetail'}, + "smtp-detail=i" => \$opts{'smtpDetail'}, + "smtpd-stats" => \$opts{'smtpdStats'}, + "smtpd-warning-detail=i" => \$opts{'smtpdWarnDetail'}, + "syslog-name=s" => \$opts{'syslogName'}, "u=i" => \$opts{'u'}, - "uucp_mung" => \$opts{'m'}, - "verbose_msg_detail" => \$opts{'verbMsgDetail'}, - "verp_mung:i" => \$opts{'verpMung'}, + "uucp-mung" => \$opts{'m'}, + "verbose-msg-detail" => \$opts{'verbMsgDetail'}, + "verp-mung:i" => \$opts{'verpMung'}, "version" => \$opts{'version'}, - "zero_fill" => \$opts{'zeroFill'} + "zero-fill" => \$opts{'zeroFill'} ) || die "$usageMsg\n"; # internally: 0 == none, undefined == -1 == all @@ -551,19 +554,19 @@ $opts{'rejectDetail'} = -1 unless(defined($opts{'rejectDetail'})); # These go away eventually if(defined($opts{'noBounceDetail'})) { $opts{'bounceDetail'} = 0; - warn "$progName: \"no_bounce_detail\" is depreciated, use \"bounce_detail=0\" instead\n" + warn "$progName: \"no_bounce_detail\" is deprecated, use \"bounce-detail=0\" instead\n" } if(defined($opts{'noDeferralDetail'})) { $opts{'deferralDetail'} = 0; - warn "$progName: \"no_deferral_detail\" is depreciated, use \"deferral_detail=0\" instead\n" + warn "$progName: \"no_deferral_detail\" is deprecated, use \"deferral-detail=0\" instead\n" } if(defined($opts{'noRejectDetail'})) { $opts{'rejectDetail'} = 0; - warn "$progName: \"no_reject_detail\" is depreciated, use \"reject_detail=0\" instead\n" + warn "$progName: \"no_reject_detail\" is deprecated, use \"reject-detail=0\" instead\n" } if(defined($opts{'noSMTPDWarnings'})) { $opts{'smtpdWarnDetail'} = 0; - warn "$progName: \"no_smtpd_warnings\" is depreciated, use \"smtpd_warning_detail=0\" instead\n" + warn "$progName: \"no_smtpd_warnings\" is deprecated, use \"smtpd-warning-detail=0\" instead\n" } # If --detail was specified, set anything that's not enumerated to it @@ -595,11 +598,11 @@ if($hasDateCalc) { *Delta_DHMS = *Date::Calc::Delta_DHMS; } elsif(defined($opts{'smtpdStats'})) { - # If user specified --smtpd_stats but doesn't have Date::Calc + # If user specified --smtpd-stats but doesn't have Date::Calc # installed, die with friendly help message. die < unprocessed") || # die "couldn't open \"unprocessed\": $!\n"; while(<>) { - next if(defined($dateStr) && ! /^$dateStr/o); - s/: \[ID \d+ [^\]]+\] /: /o; # lose "[ID nnnnnn some.thing]" stuff + next if(defined($dateStr) && ! (/^${dateStr} / || /^${dateStrRFC3339}T/)); + s/: \[ID \d+ [^\]]+\] /: /; # lose "[ID nnnnnn some.thing]" stuff my $logRmdr; # "Traditional" timestamp format? if((($msgMonStr, $msgDay, $msgHr, $msgMin, $msgSec, $logRmdr) = - /^(...) {1,2}(\d{1,2}) (\d{2}):(\d{2}):(\d{2}) \S+ (.+)$/o) == 6) + /^(...) {1,2}(\d{1,2}) (\d{2}):(\d{2}):(\d{2}) \S+ (.+)$/) == 6) { # Convert string to numeric value for later "month rollover" check $msgMon = $monthNums{$msgMonStr}; } else { # RFC 3339 timestamp format? next unless((($msgYr, $msgMon, $msgDay, $msgHr, $msgMin, $msgSec, $logRmdr) = - /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:[\+\-](?:\d{2}):(?:\d{2})|Z) \S+ (.+)$/o) == 10); + /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:[\+\-](?:\d{2}):(?:\d{2})|Z) \S+ (.+)$/) == 7); # RFC 3339 months start at "1", we index from 0 --$msgMon; } - unless((($cmd, $qid) = $logRmdr =~ m#^(?:postfix|$syslogName)/([^\[:]*).*?: ([^:\s]+)#o) == 2 || + unless((($cmd, $qid) = $logRmdr =~ m#^(?:postfix|$syslogName)(?:/(?:smtps|submission))?/([^\[:]*).*?: ([^:\s]+)#o) == 2 || (($cmd, $qid) = $logRmdr =~ m#^((?:postfix)(?:-script)?)(?:\[\d+\])?: ([^:\s]+)#o) == 2) { #print UNPROCD "$_"; @@ -663,9 +666,9 @@ while(<>) { # regexp rejects happen in "cleanup" if($cmd eq "cleanup" && (my($rejSubTyp, $rejReas, $rejRmdr) = $logRmdr =~ - /\/cleanup\[\d+\]: .*?\b(reject|warning|hold|discard): (header|body) (.*)$/o) == 3) + /\/cleanup\[\d+\]: .*?\b(reject|warning|hold|discard): (header|body) (.*)$/) == 3) { - $rejRmdr =~ s/( from \S+?)?; from=<.*$//o unless($opts{'verbMsgDetail'}); + $rejRmdr =~ s/( from \S+?)?; from=<.*$// unless($opts{'verbMsgDetail'}); $rejRmdr = string_trimmer($rejRmdr, 64, $opts{'verbMsgDetail'}); if($rejSubTyp eq "reject") { ++$rejects{$cmd}{$rejReas}{$rejRmdr} unless($opts{'rejectDetail'} == 0); @@ -683,17 +686,17 @@ while(<>) { ++$rejPerHr[$msgHr]; ++${$msgsPerDay{$revMsgDateStr}}[4]; } elsif($qid eq 'warning') { - (my $warnReas = $logRmdr) =~ s/^.*warning: //o; + (my $warnReas = $logRmdr) =~ s/^.*warning: //; $warnReas = string_trimmer($warnReas, 66, $opts{'verbMsgDetail'}); unless($cmd eq "smtpd" && $opts{'noSMTPDWarnings'}) { ++$warnings{$cmd}{$warnReas}; } } elsif($qid eq 'fatal') { - (my $fatalReas = $logRmdr) =~ s/^.*fatal: //o; + (my $fatalReas = $logRmdr) =~ s/^.*fatal: //; $fatalReas = string_trimmer($fatalReas, 66, $opts{'verbMsgDetail'}); ++$fatals{$cmd}{$fatalReas}; } elsif($qid eq 'panic') { - (my $panicReas = $logRmdr) =~ s/^.*panic: //o; + (my $panicReas = $logRmdr) =~ s/^.*panic: //; $panicReas = string_trimmer($panicReas, 66, $opts{'verbMsgDetail'}); ++$panics{$cmd}{$panicReas}; } elsif($qid eq 'reject') { @@ -711,7 +714,7 @@ while(<>) { } elsif($cmd eq 'master') { ++$masterMsgs{(split(/^.*master.*: /, $logRmdr))[1]}; } elsif($cmd eq 'smtpd') { - if($logRmdr =~ /\[\d+\]: \w+: client=(.+?)(,|$)/o) { + if($logRmdr =~ /\[\d+\]: \w+: client=(.+?)(,|$)/) { # # Warning: this code in two places! # @@ -719,7 +722,9 @@ while(<>) { ++${$msgsPerDay{$revMsgDateStr}}[0]; ++$msgsRcvd; $rcvdMsg{$qid} = gimme_domain($1); # Whence it came - } elsif(my($rejSubTyp) = $logRmdr =~ /\[\d+\]: \w+: (reject(?:_warning)?|hold|discard): /o) { + # DEBUG DEBUG DEBUG + #print STDERR "Received: $qid\n"; + } elsif(my($rejSubTyp) = $logRmdr =~ /\[\d+\]: \w+: (reject(?:_warning)?|hold|discard): /) { if($rejSubTyp eq 'reject') { proc_smtpd_reject($logRmdr, \%rejects, \$msgsRjctd, \$rejPerHr[$msgHr], @@ -740,12 +745,12 @@ while(<>) { } else { next unless(defined($opts{'smtpdStats'})); - if($logRmdr =~ /: connect from /o) { - $logRmdr =~ /\/smtpd\[(\d+)\]: /o; + if($logRmdr =~ /: connect from /) { + $logRmdr =~ /\/smtpd\[(\d+)\]: /; @{$connTime{$1}} = ($msgYr, $msgMon + 1, $msgDay, $msgHr, $msgMin, $msgSec); - } elsif($logRmdr =~ /: disconnect from /o) { - my ($pid, $hostID) = $logRmdr =~ /\/smtpd\[(\d+)\]: disconnect from (.+)$/o; + } elsif($logRmdr =~ /: disconnect from /) { + my ($pid, $hostID) = $logRmdr =~ /\/smtpd\[(\d+)\]: disconnect from (.+)$/; if(exists($connTime{$pid})) { $hostID = gimme_domain($hostID); my($d, $h, $m, $s) = Delta_DHMS(@{$connTime{$pid}}, @@ -780,14 +785,14 @@ while(<>) { } } else { my $toRmdr; - if((($addr, $size) = $logRmdr =~ /from=<([^>]*)>, size=(\d+)/o) == 2) + if((($addr, $size) = $logRmdr =~ /from=<([^>]*)>, size=(\d+)/) == 2) { next if($msgSizes{$qid}); # avoid double-counting! if($addr) { - if($opts{'m'} && $addr =~ /^(.*!)*([^!]+)!([^!@]+)@([^\.]+)$/o) { + if($opts{'m'} && $addr =~ /^(.*!)*([^!]+)!([^!@]+)@([^\.]+)$/) { $addr = "$4!" . ($1? "$1" : "") . $3 . "\@$2"; } - $addr =~ s/(@.+)/\L$1/o unless($opts{'i'}); + $addr =~ s/(@.+)/\L$1/ unless($opts{'i'}); $addr = lc($addr) if($opts{'i'}); $addr = verp_mung($addr); } else { @@ -800,7 +805,7 @@ while(<>) { # Get the domain out of the sender's address. If there is # none: Use the client hostname/IP-address my $domAddr; - unless((($domAddr = $addr) =~ s/^[^@]+\@(.+)$/$1/o) == 1) { + unless((($domAddr = $addr) =~ s/^[^@]+\@(.+)$/$1/) == 1) { $domAddr = $rcvdMsg{$qid} eq "pickup"? $addr : $rcvdMsg{$qid}; } ++$sendgDomCnt @@ -815,20 +820,20 @@ while(<>) { } } elsif((($addr, $relay, $delay, $status, $toRmdr) = $logRmdr =~ - /to=<([^>]*)>, (?:orig_to=<[^>]*>, )?relay=([^,]+), (?:conn_use=[^,]+, )?delay=([^,]+), (?:delays=[^,]+, )?(?:dsn=[^,]+, )?status=(\S+)(.*)$/o) >= 4) + /to=<([^>]*)>, (?:orig_to=<[^>]*>, )?relay=([^,]+), (?:conn_use=[^,]+, )?delay=([^,]+), (?:delays=[^,]+, )?(?:dsn=[^,]+, )?status=(\S+)(.*)$/) >= 4) { - if($opts{'m'} && $addr =~ /^(.*!)*([^!]+)!([^!@]+)@([^\.]+)$/o) { + if($opts{'m'} && $addr =~ /^(.*!)*([^!]+)!([^!@]+)@([^\.]+)$/) { $addr = "$4!" . ($1? "$1" : "") . $3 . "\@$2"; } - $addr =~ s/(@.+)/\L$1/o unless($opts{'i'}); + $addr =~ s/(@.+)/\L$1/ unless($opts{'i'}); $addr = lc($addr) if($opts{'i'}); $relay = lc($relay) if($opts{'i'}); - (my $domAddr = $addr) =~ s/^[^@]+\@//o; # get domain only + (my $domAddr = $addr) =~ s/^[^@]+\@//; # get domain only if($status eq 'sent') { # was it actually forwarded, rather than delivered? - if($toRmdr =~ /forwarded as /o) { + if($toRmdr =~ /forwarded as /) { ++$msgsFwdd; next; } @@ -845,6 +850,8 @@ while(<>) { ++$dlvPerHr[$msgHr]; ++${$msgsPerDay{$revMsgDateStr}}[1]; ++$msgsDlvrd; + # DEBUG DEBUG DEBUG + #print STDERR "Delivered: $qid\n"; if($msgSizes{$qid}) { ${$recipDom{$domAddr}}[$msgSizeI] += $msgSizes{$qid}; ${$recipUser{$addr}}[$msgSizeI] += $msgSizes{$qid}; @@ -860,11 +867,11 @@ while(<>) { push(@{$msgDetail{$qid}}, $addr) if($opts{'e'}); } elsif($status eq 'deferred') { unless($opts{'deferralDetail'} == 0) { - my ($deferredReas) = $logRmdr =~ /, status=deferred \(([^\)]+)/o; + my ($deferredReas) = $logRmdr =~ /, status=deferred \(([^\)]+)/; unless(defined($opts{'verbMsgDetail'})) { $deferredReas = said_string_trimmer($deferredReas, 65); - $deferredReas =~ s/^\d{3} //o; - $deferredReas =~ s/^connect to //o; + $deferredReas =~ s/^\d{3} //; + $deferredReas =~ s/^connect to //; } ++$deferred{$cmd}{$deferredReas}; } @@ -880,10 +887,10 @@ while(<>) { } } elsif($status eq 'bounced') { unless($opts{'bounceDetail'} == 0) { - my ($bounceReas) = $logRmdr =~ /, status=bounced \((.+)\)/o; + my ($bounceReas) = $logRmdr =~ /, status=bounced \((.+)\)/; unless(defined($opts{'verbMsgDetail'})) { $bounceReas = said_string_trimmer($bounceReas, 66); - $bounceReas =~ s/^\d{3} //o; + $bounceReas =~ s/^\d{3} //; } ++$bounced{$relay}{$bounceReas}; } @@ -894,7 +901,7 @@ while(<>) { # print UNPROCD "$_\n"; } } - elsif($cmd eq 'pickup' && $logRmdr =~ /: (sender|uid)=/o) { + elsif($cmd eq 'pickup' && $logRmdr =~ /: (sender|uid)=/) { # # Warning: this code in two places! # @@ -905,9 +912,9 @@ while(<>) { } elsif($cmd eq 'smtp' && $opts{'smtpDetail'} != 0) { # Was an IPv6 problem here - if($logRmdr =~ /.* connect to (\S+?): ([^;]+); address \S+ port.*$/o) { + if($logRmdr =~ /.* connect to (\S+?): ([^;]+); address \S+ port.*$/) { ++$smtpMsgs{lc($2)}{$1}; - } elsif($logRmdr =~ /.* connect to ([^[]+)\[\S+?\]: (.+?) \(port \d+\)$/o) { + } elsif($logRmdr =~ /.* connect to ([^[]+)\[\S+?\]: (.+?) \(port \d+\)$/) { ++$smtpMsgs{lc($2)}{$1}; } else { # print UNPROCD "$_\n"; @@ -1419,9 +1426,9 @@ sub normalize_host { # For IP addrs and hostnames: lop off possible " (user@dom.ain)" bit my $norm1 = (split(/\s/, $_[0]))[0]; - if((my @octets = ($norm1 =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/o)) == 4) { + if((my @octets = ($norm1 =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)) == 4) { # Dotted-quad IP address - return(pack('C4', @octets)); + return(pack('U4', @octets)); } else { # Possibly hostname or user@dom.ain return(join( '', map { lc $_ } reverse split /[.@]/, $norm1 )); @@ -1446,9 +1453,9 @@ sub by_domain_then_user { # now re-order "mach.host.dom"/"mach.host.do.co" to # "host.dom.mach"/"host.do.co.mach" - $domainA =~ s/^(.*)\.([^\.]+)\.([^\.]{3}|[^\.]{2,3}\.[^\.]{2})$/$2.$3.$1/o + $domainA =~ s/^(.*)\.([^\.]+)\.([^\.]{3}|[^\.]{2,3}\.[^\.]{2})$/$2.$3.$1/ if($domainA); - $domainB =~ s/^(.*)\.([^\.]+)\.([^\.]{3}|[^\.]{2,3}\.[^\.]{2})$/$2.$3.$1/o + $domainB =~ s/^(.*)\.([^\.]+)\.([^\.]{3}|[^\.]{2,3}\.[^\.]{2})$/$2.$3.$1/ if($domainB); # oddly enough, doing this here is marginally faster than doing @@ -1462,8 +1469,8 @@ sub by_domain_then_user { return 1; } else { # disregard leading bang-path - $userNameA =~ s/^.*!//o; - $userNameB =~ s/^.*!//o; + $userNameA =~ s/^.*!//; + $userNameB =~ s/^.*!//; if($userNameA lt $userNameB) { return -1; } elsif($userNameA gt $userNameB) { @@ -1497,9 +1504,9 @@ sub by_count_then_size { } } -# return a date string to match in log -sub get_datestr { - my $dateOpt = $_[0]; +# return traditional and RFC3339 date strings to match in log +sub get_datestrs { + my ($dateOpt) = $_[0]; my $time = time(); @@ -1509,9 +1516,9 @@ sub get_datestr { } elsif($dateOpt ne "today") { die "$usageMsg\n"; } - my ($t_mday, $t_mon) = (localtime($time))[3,4]; + my ($t_mday, $t_mon, $t_year) = (localtime($time))[3,4,5]; - return sprintf("%s %2d", $monthNames[$t_mon], $t_mday); + return sprintf("%s %2d", $monthNames[$t_mon], $t_mday), sprintf("%04d-%02d-%02d", $t_year+1900, $t_mon+1, $t_mday); } # if there's a real domain: uses that. Otherwise uses the IP addr. @@ -1529,10 +1536,10 @@ sub gimme_domain { # split domain/ipaddr into separates # newer versions of Postfix have them "dom.ain[i.p.add.ress]" # older versions of Postfix have them "dom.ain/i.p.add.ress" - unless((($domain, $ipAddr) = /^([^\[]+)\[((?:\d{1,3}\.){3}\d{1,3})\]/o) == 2 || - (($domain, $ipAddr) = /^([^\/]+)\/([0-9a-f.:]+)/oi) == 2) { + unless((($domain, $ipAddr) = /^([^\[]+)\[((?:\d{1,3}\.){3}\d{1,3})\]/) == 2 || + (($domain, $ipAddr) = /^([^\/]+)\/([0-9a-f.:]+)/i) == 2) { # more exhaustive method - ($domain, $ipAddr) = /^([^\[\(\/]+)[\[\(\/]([^\]\)]+)[\]\)]?:?\s*$/o; + ($domain, $ipAddr) = /^([^\[\(\/]+)[\[\(\/]([^\]\)]+)[\]\)]?:?\s*$/; } # "mach.host.dom"/"mach.host.do.co" to "host.dom"/"host.do.co" @@ -1540,10 +1547,10 @@ sub gimme_domain { $domain = $ipAddr; # For identifying the host part on a Class C network (commonly # seen with dial-ups) the following is handy. - # $domain =~ s/\.\d+$//o; + # $domain =~ s/\.\d+$//; } else { $domain =~ - s/^(.*)\.([^\.]+)\.([^\.]{3}|[^\.]{2,3}\.[^\.]{2})$/\L$2.$3/o; + s/^(.*)\.([^\.]+)\.([^\.]{3}|[^\.]{2,3}\.[^\.]{2})$/\L$2.$3/; } return $domain; @@ -1586,10 +1593,10 @@ sub said_string_trimmer { my($trimmedString, $maxLen) = @_; while(length($trimmedString) > $maxLen) { - if($trimmedString =~ /^.* said: /o) { - $trimmedString =~ s/^.* said: //o; - } elsif($trimmedString =~ /^.*: */o) { - $trimmedString =~ s/^.*?: *//o; + if($trimmedString =~ /^.* said: /) { + $trimmedString =~ s/^.* said: //; + } elsif($trimmedString =~ /^.*: */) { + $trimmedString =~ s/^.*?: *//; } else { $trimmedString = substr($trimmedString, 0, $maxLen - 3) . "..."; last; @@ -1638,7 +1645,7 @@ sub proc_smtpd_reject { # First: get everything following the "reject: ", etc. token # Was an IPv6 problem here ($rejTyp, $rejFrom, $rejRmdr) = - ($logLine =~ /^.* \b(?:reject(?:_warning)?|hold|discard): (\S+) from (\S+?): (.*)$/o); + ($logLine =~ /^.* \b(?:reject(?:_warning)?|hold|discard): (\S+) from (\S+?): (.*)$/); # Next: get the reject "reason" $rejReas = $rejRmdr; @@ -1648,14 +1655,14 @@ sub proc_smtpd_reject { # an email address or HELO string. There can be *anything* in # those--incl. stuff that'll screw up subsequent parsing. So just # get rid of it right off. - $rejReas =~ s/^(\d{3} <).*?(>:)/$1$2/o; - $rejReas =~ s/^(?:.*?[:;] )(?:\[[^\]]+\] )?([^;,]+)[;,].*$/$1/o; - $rejReas =~ s/^((?:Sender|Recipient) address rejected: [^:]+):.*$/$1/o; - $rejReas =~ s/(Client host|Sender address) .+? blocked/blocked/o; + $rejReas =~ s/^(\d{3} <).*?(>:)/$1$2/; + $rejReas =~ s/^(?:.*?[:;] )(?:\[[^\]]+\] )?([^;,]+)[;,].*$/$1/; + $rejReas =~ s/^((?:Sender|Recipient) address rejected: [^:]+):.*$/$1/; + $rejReas =~ s/(Client host|Sender address) .+? blocked/blocked/; } elsif($rejTyp eq "MAIL") { # *more* special treatment :-( grrrr... - $rejReas =~ s/^\d{3} (?:<.+>: )?([^;:]+)[;:]?.*$/$1/o; + $rejReas =~ s/^\d{3} (?:<.+>: )?([^;:]+)[;:]?.*$/$1/; } else { - $rejReas =~ s/^(?:.*[:;] )?([^,]+).*$/$1/o; + $rejReas =~ s/^(?:.*[:;] )?([^,]+).*$/$1/; } } @@ -1663,14 +1670,14 @@ sub proc_smtpd_reject { # Second expression is for unknown recipient--where there is no # "to=" field, third for pathological case where recipient # field is unterminated, forth when all else fails. - (($to) = $rejRmdr =~ /to=<([^>]+)>/o) || - (($to) = $rejRmdr =~ /\d{3} <([^>]+)>: User unknown /o) || - (($to) = $rejRmdr =~ /to=<(.*?)(?:[, ]|$)/o) || + (($to) = $rejRmdr =~ /to=<([^>]+)>/) || + (($to) = $rejRmdr =~ /\d{3} <([^>]+)>: User unknown /) || + (($to) = $rejRmdr =~ /to=<(.*?)(?:[, ]|$)/) || ($to = "<>"); $to = lc($to) if($opts{'i'}); # Snag sender address - (($from) = $rejRmdr =~ /from=<([^>]+)>/o) || ($from = "<>"); + (($from) = $rejRmdr =~ /from=<([^>]+)>/) || ($from = "<>"); if(defined($from)) { $rejAddFrom = $opts{'rejAddFrom'}; @@ -1679,11 +1686,11 @@ sub proc_smtpd_reject { } # stash in "triple-subscripted-array" - if($rejReas =~ m/^Sender address rejected:/o) { + if($rejReas =~ m/^Sender address rejected:/) { # Sender address rejected: Domain not found # Sender address rejected: need fully-qualified address ++$rejects->{$rejTyp}{$rejReas}{$from}; - } elsif($rejReas =~ m/^(Recipient address rejected:|User unknown( |$))/o) { + } elsif($rejReas =~ m/^(Recipient address rejected:|User unknown( |$))/) { # Recipient address rejected: Domain not found # Recipient address rejected: need fully-qualified address # User unknown (in local/relay recipient table) @@ -1693,15 +1700,15 @@ sub proc_smtpd_reject { $rejData .= " (" . ($from? $from : gimme_domain($rejFrom)) . ")"; } ++$rejects->{$rejTyp}{$rejReas}{$rejData}; - } elsif($rejReas =~ s/^.*?\d{3} (Improper use of SMTP command pipelining);.*$/$1/o) { + } elsif($rejReas =~ s/^.*?\d{3} (Improper use of SMTP command pipelining);.*$/$1/) { # Was an IPv6 problem here - my ($src) = $logLine =~ /^.+? from (\S+?):.*$/o; + my ($src) = $logLine =~ /^.+? from (\S+?):.*$/; ++$rejects->{$rejTyp}{$rejReas}{$src}; - } elsif($rejReas =~ s/^.*?\d{3} (Message size exceeds fixed limit);.*$/$1/o) { + } elsif($rejReas =~ s/^.*?\d{3} (Message size exceeds fixed limit);.*$/$1/) { my $rejData = gimme_domain($rejFrom); $rejData .= " ($from)" if($rejAddFrom); ++$rejects->{$rejTyp}{$rejReas}{$rejData}; - } elsif($rejReas =~ s/^.*?\d{3} (Server configuration (?:error|problem));.*$/(Local) $1/o) { + } elsif($rejReas =~ s/^.*?\d{3} (Server configuration (?:error|problem));.*$/(Local) $1/) { my $rejData = gimme_domain($rejFrom); $rejData .= " ($from)" if($rejAddFrom); ++$rejects->{$rejTyp}{$rejReas}{$rejData}; @@ -1724,9 +1731,9 @@ sub verp_mung { my $addr = $_[0]; if(defined($opts{'verpMung'})) { - $addr =~ s/((?:bounce[ds]?|no(?:list|reply|response)|return|sentto|\d+).*?)(?:[\+_\.\*-]\d+\b)+/$1-ID/oi; + $addr =~ s/((?:bounce[ds]?|no(?:list|reply|response)|return|sentto|\d+).*?)(?:[\+_\.\*-]\d+\b)+/$1-ID/i; if($opts{'verpMung'} > 1) { - $addr =~ s/[\*-](\d+[\*-])?[^=\*-]+[=\*][^\@]+\@/\@/o; + $addr =~ s/[\*-](\d+[\*-])?[^=\*-]+[=\*][^\@]+\@/\@/; } }