]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-1.1.12-20021214
authorWietse Venema <wietse@porcupine.org>
Sat, 14 Dec 2002 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:28:33 +0000 (06:28 +0000)
12 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/conf/main.cf
postfix/conf/sample-local.cf
postfix/html/local.8.html
postfix/html/rewrite.html
postfix/man/man8/local.8
postfix/src/global/mail_version.h
postfix/src/local/local.c
postfix/src/smtpd/smtpd.c
postfix/src/trivial-rewrite/resolve.c
postfix/src/trivial-rewrite/transport.c

index 14f135d5990b637eeb96aa379fee6d7347cbcba6..61c98c0b8031abe993b8994c0d029b8f63b22741 100644 (file)
@@ -7418,6 +7418,17 @@ Apologies for any names omitted.
        explicit process count limit. If an incorrect process limit
        is specified in master.cf the service aborts.
 
+20021214
+
+       Cleanup: it looks like we finally get it right with transport
+       lookup table entries that either override or specify an
+       error transport without updating the nexthop information.
+       File:  trivial-rewrite/resolve.c.
+
+       Performance: don't do UCE checks (which may result in 4xx
+       SMTP reply codes) when we already know that the recipient
+       is undeliverable. Files:  smtpd/smtpd.c, smtpd/smtpd_check.c.
+
 Open problems:
 
        Low: after successful delivery, per-queue window += 1/window,
index 102edaf42163a3262f080eac1ee7159630111614..6232a89a44816e262da32bf750f6bf59b10ed11c 100644 (file)
@@ -31,12 +31,13 @@ USERS" in conf/main.cf if one of the following is true:
 - You run the Postfix SMTP server chrooted (see master.cf).
 - You redefined the local delivery agent in master.cf.
 - You redefined the "local_transport" setting in main.cf.
-- You use the mailbox_transport or fallback_transport feature
-  of the Postfix local delivery agent. 
+- You use the mailbox_transport feature of the Postfix local delivery agent.
+- You use the fallback_transport feature of the Postfix local delivery agent.
+- You use the luser_relay feature of the Postfix local delivery agent.
 
 Specify "local_recipient_maps =" (i.e. empty) to make the SMTP
-server accept mail for all known and unknown local recipients. You
-will be considered a bad network citizen, though.
+server accept mail for all known and unknown local recipients.
+That was the default setting prior to Postfix version 1.2.
 
 Postfix no longer defaults to the "smtp" transport for all non-local
 destinations. This may affect your defer_transports settings. In
index f8e17b766e3b61d24d01570ae311cc927b765b90..b26e358fab3b86659422e16b120c0683f580956f 100644 (file)
@@ -172,8 +172,8 @@ mail_owner = postfix
 #
 # - You redefined the "local_transport" setting in main.cf.
 #
-# - You use the mailbox_transport or fallback_transport feature
-#   of the Postfix local delivery agent (see sample-local.cf).
+# - You use the "luser_relay", "mailbox_transport", or "fallback_transport"
+#   feature of the Postfix local delivery agent (see sample-local.cf).
 #
 # Beware: if the Postfix SMTP server runs chrooted, you may have to
 # copy the passwd (not shadow) database into the jail. This is
@@ -416,6 +416,11 @@ local_recipient_maps = unix:passwd.byname $alias_maps
 # :nexthop part is optional. For more details see the sample transport
 # configuration file.
 #
+# NOTE: if you use this feature for accounts not in the UNIX password
+# file, then you must update the "local_recipient_maps" setting in
+# the main.cf file, otherwise the SMTP server will reject mail for    
+# non-UNIX accounts with "User unknown in local recipient table".
+#
 #mailbox_transport = lmtp:unix:/file/name
 #mailbox_transport = cyrus
 
@@ -428,6 +433,11 @@ local_recipient_maps = unix:passwd.byname $alias_maps
 # :nexthop part is optional. For more details see the sample transport
 # configuration file.
 #
+# NOTE: if you use this feature for accounts not in the UNIX password
+# file, then you must update the "local_recipient_maps" setting in
+# the main.cf file, otherwise the SMTP server will reject mail for    
+# non-UNIX accounts with "User unknown in local recipient table".
+#
 #fallback_transport = lmtp:unix:/file/name
 #fallback_transport = cyrus
 #fallback_transport =
