#!/usr/bin/perl -T
##########################################################################
-# Postfix-logwatch: written and maintained by:
-#
-# Mike "MrC" Cappella <mike (at) cappella (dot) us>
-# http://logreporters.sourceforge.net/
+# Postfix-logwatch: written by Mike Capella, and maintained by Michael
+# Orlitzky <michael@orlitzky.com>.
#
# Please send all comments, suggestions, bug reports regarding this
-# program/module to the email address above. I will respond as quickly
-# as possible. [MrC]
-#
-# Questions regarding the logwatch program itself should be directed to
-# the logwatch project at:
-# http://sourceforge.net/projects/logwatch/support
+# program to the email address above.
#
#######################################################
-### All work since Dec 12, 2006 (logwatch CVS revision 1.28)
-### Copyright (c) 2006-2012 Mike Cappella
-###
+###
### Covered under the included MIT/X-Consortium License:
### http://www.opensource.org/licenses/mit-license.php
### All modifications and contributions by other persons to
### under your own copyright or a different license this
### must be explicitly stated in the contribution an the
### Logwatch project reserves the right to not accept such
-### contributions. If you have made significant
-### contributions to this script and want to claim
-### copyright please contact logwatch-devel@lists.sourceforge.net.
+### contributions.
##########################################################
-##########################################################################
-# The original postfix logwatch filter was written by
-# Kenneth Porter, and has had many contributors over the years.
-#
-# CVS log removed: see Changes file for postfix-logwatch at
-# http://logreporters.sourceforge.net/
-# or included with the standalone postfix-logwatch distribution
-##########################################################################
-
##########################################################################
#
# Test data included via inline comments starting with "#TD"
#
-#use Devel::Size qw(size total_size);
-
package Logreporters;
use 5.008;
use strict;
no warnings "uninitialized";
use re 'taint';
-our $Version = '1.40.03';
+our $Version = '1.40.04';
our $progname_prefix = 'postfix';
# Specifies the default configuration file for use in standalone mode.
1978 SpamAssassin bypassed
18 Released from quarantine
- 1982 Whitelisted
- 3 Blacklisted
+ 1982 Allowlisted
+ 3 Denylisted
12 MIME error
51 Bad header (debug supplemental)
28 Extra code modules loaded at runtime
our $service_name = $3;
my ($mailhost,$server_name,$p1) = ($1,$2,$4);
- #print "mailhost: $mailhost, servername: $server_name, servicename: $service_name, p1: $p1\n";
$service_name = $server_name unless $service_name;
- #print "service_name: $service_name\n";
# ignored postfix services...
next if $service_name eq 'postlog';
# 5:25
foreach (@policy_services) {
if ($service_name =~ $_->[0]) {
- #print "Calling policy service helper: $service_name:('$p1')\n";
&{$_->[1]}($p1);
next LINE;
}
# this test must preceed access checks below
#TDsQ replace: header From: "Postmaster" <postmaster@webmail.example.com>: From: "Postmaster" <postmaster@webmail.example.org>
if ($service_name eq 'smtp' and header_body_checks($p1)) {
- #print "main: header_body_checks\n";
next;
}
my $action = $1;
$p1 = substr($p1, length($action) + 2);
- #print "action: \"$action\", p1: \"$p1\"\n";
if ($p1 !~ /^(RCPT|MAIL|CONNECT|HELO|EHLO|DATA|VRFY|ETRN|END-OF-MESSAGE) from ([^[]+)\[([^]]+)\](?::\d+)?: (.*)$/) {
inc_unmatched('unexpected access');
next;
}
- my ($stage,$host,$hostip,$p1) = ($1,$2,$3,$4); #print "stage: \"$stage\", host: \"$host\", hostip: \"$hostip\", p1: \"$p1\"\n";
- my ($efrom,$eto,$proto,$helo) = strip_ftph($p1); #print "efrom: \"$efrom\", eto: \"$eto\", proto: \"$proto\", helo: \"$helo\"\n";
- #print "p1 now: \"$p1\"\n";
+ my ($stage,$host,$hostip,$p1) = ($1,$2,$3,$4);
+ my ($efrom,$eto,$proto,$helo) = strip_ftph($p1);
# QID: ACTION STAGE from host[hostip]: DSN trigger: explanation; ftph
#TDsdN reject_warning: VRFY from host[10.0.0.1]: 450 4.1.2 <<1F4@bs>>: Recipient address rejected: Domain not found; to=<<1F4@bs>> proto=SMTP helo=<friend>
inc_unmatched('reject1');
next;
}
- ($dsn,$p1) = ($1,$2); #print "dsn: $dsn, p1: \"$p1\"\n";
+ ($dsn,$p1) = ($1,$2);
$fmthost = formathost($hostip,$host);
# reject_warning override temp or perm reject types
$rej_type = ($action eq 'reject_warning' ? 'warn' : get_reject_key($dsn));
- #print "REJECT stage: '$rej_type'\n";
if ($Collecting{'byiprejects'} and substr($rej_type,0,1) eq '5') {
$Counts{'byiprejects'}{$fmthost}++;
else { $trigger =~ s/^<(.+)>$/$1/; }
$reason = '*unavailable' if ($reason eq '');
$fmthost = formathost ($hostip,$host);
- #print "trigger: \"$trigger\", reason: \"$reason\"\n";
# reason -> subject text
# subject -> "Helo command" : smtpd_helo_restrictions
my ($subject, $text) =
($reason =~ /^((?:Recipient|Sender) address|(?:Unverified )?Client host|Client certificate|(?:Helo|Etrn|Data) command|End-of-data) (.+)$/o);
- #printf "ACTION: '$action', SUBJECT: %-30s TEXT: \"$text\"\n", '"' . $subject . '"';
if ($action eq 'filter') {
$Totals{'filtered'}++; next unless ($Collecting{'filtered'});
#TD 47B7B074: to=<to@example.com>, relay=example.com[10.0.0.1]:25, delay=6.6, delays=6.5/0/0/0.11, dsn=5.1.1, status=bounced (host example.com[10.0.0.1] said: 550 5.1.1 <to@example.com> User unknown; rejecting (in reply to RCPT TO command))
#TDppQ to=<withheld>, relay=dbmail-pipe, delay=0.15, delays=0.09/0.01/0/0.06, dsn=5.3.0, status=bounced (Command died with signal 11: "/usr/sbin/dbmail-smtp")
- # print "bounce message from " . $to . " msg : " . $relay . "\n";
# See same code elsewhere "Note: Bounce"
### local bounce
($site,$reason) = ($5 =~ /^(.+?)(?:$|(?:[.,] )(.*))/);
$reason =~ s/^reason: // if ($reason);
$rej_type = ($rej_type =~ /_warning/ ? 'warn' : get_reject_key($dsn));
- #print "REJECT RBL NOQ: '$rej_type'\n";
# Note: similar code above: search RejectRBL
# This section required: postfix didn't always log QID (eg. postfix 1.1)
# proxy-reject, proxy-accept
elsif ($p1 =~ s/^proxy-(reject|accept): ([^:]+): //) {
# 2.7
- #TDsdN proxy-accept: END-OF-MESSAGE: 250 2.0.0 Ok: queued as 9BE3547AFE; from=<senderexample.com> to=<recipientexample.com> proto=ESMTP helo=<client.example.com>
+ #TDsdN proxy-accept: END-OF-MESSAGE: 250 2.0.0 Ok: queued as 9BE3547AFE; from=<senderexample.com> to=<recipientexample.com> proto=ESMTP helo=<client.example.com>
#TDsdN proxy-reject: END-OF-MESSAGE: 554 5.7.0 Reject, id=11912-03 - INFECTED: Eicar-Test-Signature; from=<root@example.com> to=<root@example.net> proto=ESMTP helo=<example.com>
#TDsdN proxy-reject: END-OF-MESSAGE: ; from=<user@example.com> to=<user@example.org> proto=SMTP helo=<mail.example.net>
my ($stage) = ($2);
my ($efrom,$eto,$proto,$helo) = strip_ftph($p1);
- #print "efrom: '$efrom', eto: '$eto', proto: '$proto', helo: '$helo'\n";
- #print "stage: '$stage', reply: '$p1'\n";
my ($dsn,$reject_name);
($dsn,$reply) = ($1,$2) if $p1 =~ /^($re_DSN) (.*)$/o;
- #print " dsn: '$dsn', reply: '$reply', key: ", get_reject_key($dsn), "\n";
- # DSN may not be present. Can occur, for example, when queue file size limit is reached,
- # which is logged as a Warning. Ignore these, since they can't be add to any
- # reject section (no SMTP reply code).
+
+ # DSN may not be present. Can occur, for example, when queue
+ # file size limit is reached, which is logged as a Warning.
+ # Ignore these, since they can't be add to any reject section
+ # (no SMTP reply code).
if (! defined $dsn) {
next;
}
# Print the Detail report, if detail is sufficiently high
#
if ($Opts{'detail'} >= 5) {
- #print STDERR "Counts memory usage: ", commify(Devel::Size::total_size(\%Counts)), "\n";
- #print STDERR "Delays memory usage: ", commify(Devel::Size::total_size(\%Delays)), "\n";
print_detail_report(@Sections);
if ($Opts{'delays'}) {
}
-# debug: show which ignore_list items are hit most
-#my %IGNORED;
-#for (sort { $IGNORED{$b} <=> $IGNORED{$a} } keys %IGNORED) {
-# printf "%10d: KEY: %s\n", $IGNORED{$_}, $_;
-#}
-
# Finally, print any unmatched lines
#
print_unmatched_report();
my $line = shift;
foreach (@ignore_list) {
- #return 1 if $line =~ /$_/;
if ($line =~ /$_/) {
- #$IGNORED{$_}++;
return 1;
}
}
}
# Processes postfix/bounce messages
-#
+#
sub postfix_bounce($) {
my $line = shift;
my $type;
# Processes postfix/cleanup messages
# cleanup always has a QID
-#
+#
sub postfix_cleanup($) {
my $line = shift;
my ($qid,$reply,$fmthost,$reject_name);
### cleanup bounced messages (always_bcc, recipient_bcc_maps, sender_bcc_maps)
# Note: Bounce
- # See same code elsewhere "Note: Bounce"
+ # See same code elsewhere "Note: Bounce"
#TDcQ to=<envto@example.com>, relay=none, delay=0.11, delays=0.11/0/0/0, dsn=5.7.1, status=bounced optional text...
#TDcQ to=<envto@example.com>, orig_to=<envto>, relay=none, delay=0.13, delays=0.13/0/0/0, dsn=5.7.1, status=bounced optional text...
if ($line =~ /^to=<(.*?)>,(?: orig_to=<(.*?)>,)? relay=([^,]*).*, ($re_DDD), status=([^ ]+) (.*)$/o) {
# *header_checks and body_checks
elsif (header_body_checks($line)) {
- #print "cleanup: header_body_checks\n";
return;
}
my ($action,$part,$p3) = ($1,$2,$3);
- #print "header_body_checks: action: \"$action\", part: \"$part\", p3: \"$p3\"\n";
-
my ($trigger,$host,$eto,$p4,$fmthost,$reject_name);
# $re_QID: reject: body ...
# $re_QID: reject: header ...
#TDcQ reject: body Quality replica watches!!! from hb.example.com[10.0.0.1]; from=<efrom@example.com> to=<eto@sample.net> proto=SMTP helo=<example.com>: optional text...
#TDcQ reject: header To: <user@example.com> from hb.example.com[10.0.0.1]; from=<efrom@example.com> to=<eto@sample.net> proto=ESMTP helo=<example.com>: optional text...
# message_reject_characters (postfix >= 2.3)
- #TDcQ reject: content Received: by example.com Postfix from example.com[10.0.0.1]; from=<efrom@example.com> to=<eto@sample.net> proto=ESMTP helo=.example.com>: 5.7.1 disallowed character
+ #TDcQ reject: content Received: by example.com Postfix from example.com[10.0.0.1]; from=<efrom@example.com> to=<eto@sample.net> proto=ESMTP helo=.example.com>: 5.7.1 disallowed character
#TDcQ filter: header To: to@example.com from hb.example.com[10.0.0.1]; from=<efrom@example.com> to=<eto@sample.net> proto=ESMTP helo=<example.com>: transport:destination
#TDcQ hold: header Message-ID: <user@example.com> from localhost[127.0.0.1]; from=<efrom@example.com> to=<eto@sample.net> proto=ESMTP helo=<example.com>: optional text...
else {
# smtp_body_checks, smtp_header_checks, smtp_mime_header_checks, smtp_nested_header_checks (postfix >= 2.5)
- #TDsQ replace: header Sender: <from@example.com> : Sender: <fm2@sample.net>
+ #TDsQ replace: header Sender: <from@example.com> : Sender: <fm2@sample.net>
$trigger = $p3; $host = ''; $eto = ''; $p4 = $part eq 'body' ? 'smtp_body_checks' : 'smtp_*header_checks';
#return 1;
}
- #print " trigger: \"$trigger\", host: \"$host\", eto: \"$eto\", p4: \"$p4\"\n";
$trigger =~ s/\s+/ /g;
$trigger = '*unknown reason' if ($trigger eq '');
$eto = '*unknown' if ($eto eq '');
# 84B82AC8B3: milter-reject: END-OF-MESSAGE from localhost[127.0.0.1]: 5.7.1 Blocked
my ($efrom,$eto,$proto,$helo) = strip_ftph($line);
- #print "efrom: '$efrom', eto: '$eto', proto: '$proto', helo: '$helo'\n";
$line =~ s/;$//;
if ($line =~ /^(reject|hold|discard): (\S+) from ([^[]+)\[([^]]+)\](?::\d+)?: (.*)$/) {
my ($action,$stage,$host,$hostip,$reply) = ($1,$2,$3,$4,$5);
- #print "action: '$action', stage: '$stage', host: '$host', hostip: '$hostip', reply: '$reply'\n";
if ($action eq 'reject') {
my ($dsn,$fmthost,$reject_name);
($dsn,$reply) = ($1,$2) if $reply =~ /^($re_DSN) (.*)$/o;
- #print " dsn: '$dsn', reply: '$reply'\n";
if ($Collecting{'byiprejects'} and substr($dsn,0,1) eq '5') {
$fmthost = formathost($hostip,$host);
$line =~ /discarding EHLO keywords: / or
$line =~ /: discard_mask / or
$line =~ /: sq=\d+ cq=\d+ event/ or
- $line =~ /: replacing command "/
+ $line =~ /: replacing command "/ or
+ $line =~ /^(DATA|BDAT) without valid RCPT/
);
($line =~ /^(HANGUP) (?:after \S+)? from \[([^]]+)\](?::\d+)?/)) {
$Counts{'postscreen'}{lc $1}{$2}{$END_KEY}++ if $Collecting{'postscreen'};
}
- elsif ($line =~ /^(WHITELISTED|BLACKLISTED|PASS \S+) \[([^]]+)\](?::\d+)?$/) {
+ elsif ($line =~ /^((ALLOW|WHITE|BLACK|DENY)LISTED|PASS \S+) \[([^]]+)\](?::\d+)?$/) {
+ # This will display two separate counts for e.g. "allowlisted"
+ # and "whitelisted" if you change your configuration in the
+ # middle of the day, but I don't see that as a huge problem.
+ #
+ # ALLOWLISTED [40.92.75.48]:17085
# PASS NEW [192.168.0.2]:12345
# PASS OLD [192.168.0.3]:12345
$Counts{'postscreen'}{lc $1}{$2}{$END_KEY}++ if $Collecting{'postscreen'};
}
}
- elsif ($line =~ /^NOQUEUE: reject: CONNECT from \[([^]]+)\](?::\d+)?: too many connections/) {
- # NOQUEUE: reject: CONNECT from [192.168.0.1]:7197: too many connections
- $Counts{'postscreen'}{'reject'}{'Too many connections'}{$1}{$END_KEY}++ if $Collecting{'postscreen'};
- }
-
- elsif ($line =~ /^reject: connect from \[([^]]+)\](?::\d+)?: (.+)$/) {
- # reject: connect from [192.168.0.1]:21225: all screening ports busy
- $Counts{'postscreen'}{'reject'}{"\u$2"}{$1}{$END_KEY}++ if $Collecting{'postscreen'};
+ elsif ($line =~ /^(NOQUEUE: )?reject: (connect|CONNECT) from \[([^]]+)\](?::\d+)?: (.+)$/) {
+ # NOQUEUE: reject: CONNECT from [192.168.0.1]:7197: too many connections
+ # NOQUEUE: reject: CONNECT from [192.168.0.1]:39410: all server ports busy
+ # reject: connect from [192.168.0.1]:21225: all screening ports busy
+ $Counts{'postscreen'}{'reject'}{"\u$4"}{$3}{$END_KEY}++ if $Collecting{'postscreen'};
}
- elsif ($line =~ /^(?:WHITELIST VETO) \[([^]]+)\](?::\d+)?$/) {
+ elsif ($line =~ /^(?:(WHITE|ALLOW)LIST VETO) \[([^]]+)\](?::\d+)?$/) {
# WHITELIST VETO [192.168.0.8]:43579
- $Counts{'postscreen'}{'whitelist veto'}{$1}{$END_KEY}++ if $Collecting{'postscreen'};
+ $Counts{'postscreen'}{'allowlist veto'}{$1}{$END_KEY}++ if $Collecting{'postscreen'};
}
elsif ($line =~ /^(entering|leaving) STRESS mode with (\d+) connections$/) {
$Totals{'fatalfiletoobig'}++;
- # XXX its not clear this is at all useful - consider falling through to last case
+ # XXX its not clear this is at all useful - consider falling
+ # through to last case
} elsif ( $reason =~ /^config variable (\S*): (.*)$/o ) {
#TD fatal: config variable inet_interfaces: host not found: 10.0.0.1:2525
#TD fatal: config variable inet_interfaces: host not found: all:2525
#TDsd warning: 009314BD9E: read timeout on cleanup socket
$warning =~ s/^$re_QID: (read timeout on \S+ socket)/$1/;
- #TDsd warning: Read failed in network_biopair_interop with errno=0: num_read=0, want_read=11
- #TDs warning: Read failed in network_biopair_interop with errno=0: num_read=0, want_read=11
+ #TDsd warning: Read failed in network_biopair_interop with errno=0: num_read=0, want_read=11
+ #TDs warning: Read failed in network_biopair_interop with errno=0: num_read=0, want_read=11
$warning =~ s/^(Read failed in network_biopair_interop) with .*$/$1/;
=cut
my $fmtdhost = '';
my ($r1, $r2, $dsn, $msg, $host, $event);
- #print "RELAY: $relay, RECIP: $recip, DOMAIN: $domain\n";
- #print "HOSTREPLY: \"$hostreply\"\n";
return ('Accepted', '*unknown') if $hostreply =~ /^25\d/o;
# Host or domain name not found. Name service error for name=example.com type=MX: Host not found...
or $r1 =~ /(?:no such user|user unknown)/i
)
{
- #print "UNKNOWN RECIP: $r1\n";
$r1 = 'Unknown recipient';
}
elsif ($r1 =~ /greylisted/oi) {
- #print "GREYLISTED RECIP: $r1\n";
$r1 = 'Recipient greylisted';
}
elsif ($r1 =~ /^Message temporarily deferred - (\d\.\d+\.\d+)\. Please refer to (.+)$/o) {
$dsn = "$dsn $1"; $r1 = "see $2";
}
elsif ($r1 =~ /^Resources temporarily not available - Please try again later \[#(\d\.\d+\.\d+)\]\.$/o) {
- #Yahoo 451 Resources temporarily not available - Please try again later [#4.16.5].
+ #Yahoo 451 Resources temporarily not available - Please try again later [#4.16.5].
$dsn = "$dsn $1"; $r1 = "resources not available";
}
elsif ($r1 =~ /^Message temporarily deferred - (\[\d+\])/o) {
- # Yahoo: 451 Message temporarily deferred - [160]
+ # Yahoo: 451 Message temporarily deferred - [160]
$dsn = "$dsn $1"; $r1 = '';
}
}
elsif ($hostreply =~ /^connect to (\S+): (.*)$/o) {
- #print "CONNECT: $hostreply\n";
$host = $1; $r1 = $2; $r1 =~ s/server refused to talk to me/refused/;
}
elsif ($hostreply =~ /^host (\S+) refused to talk to me: (.*)$/o) {
$host = $1; $msg = $2;
- #print "HOSTREFUSED: $hostreply\n";
#Yahoo: '421 Message from (10.0.0.1) temporarily deferred - 4.16.50. Please refer to http://...
if ($msg =~ /^(\d+) Message from \([^)]+\) temporarily deferred - (\d\.\d+\.\d+)\. Please refer to (.+)$/) {
$dsn = "$1 $2"; $msg = "see $3";
}
- #$r1 = join(': ', 'refused', $msg);
+
$r1 = $msg;
}
elsif ($hostreply =~ /^(delivery temporarily suspended): connect to (\S+): (.*)$/o) {
- #print "DELIVERY SUSP: $hostreply\n";
$host = $2; $r1 = join(': ', $1, $3);
}
elsif ($hostreply =~ /^(delivery temporarily suspended: conversation) with (\S+) (.*)$/o) {
# delivery temporarily suspended: conversation with example.com[10.0.0.1] timed out while receiving the initial server greeting)
- #print "DELIVERY SUSP2: $hostreply\n";
$host = $2; $r1 = join(' ', $1, $3);
}
elsif (($event,$host,$r1) = ($hostreply =~ /^(lost connection|conversation) with (\S+) (.*)$/o)) {
- #print "LOST conv/conn: $hostreply\n";
$r1 = join(' ',$event,$r1);
}
elsif ($hostreply =~ /^(.*: \S+maildrop: Unable to create a dot-lock) at .*$/o) {
- #print "MAILDROP: $hostreply\n";
$r1 = $1;
}
elsif ($hostreply =~ /^mail for (\S+) loops back to myself/o) {
- #print "LOOP: $hostreply\n";
$host = $1; $r1 = 'mailer loop';
}
elsif ($hostreply =~ /^unable to find primary relay for (\S+)$/o) {
- #print "NORELAY: $hostreply\n";
$host = $1; $r1 = 'no relay found';
}
elsif ($hostreply =~ /^message size \d+ exceeds size limit \d+ of server (\S+)\s*$/o) {
- #print "TOOBIG: $hostreply\n";
$host = $1; $r1 = 'message too big';
}
else {
- #print "UNMATCH: $hostreply\n";
$r1 = $hostreply;
}
- #print "R1: $r1, R2: $r2\n";
$r1 =~ s/for name=\Q$domain\E //ig;
if ($host eq '') {
#
sub strip_ftph($) {
my ($helo, $proto, $to, $from);
- #print "strip_ftph: '$_[0]\n";
$helo = ($_[0] =~ s/\s+helo=<(.*?)>\s*$//) == 1 ? $1 : '*unavailable';
$proto = ($_[0] =~ s/\s+proto=(\S+)\s*$//) == 1 ? $1 : '*unavailable';
$to = ($_[0] =~ s/\s+to=<(.*?)>\s*$//) == 1 ? (lc($1) || '<>') : '*unavailable';
$from = ($_[0] =~ s/\s+from=<(.*?)>\s*$//) == 1 ? ( $1 || '<>') : '*unavailable';
- #print "helo: $helo, proto: $proto, to: $to, from: $from\n";
- #print "strip_ftph: final: '$_[0]'\n";
return ($from,$to,$proto,$helo);
}
# 6. A hash to a divisor used to calculate the percentage of a total for that key
#
# Use begin_section_group/end_section_group to create groupings around sections.
-#
+#
# Sections can be freely reordered if desired, but maintain proper group nesting.
#
#
# require special-case processing to distinguish 4xx temporary rejects from 5xx
# permanent rejects in various Totals{'totalrejects*'} counts, and in the
# Totals{'totalrejects'} tally.
-#
+#
# Sections can be freely reordered if desired.
sub build_sect_table() {
if ($Opts{'debug'} & Logreporters::D_SECT) {
add_section ($S, 'totalacceptplusreject', 0, 'd', 'Total', \$Totals{'totalacceptplusreject'});
end_section_group ($S, 'acceptreject', $sep1);
- # The various Reject sections are built dynamically based upon a list of reject reply keys,
- # which are user-configured via $Opts{'reject_reply_patterns'}
+ # The various Reject sections are built dynamically based upon a
+ # list of reject reply keys, which are user-configured via
+ # $Opts{'reject_reply_patterns'}
@RejectPats = ();
foreach my $rejpat (split /[ ,]/, $Opts{'reject_reply_patterns'}) {
if ($rejpat !~ /^(warn|[45][\d.]{2})$/io) {
my $replyorig = $reply;
($reply) = split / /, $reply;
for (my $i = 0; $i <= $#RejectPats; $i++) {
- #print "TRYING: $RejectPats[$i]\n";
# we'll allow extended DSNs to match (eg. 5.7.1 will match 5..)
if ($reply =~ /^$RejectPats[$i]/) { # no /o here, pattern varies
- #print "MATCHED: orig: $replyorig, reply $reply matched pattern $RejectPats[$i], returning $RejectKeys[$i]\n";
return $RejectKeys[$i];
}
}
- #print "NOT MATCHED: REPLY CODE: '$replyorig', '$reply'\n";
+
return;
}
-# Replace bare reject limiters with specific reject limiters
+# Replace bare reject limiters with specific reject limiters
# based on reject_reply_patterns
#
sub expand_bare_reject_limiters()