This is the first of several patches to limit the number of address verification requests in the Postfix mail queue.
The second patch will introduce the primary, before-queue, enforcement mechanism that considers the domain in an email address. This involves more code and requires more time for quality testing. The first patch introduces the secondary, post-queue, enforcement mechanism that limits the number of probes in the active queue to 1/4 of the active queue capacity, without any regard of the domain in an email address. 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. Thus, non-selective tempfailing affects only inactive addresses that have expired (31 days) or unknown addresses. This patch is as simple as possible. It involves one configuration parameter (address_verify_pending_request_limit) for the pending request limit, and one counter (qmgr_vrfy_pend_count) for the current number of verification requests in the active queue. It tempfails all verification requests that exceed the limit. Wietse diff --exclude=man --exclude=html --exclude=README_FILES --exclude=.indent.pro --exclude=Makefile.in -cr --exclude=util --exclude=mantools --exclude=proto --exclude=oqmgr /var/tmp/postfix-2.12-20140406/src/global/mail_params.h ./src/global/mail_params.h *** /var/tmp/postfix-2.12-20140406/src/global/mail_params.h Sun Apr 6 19:00:17 2014 --- ./src/global/mail_params.h Thu Apr 24 09:04:32 2014 *************** *** 2733,2738 **** --- 2733,2742 ---- #define DEF_VRFY_XPORT_MAPS "$" VAR_TRANSPORT_MAPS extern char *var_vrfy_xport_maps; + #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; + /* * Message delivery trace service. */ diff --exclude=man --exclude=html --exclude=README_FILES --exclude=.indent.pro --exclude=Makefile.in -cr --exclude=util --exclude=mantools --exclude=proto --exclude=oqmgr /var/tmp/postfix-2.12-20140406/src/qmgr/qmgr.c ./src/qmgr/qmgr.c *** /var/tmp/postfix-2.12-20140406/src/qmgr/qmgr.c Sat Sep 28 21:03:32 2013 --- ./src/qmgr/qmgr.c Thu Apr 24 10:19:02 2014 *************** *** 310,315 **** --- 310,320 ---- /* .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 2.12 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 *************** *** 445,450 **** --- 450,456 ---- char *var_def_filter_nexthop; int var_qmgr_daemon_timeout; int var_qmgr_ipc_timeout; + int var_vrfy_pend_limit; static QMGR_SCAN *qmgr_scans[2]; *************** *** 718,723 **** --- 724,730 ---- 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 --exclude=man --exclude=html --exclude=README_FILES --exclude=.indent.pro --exclude=Makefile.in -cr --exclude=util --exclude=mantools --exclude=proto --exclude=oqmgr /var/tmp/postfix-2.12-20140406/src/qmgr/qmgr.h ./src/qmgr/qmgr.h *** /var/tmp/postfix-2.12-20140406/src/qmgr/qmgr.h Sat Jul 24 13:28:00 2010 --- ./src/qmgr/qmgr.h Thu Apr 24 10:17:33 2014 *************** *** 377,382 **** --- 377,383 ---- 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 --exclude=man --exclude=html --exclude=README_FILES --exclude=.indent.pro --exclude=Makefile.in -cr --exclude=util --exclude=mantools --exclude=proto --exclude=oqmgr /var/tmp/postfix-2.12-20140406/src/qmgr/qmgr_message.c ./src/qmgr/qmgr_message.c *** /var/tmp/postfix-2.12-20140406/src/qmgr/qmgr_message.c Fri Apr 5 17:27:48 2013 --- ./src/qmgr/qmgr_message.c Thu Apr 24 14:27:44 2014 *************** *** 8,13 **** --- 8,14 ---- /* /* 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,43 **** --- 39,51 ---- /* 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 *************** *** 149,154 **** --- 157,163 ---- int qmgr_message_count; int qmgr_recipient_count; + int qmgr_vrfy_pend_count; /* qmgr_message_create - create in-core message structure */ *************** *** 748,758 **** * 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; } continue; } --- 757,771 ---- * after the logfile is deleted. */ else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 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; } *************** *** 1159,1164 **** --- 1172,1185 ---- } /* + * 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. */ if (transport == 0 || !STREQ(transport->name, STR(reply.transport))) { *************** *** 1423,1428 **** --- 1444,1451 ---- 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((char *) message); }