@@ -445,6 +455,11 @@ local_recipient_maps = unix:passwd.byname $alias_maps
 #
 # luser_relay works only for the default Postfix local delivery agent.
 #
+# NOTE: if you use this feature for accounts not in the UNIX password
+# file, then you must specify "local_recipient_maps =" (i.e. empty) in
+# the main.cf file, otherwise the SMTP server will reject mail for    
+# non-UNIX accounts with "User unknown in local recipient table".
+#
 #luser_relay = $user@other.host
 #luser_relay = $local@other.host
 #luser_relay = admin+$local
index 6017a8173d1ac399f1f468ecb8d307977bd776b5..c901c0b2425f9643ca9289a748ac11fddb565452 100644 (file)
@@ -135,6 +135,11 @@ home_mailbox =
 #
 # luser_relay works only for the default Postfix local delivery agent.
 #
+# NOTE: if you use this feature for accounts not in the UNIX password
+# file, then you must specify "local_recipient_maps =" (i.e. empty) in
+# the main.cf file, otherwise the SMTP server will reject mail for    
+# non-UNIX accounts with "User unknown in local recipient table".
+#
 #luser_relay = $user@other.host
 #luser_relay = $local@other.host
 #luser_relay = admin+$local
@@ -188,10 +193,10 @@ mailbox_command =
 # :nexthop part is optional. For more details see the sample transport
 # configuration file.
 #
-# Beware: if you use the mailbox_transport feature for users not in
-# /etc/passwd and /etc/aliases then you also need to review the
-# section "REJECTING UNKNOWN LOCAL USERS" in the main.cf file,
-# otherwise the SMTP server may reject mail incorrectly.
+# NOTE: if you use this feature for accounts not in the UNIX password
+# file, then you must update the "local_recipient_maps" setting in
+# the main.cf file, otherwise the SMTP server will reject mail for    
+# non-UNIX accounts with "User unknown in local recipient table".
 #
 #mailbox_transport = lmtp:unix:/file/name
 #mailbox_transport = cyrus
@@ -206,10 +211,10 @@ mailbox_transport =
 # :nexthop part is optional. For more details see the sample transport
 # configuration file.
 #
-# Beware: if you use the fallback_transport feature for users not in
-# /etc/passwd and /etc/aliases then you also need to review the
-# section "REJECTING UNKNOWN LOCAL USERS" in the main.cf file,
-# otherwise the SMTP server may reject mail incorrectly.
+# NOTE: if you use this feature for accounts not in the UNIX password
+# file, then you must update the "local_recipient_maps" setting in
+# the main.cf file, otherwise the SMTP server will reject mail for    
+# non-UNIX accounts with "User unknown in local recipient table".
 #
 #fallback_transport = lmtp:unix:/file/name
 #fallback_transport = cyrus
index 235c53b72079c16bf51c4801290b0e3081b8d406..076c8fe382ed1a9f27f9558a46c3dafa24b9571f 100644 (file)
@@ -318,39 +318,57 @@ LOCAL(8)                                                 LOCAL(8)
               in  the UNIX passwd database.  This parameter over-
               rides <b>luser</b><i>_</i><b>relay</b>.
 
+              Note: you must update the <b>local</b><i>_</i><b>recipient</b><i>_</i><b>maps</b> set-
+              ting  in  the  <b>main.cf</b>  file, otherwise the Postfix
+              SMTP server will reject mail for non-UNIX  accounts
+              with "<b>User</b> <b>unknown</b> <b>in</b> <b>local</b> <b>recipient</b> <b>table</b>".
+
        <b>home</b><i>_</i><b>mailbox</b>
-              Pathname of a mailbox relative  to  a  user's  home
+              Pathname  of  a  mailbox  relative to a user's home
               directory.  Specify a path ending in <b>/</b> for maildir-
               style delivery.
 
        <b>luser</b><i>_</i><b>relay</b>
-              Destination (<i>@domain</i> or <i>address</i>)  for  non-existent
-              users.   The  <i>address</i>  is subjected to <i>$name</i> expan-
+              Destination  (<i>@domain</i>  or <i>address</i>) for non-existent
+              users.  The <i>address</i> is subjected  to  <i>$name</i>  expan-
               sion.
 
