-TPLMYSQL
-TPLPGSQL
-TPOSTMAP_KEY_STATE
+-TPOST_MAIL_FCLOSE_STATE
-TPOST_MAIL_STATE
-TPRIVATE_STR_TABLE
-TPSC_CALL_BACK_ENTRY
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.
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
--------------------------------------------------
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.
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<payload_type>.
TLS certificate provenance: indicate whether a subject
name/issuer are verified or not (for example, change the
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
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.
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
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;;
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:
+
+ <b><a href="postconf.5.html#address_verify_pending_request_limit">address_verify_pending_request_limit</a> (see 'postconf -d' output)</b>
+ A safety limit that prevents address verification requests from
+ overwhelming the Postfix queue.
+
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
figuration files.
<b><a href="postconf.5.html#defer_transports">defer_transports</a> (empty)</b>
mail unless someone issues "<b>sendmail -q</b>" or equivalent.
<b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
- 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.
<b><a href="postconf.5.html#helpful_warnings">helpful_warnings</a> (yes)</b>
- Log warnings about problematic configuration settings, and pro-
+ Log warnings about problematic configuration settings, and pro-
vide helpful suggestions.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- 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:
<b><a href="postconf.5.html#confirm_delay_cleared">confirm_delay_cleared</a> (no)</b>
- 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.
<b>FILES</b>
</p>
+</DD>
+
+<DT><b><a name="address_verify_pending_request_limit">address_verify_pending_request_limit</a>
+(default: see "postconf -d" output)</b></DT><DD>
+
+<p> 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 <a href="QSHAPE_README.html#active_queue">active queue</a> maximum size
+(<a href="postconf.5.html#qmgr_message_active_limit">qmgr_message_active_limit</a>). 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 <a href="verify.8.html">verify(8)</a> daemon automatically refreshes an active address
+before it expires. </p>
+
+<p> This feature is available in Postfix 3.1 and later. </p>
+
+
</DD>
<DT><b><a name="address_verify_poll_count">address_verify_poll_count</a>
<b>-i</b> Include the process ID in the logging tag.
- <b>-p</b> <i>priority</i>
- Specifies the logging severity: <b>info</b> (default), <b>warn</b>, <b>error</b>,
- <b>fatal</b>, or <b>panic</b>.
+ <b>-p</b> <i>priority</i> (default: <b>info</b>)
+ Specifies the logging severity: <b>info</b>, <b>warn</b>, <b>error</b>, <b>fatal</b>, or
+ <b>panic</b>. With Postfix 3.1 and later, the program will pause for 1
+ second after reporting a <b>fatal</b> or <b>panic</b> condition, just like
+ other Postfix programs.
<b>-t</b> <i>tag</i> Specifies the logging tag, that is, the identifying name that
appears at the beginning of each logging record. A default tag
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:
+
+ <b><a href="postconf.5.html#address_verify_pending_request_limit">address_verify_pending_request_limit</a> (see 'postconf -d' output)</b>
+ A safety limit that prevents address verification requests from
+ overwhelming the Postfix queue.
+
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
figuration files.
<b><a href="postconf.5.html#defer_transports">defer_transports</a> (empty)</b>
mail unless someone issues "<b>sendmail -q</b>" or equivalent.
<b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
- 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.
<b><a href="postconf.5.html#helpful_warnings">helpful_warnings</a> (yes)</b>
- Log warnings about problematic configuration settings, and pro-
+ Log warnings about problematic configuration settings, and pro-
vide helpful suggestions.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- 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:
<b><a href="postconf.5.html#confirm_delay_cleared">confirm_delay_cleared</a> (no)</b>
- 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.
<b>FILES</b>
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
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.
.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
.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
s;\baddress_verify_service_name\b;<a href="postconf.5.html#address_verify_service_name">$&</a>;g;
s;\baddress_verify_transport_maps\b;<a href="postconf.5.html#address_verify_transport_maps">$&</a>;g;
s;\baddress_verify_virtual_transport\b;<a href="postconf.5.html#address_verify_virtual_transport">$&</a>;g;
+ s;\baddress_verify_pending_request_limit\b;<a href="postconf.5.html#address_verify_pending_request_limit">$&</a>;g;
s;\bsmtp_address_verify_target\b;<a href="postconf.5.html#smtp_address_verify_target">$&</a>;g;
s;\blmtp_address_verify_target\b;<a href="postconf.5.html#lmtp_address_verify_target">$&</a>;g;
s;\balias_database\b;<a href="postconf.5.html#alias_database">$&</a>;g;
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
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
<p>
This feature is available in Postfix 3.1 and later.
</p>
+
+%PARAM address_verify_pending_request_limit see "postconf -d" output
+
+<p> 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. </p>
+
+<p> This feature is available in Postfix 3.1 and later. </p>
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
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
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
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 */
#include <dsn_mask.h>
#include <rec_attr_map.h>
#include <smtputf8.h>
+#include <deliver_request.h>
/* Application-specific. */
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;
#include <recipient_list.h>
#include <dsn.h>
#include <trace.h>
+#include <verify.h>
#include <mail_queue.h> /* cleanup_trace_path */
#include <mail_proto.h>
#include <msg_stats.h>
}
}
+/* 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,
* 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;
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");
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;
/*
* 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);
}
/*
* 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);
}
#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.
*/
* 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
/*
/* 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
/*
/* 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
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,
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.
*/
(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);
+ }
+}
/*
* 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 *);
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))
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 {
/* .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
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];
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[] = {
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 *);
/*
/* 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;
/* 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
int qmgr_message_count;
int qmgr_recipient_count;
+int qmgr_vrfy_pend_count;
/* qmgr_message_create - create in-core message structure */
* 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;
}
}
}
+ /*
+ * 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.
*/
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);
}
/* 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
} else {
log_stream(level, VSTREAM_IN);
}
+
+ /*
+ * Consistency with msg(3) functions.
+ */
+ if (level >= MSG_FATAL)
+ sleep(1);
exit(0);
}
/* .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
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];
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[] = {
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 *);
/*
/* 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;
/* 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
int qmgr_message_count;
int qmgr_recipient_count;
+int qmgr_vrfy_pend_count;
/* qmgr_message_create - create in-core message structure */
* 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;
}
}
}
+ /*
+ * 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.
*/
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);
}
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)
{
/*
* 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 */
(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);