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.