On Mon, Jan 27, 2014 at 02:51:20PM -0800, Quanah Gibson-Mount wrote: > >The fallback relay setting is a fixed per-transport setting. So > >the fallback relay would not be per-user. Only the first LMTP > >server to try (per-user transport table). Each transport carries > >a fixed fallback relay in master.cf. > > > >So you'd have one transport per "cluster" of mailstores, and an > >associated fallback that uses the cluster round-robin address. The > >user's transport entry would direct the first delivery attempt to > >"somelmtp:primary-store:port" if it is best to not simply round-robin > >the deliveries and sending each user's mail to the primary destination > >for that user is substantially better. > > Ok, makes sense. That would work well. Thanks!
The patch below may not even compile, but probably works, give it a try. As you can see, it is mostly a matter of adding a bit of documentation and disabling conditionals that make existing code apply only to SMTP. If it works well for you, and Wietse is not opposed to an "lmtp_fallback_relay" feature, something like this could be part of Postfix 2.12. diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index bba32ac..18e6288 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -1492,6 +1492,25 @@ as the right-hand side for backup or primary MX domain entries. for destinations that it is MX host for. </p> +%PARAM lmtp_fallback_relay + +<p> Optional list of relay hosts for LMTP destinations that can't be +found or that are unreachable. In main.cf elements are separated by +whitespace or commas. </p> + +<p> By default, mail is returned to the sender when a destination is not +found, and delivery is deferred when a destination is unreachable. </p> + +<p> The fallback relays must be TCP LMTP destinations, specified without +a leading "inet:" prefix. Specify a host or host:port. Since MX +lookups do not apply with LMTP, there is no need to use the "[host]" or +"[host]:port" forms. If you specify multiple LMTP destinations, Postfix +will try them in the specified order. </p> + +<p> +This feature is available in Postfix 2.12 and later. +</p> + %PARAM fast_flush_domains $relay_domains <p> diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 12fd0e1..963d438 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -198,7 +198,8 @@ extern char *var_null_relay_maps_key; #define VAR_SMTP_FALLBACK "smtp_fallback_relay" #define DEF_SMTP_FALLBACK "$fallback_relay" -#define VAR_LMTP_FALLBACK "smtp_fallback_relay" +#define VAR_LMTP_FALLBACK "lmtp_fallback_relay" +#define DEF_LMTP_FALLBACK "" #define DEF_FALLBACK_RELAY "" extern char *var_fallback_relay; diff --git a/postfix/src/smtp/lmtp_params.c b/postfix/src/smtp/lmtp_params.c index 68a2739..5af852f 100644 --- a/postfix/src/smtp/lmtp_params.c +++ b/postfix/src/smtp/lmtp_params.c @@ -1,5 +1,6 @@ static const CONFIG_STR_TABLE lmtp_str_table[] = { VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0, + VAR_LMTP_FALLBACK, DEF_LMTP_FALLBACK, &var_fallback_relay, 0, 0, VAR_BESTMX_TRANSP, DEF_BESTMX_TRANSP, &var_bestmx_transp, 0, 0, VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0, VAR_LMTP_SASL_PASSWD, DEF_LMTP_SASL_PASSWD, &var_smtp_sasl_passwd, 0, 0, diff --git a/postfix/src/smtp/smtp_connect.c b/postfix/src/smtp/smtp_connect.c index ff278c1..0b84adc 100644 --- a/postfix/src/smtp/smtp_connect.c +++ b/postfix/src/smtp/smtp_connect.c @@ -778,9 +778,7 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop, if (sites->argc == 0) msg_panic("null destination: \"%s\"", nexthop); non_fallback_sites = sites->argc; - /* When we are lmtp(8) var_fallback_relay is null */ - if (smtp_mode) - argv_split_append(sites, var_fallback_relay, ", \t\r\n"); + argv_split_append(sites, var_fallback_relay, ", \t\r\n"); /* * Don't give up after a hard host lookup error until we have tried the @@ -1055,7 +1053,7 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop, * Pay attention to what could be configuration problems, and pretend * that these are recoverable rather than bouncing the mail. */ - else if (!SMTP_HAS_SOFT_DSN(why) && smtp_mode) { + else if (!SMTP_HAS_SOFT_DSN(why)) { /* * The fall-back destination did not resolve as expected, or it @@ -1071,7 +1069,7 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop, * The next-hop relayhost did not resolve as expected, or it is * refusing to talk to us, or mail for it loops back to us. */ - else if (strcmp(sites->argv[0], var_relayhost) == 0) { + else if (smtp_mode && strcmp(sites->argv[0], var_relayhost) == 0) { msg_warn("%s configuration problem", VAR_RELAYHOST); vstring_strcpy(why->status, "4.3.5"); /* XXX Keep the diagnostic code and MTA. */ @@ -1081,7 +1079,7 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop, * Mail for the next-hop destination loops back to myself. Pass * the mail to the best_mx_transport or bounce it. */ - else if (SMTP_HAS_LOOP_DSN(why) && *var_bestmx_transp) { + else if (smtp_mode && SMTP_HAS_LOOP_DSN(why) && *var_bestmx_transp) { dsb_reset(why); /* XXX */ state->status = deliver_pass_all(MAIL_CLASS_PRIVATE, var_bestmx_transp, -- Viktor.