Viktor Dukhovni: > > -o soft_bounce=yes > > -o smtp_fallback_relay=relayusa.example.com > > That said, neither form will forward rejected mail to the fallback > relay. The soft-bounce feature operates at the wrong layer for that > to happen. First the SMTP delivery agent gives up on the rejected
That seems to violate the principle of least astonishment. Conceptually, soft-bounce means treat 5xx replies as 4xx replies. The observed behavior originates from the time that Postfix, like qmail, did not connect to an alternate SMTP server after receiving a 4xx response. This was fixed for the general case, but somehow the soft-bounce feature was overlooked. I also note that the Postfix SMTP client is the only program that tries to make alternate deliveries, so this problem did not surface elsewhere in Postfix. [I also recall that this came up a few years ago, but then there was no time to address this properly]. Wietse *** ./src/smtp/smtp_trouble.c- Sat Jan 14 20:09:23 2012 --- ./src/smtp/smtp_trouble.c Mon Jun 11 11:25:02 2012 *************** *** 151,156 **** --- 151,157 ---- #include <mail_error.h> #include <dsn_buf.h> #include <dsn.h> + #include <mail_params.h> /* Application-specific. */ *************** *** 190,195 **** --- 191,197 ---- RECIPIENT *rcpt; int status; int soft_error = (STR(why->status)[0] == '4'); + int soft_bounce_error = (STR(why->status)[0] == '5' && var_soft_bounce); int nrcpt; /* *************** *** 197,203 **** * delivery to a backup server. Just log something informative to show * why we're skipping this host. */ ! if (soft_error && (state->misc_flags & SMTP_MISC_FLAG_FINAL_SERVER) == 0) { msg_info("%s: %s", request->queue_id, STR(why->reason)); for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) { rcpt = request->rcpt_list.info + nrcpt; --- 199,206 ---- * delivery to a backup server. Just log something informative to show * why we're skipping this host. */ ! if ((soft_error || soft_bounce_error) ! && (state->misc_flags & SMTP_MISC_FLAG_FINAL_SERVER) == 0) { msg_info("%s: %s", request->queue_id, STR(why->reason)); for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) { rcpt = request->rcpt_list.info + nrcpt; *************** *** 245,251 **** state->status |= status; } if ((state->misc_flags & SMTP_MISC_FLAG_COMPLETE_SESSION) == 0 ! && throttle_queue && soft_error && request->hop_status == 0) request->hop_status = DSN_COPY(&why->dsn); } --- 248,255 ---- state->status |= status; } if ((state->misc_flags & SMTP_MISC_FLAG_COMPLETE_SESSION) == 0 ! && throttle_queue && (soft_error || soft_bounce_error) ! && request->hop_status == 0) request->hop_status = DSN_COPY(&why->dsn); } *************** *** 354,359 **** --- 358,364 ---- DSN_BUF *why = state->why; int status; int soft_error; + int soft_bounce_error; va_list ap; /* *************** *** 369,374 **** --- 374,380 ---- vsmtp_fill_dsn(state, mta_name, resp->dsn, resp->str, format, ap); va_end(ap); soft_error = STR(why->status)[0] == '4'; + soft_bounce_error = (STR(why->status)[0] == '5' && var_soft_bounce); if (state->session && mta_name) smtp_check_code(state->session, resp->code); *************** *** 378,384 **** * for trying other mail servers. Just log something informative to show * why we're skipping this recipient now. */ ! if (soft_error && (state->misc_flags & SMTP_MISC_FLAG_FINAL_SERVER) == 0) { msg_info("%s: %s", request->queue_id, STR(why->reason)); SMTP_RCPT_KEEP(state, rcpt); } --- 384,391 ---- * for trying other mail servers. Just log something informative to show * why we're skipping this recipient now. */ ! if ((soft_error || soft_bounce_error) ! && (state->misc_flags & SMTP_MISC_FLAG_FINAL_SERVER) == 0) { msg_info("%s: %s", request->queue_id, STR(why->reason)); SMTP_RCPT_KEEP(state, rcpt); } *** ./src/smtp/Makefile.in- Sun Jan 22 10:55:20 2012 --- ./src/smtp/Makefile.in Mon Jun 11 11:23:52 2012 *************** *** 591,596 **** --- 591,597 ---- smtp_trouble.o: ../../include/header_opts.h smtp_trouble.o: ../../include/htable.h smtp_trouble.o: ../../include/mail_error.h + smtp_trouble.o: ../../include/mail_params.h smtp_trouble.o: ../../include/maps.h smtp_trouble.o: ../../include/match_list.h smtp_trouble.o: ../../include/mime_state.h