+              Note:  you  must  specify  "<b>local</b><i>_</i><b>recipient</b><i>_</i><b>maps</b> <b>=</b>"
+              (i.e. empty) in the  <b>main.cf</b>  file,  otherwise  the
+              Postfix  SMTP  server will reject mail for non-UNIX
+              accounts with  "<b>User</b>  <b>unknown</b>  <b>in</b>  <b>local</b>  <b>recipient</b>
+              <b>table</b>".
+
        <b>mail</b><i>_</i><b>spool</b><i>_</i><b>directory</b>
-              Directory with UNIX-style  mailboxes.  The  default
-              pathname  is system dependent.  Specify a path end-
+              Directory  with  UNIX-style  mailboxes. The default
+              pathname is system dependent.  Specify a path  end-
               ing in <b>/</b> for maildir-style delivery.
 
        <b>mailbox</b><i>_</i><b>command</b>
-              External command to use for mailbox  delivery.  The
+              External  command  to use for mailbox delivery. The
               command  executes  with  the  recipient  privileges
-              (exception: root). The string is subject  to  $name
+              (exception:  root).  The string is subject to $name
               expansions.
 
        <b>mailbox</b><i>_</i><b>command</b><i>_</i><b>maps</b>
-              Lookup  tables with per-recipient external commands
-              to use for mailbox delivery. Behavior  is  as  with
+              Lookup tables with per-recipient external  commands
+              to  use  for  mailbox delivery. Behavior is as with
               <b>mailbox</b><i>_</i><b>command</b>.
 
        <b>mailbox</b><i>_</i><b>transport</b>
-              Message  transport  to  use for mailbox delivery to
+              Message transport to use for  mailbox  delivery  to
               all local recipients, whether or not they are found
-              in  the UNIX passwd database.  This parameter over-
-              rides all other configuration parameters that  con-
+              in the UNIX passwd database.  This parameter  over-
+              rides  all other configuration parameters that con-
               trol mailbox delivery, including <b>luser</b><i>_</i><b>relay</b>.
 
+              Note: if you use this feature to receive  mail  for
+              non-UNIX   accounts   then   you  must  update  the
+              <b>local</b><i>_</i><b>recipient</b><i>_</i><b>maps</b> setting in the  <b>main.cf</b>  file,
+              otherwise  the Postfix SMTP server will reject mail
+              for non-UNIX accounts with "<b>User</b> <b>unknown</b>  <b>in</b>  <b>local</b>
+              <b>recipient</b> <b>table</b>".
+
 <b>Locking</b> <b>controls</b>
        <b>deliver</b><i>_</i><b>lock</b><i>_</i><b>attempts</b>
               Limit  the  number of attempts to acquire an exclu-
index b007757be62930e9444d2119d84d1062a332afc5..eeb374310216470347e2cedc72b315267df20323 100644 (file)
@@ -489,6 +489,21 @@ see the <a href="local.8.html"> local</a> delivery agent.
 
 <p>
 
+Note: if you use the <b>luser_relay</b> feature in order to receive
+mail for non-UNIX accounts, then you must specify:
+
+<blockquote>
+<pre>
+<b>local_recipient_maps =</b>
+</pre>
+</blockquote>
+
+(i.e. empty) in the <b>main.cf</b> file, otherwise the Postfix SMTP
+server will reject mail for non-UNIX accounts with "User unknown
+in local recipient table".
+
+<p>
+
 <b>luser_relay</b> can specify one address. It is subjected to
 <i>$name</i> expansions. The most useful examples are:
 
index 6a31f08db740899692fc1863c52be15e567e340f..9f85c78d0a7cd4192a028b2d7f4f531848e0ceff 100644 (file)
@@ -337,12 +337,22 @@ recipient before attempting delivery. Defer delivery otherwise.
 Message transport for recipients that are not found in the UNIX
 passwd database.
 This parameter overrides \fBluser_relay\fR.
