From: Sven Hoexter Date: Fri, 13 Feb 2026 15:35:30 +0000 (+0100) Subject: New upstream version 1.1.14 X-Git-Tag: upstream/1.1.14^0 X-Git-Url: https://git.sven.stormbind.net/?a=commitdiff_plain;h=dc534b212ba472ad0fb653861355863ff2cf51e2;p=sven%2Fpflogsumm.git New upstream version 1.1.14 --- diff --git a/ChangeLog b/ChangeLog index 35b2707..d8c7ac9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,30 @@ ChangeLog for pflogsumm feed for update notifications.] +rel-1.1.14 20260209 + + Bug Fixes + + Date range not displayed in multi-day reports for January (month 0). + + Enhancements + + Now captures and reports messages expired (queue lifetime exceeded). + Thanks and a tip o' the hat to Bill Carson + (bill-carlson-at-wkks-dot-org) for bringing this to my attention. + + Modified status line capture to account for new TLS status logging. + (N.B.: Not currently doing anything with the captured TLS info.) + + Now condenses "Domain does not accept mail (nullMX)" under + single subheading. + + Added long-form options to doc header and --help output. + + Miscellaneous + + A bit of minor refactoring. + rel-1.1.13 20251023 Bug Fixes diff --git a/pffrombyto.1 b/pffrombyto.1 index 7b625d6..55fef3a 100644 --- a/pffrombyto.1 +++ b/pffrombyto.1 @@ -55,7 +55,7 @@ .\" ======================================================================== .\" .IX Title "PFFROMBYTO 1" -.TH PFFROMBYTO 1 2025-05-22 1.1.13 "User Contributed Perl Documentation" +.TH PFFROMBYTO 1 2025-05-22 1.1.14 "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/pflogsumm b/pflogsumm index 8d14a12..40feefd 100755 --- a/pflogsumm +++ b/pflogsumm @@ -6,20 +6,21 @@ eval 'exec perl -S $0 "$@"' pflogsumm - Produce Postfix MTA logfile summary -Copyright (C) 1998-2025 by James S. Seymour, Release 1.1.13 +Copyright (C) 1998-2025 by James S. Seymour, Release 1.1.14 =head1 SYNOPSIS - - pflogsumm [--config ] [--bounce-detail ] - [--colwidth ] [--deferral-detail ] [--detail ] - [-d ] [--dow0mon] [-e] [-h ] [-i] - [--iso-date-time] [--mailq] [-m] [--no-no-msg-size] + pflogsumm [--config ] [--bounce-detail ] [--colwidth ] + [-d|--date-range ] [--deferral-detail ] + [--detail ] [--dow0mon] [-e|--extended-detail] + [--expired-detail ] [-h|--host-cnt ] [-i|--ignore-case] + [--iso-date-time] [-m|--uucp-mung] [--mailq] [--no-no-msg-size] [--problems-first] [--pscrn-detail ] [--pscrn-stats] - [-q] [--rej-add-from] [--rej-add-to] [--reject-detail ] - [--smtp-detail ] [--smtpd-stats] [--smtpd-warning-detail ] - [--srs-mung] [--syslog-name=string] [-u ] - [--unprocd-file ] [--use-orig-to] [--verbose-msg-detail] - [--verp-mung[=]] [-x] [--zero-fill] [file1 [filen]] + [-q|--quiet] [--rej-add-from] [--rej-add-to] [--reject-detail ] + [--smtp-detail ] [--smtpd-stats] + [--smtpd-warning-detail ] [--srs-mung] [--syslog-name=string] + [-u|--user-cnt ] [--unprocd-file ] [--use-orig-to] + [--verbose-msg-detail] [--verp-mung[=]] [-x|--debug] [--zero-fill] + [file1 [filen]] pflogsumm --[dump-config|help|version] @@ -117,6 +118,10 @@ Copyright (C) 1998-2025 by James S. Seymour, Release 1.1.13 "2025-07 - 2025-08" == 2025-07-01 - 2025-08-31 + --debug Enable debugging to STDERR + + See Also: -x + --dow0mon First day of the week is Monday, rather than Sunday. @@ -144,6 +149,11 @@ Copyright (C) 1998-2025 by James S. Seymour, Release 1.1.13 pflogsumm --dump-config |grep -v ' = $' + --expired-detail + + Limit detailed message queue time expired reports to + the top . 0 to suppress entirely. + -e --extended-detail @@ -364,6 +374,8 @@ Copyright (C) 1998-2025 by James S. Seymour, Release 1.1.13 -x Enable debugging to STDERR + See Also: --debug + --zero-fill "Zero-fill" certain arrays so reports come out with data in columns that that might otherwise be blank. @@ -561,7 +573,7 @@ eval { require Config::Simple }; my $haveConfigSimple = $@ ? 0 : 1; my $mailqCmd = "mailq"; -my $release = "1.1.13"; +my $release = "1.1.14"; # Variables and constants used throughout pflogsumm our ( @@ -610,10 +622,10 @@ use constant { }; my ( - $cmd, $qid, $addr, $orig_to, $size, $relay, $status, $delay, + $svc, $qid, $addr, $orig_to, $size, $relay, $status, $delay, $tls, $strtDate, $endDate, %panics, %fatals, %warnings, %masterMsgs, - %deferred, %bounced, + %deferred, %bounced, %expired, %noMsgSize, %msgDetail, $msgsRcvd, $msgsDlvrd, $sizeRcvd, $sizeDlvrd, $msgMonStr, $msgMon, $msgDay, $msgTimeStr, $msgHr, $msgMin, $msgSec, @@ -623,7 +635,7 @@ my ( %warns, $msgsWrnd, %discards, $msgsDscrdd, %holds, $msgsHld, - %rcvdMsg, $msgsFwdd, $msgsBncd, + %rcvdMsg, $msgsFwdd, $msgsBncd, $msgsExprd, $msgsDfrdCnt, $msgsDfrd, %msgDfrdFlgs, %connTime, %smtpdPerDay, %smtpdPerDom, $smtpdConnCnt, $smtpdTotTime, %pscrnConnTime, %pscrnPerDay, %pscrnPerIP, $pscrnConnCnt, $pscrnTotTime, @@ -695,21 +707,20 @@ my %pscrnHits; ($progName = $0) =~ s/^.*\///; $usageMsg = - "usage: $progName [--config ] [--bounce-detail ] - [--colwidth ] [--deferral-detail ] [--detail ] - [-d ] [--dow0mon] [-e] [-h ] [-i] - [--iso-date-time] [--mailq] [-m] [--no-no-msg-size] + "usage: $progName [--config ] [--bounce-detail ] [--colwidth ] + [-d|--date-range ] [--deferral-detail ] + [--detail ] [--dow0mon] [-e|--extended-detail] + [--expired-detail ] [-h|--host-cnt ] [-i|--ignore-case] + [--iso-date-time] [-m|--uucp-mung] [--mailq] [--no-no-msg-size] [--problems-first] [--pscrn-detail ] [--pscrn-stats] - [-q] [--rej-add-from] [--rej-add-to] [--reject-detail ] - [--smtp-detail ] [--smtpd-stats] [--smtpd-warning-detail ] - [--srs-mung] [--syslog-name=string] [-u ] - [--unprocd-file ] [--use-orig-to] [--verbose-msg-detail] - [--verp-mung[=]] [-x] [--zero-fill] [file1 [filen]] - - $progName --[dump-config|help|version] + [-q|--quiet] [--rej-add-from] [--rej-add-to] [--reject-detail ] + [--smtp-detail ] [--smtpd-stats] + [--smtpd-warning-detail ] [--srs-mung] [--syslog-name=string] + [-u|--user-cnt ] [--unprocd-file ] [--use-orig-to] + [--verbose-msg-detail] [--verp-mung[=]] [-x|--debug] [--zero-fill] + [file1 [filen]] - Note: Where both long- and short-form options exist only the - latter are shown above. See man page for long-form equivalents."; + $progName --[dump-config|help|version]"; # # Central options specifications. This allows us to create a unified set @@ -729,6 +740,7 @@ my %optionSpec = ( 'detail' => { type => 'i' }, 'dow0mon' => { type => 'b' }, 'dump-config' => { type => 'b' }, + 'expired-detail' => { type => 'i' }, 'extended-detail' => { type => 'b', short => 'e' }, 'help' => { type => 'b' }, 'host-cnt' => { type => 'i', short => 'h' }, @@ -935,13 +947,13 @@ GetOptions(@getopt_args) or die "Invalid command-line arguments\n\n$usageMsg\n"; # internally: 0 == none, undefined == -1 == all # $opts{'colwidth'} = 0 if($opts{'verbose-msg-detail'}); # This one's a bit different -foreach my $optName (qw(bounce-detail colwidth deferral-detail host-cnt pscrn-detail reject-detail smtp-detail smtpd-warning-detail user-cnt)) { +foreach my $optName (qw(bounce-detail colwidth deferral-detail expired-detail host-cnt pscrn-detail reject-detail smtp-detail smtpd-warning-detail user-cnt)) { $opts{$optName} = -1 unless(defined($opts{$optName})); } # If --detail was specified, set anything that's not enumerated to it if(defined($opts{'detail'})) { - foreach my $optName (qw (bounce-detail deferral-detail host-cnt pscrn-detail reject-detail smtp-detail smtpd-warning-detail user-cnt)) { + foreach my $optName (qw (bounce-detail deferral-detail expired-detail host-cnt pscrn-detail reject-detail smtp-detail smtpd-warning-detail user-cnt)) { $opts{$optName} = $opts{'detail'} unless($opts{"$optName"} != -1); } } @@ -999,12 +1011,12 @@ while(<>) { next unless((($msgYr, $msgMon, $msgDay, $msgHr, $msgMin, $msgSec, $logRmdr) = line_matches_dates($_, $strtDate, $endDate)) == 7); # Snag first date seen - ($fromDate{'yr'}, $fromDate{'mon'}, $fromDate{'day'}) = ($msgYr, $msgMon, $msgDay) unless($fromDate{'mon'}); + ($fromDate{'yr'}, $fromDate{'mon'}, $fromDate{'day'}) = ($msgYr, $msgMon, $msgDay) unless(defined($fromDate{'mon'})); # Snag last date seen ($thruDate{'yr'}, $thruDate{'mon'}, $thruDate{'day'}) = ($msgYr, $msgMon, $msgDay); - unless((($cmd, $qid) = $logRmdr =~ m#^(?:postfix|$syslogName)(?:/(?:smtps|submission))?/([^\[:]*).*?: ([^:\s]+)#o) == 2 || - (($cmd, $qid) = $logRmdr =~ m#^((?:postfix)(?:-script)?)(?:\[\d+\])?: ([^:\s]+)#o) == 2) + unless((($svc, $qid) = $logRmdr =~ m#^(?:postfix|$syslogName)(?:/(?:smtps|submission))?/([^\[:]*).*?: ([^:\s]+)#o) == 2 || + (($svc, $qid) = $logRmdr =~ m#^((?:postfix)(?:-script)?)(?:\[\d+\])?: ([^:\s]+)#o) == 2) { print $unProcd "[01]: $_" if $unProcd; next; @@ -1024,30 +1036,30 @@ while(<>) { } # regexp rejects happen in "cleanup" - if($cmd eq "cleanup" && (my($rejSubTyp, $rejReas, $rejRmdr) = $logRmdr =~ + if($svc eq "cleanup" && (my($rejSubTyp, $rejReas, $rejRmdr) = $logRmdr =~ /\/cleanup\[\d+\]: .*?\b((?:milter-)?reject|warning|hold|discard): (header|body|END-OF-MESSAGE) (.*)$/) == 3) { $rejRmdr =~ s/( from \S+?)?; from=<.*$// unless($opts{'verbose-msg-detail'}); # FIXME: In retrospect: I've no idea where I came up with the magic numbers I pass to this function. $rejRmdr = string_trimmer($rejRmdr, 64); if($rejSubTyp eq "reject" or $rejSubTyp eq "milter-reject") { - ++$rejects{$cmd}{$rejReas}{$rejRmdr} unless($opts{'reject-detail'} == 0); + ++$rejects{$svc}{$rejReas}{$rejRmdr} unless($opts{'reject-detail'} == 0); ++$msgsRjctd; if($opts{'debug'}) { - push(@{$qidTracker{$qid}{'status'}}, "\$cmd: $cmd, \$rejSubTyp: $rejSubTyp, --\$msgsRcvd"); + push(@{$qidTracker{$qid}{'status'}}, "\$svc: $svc, \$rejSubTyp: $rejSubTyp, --\$msgsRcvd"); ++$qidTracker{$qid}{'lateRejects'}; print STDERR "dbg: late reject \$rcvdMsg{$qid}{'size'}: $rcvdMsg{$qid}{'size'}\n" if $rcvdMsg{$qid}{'size'}; } --$msgsRcvd; # Late Reject: It will have already been counted as "Received," even though it ultimately is not } elsif($rejSubTyp eq "warning") { - ++$warns{$cmd}{$rejReas}{$rejRmdr} unless($opts{'reject-detail'} == 0); + ++$warns{$svc}{$rejReas}{$rejRmdr} unless($opts{'reject-detail'} == 0); ++$msgsWrnd; } elsif($rejSubTyp eq "hold") { - ++$holds{$cmd}{$rejReas}{$rejRmdr} unless($opts{'reject-detail'} == 0); + ++$holds{$svc}{$rejReas}{$rejRmdr} unless($opts{'reject-detail'} == 0); ++$msgsHld; } elsif($rejSubTyp eq "discard") { - push(@{$qidTracker{$qid}{'status'}}, "\$cmd: $cmd, \$rejSubTyp: $rejSubTyp") if $opts{'debug'}; - ++$discards{$cmd}{$rejReas}{$rejRmdr} unless($opts{'reject-detail'} == 0); + push(@{$qidTracker{$qid}{'status'}}, "\$svc: $svc, \$rejSubTyp: $rejSubTyp") if $opts{'debug'}; + ++$discards{$svc}{$rejReas}{$rejRmdr} unless($opts{'reject-detail'} == 0); ++$msgsDscrdd; } delete($rcvdMsg{$qid}); # We're done with this @@ -1077,17 +1089,17 @@ while(<>) { $warnReas =~ s/(process .+) pid \d+ (exit status \d+)/$1 $2/; } $warnReas = string_trimmer($warnReas, 66); - unless($cmd eq "smtpd" && $opts{'smtpd-warning-detail'} == 0) { - ++$warnings{$cmd}{$warnReas}; + unless($svc eq "smtpd" && $opts{'smtpd-warning-detail'} == 0) { + ++$warnings{$svc}{$warnReas}; } } elsif($qid eq 'fatal') { (my $fatalReas = $logRmdr) =~ s/^.*fatal: //; $fatalReas = string_trimmer($fatalReas, 66); - ++$fatals{$cmd}{$fatalReas}; + ++$fatals{$svc}{$fatalReas}; } elsif($qid eq 'panic') { (my $panicReas = $logRmdr) =~ s/^.*panic: //; $panicReas = string_trimmer($panicReas, 66); - ++$panics{$cmd}{$panicReas}; + ++$panics{$svc}{$panicReas}; } elsif($qid eq 'reject') { proc_smtpd_reject($logRmdr, \%rejects, \$msgsRjctd, \$rejPerHr[$msgHr], \${$msgsPerDay{$revMsgDateStr}}[4]); @@ -1100,21 +1112,18 @@ while(<>) { } elsif($qid eq 'discard') { proc_smtpd_reject($logRmdr, \%discards, \$msgsDscrdd, \$rejPerHr[$msgHr], \${$msgsPerDay{$revMsgDateStr}}[4]); - } elsif($cmd eq 'master') { + } elsif($svc eq 'master') { ++$masterMsgs{(split(/^.*master.*: /, $logRmdr))[1]}; - } elsif($cmd eq 'smtpd' || $cmd eq 'postscreen') { - if((my ($clientInfo)) = $logRmdr =~ /\[\d+\]: \w+: client=(.+?)(?:,|$)/) { - # - # Warning: this code in two places! - # + } elsif($svc eq 'smtpd' || $svc eq 'postscreen' || $svc eq 'pickup') { + if((my ($clientInfo)) = $logRmdr =~ /(?|\[\d+\]: \w+: client=(.+?)(?:,|$)|\/(pickup)\[\d+\]: \w+: (?:sender|uid)=)/) { ++$rcvPerHr[$msgHr]; ++${$msgsPerDay{$revMsgDateStr}}[0]; if($opts{'debug'}) { - push(@{$qidTracker{$qid}{'status'}}, "\$cmd: $cmd, ++\$msgsRcvd"); + push(@{$qidTracker{$qid}{'status'}}, "\$svc: $svc, ++\$msgsRcvd"); ++$qidTracker{$qid}{'rcvdCnt'}; } ++$msgsRcvd; - $rcvdMsg{$qid}{'whence'} = gimme_domain($clientInfo); # Whence it came + $rcvdMsg{$qid}{'whence'} = $clientInfo eq 'pickup'? $clientInfo : gimme_domain($clientInfo); # Whence it came } elsif(my($rejSubTyp) = $logRmdr =~ /\[\d+\]: \w+: (reject(?:_warning)?|hold|discard): /) { if($rejSubTyp eq 'reject') { proc_smtpd_reject($logRmdr, \%rejects, \$msgsRjctd, @@ -1123,7 +1132,7 @@ while(<>) { # Experimental unless($qid eq 'NOQUEUE') { if($opts{'debug'}) { - push(@{$qidTracker{$qid}{'status'}}, "\$cmd: $cmd, \$rejSubTyp: $rejSubTyp, --\$msgsRcvd"); + push(@{$qidTracker{$qid}{'status'}}, "\$svc: $svc, \$rejSubTyp: $rejSubTyp, --\$msgsRcvd"); ++$qidTracker{$qid}{'lateRejects'}; print STDERR "dbg: late reject \$rcvdMsg{$qid}{'size'}: $rcvdMsg{$qid}{'size'}\n" if $rcvdMsg{$qid}{'size'}; } @@ -1135,19 +1144,19 @@ while(<>) { \$rejPerHr[$msgHr], \${$msgsPerDay{$revMsgDateStr}}[4]); } elsif($rejSubTyp eq 'hold') { - push(@{$qidTracker{$qid}{'status'}}, "\$cmd: $cmd, \$rejSubTyp: $rejSubTyp") if $opts{'debug'}; + push(@{$qidTracker{$qid}{'status'}}, "\$svc: $svc, \$rejSubTyp: $rejSubTyp") if $opts{'debug'}; proc_smtpd_reject($logRmdr, \%holds, \$msgsHld, \$rejPerHr[$msgHr], \${$msgsPerDay{$revMsgDateStr}}[4]); } elsif($rejSubTyp eq 'discard') { - push(@{$qidTracker{$qid}{'status'}}, "\$cmd: $cmd, \$rejSubTyp: $rejSubTyp") if $opts{'debug'}; + push(@{$qidTracker{$qid}{'status'}}, "\$svc: $svc, \$rejSubTyp: $rejSubTyp") if $opts{'debug'}; proc_smtpd_reject($logRmdr, \%discards, \$msgsDscrdd, \$rejPerHr[$msgHr], \${$msgsPerDay{$revMsgDateStr}}[4]); } } else { - if($cmd eq 'smtpd') { + if($svc eq 'smtpd') { next unless(defined($opts{'smtpd-stats'})); if($logRmdr =~ /: connect from /) { $logRmdr =~ /\/smtpd\[(\d+)\]: /; @@ -1188,7 +1197,7 @@ while(<>) { $smtpdTotTime += $tSecs; } } - } elsif($cmd eq 'postscreen' && (defined $opts{'pscrn-stats'} || $opts{'pscrn-detail'})) { + } elsif($svc eq 'postscreen' && (defined $opts{'pscrn-stats'} || $opts{'pscrn-detail'})) { my ($pscrnAct, $clientIP, $clientPort, $pscrnAddl, $capCnt); print STDERR "\n" if($opts{'debug'}); @@ -1212,11 +1221,11 @@ while(<>) { if($capCnt == 4) { print STDERR "Bumping \$pscrnHits{\"$pscrnAct $pscrnAddl\"}{\"$clientIP\"} on \$logRmdr: \"$logRmdr\"\n" if($opts{'debug'}); ++$pscrnHits{"$pscrnAct $pscrnAddl"}{$clientIP} if($opts{'pscrn-detail'}); - print STDERR "\$cmd: \"$cmd\", \$logRmdr: \"$logRmdr\"\n" if($opts{'debug'}); + print STDERR "\$svc: \"$svc\", \$logRmdr: \"$logRmdr\"\n" if($opts{'debug'}); } else { print STDERR "Bumping \$pscrnHits{\"$pscrnAct\"}{\"$clientIP\"} on \$logRmdr: \"$logRmdr\"\n" if($opts{'debug'}); ++$pscrnHits{$pscrnAct}{$clientIP} if($opts{'pscrn-detail'}); - print STDERR "\$cmd: \"$cmd\", \$logRmdr: \"$logRmdr\"\n" if($opts{'debug'}); + print STDERR "\$svc: \"$svc\", \$logRmdr: \"$logRmdr\"\n" if($opts{'debug'}); } }; @@ -1311,8 +1320,25 @@ while(<>) { $sizeRcvd += $size; } } - elsif((($addr, $orig_to, $relay, $delay, $status, $toRmdr) = $logRmdr =~ - /to=<([^>]*)>, (?:orig_to=<([^>]*)>, )?relay=([^,]+), (?:conn_use=[^,]+, )?delay=([^,]+), (?:delays=[^,]+, )?(?:dsn=[^,]+, )?status=(\S+)(.*)$/) >= 4) + elsif((( + $addr, + $orig_to, + $relay, + $delay, + $tls, # <— new optional capture + $status, + $toRmdr + ) = $logRmdr =~ m{ + to=<([^>]*)>,\s+ + (?:orig_to=<([^>]*)>,\s+)? # optional + relay=([^,]+),\s+ + (?:conn_use=[^,]+,\s+)? # optional + delay=([^,]+),\s+ + (?:delays=[^,]+,\s+)? # optional + (?:tls=([^,]+),\s+)? # <— optional tls=... (captures if present) + (?:dsn=[^,]+,\s+)? # optional + status=(\S+)(.*)$ + }x) >= 4) { $addr = $orig_to if($opts{'use-orig-to'} && $orig_to); @@ -1327,7 +1353,7 @@ while(<>) { # was it actually forwarded, rather than delivered? if(my ($newQid) = $toRmdr =~ /\(forwarded as ([^\)]+)\)/) { - push(@{$qidTracker{$qid}{'status'}}, "\$cmd: $cmd, \$status: $status, forwarded as new qid $1, ++\$msgsFwdd") if $opts{'debug'}; + push(@{$qidTracker{$qid}{'status'}}, "\$svc: $svc, \$status: $status, forwarded as new qid $1, ++\$msgsFwdd") if $opts{'debug'}; ++$msgsFwdd; delete($rcvdMsg{$qid}); # We're done with this next; @@ -1345,7 +1371,7 @@ while(<>) { ++$dlvPerHr[$msgHr]; ++${$msgsPerDay{$revMsgDateStr}}[1]; if($opts{'debug'}) { - push(@{$qidTracker{$qid}{'status'}}, "\$cmd: $cmd, \$status: $status, ++\$msgsDlvrd"); + push(@{$qidTracker{$qid}{'status'}}, "\$svc: $svc, \$status: $status, ++\$msgsDlvrd"); ++$qidTracker{$qid}{'dlvrdCnt'}; } ++$msgsDlvrd; @@ -1383,14 +1409,14 @@ while(<>) { $reason .= $moreReason if($moreReason); # ick # Finally... $reason = said_string_trimmer($reason, 66); - ++$deferred{$cmd}{$host}{$reason}; + ++$deferred{$svc}{$host}{$reason}; } else { - ++$deferred{$cmd}{$deferredReas}; + ++$deferred{$svc}{$deferredReas}; } } ++$dfrPerHr[$msgHr]; ++${$msgsPerDay{$revMsgDateStr}}[2]; - push(@{$qidTracker{$qid}{'status'}}, "\$cmd: $cmd, \$status: $status, ++\$msgsDfrd") if $opts{'debug'}; + push(@{$qidTracker{$qid}{'status'}}, "\$svc: $svc, \$status: $status, ++\$msgsDfrd") if $opts{'debug'}; ++$msgsDfrdCnt; ++$msgsDfrd unless($msgDfrdFlgs{$qid}++); ++${$recipDom{$domAddr}}[MSG_DFRS_I]; @@ -1399,6 +1425,12 @@ while(<>) { { ${$recipDom{$domAddr}}[MSG_DLY_MAX_I] = $delay } + # For "expired" detail reports + if($rcvdMsg{$qid}) { + my ($relay) = $logRmdr =~ /, relay=([^:]+):/; + $rcvdMsg{$qid}{'relay'} = $relay; + } + } elsif($status eq 'bounced') { unless($opts{'bounce-detail'} == 0) { my ($bounceReas) = $logRmdr =~ /, status=bounced \((.+)\)/; @@ -1409,26 +1441,13 @@ while(<>) { } ++$bncPerHr[$msgHr]; ++${$msgsPerDay{$revMsgDateStr}}[3]; - push(@{$qidTracker{$qid}{'status'}}, "\$cmd: $cmd, \$status: $status, ++\$msgsBncd") if $opts{'debug'}; + push(@{$qidTracker{$qid}{'status'}}, "\$svc: $svc, \$status: $status, ++\$msgsBncd") if $opts{'debug'}; ++$msgsBncd; } else { print $unProcd "[03]: $_\n" if $unProcd; } } - elsif($cmd eq 'pickup' && $logRmdr =~ /: (sender|uid)=/) { - # - # Warning: this code in two places! - # - ++$rcvPerHr[$msgHr]; - ++${$msgsPerDay{$revMsgDateStr}}[0]; - if($opts{'debug'}) { - push(@{$qidTracker{$qid}{'status'}}, "\$cmd: $cmd, ++\$msgsRcvd"); - ++$qidTracker{$qid}{'rcvdCnt'}; - } - ++$msgsRcvd; - $rcvdMsg{$qid}{'whence'} = "pickup"; # Whence it came - } - elsif($cmd eq 'smtp' && $opts{'smtp-detail'} != 0) { + elsif($svc eq 'smtp' && $opts{'smtp-detail'} != 0) { # Was an IPv6 problem here if($logRmdr =~ /.* connect to (\S+?): ([^;]+); address \S+ port.*$/) { ++$smtpMsgs{lc($2)}{$1}; @@ -1438,12 +1457,16 @@ while(<>) { print $unProcd "[04]: $_\n" if $unProcd; } } - elsif($cmd =~ /^n?qmgr$/ && $logRmdr =~ /\bremoved$/) { + elsif($svc =~ /^n?qmgr$/ && $logRmdr =~ /, status=expired, returned to sender$/) { + ++$expired{$rcvdMsg{$qid}{'relay'}}; + ++$msgsExprd; + } + elsif($svc =~ /^n?qmgr$/ && $logRmdr =~ /\bremoved$/) { delete($rcvdMsg{$qid}); # We're done with this } else { - print $unProcd "[05]: $_\n" if $unProcd; + print $unProcd "[05]: (\$svc: \"$svc\") $_\n" if $unProcd; } } } @@ -1578,6 +1601,7 @@ printf " %6d%s deferred", adj_int_units($msgsDfrd); printf " (%d%s deferrals)", adj_int_units($msgsDfrdCnt) if($msgsDfrdCnt); print "\n"; printf " %6d%s bounced\n", adj_int_units($msgsBncd); +printf " %6d%s expired\n", adj_int_units($msgsExprd); printf " %6d%s rejected (%d%%)\n", adj_int_units($msgsRjctd), $msgsRjctdPct; printf " %6d%s reject warnings\n", adj_int_units($msgsWrnd); printf " %6d%s held\n", adj_int_units($msgsHld); @@ -1653,6 +1677,9 @@ sub print_problems_reports { unless($opts{'bounce-detail'} == 0) { print_nested_hash(\%bounced, "message bounce detail (by relay)", $opts{'bounce-detail'}, $opts{'quiet'}); } + unless($opts{'expired-detail'} == 0) { + print_nested_hash(\%expired, "message expired detail (by relay)", $opts{'expired-detail'}, $opts{'quiet'}); + } unless($opts{'reject-detail'} == 0) { print_nested_hash(\%rejects, "message reject detail", $opts{'reject-detail'}, $opts{'quiet'}); print_nested_hash(\%warns, "message reject warning detail", $opts{'reject-detail'}, $opts{'quiet'}); @@ -2530,6 +2557,8 @@ sub proc_smtpd_reject { $rejReas =~ s/^\d{3} \d\.\d\.\d (Server configuration (?:error|problem));.+$/$1/; # Condense fqrdns.pcre reports $rejReas =~ s/^Unverified (Client host rejected: Generic - Please relay via ISP).*$/$1/; + # Condense nullMX reports + $rejReas =~ s/^(Sender address rejected: Domain) .+ (does not accept mail \(nullMX\)).*$/$1 $2/; } elsif($rejTyp eq "MAIL") { # *more* special treatment :-( grrrr... $rejReas =~ s/^\d{3} (?:<.+>: )?([^;:]+)[;:]?.*$/$1/; } elsif($rejTyp eq "connect") { # and still *more* special treatment :-( *sigh*... diff --git a/pflogsumm.1 b/pflogsumm.1 index 8304080..05afaa4 100644 --- a/pflogsumm.1 +++ b/pflogsumm.1 @@ -55,7 +55,7 @@ .\" ======================================================================== .\" .IX Title "PFLOGSUMM 1" -.TH PFLOGSUMM 1 2025-10-22 1.1.13 "User Contributed Perl Documentation" +.TH PFLOGSUMM 1 2026-02-09 1.1.14 "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -63,21 +63,10 @@ .SH NAME pflogsumm \- Produce Postfix MTA logfile summary .PP -Copyright (C) 1998\-2025 by James S. Seymour, Release 1.1.13 -.SH SYNOPSIS -.IX Header "SYNOPSIS" -.Vb 10 -\& pflogsumm [\-\-config ] [\-\-bounce\-detail ] -\& [\-\-colwidth ] [\-\-deferral\-detail ] [\-\-detail ] -\& [\-d ] [\-\-dow0mon] [\-e] [\-h ] [\-i] -\& [\-\-iso\-date\-time] [\-\-mailq] [\-m] [\-\-no\-no\-msg\-size] -\& [\-\-problems\-first] [\-\-pscrn\-detail ] [\-\-pscrn\-stats] -\& [\-q] [\-\-rej\-add\-from] [\-\-rej\-add\-to] [\-\-reject\-detail ] -\& [\-\-smtp\-detail ] [\-\-smtpd\-stats] [\-\-smtpd\-warning\-detail ] -\& [\-\-srs\-mung] [\-\-syslog\-name=string] [\-u ] -\& [\-\-unprocd\-file ] [\-\-use\-orig\-to] [\-\-verbose\-msg\-detail] -\& [\-\-verp\-mung[=]] [\-x] [\-\-zero\-fill] [file1 [filen]] -\& +Copyright (C) 1998\-2025 by James S. Seymour, Release 1.1.14 +.SH "SYNOPSIS pflogsumm [\-\-config ] [\-\-bounce\-detail ] [\-\-colwidth ] [\-d|\-\-date\-range ] [\-\-deferral\-detail ] [\-\-detail ] [\-\-dow0mon] [\-e|\-\-extended\-detail] [\-\-expired\-detail ] [\-h|\-\-host\-cnt ] [\-i|\-\-ignore\-case] [\-\-iso\-date\-time] [\-m|\-\-uucp\-mung] [\-\-mailq] [\-\-no\-no\-msg\-size] [\-\-problems\-first] [\-\-pscrn\-detail ] [\-\-pscrn\-stats] [\-q|\-\-quiet] [\-\-rej\-add\-from] [\-\-rej\-add\-to] [\-\-reject\-detail ] [\-\-smtp\-detail ] [\-\-smtpd\-stats] [\-\-smtpd\-warning\-detail ] [\-\-srs\-mung] [\-\-syslog\-name=string] [\-u|\-\-user\-cnt ] [\-\-unprocd\-file ] [\-\-use\-orig\-to] [\-\-verbose\-msg\-detail] [\-\-verp\-mung[=]] [\-x|\-\-debug] [\-\-zero\-fill] [file1 [filen]]" +.IX Header "SYNOPSIS pflogsumm [--config ] [--bounce-detail ] [--colwidth ] [-d|--date-range ] [--deferral-detail ] [--detail ] [--dow0mon] [-e|--extended-detail] [--expired-detail ] [-h|--host-cnt ] [-i|--ignore-case] [--iso-date-time] [-m|--uucp-mung] [--mailq] [--no-no-msg-size] [--problems-first] [--pscrn-detail ] [--pscrn-stats] [-q|--quiet] [--rej-add-from] [--rej-add-to] [--reject-detail ] [--smtp-detail ] [--smtpd-stats] [--smtpd-warning-detail ] [--srs-mung] [--syslog-name=string] [-u|--user-cnt ] [--unprocd-file ] [--use-orig-to] [--verbose-msg-detail] [--verp-mung[=]] [-x|--debug] [--zero-fill] [file1 [filen]]" +.Vb 1 \& pflogsumm \-\-[dump\-config|help|version] \& \& Note: Where both long\- and short\-form options exist only the @@ -176,6 +165,10 @@ Copyright (C) 1998\-2025 by James S. Seymour, Release 1.1.13 \& \& "2025\-07 \- 2025\-08" == 2025\-07\-01 \- 2025\-08\-31 \& +\& \-\-debug Enable debugging to STDERR +\& +\& See Also: \-x +\& \& \-\-dow0mon \& First day of the week is Monday, rather than Sunday. \& @@ -203,6 +196,11 @@ Copyright (C) 1998\-2025 by James S. Seymour, Release 1.1.13 \& \& pflogsumm \-\-dump\-config |grep \-v \*(Aq = $\*(Aq \& +\& \-\-expired\-detail +\& +\& Limit detailed message queue time expired reports to +\& the top . 0 to suppress entirely. +\& \& \-e \& \-\-extended\-detail \& @@ -423,6 +421,8 @@ Copyright (C) 1998\-2025 by James S. Seymour, Release 1.1.13 \& \& \-x Enable debugging to STDERR \& +\& See Also: \-\-debug +\& \& \-\-zero\-fill "Zero\-fill" certain arrays so reports come out with \& data in columns that that might otherwise be blank. .Ve diff --git a/pftobyfrom.1 b/pftobyfrom.1 index e9d6faa..2a010ab 100644 --- a/pftobyfrom.1 +++ b/pftobyfrom.1 @@ -55,7 +55,7 @@ .\" ======================================================================== .\" .IX Title "PFTOBYFROM 1" -.TH PFTOBYFROM 1 2025-05-22 1.1.13 "User Contributed Perl Documentation" +.TH PFTOBYFROM 1 2025-05-22 1.1.14 "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l