From 370fdfce00b1582af42d8716ccf56fbef1b4bec4 Mon Sep 17 00:00:00 2001
From: Wietse Venema
Date: Sun, 27 Dec 2015 00:00:00 -0500
Subject: [PATCH] postfix-3.1-20151227
---
postfix/.indent.pro | 1 +
postfix/HISTORY | 29 +++++
postfix/RELEASE_NOTES | 17 +++
postfix/WISHLIST | 22 ++--
postfix/conf/post-install | 2 +
postfix/html/oqmgr.8.html | 18 ++-
postfix/html/postconf.5.html | 17 +++
postfix/html/postlog.1.html | 8 +-
postfix/html/qmgr.8.html | 18 ++-
postfix/man/man1/postlog.1 | 9 +-
postfix/man/man5/postconf.5 | 11 ++
postfix/man/man8/oqmgr.8 | 5 +
postfix/man/man8/qmgr.8 | 5 +
postfix/mantools/postlink | 1 +
postfix/postfix-install | 15 +--
postfix/proto/postconf.proto | 13 +++
postfix/src/cleanup/Makefile.in | 4 +
postfix/src/cleanup/cleanup.h | 1 +
postfix/src/cleanup/cleanup_envelope.c | 11 ++
postfix/src/cleanup/cleanup_out_recipient.c | 32 ++++++
postfix/src/cleanup/cleanup_state.c | 1 +
postfix/src/global/mail_params.c | 15 +++
postfix/src/global/mail_params.h | 4 +
postfix/src/global/mail_version.h | 2 +-
postfix/src/global/post_mail.c | 118 ++++++++++++++++++++
postfix/src/global/post_mail.h | 4 +-
postfix/src/global/verify.c | 3 +-
postfix/src/oqmgr/qmgr.c | 7 ++
postfix/src/oqmgr/qmgr.h | 1 +
postfix/src/oqmgr/qmgr_message.c | 33 +++++-
postfix/src/postlog/postlog.c | 15 ++-
postfix/src/qmgr/qmgr.c | 7 ++
postfix/src/qmgr/qmgr.h | 1 +
postfix/src/qmgr/qmgr_message.c | 33 +++++-
postfix/src/verify/verify.c | 16 ++-
35 files changed, 442 insertions(+), 57 deletions(-)
diff --git a/postfix/.indent.pro b/postfix/.indent.pro
index 0e9462f19..5502f64db 100644
--- a/postfix/.indent.pro
+++ b/postfix/.indent.pro
@@ -249,6 +249,7 @@
-TPLMYSQL
-TPLPGSQL
-TPOSTMAP_KEY_STATE
+-TPOST_MAIL_FCLOSE_STATE
-TPOST_MAIL_STATE
-TPRIVATE_STR_TABLE
-TPSC_CALL_BACK_ENTRY
diff --git a/postfix/HISTORY b/postfix/HISTORY
index 975fbec70..47bb88bfc 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -22030,3 +22030,32 @@ Apologies for any names omitted.
Bugfix (introduced: 20151128) bogus queue file parsing error.
File: showq/showq.c.
+
+20151226
+
+ Cleanup: postlog(1) now pauses for 1s after reporting a
+ fatal or panic error. This makes behavior of scripts such
+ as postfix-script consistent with built-in error messages.
+ File: postlog/postlog.c.
+
+20151227
+
+ Robustness: don't allow for whitespace in command-line
+ arguments. Files; postfix-install, conf/post-install.
+
+ Robustness: added a comment to discourage people who keep
+ adding code that calls gethostbyname() to determine the
+ default myhostname setting. This is a mistake: all Postfix
+ programs will hang when the DNS is unavailable. File:
+ global/mail_params.c.
+
+ Safety: a limit on the number of address verification probes
+ in the active queue (address_verify_pending_request_limit),
+ by default 1/4 of the active queue maximum size. The queue
+ manager tempfails probe messages that exceed the limit.
+ Files: mantools/postlink, proto/postconf.proto, cleanup/cleanup.h,
+ cleanup/cleanup_envelope.c, cleanup/cleanup_out_recipient.c,
+ cleanup/cleanup_state.c, global/mail_params.h, global/post_mail.c,
+ global/post_mail.h, global/verify.c, oqmgr/qmgr.c, oqmgr/qmgr.h,
+ oqmgr/qmgr_message.c, qmgr/qmgr.c, qmgr/qmgr.h,
+ qmgr/qmgr_message.c, verify/verify.c.
diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES
index 0b51dee8d..08f899c4b 100644
--- a/postfix/RELEASE_NOTES
+++ b/postfix/RELEASE_NOTES
@@ -16,6 +16,23 @@ specifies the release date of a stable release or snapshot release.
If you upgrade from Postfix 2.11 or earlier, read RELEASE_NOTES-3.0
before proceeding.
+
+Major changes with snaphot 20151227
+===================================
+
+This introduces a safety limit on the number of address verification
+probes in the active queue (address_verify_pending_request_limit),
+by default 1/4 of the active queue maximum size. The queue manager
+enforces the limit by tempfailing probe messages that exceed the
+limit. The design avoids dependency on global counters that may get
+out of sync after a process crashes.
+
+Tempfailing requests in this manner is not as bad as one might
+think. The Postfix verify cache proactively updates active addresses
+well before they expire. The address_verify_pending_request_limit
+affects only unknown addresses and inactive addresses that have
+expired (by default, after 31 days).
+
Incompatible change with Postfix snapshot 20150721
--------------------------------------------------
diff --git a/postfix/WISHLIST b/postfix/WISHLIST
index 4f2ec862f..f85ae3197 100644
--- a/postfix/WISHLIST
+++ b/postfix/WISHLIST
@@ -2,6 +2,12 @@ Wish list:
Things to do before the stable release:
+ Viktor's bitrot patches.
+
+ Not: SMTPUTF8 auto-conversion of lookups/matches.
+
+ ---------------------end of Postfix 3.1.0 todo list
+
Spell-check, double-word check, and HTML validator check.
Disable -DSNAPSHOT and -DNONPROD in makedefs.
@@ -17,7 +23,8 @@ Wish list:
smtp_reply_footer() undoable.
Type-checking wrappers for htable(3), ctable(3) and other
- modules that take and return a void* pointer.
+ modules that take and return a void* pointer. This is
+ the next best thing to C++ style HTABLE.
TLS certificate provenance: indicate whether a subject
name/issuer are verified or not (for example, change the
@@ -76,9 +83,8 @@ Wish list:
Log command=good/bad statistics in postscreen?
- Implement smtpd_client_auth_rate limit?
-
- Make the access map BCC action consistent with header_checks.
+ Remember multiple access map BCC actions, for consistency
+ with header_checks.
smtpd_checks tests either must use a DNS dummy resolver
(override the res_search API) or all names must be under
@@ -93,11 +99,6 @@ Wish list:
along with other header-extracted information, and forward
the Message-ID in the bounce server notification request.
- Find a way to show non-default OPT, DEBUG etc. settings at
- the top of the makedefs.out file.
-
- Update smtputf8_enable in postconf(5)
-
Clobber ORCPT when sender is owner-mumble?
Add milter_mumble_macros to the list of per-macro features.
@@ -114,9 +115,6 @@ Wish list:
can return error descriptions instead of terminating with
a fatal error.
- Make sure that proxy: can handle random:, pipe:, and other
- multimaps.
-
Add a switch to consider postscreen deep protocol tests as
"completed" when receiving "RSET" after "RCPT TO" and the
session has passed all tests up to that point. RSET becomes
diff --git a/postfix/conf/post-install b/postfix/conf/post-install
index d5db2600e..904cefa58 100644
--- a/postfix/conf/post-install
+++ b/postfix/conf/post-install
@@ -234,6 +234,8 @@ obsolete=; keep_list=;
for arg
do
case $arg in
+ *[" "]*) echo $0: "Error: argument contains whitespace: '$arg'"
+ exit 1;;
*=*) IFS= eval $arg; IFS="$BACKUP_IFS";;
create-missing) create=1;;
set-perm*) create=1; set_perms=1;;
diff --git a/postfix/html/oqmgr.8.html b/postfix/html/oqmgr.8.html
index d97ffc8d2..d952c0c7c 100644
--- a/postfix/html/oqmgr.8.html
+++ b/postfix/html/oqmgr.8.html
@@ -314,9 +314,15 @@ OQMGR(8) OQMGR(8)
The time limit for the queue manager to send or receive informa-
tion over an internal communication channel.
+ Available in Postfix version 3.1 and later:
+
+ address_verify_pending_request_limit (see 'postconf -d' output)
+ A safety limit that prevents address verification requests from
+ overwhelming the Postfix queue.
+
MISCELLANEOUS CONTROLS
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and master.cf con-
+ The default location of the Postfix main.cf and master.cf con-
figuration files.
defer_transports (empty)
@@ -324,11 +330,11 @@ OQMGR(8) OQMGR(8)
mail unless someone issues "sendmail -q" or equivalent.
delay_logging_resolution_limit (2)
- The maximal number of digits after the decimal point when log-
+ The maximal number of digits after the decimal point when log-
ging sub-second delay values.
helpful_warnings (yes)
- Log warnings about problematic configuration settings, and pro-
+ Log warnings about problematic configuration settings, and pro-
vide helpful suggestions.
process_id (read-only)
@@ -344,14 +350,14 @@ OQMGR(8) OQMGR(8)
The syslog facility of Postfix logging.
syslog_name (see 'postconf -d' output)
- The mail system name that is prepended to the process name in
- syslog records, so that "smtpd" becomes, for example, "post-
+ The mail system name that is prepended to the process name in
+ syslog records, so that "smtpd" becomes, for example, "post-
fix/smtpd".
Available in Postfix version 3.0 and later:
confirm_delay_cleared (no)
- After sending a "your message is delayed" notification, inform
+ After sending a "your message is delayed" notification, inform
the sender when the delay clears up.
FILES
diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html
index 67edf42b6..0cab4cfd1 100644
--- a/postfix/html/postconf.5.html
+++ b/postfix/html/postconf.5.html
@@ -294,6 +294,23 @@ This feature is available in Postfix 2.1 and later.
+
+
+address_verify_pending_request_limit
+(default: see "postconf -d" output)
+
+ A safety limit that prevents address verification requests from
+overwhelming the Postfix queue. By default, the number of pending
+requests is limited to 1/4 of the active queue maximum size
+(qmgr_message_active_limit). The queue manager enforces the limit
+by tempfailing requests that exceed the limit. This affects only
+unknown addresses and inactive addresses that have expired, because
+the verify(8) daemon automatically refreshes an active address
+before it expires.
+
+ This feature is available in Postfix 3.1 and later.
+
+
address_verify_poll_count
diff --git a/postfix/html/postlog.1.html b/postfix/html/postlog.1.html
index 3ecbcbc08..514e7f305 100644
--- a/postfix/html/postlog.1.html
+++ b/postfix/html/postlog.1.html
@@ -31,9 +31,11 @@ POSTLOG(1) POSTLOG(1)
-i Include the process ID in the logging tag.
- -p priority
- Specifies the logging severity: info (default), warn, error,
- fatal, or panic.
+ -p priority (default: info)
+ Specifies the logging severity: info, warn, error, fatal, or
+ panic. With Postfix 3.1 and later, the program will pause for 1
+ second after reporting a fatal or panic condition, just like
+ other Postfix programs.
-t tag Specifies the logging tag, that is, the identifying name that
appears at the beginning of each logging record. A default tag
diff --git a/postfix/html/qmgr.8.html b/postfix/html/qmgr.8.html
index 7f2225d4c..a919a173d 100644
--- a/postfix/html/qmgr.8.html
+++ b/postfix/html/qmgr.8.html
@@ -376,9 +376,15 @@ QMGR(8) QMGR(8)
The time limit for the queue manager to send or receive informa-
tion over an internal communication channel.
+ Available in Postfix version 3.1 and later:
+
+ address_verify_pending_request_limit (see 'postconf -d' output)
+ A safety limit that prevents address verification requests from
+ overwhelming the Postfix queue.
+
MISCELLANEOUS CONTROLS
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and master.cf con-
+ The default location of the Postfix main.cf and master.cf con-
figuration files.
defer_transports (empty)
@@ -386,11 +392,11 @@ QMGR(8) QMGR(8)
mail unless someone issues "sendmail -q" or equivalent.
delay_logging_resolution_limit (2)
- The maximal number of digits after the decimal point when log-
+ The maximal number of digits after the decimal point when log-
ging sub-second delay values.
helpful_warnings (yes)
- Log warnings about problematic configuration settings, and pro-
+ Log warnings about problematic configuration settings, and pro-
vide helpful suggestions.
process_id (read-only)
@@ -406,14 +412,14 @@ QMGR(8) QMGR(8)
The syslog facility of Postfix logging.
syslog_name (see 'postconf -d' output)
- The mail system name that is prepended to the process name in
- syslog records, so that "smtpd" becomes, for example, "post-
+ The mail system name that is prepended to the process name in
+ syslog records, so that "smtpd" becomes, for example, "post-
fix/smtpd".
Available in Postfix version 3.0 and later:
confirm_delay_cleared (no)
- After sending a "your message is delayed" notification, inform
+ After sending a "your message is delayed" notification, inform
the sender when the delay clears up.
FILES
diff --git a/postfix/man/man1/postlog.1 b/postfix/man/man1/postlog.1
index b1fc21822..8aa798b54 100644
--- a/postfix/man/man1/postlog.1
+++ b/postfix/man/man1/postlog.1
@@ -32,9 +32,12 @@ Read the \fBmain.cf\fR configuration file in the named directory
instead of the default configuration directory.
.IP \fB\-i\fR
Include the process ID in the logging tag.
-.IP "\fB\-p \fIpriority\fR"
-Specifies the logging severity: \fBinfo\fR (default), \fBwarn\fR,
-\fBerror\fR, \fBfatal\fR, or \fBpanic\fR.
+.IP "\fB\-p \fIpriority\fR (default: \fBinfo\fR)"
+Specifies the logging severity: \fBinfo\fR, \fBwarn\fR,
+\fBerror\fR, \fBfatal\fR, or \fBpanic\fR. With Postfix 3.1
+and later, the program will pause for 1 second after reporting
+a \fBfatal\fR or \fBpanic\fR condition, just like other
+Postfix programs.
.IP "\fB\-t \fItag\fR"
Specifies the logging tag, that is, the identifying name that
appears at the beginning of each logging record. A default tag
diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5
index 24cdf21e0..273a6164f 100644
--- a/postfix/man/man5/postconf.5
+++ b/postfix/man/man5/postconf.5
@@ -177,6 +177,17 @@ be refreshed.
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
.PP
This feature is available in Postfix 2.1 and later.
+.SH address_verify_pending_request_limit (default: see "postconf \-d" output)
+A safety limit that prevents address verification requests from
+overwhelming the Postfix queue. By default, the number of pending
+requests is limited to 1/4 of the active queue maximum size
+(qmgr_message_active_limit). The queue manager enforces the limit
+by tempfailing requests that exceed the limit. This affects only
+unknown addresses and inactive addresses that have expired, because
+the \fBverify\fR(8) daemon automatically refreshes an active address
+before it expires.
+.PP
+This feature is available in Postfix 3.1 and later.
.SH address_verify_poll_count (default: normal: 3, overload: 1)
How many times to query the \fBverify\fR(8) service for the completion
of an address verification request in progress.
diff --git a/postfix/man/man8/oqmgr.8 b/postfix/man/man8/oqmgr.8
index 46514085a..54a01f060 100644
--- a/postfix/man/man8/oqmgr.8
+++ b/postfix/man/man8/oqmgr.8
@@ -308,6 +308,11 @@ a request before it is terminated by a built\-in watchdog timer.
.IP "\fBqmgr_ipc_timeout (60s)\fR"
The time limit for the queue manager to send or receive information
over an internal communication channel.
+.PP
+Available in Postfix version 3.1 and later:
+.IP "\fBaddress_verify_pending_request_limit (see 'postconf -d' output)\fR"
+A safety limit that prevents address verification requests
+from overwhelming the Postfix queue.
.SH "MISCELLANEOUS CONTROLS"
.na
.nf
diff --git a/postfix/man/man8/qmgr.8 b/postfix/man/man8/qmgr.8
index 400f789c5..de116a043 100644
--- a/postfix/man/man8/qmgr.8
+++ b/postfix/man/man8/qmgr.8
@@ -356,6 +356,11 @@ a request before it is terminated by a built\-in watchdog timer.
.IP "\fBqmgr_ipc_timeout (60s)\fR"
The time limit for the queue manager to send or receive information
over an internal communication channel.
+.PP
+Available in Postfix version 3.1 and later:
+.IP "\fBaddress_verify_pending_request_limit (see 'postconf -d' output)\fR"
+A safety limit that prevents address verification requests
+from overwhelming the Postfix queue.
.SH "MISCELLANEOUS CONTROLS"
.na
.nf
diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink
index 82ec6bece..2d1ab0736 100755
--- a/postfix/mantools/postlink
+++ b/postfix/mantools/postlink
@@ -89,6 +89,7 @@ while (<>) {
s;\baddress_verify_service_name\b;$&;g;
s;\baddress_verify_transport_maps\b;$&;g;
s;\baddress_verify_virtual_transport\b;$&;g;
+ s;\baddress_verify_pending_request_limit\b;$&;g;
s;\bsmtp_address_verify_target\b;$&;g;
s;\blmtp_address_verify_target\b;$&;g;
s;\balias_database\b;$&;g;
diff --git a/postfix/postfix-install b/postfix/postfix-install
index 01d17b485..b80069093 100644
--- a/postfix/postfix-install
+++ b/postfix/postfix-install
@@ -216,10 +216,11 @@ USAGE="Usage: $0 [name=value] [option]
for arg
do
case $arg in
- *=*) IFS= eval $arg; IFS="$BACKUP_IFS";;
--non-int*) non_interactive=1;;
- -package) need_install_root=install_root;;
- *) echo "$0: Error: $USAGE" 1>&2; exit 1;;
+*[" "]*) echo "$0: Error: argument contains whitespace: '$arg'"; exit 1;;
+ *=*) IFS= eval $arg; IFS="$BACKUP_IFS";;
+ -non-int*) non_interactive=1;;
+ -package) need_install_root=install_root;;
+ *) echo "$0: Error: $USAGE" 1>&2; exit 1;;
esac
shift
done
@@ -597,14 +598,14 @@ do
esac
done
-# Don't allow whitespace in parameter settings.
+# Don't allow space or tab in parameter settings.
for name in $CONFIG_PARAMS sample_directory
do
eval junk=\$$name
case "$junk" in
-*" "*|*" "*) echo $0: Error: $name value contains whitespace: "'$junk'" 1>&2
- exit 1;;
+*"[ ]"*) echo "$0: Error: $name value contains whitespace: '$junk'" 1>&2
+ exit 1;;
esac
done
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto
index 7097015fd..33cf62923 100644
--- a/postfix/proto/postconf.proto
+++ b/postfix/proto/postconf.proto
@@ -16592,3 +16592,16 @@ clients).
This feature is available in Postfix 3.1 and later.
+
+%PARAM address_verify_pending_request_limit see "postconf -d" output
+
+ A safety limit that prevents address verification requests from
+overwhelming the Postfix queue. By default, the number of pending
+requests is limited to 1/4 of the active queue maximum size
+(qmgr_message_active_limit). The queue manager enforces the limit
+by tempfailing requests that exceed the limit. This affects only
+unknown addresses and inactive addresses that have expired, because
+the verify(8) daemon automatically refreshes an active address
+before it expires.
+
+ This feature is available in Postfix 3.1 and later.
diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in
index ad479d09c..e44418862 100644
--- a/postfix/src/cleanup/Makefile.in
+++ b/postfix/src/cleanup/Makefile.in
@@ -760,7 +760,9 @@ cleanup_envelope.o: ../../include/attr.h
cleanup_envelope.o: ../../include/been_here.h
cleanup_envelope.o: ../../include/check_arg.h
cleanup_envelope.o: ../../include/cleanup_user.h
+cleanup_envelope.o: ../../include/deliver_request.h
cleanup_envelope.o: ../../include/dict.h
+cleanup_envelope.o: ../../include/dsn.h
cleanup_envelope.o: ../../include/dsn_mask.h
cleanup_envelope.o: ../../include/header_body_checks.h
cleanup_envelope.o: ../../include/header_opts.h
@@ -775,6 +777,7 @@ cleanup_envelope.o: ../../include/match_list.h
cleanup_envelope.o: ../../include/milter.h
cleanup_envelope.o: ../../include/mime_state.h
cleanup_envelope.o: ../../include/msg.h
+cleanup_envelope.o: ../../include/msg_stats.h
cleanup_envelope.o: ../../include/myflock.h
cleanup_envelope.o: ../../include/mymalloc.h
cleanup_envelope.o: ../../include/nvtable.h
@@ -1161,6 +1164,7 @@ cleanup_out_recipient.o: ../../include/sys_defs.h
cleanup_out_recipient.o: ../../include/tok822.h
cleanup_out_recipient.o: ../../include/trace.h
cleanup_out_recipient.o: ../../include/vbuf.h
+cleanup_out_recipient.o: ../../include/verify.h
cleanup_out_recipient.o: ../../include/vstream.h
cleanup_out_recipient.o: ../../include/vstring.h
cleanup_out_recipient.o: cleanup.h
diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h
index 9bd7f1b87..a0dc9fbc9 100644
--- a/postfix/src/cleanup/cleanup.h
+++ b/postfix/src/cleanup/cleanup.h
@@ -64,6 +64,7 @@ typedef struct CLEANUP_STATE {
ARGV *auto_hdrs; /* MTA's own header(s) */
ARGV *hbc_rcpt; /* header/body checks BCC addresses */
int flags; /* processing options, status flags */
+ int tflags; /* User- or MTA-requested tracing */
int qmgr_opts; /* qmgr processing options */
int errs; /* any badness experienced */
int err_mask; /* allowed badness */
diff --git a/postfix/src/cleanup/cleanup_envelope.c b/postfix/src/cleanup/cleanup_envelope.c
index 261542ba8..abdc8f5d0 100644
--- a/postfix/src/cleanup/cleanup_envelope.c
+++ b/postfix/src/cleanup/cleanup_envelope.c
@@ -68,6 +68,7 @@
#include
#include
#include
+#include
/* Application-specific. */
@@ -488,6 +489,16 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
return;
}
}
+ if (strcmp(attr_name, MAIL_ATTR_TRACE_FLAGS) == 0) {
+ if (!alldig(attr_value)) {
+ msg_warn("%s: message rejected: bad TFLAG record <%.200s>",
+ state->queue_id, buf);
+ state->errs |= CLEANUP_STAT_BAD;
+ return;
+ }
+ if (state->tflags == 0)
+ state->tflags = DEL_REQ_TRACE_FLAGS(atoi(attr_value));
+ }
nvtable_update(state->attr, attr_name, attr_value);
cleanup_out(state, type, buf, len);
return;
diff --git a/postfix/src/cleanup/cleanup_out_recipient.c b/postfix/src/cleanup/cleanup_out_recipient.c
index 25ffb9052..bbe080365 100644
--- a/postfix/src/cleanup/cleanup_out_recipient.c
+++ b/postfix/src/cleanup/cleanup_out_recipient.c
@@ -76,6 +76,7 @@
#include
#include
#include
+#include
#include /* cleanup_trace_path */
#include
#include
@@ -104,6 +105,20 @@ static void cleanup_trace_append(CLEANUP_STATE *state, RECIPIENT *rcpt,
}
}
+/* cleanup_verify_append - update verify daemon */
+
+static void cleanup_verify_append(CLEANUP_STATE *state, RECIPIENT *rcpt,
+ DSN *dsn, int verify_status)
+{
+ MSG_STATS stats;
+
+ if (verify_append(state->queue_id, CLEANUP_MSG_STATS(&stats, state),
+ rcpt, "none", dsn, verify_status) != 0) {
+ msg_warn("%s: verify service update error", state->queue_id);
+ state->errs |= CLEANUP_STAT_WRITE;
+ }
+}
+
/* cleanup_out_recipient - envelope recipient output filter */
void cleanup_out_recipient(CLEANUP_STATE *state,
@@ -193,6 +208,15 @@ void cleanup_out_recipient(CLEANUP_STATE *state,
* recipient information, also ignore differences in DSN attributes. We
* do, however, keep the DSN attributes of the recipient that survives
* duplicate elimination.
+ *
+ * In the case of a verify(8) request for a one-to-many alias, declare the
+ * alias address as "deliverable". Do not verify the individual addresses
+ * in the expansion because that results in multiple verify(8) updates
+ * for one verify(8) request.
+ *
+ * Multiple verify(8) updates for one verify(8) request would overwrite
+ * each other's status, and if the last status update is "undeliverable",
+ * then the whole alias is flagged as undeliverable.
*/
else {
RECIPIENT rcpt;
@@ -200,6 +224,14 @@ void cleanup_out_recipient(CLEANUP_STATE *state,
argv = cleanup_map1n_internal(state, recip, cleanup_virt_alias_maps,
cleanup_ext_prop_mask & EXT_PROP_VIRTUAL);
+ if (argv->argc > 1 && (state->tflags & DEL_REQ_FLAG_MTA_VRFY)) {
+ (void) DSN_SIMPLE(&dsn, "2.0.0", "aliased to multiple recipients");
+ dsn.action = "deliverable";
+ RECIPIENT_ASSIGN(&rcpt, 0, dsn_orcpt, dsn_notify, orcpt, recip);
+ cleanup_verify_append(state, &rcpt, &dsn, DEL_RCPT_STAT_OK);
+ argv_free(argv);
+ return;
+ }
if ((dsn_notify & DSN_NOTIFY_SUCCESS)
&& (argv->argc > 1 || strcmp(recip, argv->argv[0]) != 0)) {
(void) DSN_SIMPLE(&dsn, "2.0.0", "alias expanded");
diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c
index 0d71b44ab..17a46172b 100644
--- a/postfix/src/cleanup/cleanup_state.c
+++ b/postfix/src/cleanup/cleanup_state.c
@@ -81,6 +81,7 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src)
state->auto_hdrs = argv_alloc(1);
state->hbc_rcpt = 0;
state->flags = 0;
+ state->tflags = 0;
state->qmgr_opts = 0;
state->errs = 0;
state->err_mask = 0;
diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c
index 85e1ecfdb..4842d572f 100644
--- a/postfix/src/global/mail_params.c
+++ b/postfix/src/global/mail_params.c
@@ -368,13 +368,21 @@ static const char *check_myhostname(void)
/*
* If the local machine name is not in FQDN form, try to append the
* contents of $mydomain. Use a default domain as a final workaround.
+ *
+ * DO NOT CALL GETHOSTBYNAME OR GETNAMEINFO HERE - IT MAKES EVERY POSTFIX
+ * PROGRAM HANG WHEN DNS SERVICE IS UNAVAILABLE. IF YOU DON'T LIKE THE
+ * DEFAULT, THEN EDIT MAIN.CF.
*/
name = get_hostname();
+ /* DO NOT CALL GETHOSTBYNAME OR GETNAMEINFO HERE - EDIT MAIN.CF */
if ((dot = strchr(name, '.')) == 0) {
+ /* DO NOT CALL GETHOSTBYNAME OR GETNAMEINFO HERE - EDIT MAIN.CF */
if ((domain = mail_conf_lookup_eval(VAR_MYDOMAIN)) == 0)
domain = DEF_MYDOMAIN;
+ /* DO NOT CALL GETHOSTBYNAME OR GETNAMEINFO HERE - EDIT MAIN.CF */
name = concatenate(name, ".", domain, (char *) 0);
}
+ /* DO NOT CALL GETHOSTBYNAME OR GETNAMEINFO HERE - EDIT MAIN.CF */
return (name);
}
@@ -386,9 +394,16 @@ static const char *check_mydomainname(void)
/*
* Use a default domain when the hostname is not a FQDN ("foo").
+ *
+ * DO NOT CALL GETHOSTBYNAME OR GETNAMEINFO HERE - IT MAKES EVERY POSTFIX
+ * PROGRAM HANG WHEN DNS SERVICE IS UNAVAILABLE. IF YOU DON'T LIKE THE
+ * DEFAULT, THEN EDIT MAIN.CF.
*/
+ /* DO NOT CALL GETHOSTBYNAME OR GETNAMEINFO HERE - EDIT MAIN.CF */
if ((dot = strchr(var_myhostname, '.')) == 0)
+ /* DO NOT CALL GETHOSTBYNAME OR GETNAMEINFO HERE - EDIT MAIN.CF */
return (DEF_MYDOMAIN);
+ /* DO NOT CALL GETHOSTBYNAME OR GETNAMEINFO HERE - EDIT MAIN.CF */
return (dot + 1);
}
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index 91c7f126e..81464b1e0 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -2706,6 +2706,10 @@ extern int var_scache_ttl_lim;
#define DEF_SCACHE_STAT_TIME "600s"
extern int var_scache_stat_time;
+#define VAR_VRFY_PEND_LIMIT "address_verify_pending_request_limit"
+#define DEF_VRFY_PEND_LIMIT (DEF_QMGR_ACT_LIMIT / 4)
+extern int var_vrfy_pend_limit;
+
/*
* Address verification service.
*/
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index e7538e5b7..3fa1ccd16 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20151218"
+#define MAIL_RELEASE_DATE "20151227"
#define MAIL_VERSION_NUMBER "3.1"
#ifdef SNAPSHOT
diff --git a/postfix/src/global/post_mail.c b/postfix/src/global/post_mail.c
index 002b8d99d..fbb631d9b 100644
--- a/postfix/src/global/post_mail.c
+++ b/postfix/src/global/post_mail.c
@@ -54,6 +54,11 @@
/*
/* int post_mail_fclose(stream)
/* VSTREAM *STREAM;
+/*
+/* void post_mail_fclose_async(stream, notify, context)
+/* VSTREAM *stream;
+/* void (*notify)(int status, void *context);
+/* void *context;
/* DESCRIPTION
/* This module provides a convenient interface for the most
/* common case of sending one message to one recipient. It
@@ -91,6 +96,11 @@
/*
/* post_mail_fclose() completes the posting of a message.
/*
+/* post_mail_fclose_async() completes the posting of a message
+/* and upon completion invokes the caller-specified notify
+/* routine, with the cleanup status and caller-specified context
+/* as arguments.
+/*
/* Arguments:
/* .IP sender
/* The sender envelope address. It is up to the application
@@ -187,6 +197,16 @@ typedef struct {
VSTRING *queue_id;
} POST_MAIL_STATE;
+ /*
+ * Call-back state for asynchronous close requests.
+ */
+typedef struct {
+ int status;
+ VSTREAM *stream;
+ POST_MAIL_FCLOSE_NOTIFY notify;
+ void *context;
+} POST_MAIL_FCLOSE_STATE;
+
/* post_mail_init - initial negotiations */
static void post_mail_init(VSTREAM *stream, const char *sender,
@@ -205,6 +225,13 @@ static void post_mail_init(VSTREAM *stream, const char *sender,
GETTIMEOFDAY(&now);
date = mail_date(now.tv_sec);
+ /*
+ * XXX Don't flush buffers while sending the initial message records.
+ * That would cause deadlock between verify(8) and cleanup(8) servers.
+ */
+ vstream_control(stream, VSTREAM_CTL_BUFSIZE, 2 * VSTREAM_BUFSIZE,
+ VSTREAM_CTL_END);
+
/*
* Negotiate with the cleanup service. Give up if we can't agree.
*/
@@ -435,3 +462,94 @@ int post_mail_fclose(VSTREAM *cleanup)
(void) vstream_fclose(cleanup);
return (status);
}
+
+/* post_mail_fclose_event - event handler */
+
+static void post_mail_fclose_event(int event, void *context)
+{
+ POST_MAIL_FCLOSE_STATE *state = (POST_MAIL_FCLOSE_STATE *) context;
+ int status = state->status;
+
+ switch (event) {
+
+ /*
+ * Final server reply. Pick up the completion status.
+ */
+ case EVENT_READ:
+ if (status == 0) {
+ if (vstream_ferror(state->stream) != 0
+ || attr_scan(state->stream, ATTR_FLAG_MISSING,
+ ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status,
+ ATTR_TYPE_END) != 1)
+ status = CLEANUP_STAT_WRITE;
+ }
+ break;
+
+ /*
+ * No response or error.
+ */
+ default:
+ msg_warn("error talking to service: %s", var_cleanup_service);
+ status = CLEANUP_STAT_WRITE;
+ break;
+ }
+
+ /*
+ * Stop the watchdog timer, and disable further read events that end up
+ * calling this function.
+ */
+ event_cancel_timer(post_mail_fclose_event, context);
+ event_disable_readwrite(vstream_fileno(state->stream));
+
+ /*
+ * Notify the requestor and clean up.
+ */
+ state->notify(status, state->context);
+ (void) vstream_fclose(state->stream);
+ myfree((void *) state);
+}
+
+/* post_mail_fclose_async - finish posting of message */
+
+void post_mail_fclose_async(VSTREAM *stream,
+ void (*notify) (int status, void *context),
+ void *context)
+{
+ POST_MAIL_FCLOSE_STATE *state;
+ int status = 0;
+
+
+ /*
+ * Send the message end marker only when there were no errors.
+ */
+ if (vstream_ferror(stream) != 0) {
+ status = CLEANUP_STAT_WRITE;
+ } else {
+ rec_fputs(stream, REC_TYPE_XTRA, "");
+ rec_fputs(stream, REC_TYPE_END, "");
+ if (vstream_fflush(stream))
+ status = CLEANUP_STAT_WRITE;
+ }
+
+ /*
+ * Bundle up the suspended state.
+ */
+ state = (POST_MAIL_FCLOSE_STATE *) mymalloc(sizeof(*state));
+ state->status = status;
+ state->stream = stream;
+ state->notify = notify;
+ state->context = context;
+
+ /*
+ * To keep interfaces as simple as possible we report all errors via the
+ * same interface as all successes.
+ */
+ if (status == 0) {
+ event_enable_read(vstream_fileno(stream), post_mail_fclose_event,
+ (void *) state);
+ event_request_timer(post_mail_fclose_event, (void *) state,
+ var_daemon_timeout);
+ } else {
+ event_request_timer(post_mail_fclose_event, (void *) state, 0);
+ }
+}
diff --git a/postfix/src/global/post_mail.h b/postfix/src/global/post_mail.h
index 70bb34f0d..eb7974a07 100644
--- a/postfix/src/global/post_mail.h
+++ b/postfix/src/global/post_mail.h
@@ -28,7 +28,7 @@
/*
* External interface.
*/
-typedef void (*POST_MAIL_NOTIFY)(VSTREAM *, void *);
+typedef void (*POST_MAIL_NOTIFY) (VSTREAM *, void *);
extern VSTREAM *post_mail_fopen(const char *, const char *, int, int, int, VSTRING *);
extern VSTREAM *post_mail_fopen_nowait(const char *, const char *, int, int, int, VSTRING *);
extern void post_mail_fopen_async(const char *, const char *, int, int, int, VSTRING *, POST_MAIL_NOTIFY, void *);
@@ -36,6 +36,8 @@ extern int PRINTFLIKE(2, 3) post_mail_fprintf(VSTREAM *, const char *,...);
extern int post_mail_fputs(VSTREAM *, const char *);
extern int post_mail_buffer(VSTREAM *, const char *, int);
extern int post_mail_fclose(VSTREAM *);
+typedef void (*POST_MAIL_FCLOSE_NOTIFY) (int, void *);
+extern void post_mail_fclose_async(VSTREAM *, POST_MAIL_FCLOSE_NOTIFY, void *);
#define POST_MAIL_BUFFER(v, b) \
post_mail_buffer((v), vstring_str(b), VSTRING_LEN(b))
diff --git a/postfix/src/global/verify.c b/postfix/src/global/verify.c
index d6bf36f67..8b20ac710 100644
--- a/postfix/src/global/verify.c
+++ b/postfix/src/global/verify.c
@@ -102,8 +102,9 @@ int verify_append(const char *queue_id, MSG_STATS *stats,
if (var_verify_neg_cache || vrfy_stat == DEL_RCPT_STAT_OK) {
req_stat = verify_clnt_update(recipient->orig_addr, vrfy_stat,
my_dsn.reason);
+ /* Two verify updates for one verify request! */
if (req_stat == VRFY_STAT_OK
- && strcasecmp_utf8(recipient->address, recipient->orig_addr) != 0)
+ && strcasecmp_utf8(recipient->address, recipient->orig_addr) != 0)
req_stat = verify_clnt_update(recipient->address, vrfy_stat,
my_dsn.reason);
} else {
diff --git a/postfix/src/oqmgr/qmgr.c b/postfix/src/oqmgr/qmgr.c
index cca95c773..4ea89e700 100644
--- a/postfix/src/oqmgr/qmgr.c
+++ b/postfix/src/oqmgr/qmgr.c
@@ -272,6 +272,11 @@
/* .IP "\fBqmgr_ipc_timeout (60s)\fR"
/* The time limit for the queue manager to send or receive information
/* over an internal communication channel.
+/* .PP
+/* Available in Postfix version 3.1 and later:
+/* .IP "\fBaddress_verify_pending_request_limit (see 'postconf -d' output)\fR"
+/* A safety limit that prevents address verification requests
+/* from overwhelming the Postfix queue.
/* MISCELLANEOUS CONTROLS
/* .ad
/* .fi
@@ -405,6 +410,7 @@ char *var_def_filter_nexthop;
int var_qmgr_daemon_timeout;
int var_qmgr_ipc_timeout;
int var_dsn_delay_cleared;
+int var_vrfy_pend_limit;
static QMGR_SCAN *qmgr_scans[2];
@@ -664,6 +670,7 @@ int main(int argc, char **argv)
VAR_LOCAL_RCPT_LIMIT, DEF_LOCAL_RCPT_LIMIT, &var_local_rcpt_lim, 0, 0,
VAR_LOCAL_CON_LIMIT, DEF_LOCAL_CON_LIMIT, &var_local_con_lim, 0, 0,
VAR_CONC_COHORT_LIM, DEF_CONC_COHORT_LIM, &var_conc_cohort_limit, 0, 0,
+ VAR_VRFY_PEND_LIMIT, DEF_VRFY_PEND_LIMIT, &var_vrfy_pend_limit, 1, 0,
0,
};
static const CONFIG_BOOL_TABLE bool_table[] = {
diff --git a/postfix/src/oqmgr/qmgr.h b/postfix/src/oqmgr/qmgr.h
index b8c8d0e48..db4b394eb 100644
--- a/postfix/src/oqmgr/qmgr.h
+++ b/postfix/src/oqmgr/qmgr.h
@@ -330,6 +330,7 @@ struct QMGR_MESSAGE {
extern int qmgr_message_count;
extern int qmgr_recipient_count;
+extern int qmgr_vrfy_pend_count;
extern void qmgr_message_free(QMGR_MESSAGE *);
extern void qmgr_message_update_warn(QMGR_MESSAGE *);
diff --git a/postfix/src/oqmgr/qmgr_message.c b/postfix/src/oqmgr/qmgr_message.c
index 5b8596b07..26d9bd37e 100644
--- a/postfix/src/oqmgr/qmgr_message.c
+++ b/postfix/src/oqmgr/qmgr_message.c
@@ -8,6 +8,7 @@
/*
/* int qmgr_message_count;
/* int qmgr_recipient_count;
+/* int qmgr_vrfy_pend_count;
/*
/* QMGR_MESSAGE *qmgr_message_alloc(class, name, qflags, mode)
/* const char *class;
@@ -38,6 +39,13 @@
/* of in-core recipient structures (i.e. the sum of all recipients
/* in all in-core message structures).
/*
+/* qmgr_vrfy_pend_count is a global counter for the total
+/* number of in-core message structures that are associated
+/* with an address verification request. Requests that exceed
+/* the address_verify_pending_limit are deferred immediately.
+/* This is a backup mechanism for a more refined enforcement
+/* mechanism in the verify(8) daemon.
+/*
/* qmgr_message_alloc() creates an in-core message structure
/* with sender and recipient information taken from the named queue
/* file. A null result means the queue file could not be read or
@@ -136,6 +144,7 @@
int qmgr_message_count;
int qmgr_recipient_count;
+int qmgr_vrfy_pend_count;
/* qmgr_message_create - create in-core message structure */
@@ -705,11 +714,15 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
* after the logfile is deleted.
*/
else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
- message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
- if (message->tflags == DEL_REQ_FLAG_RECORD)
- message->tflags_offset = curr_offset;
- else
- message->tflags_offset = 0;
+ if (message->tflags == 0) {
+ message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
+ if (message->tflags == DEL_REQ_FLAG_RECORD)
+ message->tflags_offset = curr_offset;
+ else
+ message->tflags_offset = 0;
+ if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0)
+ qmgr_vrfy_pend_count++;
+ }
}
continue;
}
@@ -1107,6 +1120,14 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
}
}
+ /*
+ * Safety: defer excess address verification requests.
+ */
+ if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0
+ && qmgr_vrfy_pend_count > var_vrfy_pend_limit)
+ QMGR_REDIRECT(&reply, MAIL_SERVICE_RETRY,
+ "4.3.2 Too many address verification requests");
+
/*
* Look up or instantiate the proper transport.
*/
@@ -1310,6 +1331,8 @@ void qmgr_message_free(QMGR_MESSAGE *message)
myfree(message->rewrite_context);
recipient_list_free(&message->rcpt_list);
qmgr_message_count--;
+ if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0)
+ qmgr_vrfy_pend_count--;
myfree((void *) message);
}
diff --git a/postfix/src/postlog/postlog.c b/postfix/src/postlog/postlog.c
index 518f45a1a..7403b079c 100644
--- a/postfix/src/postlog/postlog.c
+++ b/postfix/src/postlog/postlog.c
@@ -26,9 +26,12 @@
/* instead of the default configuration directory.
/* .IP \fB-i\fR
/* Include the process ID in the logging tag.
-/* .IP "\fB-p \fIpriority\fR"
-/* Specifies the logging severity: \fBinfo\fR (default), \fBwarn\fR,
-/* \fBerror\fR, \fBfatal\fR, or \fBpanic\fR.
+/* .IP "\fB-p \fIpriority\fR (default: \fBinfo\fR)"
+/* Specifies the logging severity: \fBinfo\fR, \fBwarn\fR,
+/* \fBerror\fR, \fBfatal\fR, or \fBpanic\fR. With Postfix 3.1
+/* and later, the program will pause for 1 second after reporting
+/* a \fBfatal\fR or \fBpanic\fR condition, just like other
+/* Postfix programs.
/* .IP "\fB-t \fItag\fR"
/* Specifies the logging tag, that is, the identifying name that
/* appears at the beginning of each logging record. A default tag
@@ -261,5 +264,11 @@ int main(int argc, char **argv)
} else {
log_stream(level, VSTREAM_IN);
}
+
+ /*
+ * Consistency with msg(3) functions.
+ */
+ if (level >= MSG_FATAL)
+ sleep(1);
exit(0);
}
diff --git a/postfix/src/qmgr/qmgr.c b/postfix/src/qmgr/qmgr.c
index 137cd9308..657e44216 100644
--- a/postfix/src/qmgr/qmgr.c
+++ b/postfix/src/qmgr/qmgr.c
@@ -318,6 +318,11 @@
/* .IP "\fBqmgr_ipc_timeout (60s)\fR"
/* The time limit for the queue manager to send or receive information
/* over an internal communication channel.
+/* .PP
+/* Available in Postfix version 3.1 and later:
+/* .IP "\fBaddress_verify_pending_request_limit (see 'postconf -d' output)\fR"
+/* A safety limit that prevents address verification requests
+/* from overwhelming the Postfix queue.
/* MISCELLANEOUS CONTROLS
/* .ad
/* .fi
@@ -465,6 +470,7 @@ char *var_def_filter_nexthop;
int var_qmgr_daemon_timeout;
int var_qmgr_ipc_timeout;
int var_dsn_delay_cleared;
+int var_vrfy_pend_limit;
static QMGR_SCAN *qmgr_scans[2];
@@ -739,6 +745,7 @@ int main(int argc, char **argv)
VAR_LOCAL_RCPT_LIMIT, DEF_LOCAL_RCPT_LIMIT, &var_local_rcpt_lim, 0, 0,
VAR_LOCAL_CON_LIMIT, DEF_LOCAL_CON_LIMIT, &var_local_con_lim, 0, 0,
VAR_CONC_COHORT_LIM, DEF_CONC_COHORT_LIM, &var_conc_cohort_limit, 0, 0,
+ VAR_VRFY_PEND_LIMIT, DEF_VRFY_PEND_LIMIT, &var_vrfy_pend_limit, 1, 0,
0,
};
static const CONFIG_BOOL_TABLE bool_table[] = {
diff --git a/postfix/src/qmgr/qmgr.h b/postfix/src/qmgr/qmgr.h
index 88ce7920e..17919d183 100644
--- a/postfix/src/qmgr/qmgr.h
+++ b/postfix/src/qmgr/qmgr.h
@@ -380,6 +380,7 @@ struct QMGR_MESSAGE {
extern int qmgr_message_count;
extern int qmgr_recipient_count;
+extern int qmgr_vrfy_pend_count;
extern void qmgr_message_free(QMGR_MESSAGE *);
extern void qmgr_message_update_warn(QMGR_MESSAGE *);
diff --git a/postfix/src/qmgr/qmgr_message.c b/postfix/src/qmgr/qmgr_message.c
index a83e4a0aa..495d52d93 100644
--- a/postfix/src/qmgr/qmgr_message.c
+++ b/postfix/src/qmgr/qmgr_message.c
@@ -8,6 +8,7 @@
/*
/* int qmgr_message_count;
/* int qmgr_recipient_count;
+/* int qmgr_vrfy_pend_count;
/*
/* QMGR_MESSAGE *qmgr_message_alloc(class, name, qflags, mode)
/* const char *class;
@@ -38,6 +39,13 @@
/* of in-core recipient structures (i.e. the sum of all recipients
/* in all in-core message structures).
/*
+/* qmgr_vrfy_pend_count is a global counter for the total
+/* number of in-core message structures that are associated
+/* with an address verification request. Requests that exceed
+/* the address_verify_pending_limit are deferred immediately.
+/* This is a backup mechanism for a more refined enforcement
+/* mechanism in the verify(8) daemon.
+/*
/* qmgr_message_alloc() creates an in-core message structure
/* with sender and recipient information taken from the named queue
/* file. A null result means the queue file could not be read or
@@ -145,6 +153,7 @@
int qmgr_message_count;
int qmgr_recipient_count;
+int qmgr_vrfy_pend_count;
/* qmgr_message_create - create in-core message structure */
@@ -746,11 +755,15 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
* after the logfile is deleted.
*/
else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
- message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
- if (message->tflags == DEL_REQ_FLAG_RECORD)
- message->tflags_offset = curr_offset;
- else
- message->tflags_offset = 0;
+ if (message->tflags == 0) {
+ message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
+ if (message->tflags == DEL_REQ_FLAG_RECORD)
+ message->tflags_offset = curr_offset;
+ else
+ message->tflags_offset = 0;
+ if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0)
+ qmgr_vrfy_pend_count++;
+ }
}
continue;
}
@@ -1166,6 +1179,14 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
}
}
+ /*
+ * Safety: defer excess address verification requests.
+ */
+ if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0
+ && qmgr_vrfy_pend_count > var_vrfy_pend_limit)
+ QMGR_REDIRECT(&reply, MAIL_SERVICE_RETRY,
+ "4.3.2 Too many address verification requests");
+
/*
* Look up or instantiate the proper transport.
*/
@@ -1431,6 +1452,8 @@ void qmgr_message_free(QMGR_MESSAGE *message)
myfree(message->rewrite_context);
recipient_list_free(&message->rcpt_list);
qmgr_message_count--;
+ if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0)
+ qmgr_vrfy_pend_count--;
myfree((void *) message);
}
diff --git a/postfix/src/verify/verify.c b/postfix/src/verify/verify.c
index 300bd9ea3..d9538a8b2 100644
--- a/postfix/src/verify/verify.c
+++ b/postfix/src/verify/verify.c
@@ -400,9 +400,17 @@ static void verify_update_service(VSTREAM *client_stream)
vstring_free(text);
}
+/* verify_post_mail_fclose_action - callback */
+
+static void verify_post_mail_fclose_action(int unused_status,
+ void *unused_context)
+{
+ /* no code here, we just need to avoid blocking in post_mail_fclose() */
+}
+
/* verify_post_mail_action - callback */
-static void verify_post_mail_action(VSTREAM *stream, void *unused_context)
+static void verify_post_mail_action(VSTREAM *stream, void *context)
{
/*
@@ -410,7 +418,7 @@ static void verify_post_mail_action(VSTREAM *stream, void *unused_context)
* deferred, or bounced.
*/
if (stream != 0)
- post_mail_fclose(stream);
+ post_mail_fclose_async(stream, verify_post_mail_fclose_action, context);
}
/* verify_query_service - query address status */
@@ -500,8 +508,8 @@ static void verify_query_service(VSTREAM *client_stream)
(addr_status != DEL_RCPT_STAT_OK && updated + var_verify_neg_try < now)
if (now - probed > PROBE_TTL
- && (POSITIVE_REFRESH_NEEDED(addr_status, updated)
- || NEGATIVE_REFRESH_NEEDED(addr_status, updated))) {
+ && (POSITIVE_REFRESH_NEEDED(addr_status, updated)
+ || NEGATIVE_REFRESH_NEEDED(addr_status, updated))) {
if (msg_verbose)
msg_info("PROBE %s status=%d probed=%ld updated=%ld",
STR(addr), addr_status, now, updated);