+.sp
+Note: you must update the \fBlocal_recipient_maps\fR
+setting in the \fBmain.cf\fR file, otherwise the Postfix SMTP
+server will reject mail for non-UNIX accounts with "\fBUser
+unknown in local recipient table\fR".
 .IP \fBhome_mailbox\fR
 Pathname of a mailbox relative to a user's home directory.
 Specify a path ending in \fB/\fR for maildir-style delivery.
 .IP \fBluser_relay\fR
 Destination (\fI@domain\fR or \fIaddress\fR) for non-existent users.
 The \fIaddress\fR is subjected to \fI$name\fR expansion.
+.sp
+Note: you must specify "\fBlocal_recipient_maps =\fR"
+(i.e. empty) in the \fBmain.cf\fR file, otherwise the Postfix SMTP
+server will reject mail for non-UNIX accounts with "\fBUser
+unknown in local recipient table\fR".
 .IP \fBmail_spool_directory\fR
 Directory with UNIX-style mailboxes. The default pathname is system
 dependent.
@@ -359,6 +369,12 @@ Message transport to use for mailbox delivery to all local
 recipients, whether or not they are found in the UNIX passwd database.
 This parameter overrides all other configuration parameters that
 control mailbox delivery, including \fBluser_relay\fR.
+.sp
+Note: if you use this feature to receive mail for non-UNIX
+accounts then you must update the \fBlocal_recipient_maps\fR
+setting in the \fBmain.cf\fR file, otherwise the Postfix SMTP
+server will reject mail for non-UNIX accounts with "\fBUser
+unknown in local recipient table\fR".
 .SH "Locking controls"
 .ad
 .fi
index 1405ab0884128956c512c962ec34a8174eaff100..156eb251e49b40114a8c1b5ab8bfa325ce87b983 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change the patchlevel and the release date. Snapshots change the
   * release date only, unless they include the same bugfix as a patch release.
   */
-#define MAIL_RELEASE_DATE      "20021213"
+#define MAIL_RELEASE_DATE      "20021214"
 
 #define VAR_MAIL_VERSION       "mail_version"
 #define DEF_MAIL_VERSION       "1.1.12-" MAIL_RELEASE_DATE
