A. Schulze: > > wietse: > > > If it is DATA, then address verification is possible but it requires > > source code > > changes to Postfix: > > > > - After successful RCPT TO, do not assume that the recipient exists, > > but send DATA and disconnect after the DATA response is received. > > > > This will cause extra noise in the logfile, therefore it should be > > configurable: > > > > - Configure what sites reject recipients after DATA. The list of > > such domains is limited, so this is not a big burden. > > this would be indeed a useful extension...
Patch follows. Most if not all *should* also work with Postfix 2.11 and possibly earlier versions. This introduces a new parameter smtp_address_verify_target (default: rcpt) that can be set to "data" for qmail-like servers. Since this setting causes the Postfix SMTP client to hang up after a positive DATA response, the remote SMTP server may log something like this: Dec 27 10:53:14 server postfix/smtpd[51624]: lost connection after DATA (0 bytes) from host.example.org[192.168.1.3] Dec 27 10:53:14 server postfix/smtpd[51624]: disconnect from host.example.org[192.168.1.3] ehlo=1 mail=1 rcpt=1 data=0/1 Most of the patch is documentation and user interface stuff. Wietse 20141227 Feature: smtp_address_verify_target (default: rcpt) that determines what protocol stage decides if a recipient is valid. Specify "data" for servers that reject recipients after the DATA command. mantools/postlink, proto/postconf.proto, global/mail_params.h, smtp/lmtp_params.c, smtp/smtp.c, smtp/smtp.h, smtp/smtp_params.c, smtp/smtp_proto.c. diff -cr /var/tmp/postfix-2.12-20141226/man/man5/postconf.5 ./man/man5/postconf.5 *** /var/tmp/postfix-2.12-20141226/man/man5/postconf.5 2014-12-21 19:49:22.000000000 -0500 --- ./man/man5/postconf.5 2014-12-27 10:47:44.000000000 -0500 *************** *** 2472,2477 **** --- 2472,2484 ---- configuration parameter. See there for details. .PP This feature is available in Postfix 2.8 and later. + .SH lmtp_address_verify_target (default: rcpt) + The LMTP protocol stage that determines whether a recipient is + deliverable. Specify one of "rcpt" or "data". The latter is needed + with remote LMTP servers that reject recipients after the DATA + command. + .PP + This feature is available in Postfix 2.12 and later. .SH lmtp_assume_final (default: no) When a remote LMTP server announces no DSN support, assume that the *************** *** 6085,6090 **** --- 6092,6104 ---- .br .PP This feature is available in Postfix 2.8 and later. + .SH smtp_address_verify_target (default: rcpt) + The SMTP protocol stage that determines whether a recipient is + deliverable. Specify one of "rcpt" or "data". The latter is needed + with remote SMTP servers that reject recipients after the DATA + command. + .PP + This feature is available in Postfix 2.12 and later. .SH smtp_always_send_ehlo (default: yes) Always send EHLO at the start of an SMTP session. .PP diff -cr /var/tmp/postfix-2.12-20141226/man/man8/smtp.8 ./man/man8/smtp.8 *** /var/tmp/postfix-2.12-20141226/man/man8/smtp.8 2014-12-25 11:52:01.000000000 -0500 --- ./man/man8/smtp.8 2014-12-27 10:47:44.000000000 -0500 *************** *** 725,730 **** --- 725,735 ---- .IP "\fBsmtp_fallback_relay ($fallback_relay)\fR" Optional list of relay hosts for SMTP destinations that can't be found or that are unreachable. + .PP + Available with Postfix 2.12 and later: + .IP "\fBsmtp_address_verify_target (rcpt)\fR" + The SMTP protocol stage that determines whether a recipient is + deliverable. .SH "SEE ALSO" .na .nf diff -cr /var/tmp/postfix-2.12-20141226/mantools/postlink ./mantools/postlink *** /var/tmp/postfix-2.12-20141226/mantools/postlink 2014-12-12 20:44:45.000000000 -0500 --- ./mantools/postlink 2014-12-27 10:38:24.000000000 -0500 *************** *** 89,94 **** --- 89,96 ---- 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;\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; s;\balias_maps\b;<a href="postconf.5.html#alias_maps">$&</a>;g; s;\ballow_mail_to_com[-</bB>]*\n*[ <bB>]*mands\b;<a href="postconf.5.html#allow_mail_to_commands">$&</a>;g; diff -cr /var/tmp/postfix-2.12-20141226/proto/postconf.proto ./proto/postconf.proto *** /var/tmp/postfix-2.12-20141226/proto/postconf.proto 2014-12-21 19:47:44.000000000 -0500 --- ./proto/postconf.proto 2014-12-27 10:37:56.000000000 -0500 *************** *** 15419,15424 **** --- 15419,15442 ---- <p> This feature is available in Postfix 2.9 and later. </p> + %PARAM smtp_address_verify_target rcpt + + <p> The SMTP protocol stage that determines whether a recipient is + deliverable. Specify one of "rcpt" or "data". The latter is needed + with remote SMTP servers that reject recipients after the DATA + command. </p> + + <p> This feature is available in Postfix 2.12 and later. </p> + + %PARAM lmtp_address_verify_target rcpt + + <p> The LMTP protocol stage that determines whether a recipient is + deliverable. Specify one of "rcpt" or "data". The latter is needed + with remote LMTP servers that reject recipients after the DATA + command. </p> + + <p> This feature is available in Postfix 2.12 and later. </p> + %PARAM daemon_table_open_error_is_fatal no <p> How a Postfix daemon process handles errors while opening lookup diff -cr /var/tmp/postfix-2.12-20141226/src/global/mail_params.h ./src/global/mail_params.h *** /var/tmp/postfix-2.12-20141226/src/global/mail_params.h 2014-12-12 20:42:53.000000000 -0500 --- ./src/global/mail_params.h 2014-12-27 10:44:18.000000000 -0500 *************** *** 2778,2783 **** --- 2778,2791 ---- #define DEF_VRFY_XPORT_MAPS "$" VAR_TRANSPORT_MAPS extern char *var_vrfy_xport_maps; + #define SMTP_VRFY_TGT_RCPT "rcpt" + #define SMTP_VRFY_TGT_DATA "data" + #define VAR_LMTP_VRFY_TGT "lmtp_address_verify_target" + #define DEF_LMTP_VRFY_TGT SMTP_VRFY_TGT_RCPT + #define VAR_SMTP_VRFY_TGT "smtp_address_verify_target" + #define DEF_SMTP_VRFY_TGT SMTP_VRFY_TGT_RCPT + extern char *var_smtp_vrfy_tgt; + /* * Message delivery trace service. */ diff -cr /var/tmp/postfix-2.12-20141226/src/smtp/lmtp_params.c ./src/smtp/lmtp_params.c *** /var/tmp/postfix-2.12-20141226/src/smtp/lmtp_params.c 2014-11-27 12:18:44.000000000 -0500 --- ./src/smtp/lmtp_params.c 2014-12-27 10:43:46.000000000 -0500 *************** *** 33,38 **** --- 33,39 ---- VAR_LMTP_SASL_TYPE, DEF_LMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0, VAR_LMTP_BIND_ADDR, DEF_LMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0, VAR_LMTP_BIND_ADDR6, DEF_LMTP_BIND_ADDR6, &var_smtp_bind_addr6, 0, 0, + VAR_LMTP_VRFY_TGT, DEF_LMTP_VRFY_TGT, &var_smtp_vrfy_tgt, 1, 0, VAR_LMTP_HELO_NAME, DEF_LMTP_HELO_NAME, &var_smtp_helo_name, 1, 0, VAR_LMTP_HOST_LOOKUP, DEF_LMTP_HOST_LOOKUP, &var_smtp_host_lookup, 1, 0, VAR_LMTP_DNS_SUPPORT, DEF_LMTP_DNS_SUPPORT, &var_smtp_dns_support, 0, 0, diff -cr /var/tmp/postfix-2.12-20141226/src/smtp/smtp.c ./src/smtp/smtp.c *** /var/tmp/postfix-2.12-20141226/src/smtp/smtp.c 2014-12-25 11:47:18.000000000 -0500 --- ./src/smtp/smtp.c 2014-12-27 10:47:44.000000000 -0500 *************** *** 685,690 **** --- 685,695 ---- /* .IP "\fBsmtp_fallback_relay ($fallback_relay)\fR" /* Optional list of relay hosts for SMTP destinations that can't be /* found or that are unreachable. + /* .PP + /* Available with Postfix 2.12 and later: + /* .IP "\fBsmtp_address_verify_target (rcpt)\fR" + /* The SMTP protocol stage that determines whether a recipient is + /* deliverable. /* SEE ALSO /* generic(5), output address rewriting /* header_checks(5), message header content inspection *************** *** 816,821 **** --- 821,827 ---- char *var_smtp_sasl_type; char *var_smtp_bind_addr; char *var_smtp_bind_addr6; + char *var_smtp_vrfy_tgt; bool var_smtp_rand_addr; int var_smtp_pix_thresh; int var_queue_run_delay; *************** *** 1077,1082 **** --- 1083,1093 ---- */ smtp_dns_res_opt = name_mask(VAR_LMTP_SMTP(DNS_RES_OPT), dns_res_opt_masks, var_smtp_dns_res_opt); + + /* + * Address verification. + */ + smtp_vrfy_init(); } /* pre_init - pre-jail initialization */ diff -cr /var/tmp/postfix-2.12-20141226/src/smtp/smtp.h ./src/smtp/smtp.h *** /var/tmp/postfix-2.12-20141226/src/smtp/smtp.h 2014-12-02 17:37:41.000000000 -0500 --- ./src/smtp/smtp.h 2014-12-27 10:44:43.000000000 -0500 *************** *** 365,370 **** --- 365,371 ---- /* * smtp_proto.c */ + extern void smtp_vrfy_init(void); extern int smtp_helo(SMTP_STATE *); extern int smtp_xfer(SMTP_STATE *); extern int smtp_rset(SMTP_STATE *); diff -cr /var/tmp/postfix-2.12-20141226/src/smtp/smtp_params.c ./src/smtp/smtp_params.c *** /var/tmp/postfix-2.12-20141226/src/smtp/smtp_params.c 2014-11-27 12:18:44.000000000 -0500 --- ./src/smtp/smtp_params.c 2014-12-27 10:42:04.000000000 -0500 *************** *** 34,39 **** --- 34,40 ---- VAR_SMTP_SASL_TYPE, DEF_SMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0, VAR_SMTP_BIND_ADDR, DEF_SMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0, VAR_SMTP_BIND_ADDR6, DEF_SMTP_BIND_ADDR6, &var_smtp_bind_addr6, 0, 0, + VAR_SMTP_VRFY_TGT, DEF_SMTP_VRFY_TGT, &var_smtp_vrfy_tgt, 1, 0, VAR_SMTP_HELO_NAME, DEF_SMTP_HELO_NAME, &var_smtp_helo_name, 1, 0, VAR_SMTP_HOST_LOOKUP, DEF_SMTP_HOST_LOOKUP, &var_smtp_host_lookup, 1, 0, VAR_SMTP_DNS_SUPPORT, DEF_SMTP_DNS_SUPPORT, &var_smtp_dns_support, 0, 0, diff -cr /var/tmp/postfix-2.12-20141226/src/smtp/smtp_proto.c ./src/smtp/smtp_proto.c *** /var/tmp/postfix-2.12-20141226/src/smtp/smtp_proto.c 2014-12-06 20:35:33.000000000 -0500 --- ./src/smtp/smtp_proto.c 2014-12-27 10:44:33.000000000 -0500 *************** *** 261,266 **** --- 261,284 ---- smtp_text_out, }; + static int smtp_vrfy_tgt; + + /* smtp_vrfy_init - initialize */ + + void smtp_vrfy_init(void) + { + static const NAME_CODE vrfy_init_table[] = { + SMTP_VRFY_TGT_RCPT, SMTP_STATE_RCPT, + SMTP_VRFY_TGT_DATA, SMTP_STATE_DATA, + 0, + }; + + if ((smtp_vrfy_tgt = name_code(vrfy_init_table, NAME_CODE_FLAG_NONE, + var_smtp_vrfy_tgt)) == 0) + msg_fatal("bad protocol stage: \"%s = %s\"", + VAR_SMTP_VRFY_TGT, var_smtp_vrfy_tgt); + } + /* smtp_helo - perform initial handshake with SMTP server */ int smtp_helo(SMTP_STATE *state) *************** *** 1541,1547 **** dsn_notify_str(rcpt->dsn_notify)); } if ((next_rcpt = send_rcpt + 1) == SMTP_RCPT_LEFT(state)) ! next_state = DEL_REQ_TRACE_ONLY(request->flags) ? SMTP_STATE_ABORT : SMTP_STATE_DATA; break; --- 1559,1566 ---- dsn_notify_str(rcpt->dsn_notify)); } if ((next_rcpt = send_rcpt + 1) == SMTP_RCPT_LEFT(state)) ! next_state = (DEL_REQ_TRACE_ONLY(request->flags) ! && smtp_vrfy_tgt == SMTP_STATE_RCPT) ? SMTP_STATE_ABORT : SMTP_STATE_DATA; break; *************** *** 1551,1557 **** */ case SMTP_STATE_DATA: vstring_strcpy(next_command, "DATA"); ! next_state = SMTP_STATE_DOT; break; /* --- 1570,1578 ---- */ case SMTP_STATE_DATA: vstring_strcpy(next_command, "DATA"); ! next_state = (DEL_REQ_TRACE_ONLY(request->flags) ! && smtp_vrfy_tgt == SMTP_STATE_DATA) ? ! SMTP_STATE_LAST : SMTP_STATE_DOT; break; /*