index 40af80a80b33fb9f6b86262c2ec5b6040a5d8079..ac6c0ca703df48c414a337adaf1a1b6f6cab4b6a 100644 (file)
 /*     Message transport for recipients that are not found in the UNIX
 /*     passwd database.
 /*     This parameter overrides \fBluser_relay\fR.
+/* .sp
+/*     Note: you must update the \fBlocal_recipient_maps\fR
+/*     setting in the \fBmain.cf\fR file, otherwise the Postfix SMTP
+/*     server will reject mail for non-UNIX accounts with "\fBUser
+/*     unknown in local recipient table\fR".
 /* .IP \fBhome_mailbox\fR
 /*     Pathname of a mailbox relative to a user's home directory.
 /*     Specify a path ending in \fB/\fR for maildir-style delivery.
 /* .IP \fBluser_relay\fR
 /*     Destination (\fI@domain\fR or \fIaddress\fR) for non-existent users.
 /*     The \fIaddress\fR is subjected to \fI$name\fR expansion.
+/* .sp
+/*     Note: you must specify "\fBlocal_recipient_maps =\fR"
+/*     (i.e. empty) in the \fBmain.cf\fR file, otherwise the Postfix SMTP
+/*     server will reject mail for non-UNIX accounts with "\fBUser
+/*     unknown in local recipient table\fR".
 /* .IP \fBmail_spool_directory\fR
 /*     Directory with UNIX-style mailboxes. The default pathname is system
 /*     dependent.
 /*     recipients, whether or not they are found in the UNIX passwd database.
 /*     This parameter overrides all other configuration parameters that
 /*     control mailbox delivery, including \fBluser_relay\fR.
+/* .sp
+/*     Note: if you use this feature to receive mail for non-UNIX
+/*     accounts then you must update the \fBlocal_recipient_maps\fR
+/*     setting in the \fBmain.cf\fR file, otherwise the Postfix SMTP
+/*     server will reject mail for non-UNIX accounts with "\fBUser
+/*     unknown in local recipient table\fR".
 /* .SH "Locking controls"
 /* .ad
 /* .fi
index e08a2f3d3bd66216785c14df446f01147b4a3a8b..5d757afd428a4281c1314b46692bbcb17ce67396 100644 (file)
@@ -923,11 +923,11 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        return (-1);
     }
     if (SMTPD_STAND_ALONE(state) == 0) {
-       if ((err = smtpd_check_rcpt(state, argv[2].strval)) != 0) {
+       if ((err = smtpd_check_rcptmap(state, argv[2].strval)) != 0) {
            smtpd_chat_reply(state, "%s", err);
            return (-1);
        }
-       if ((err = smtpd_check_rcptmap(state, argv[2].strval)) != 0) {
+       if ((err = smtpd_check_rcpt(state, argv[2].strval)) != 0) {
            smtpd_chat_reply(state, "%s", err);
            return (-1);
        }
index 69edaaafb31178f617b2b7178f24f846330753fd..8e55123c80d7261e2e52bd93a90ffa3733b4c794 100644 (file)
 #include "trivial-rewrite.h"
 #include "transport.h"
 
+ /*
+  * The job of the address resolver is to map one recipient address to a
+  * triple of (channel, nexthop, recipient). The channel is the name of the
+  * delivery service specified in master.cf, the nexthop is (usually) a
+  * description of the next host to deliver to, and recipient is the final
+  * recipient address. The latter may differ from the input address as the
+  * result of stripping multiple layers of sender-specified routing.
+  * 
+  * Addresses are resolved by their domain name. Known domain names are
+  * categorized into classes: local, virtual alias, virtual mailbox, relay,
+  * and everything else. Finding the address domain class is a matter of
+  * table lookups.
+  * 
+  * Different address domain classes generally use different delivery channels,
+  * and may use class dependent ways to arrive at the corresponding nexthop
+  * information. With classes that do final delivery, the nexthop is
+  * typically the local machine hostname.
+  * 
+  * The transport lookup table provides a means to override the domain class
+  * channel and/or nexhop information for specific recipients or for entire
+  * domain hierarchies.
+  * 
+  * This works well in the general case. The only bug in this approach is that
+  * the structure of the nexthop information is transport dependent.
+  * Typically, the nexthop specifies a hostname, hostname + TCP Port, or the
+  * pathname of a UNIX-domain socket. However, with the error transport the
+  * nexthop field contains free text with the reason for non-delivery.
+  * 
+  * Therefore, a transport map entry that overrides the channel but not the
+  * nexthop information (or vice versa) may produce surprising results. In
+  * particular, the free text nexthop information for the error transport is
+  * likely to confuse regular delivery agents; and conversely, a hostname or
+  * socket pathname is not a useful reason for non-delivery.
+  * 
+  * In the code below, the class_domain variable specifies the domain name that
+  * we will use when (the class transport is the error transport and the
+  * class transport is replaced by a transport map lookup result) but the
+  * nexthop information is not updated.
+  * 
+  * For the sake of completeness, we also take action when the reverse happens:
+  * replacing the class transport by the error transport without updating the
+  * nexthop information.
+  * 
+  * The ability to specify "error:reason for non-delivery" in main.cf and in
+  * transport maps is just too convenient to take it away.
+  */
+
 #define STR    vstring_str
 
+ /*
+  * Some of the lists that define the address domain classes.
+  */
 static DOMAIN_LIST *relay_domains;
 static STRING_LIST *virt_alias_doms;
 static STRING_LIST *virt_mailbox_doms;
+
+ /*
+  * Saved address domain class information.
+  */
+static VSTRING *saved_class_channel;
+static VSTRING *saved_class_nexthop;
+static VSTRING *saved_class_domain;
+
 static MAPS *relocated_maps;
 
 /* resolve_addr - resolve address according to rule set */
@@ -106,6 +164,7 @@ void    resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
     const char *blame = 0;
     const char *rcpt_domain;
 
+    vstring_strcpy(saved_class_domain, "UNINITIALIZED SAVED_CLASS_DOMAIN");
     *flags = 0;
 
     /*
@@ -239,13 +298,12 @@ void    resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
      * XXX Nag if the domain is listed in multiple domain lists. The effect is
      * implementation defined, and may break when internals change.
      */
-#define VIRT_ALIAS_TRANSPORT   var_error_transport
-#define VIRT_ALIAS_NEXTHOP     "User unknown in virtual alias table"
+#define STREQ(x,y) (strcmp((x), (y)) == 0)
 
     dict_errno = 0;
     if (domain != 0) {
        tok822_internalize(nexthop, domain->next, TOK822_STR_DEFL);
-       lowercase(STR(nexthop));
+       vstring_strcpy(saved_class_domain, STR(nexthop));
        if (STR(nexthop)[strspn(STR(nexthop), "[]0123456789.")] != 0
            && valid_hostname(STR(nexthop), DONT_GRIPE) == 0)
            *flags |= RESOLVE_FLAG_ERROR;
@@ -256,8 +314,9 @@ void    resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
                && string_list_match(virt_mailbox_doms, STR(nexthop)))
                msg_warn("do not list domain %s in BOTH %s and %s",
                  STR(nexthop), VAR_VIRT_ALIAS_DOMS, VAR_VIRT_MAILBOX_DOMS);
-           vstring_strcpy(channel, VIRT_ALIAS_TRANSPORT);
-           vstring_strcpy(nexthop, VIRT_ALIAS_NEXTHOP);
+           vstring_strcpy(channel, var_error_transport);
+           vstring_strcpy(nexthop, "User unknown in virtual alias table");
+           vstring_strcpy(saved_class_domain, var_myhostname);
            blame = VAR_ERROR_TRANSPORT;
            *flags |= RESOLVE_CLASS_ALIAS;
        } else if (dict_errno != 0) {
@@ -267,6 +326,7 @@ void    resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
                   && string_list_match(virt_mailbox_doms, STR(nexthop))) {
            vstring_strcpy(channel, var_virt_transport);
            vstring_strcpy(nexthop, var_myhostname);
+           vstring_strcpy(saved_class_domain, var_myhostname);
            blame = VAR_VIRT_TRANSPORT;
            *flags |= RESOLVE_CLASS_VIRTUAL;
        } else if (dict_errno != 0) {
@@ -288,12 +348,14 @@ void    resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
            }
            if (*var_relayhost) {
                vstring_strcpy(nexthop, var_relayhost);
-               lowercase(STR(nexthop));
+               if (!STREQ(STR(channel), var_error_transport))
+                   vstring_strcpy(saved_class_domain, STR(nexthop));
            }
        }
        if ((destination = split_at(STR(channel), ':')) != 0 && *destination) {
            vstring_strcpy(nexthop, destination);
-           lowercase(STR(nexthop));
+           if (!STREQ(STR(channel), var_error_transport))
+               vstring_strcpy(saved_class_domain, STR(nexthop));
        }
     }
 
@@ -309,15 +371,14 @@ void    resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
      * implementation defined, and may break when internals change.
      */
     else {
-       if ((rcpt_domain = strrchr(STR(nextrcpt), '@')) != 0) {
+       if (var_helpful_warnings
+           && (rcpt_domain = strrchr(STR(nextrcpt), '@')) != 0) {
            rcpt_domain++;
-           if (var_helpful_warnings
-               && virt_alias_doms
+           if (virt_alias_doms
                && string_list_match(virt_alias_doms, rcpt_domain))
                msg_warn("do not list domain %s in BOTH %s and %s",
                         rcpt_domain, VAR_MYDEST, VAR_VIRT_ALIAS_DOMS);
-           if (var_helpful_warnings
-               && virt_mailbox_doms
+           if (virt_mailbox_doms
                && string_list_match(virt_mailbox_doms, rcpt_domain))
                msg_warn("do not list domain %s in BOTH %s and %s",
                         rcpt_domain, VAR_MYDEST, VAR_VIRT_MAILBOX_DOMS);
@@ -328,6 +389,10 @@ void    resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
            || *destination == 0)
            destination = var_myhostname;
        vstring_strcpy(nexthop, destination);
+       if (!STREQ(STR(channel), var_error_transport))
+           vstring_strcpy(saved_class_domain, STR(nexthop));
+       else
+           vstring_strcpy(saved_class_domain, var_myhostname);
        *flags |= RESOLVE_CLASS_LOCAL;
     }
 
@@ -349,34 +414,37 @@ void    resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
     /*
      * The transport map overrides any transport and next-hop host info that
      * is set up above.
+     * 
+     * With error transports, the nexthop info is arbitrary text that must not
+     * be passed on to regular delivery agents. When the transport map
+     * overrides an error transport without overriding the nexthop
+     * information, or vice versa, update the nexthop information
+     * appropriately.
      */
     if ((*flags & RESOLVE_FLAG_FAIL) == 0 && *var_transport_maps) {
-       if (transport_lookup(STR(nextrcpt), channel, nexthop) == 0
-           && dict_errno != 0) {
+       vstring_strcpy(saved_class_channel, STR(channel));
+       vstring_strcpy(saved_class_nexthop, STR(nexthop));
+
+       if (transport_lookup(STR(nextrcpt), channel, nexthop) != 0) {
+           if (!STREQ(STR(saved_class_channel), STR(channel))
+               && STREQ(STR(saved_class_nexthop), STR(nexthop))) {
+               vstring_strcpy(nexthop, STREQ(STR(channel), var_error_transport) ?
+                   "Address is not deliverable" : STR(saved_class_domain));
+           }
+       } else if (dict_errno != 0) {
            msg_warn("%s lookup failure", VAR_TRANSPORT_MAPS);
            *flags |= RESOLVE_FLAG_FAIL;
        }
     }
 
-    /*
-     * Kludge for virtual alias domains. Their next-hop info is arbitrary
-     * text that must not be passed on to regular delivery agents. So, if the
-     * transport was changed, but the nexthop was not, copy over the local
-     * hostname instead.
-     */
-#define STREQ(x, y) (strcmp((x), (y)) == 0)
-
-    if ((*flags & RESOLVE_FLAG_FAIL) == 0
-       && (*flags & RESOLVE_CLASS_ALIAS) != 0
-       && !STREQ(STR(channel), VIRT_ALIAS_TRANSPORT)
-       && STREQ(STR(nexthop), VIRT_ALIAS_NEXTHOP))
-       vstring_strcpy(nexthop, var_myhostname);
-
     /*
      * Bounce recipients that have moved, regardless of domain address class.
-     * The downside of doing this here is that this table has no effect on
-     * local alias expansion results. Such mail will have to make almost an
-     * entire iteration through the mail system.
+     * We do this last, in anticipation of transport maps that can override
+     * the recipient address.
+     * 
+     * The downside of not doing this in delivery agents is that this table has
+     * no effect on local alias expansion results. Such mail will have to
+     * make almost an entire iteration through the mail system.
      */
 #define IGNORE_ADDR_EXTENSION   ((char **) 0)
 
@@ -448,6 +516,9 @@ void    resolve_init(void)
     channel = vstring_alloc(100);
     nexthop = vstring_alloc(100);
     nextrcpt = vstring_alloc(100);
+    saved_class_channel = vstring_alloc(100);
+    saved_class_nexthop = vstring_alloc(100);
+    saved_class_domain = vstring_alloc(100);
 
     if (*var_virt_alias_doms)
        virt_alias_doms =
index d0c6211d0e07d557a6a3f91cefdd509e19f40ff0..0ac8a4fe33c9a2acd46f2c708e4a10ac105114d8 100644 (file)
@@ -111,7 +111,7 @@ static int find_transport_entry(const char *key, int flags,
        msg_panic("find_transport_entry: missing initialization");
 
     /*
-     * Look up an entry with extreme prejedice.
+     * Look up an entry with extreme prejudice.
      * 
      * XXX Should report lookup failure status to caller instead of aborting.
      */
@@ -122,8 +122,11 @@ static int find_transport_entry(const char *key, int flags,
     }
 
     /*
-     * Can't do transport:user@domain because the right-hand side can have
-     * arbitrary content (especially in the case of the error mailer).
+     * It would be great if we could specify a recipient address in the
+     * lookup result. Unfortunately, we cannot simply run the result through
+     * a parser that recognizes "transport:user@domain" because the lookup
+     * result can have arbitrary content (especially in the case of the error
+     * mailer).
      */
     else {
        saved_value = mystrdup(value);