From: Wietse Venema
Upon receipt of an initial XFORWARD command, the SMTP server initializes all XFORWARD attributes to [UNAVAILABLE]. With each -XFORWARD command, the server overwrites attributes with the specified -attribute values, and erases attributes whose value is specified -as [UNAVAILABLE]. Attributes that are not specified in an XFORWARD -command retain their current value.
+valid XFORWARD command, the server overwrites attributes with the +specified values, and erases attributes whose value is specified +as [UNAVAILABLE]. -An ADDR attribute value of [UNAVAILABLE] indicates that the -next MAIL FROM transaction is a forwarded local submission. In -this case the SMTP server should ignore other client attributes. -This behavior is available with Postfix version 2.6.
+When both the NAME and ADDR attributes have a value of +[UNAVAILABLE], the next MAIL FROM transaction corresponds to a local +submission. In this case the SMTP server must ignore the PORT and +PROTO attributes. This behavior is available with Postfix version +2.6.
-At the end of the next MAIL FROM transaction (i.e. RSET or DOT), +
At the end of each MAIL FROM transaction (i.e. RSET or DOT), all XFORWARD attributes are reset to the real client information, and the SMTP server is ready to receive another initial XFORWARD command.
diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 1f59f68d5..5b2039f1b 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -7303,7 +7303,9 @@ Example:A sender-dependent override for the global relayhost parameter setting. The tables are searched by the envelope sender address and -@domain. This information is overruled with relay_transport, +@domain. A lookup result of DUNNO terminates the search without +overriding the global relayhost parameter setting. This information +is overruled with relay_transport, default_transport and with the transport(5) table.
For safety reasons, this feature does not allow $number diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 1f47ddb8a..e61646f80 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -4113,7 +4113,9 @@ sender_canonical_maps = hash:/etc/postfix/sender_canonical .SH sender_dependent_relayhost_maps (default: empty) A sender-dependent override for the global relayhost parameter setting. The tables are searched by the envelope sender address and -@domain. This information is overruled with relay_transport, +@domain. A lookup result of DUNNO terminates the search without +overriding the global relayhost parameter setting. This information +is overruled with relay_transport, default_transport and with the \fBtransport\fR(5) table. .PP For safety reasons, this feature does not allow $number diff --git a/postfix/proto/XFORWARD_README.html b/postfix/proto/XFORWARD_README.html index da08b80a4..a99fb13f1 100644 --- a/postfix/proto/XFORWARD_README.html +++ b/postfix/proto/XFORWARD_README.html @@ -144,17 +144,17 @@ unencoded information.
Upon receipt of an initial XFORWARD command, the SMTP server initializes all XFORWARD attributes to [UNAVAILABLE]. With each -XFORWARD command, the server overwrites attributes with the specified -attribute values, and erases attributes whose value is specified -as [UNAVAILABLE]. Attributes that are not specified in an XFORWARD -command retain their current value.
+valid XFORWARD command, the server overwrites attributes with the +specified values, and erases attributes whose value is specified +as [UNAVAILABLE]. -An ADDR attribute value of [UNAVAILABLE] indicates that the -next MAIL FROM transaction is a forwarded local submission. In -this case the SMTP server should ignore other client attributes. -This behavior is available with Postfix version 2.6.
+When both the NAME and ADDR attributes have a value of +[UNAVAILABLE], the next MAIL FROM transaction corresponds to a local +submission. In this case the SMTP server must ignore the PORT and +PROTO attributes. This behavior is available with Postfix version +2.6.
-At the end of the next MAIL FROM transaction (i.e. RSET or DOT), +
At the end of each MAIL FROM transaction (i.e. RSET or DOT), all XFORWARD attributes are reset to the real client information, and the SMTP server is ready to receive another initial XFORWARD command.
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index c453b095a..8ac9def8e 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -9339,7 +9339,9 @@ is placed into the Postfix configuration directory.A sender-dependent override for the global relayhost parameter setting. The tables are searched by the envelope sender address and -@domain. This information is overruled with relay_transport, +@domain. A lookup result of DUNNO terminates the search without +overriding the global relayhost parameter setting. This information +is overruled with relay_transport, default_transport and with the transport(5) table.
For safety reasons, this feature does not allow $number diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index 82a026ca8..251595214 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -201,7 +201,7 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_VAL_UNKNOWN "unknown" #define MAIL_ATTR_IS_EXIST(a) (*(a)) -#define MAIL_ATTR_IS_KNOWN(a) (*(a)) && strcmp((a), MAIL_ATTR_VAL_UNKNOWN) +#define MAIL_ATTR_IS_KNOWN(a) ((*(a)) && strcmp((a), MAIL_ATTR_VAL_UNKNOWN)) /* * XCLIENT/XFORWARD in SMTP. diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 27e4c43de..83cc90ac8 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20081002" +#define MAIL_RELEASE_DATE "20081003" #define MAIL_VERSION_NUMBER "2.6" #ifdef SNAPSHOT diff --git a/postfix/src/oqmgr/qmgr_message.c b/postfix/src/oqmgr/qmgr_message.c index c4e012013..b3a7b15a1 100644 --- a/postfix/src/oqmgr/qmgr_message.c +++ b/postfix/src/oqmgr/qmgr_message.c @@ -626,15 +626,15 @@ static int qmgr_message_read(QMGR_MESSAGE *message) } else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_ADDR) == 0) { if (have_log_client_attr == 0 && message->client_addr == 0) message->client_addr = mystrdup(value); + } else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_PORT) == 0) { + if (have_log_client_attr == 0 && message->client_port == 0) + message->client_port = mystrdup(value); } else if (strcmp(name, MAIL_ATTR_ACT_PROTO_NAME) == 0) { if (have_log_client_attr == 0 && message->client_proto == 0) message->client_proto = mystrdup(value); } else if (strcmp(name, MAIL_ATTR_ACT_HELO_NAME) == 0) { if (have_log_client_attr == 0 && message->client_helo == 0) message->client_helo = mystrdup(value); - } else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_PORT) == 0) { - if (have_log_client_attr == 0 && message->client_port == 0) - message->client_port = mystrdup(value); } /* Original client attributes. */ else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_NAME) == 0) { diff --git a/postfix/src/qmgr/qmgr_message.c b/postfix/src/qmgr/qmgr_message.c index 5fd73e924..24a981ed7 100644 --- a/postfix/src/qmgr/qmgr_message.c +++ b/postfix/src/qmgr/qmgr_message.c @@ -667,15 +667,15 @@ static int qmgr_message_read(QMGR_MESSAGE *message) } else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_ADDR) == 0) { if (have_log_client_attr == 0 && message->client_addr == 0) message->client_addr = mystrdup(value); + } else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_PORT) == 0) { + if (have_log_client_attr == 0 && message->client_port == 0) + message->client_port = mystrdup(value); } else if (strcmp(name, MAIL_ATTR_ACT_PROTO_NAME) == 0) { if (have_log_client_attr == 0 && message->client_proto == 0) message->client_proto = mystrdup(value); } else if (strcmp(name, MAIL_ATTR_ACT_HELO_NAME) == 0) { if (have_log_client_attr == 0 && message->client_helo == 0) message->client_helo = mystrdup(value); - } else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_PORT) == 0) { - if (have_log_client_attr == 0 && message->client_port == 0) - message->client_port = mystrdup(value); } /* Original client attributes. */ else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_NAME) == 0) { diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index 0ee036cd0..a4d1a00a1 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -318,7 +318,19 @@ static void qmqpd_write_attributes(QMQPD_STATE *state) { /* - * Provenance attributes for Milter policy etc. + * Logging attribute for the Postfix 2.3+ cleanup server. + */ + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_LOG_ORIGIN, state->namaddr); + + /* + * For consistency with the smtpd Milter client, we need to provide the + * real client attributes to the cleanup Milter client. This does not + * matter much with qmqpd which speaks to trusted clients only, but we + * want to be sure that the cleanup input protocol is ready when a new + * type of network daemon is added to receive mail from the Internet. + * + * See also the comments in smtpd.c. */ rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_ACT_CLIENT_NAME, state->name); diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index e00ef6454..26668620e 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -1931,7 +1931,15 @@ int smtp_xfer(SMTP_STATE *state) } /* - * Use the XFORWARD command to send local/remote submission information. + * Use XFORWARD to forward the origin of this email message across an + * SMTP-based content filter. Send client attribute information even in + * the case of local submissions, which have no client attributes. This + * fixes a minor problem that was introduced with Postfix 2.1: no client + * attribute information was sent in the case of local submissions, and + * therefore local submissions appeared to originate from the SMTP-based + * content filter. To make this work we introduced one change to the + * XFORWARD protocol: when both NAME and ADDR values are [UNAVAILABLE], + * this is a local submission. */ send_name_addr = var_smtp_send_xforward diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index de017cf8e..09e608ace 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -1754,41 +1754,63 @@ static int mail_open_stream(SMTPD_STATE *state) if (SMTPD_STAND_ALONE(state) == 0) { /* - * Forwarded client attributes. + * Forwarded client attributes. These propagate original client + * information through an SMTP-based content filter, to improve + * the logging from an after-filter MTA. They are also used in + * $name expansions by the local(8) and pipe(8) delivery agents. * * In the case of a forwarded remote submission, store original * client attributes in our own internal representation: either - * actual values or "unknown"; don't bother with storing - * non-existent HELO attributes. + * actual values or "unknown". This fixes a problem that was + * introduced with Postfix 2.1: "unknown" got treated the same + * way as "non-existent". As before, we don't store non-existent + * HELO attributes. * * In the case of a forwarded local submission, specify explicitly - * that the original client attributes are non-existent. + * that the original client attributes are non-existent. This + * fixes another problem that was introduced with Postfix 2.1: + * forwarded local submissions could not override the content + * filter's own client attributes, so the message would appear to + * originate from the content filter. To make this work we + * introduced one change to the XFORWARD protocol: when both NAME + * and ADDR values are [UNAVAILABLE], this is a local submission. */ if (state->xforward.flags & SMTPD_STATE_XFORWARD_CLIENT_MASK) { - if (MAIL_ATTR_IS_KNOWN(FORWARD_ADDR(state))) { + if (MAIL_ATTR_IS_KNOWN(FORWARD_NAME(state)) + || MAIL_ATTR_IS_KNOWN(FORWARD_ADDR(state))) { rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_LOG_CLIENT_NAME, FORWARD_NAME(state)); rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_LOG_CLIENT_ADDR, FORWARD_ADDR(state)); rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_LOG_CLIENT_PORT, FORWARD_PORT(state)); - rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", - MAIL_ATTR_LOG_ORIGIN, FORWARD_NAMADDR(state)); if (FORWARD_HELO(state)) rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_LOG_HELO_NAME, FORWARD_HELO(state)); rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_LOG_PROTO_NAME, FORWARD_PROTO(state)); } else { - /* Local submission. */ + /* Local submission. See also qmgr_message_read(). */ rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_LOG_CLIENT_ADDR, MAIL_ATTR_VAL_NONEXIST); } } + /* + * Logging attribute for the Postfix 2.3+ cleanup server. + */ + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_LOG_ORIGIN, FORWARD_NAMADDR(state)); + /* * Attributes with actual client information. These are used by - * Milters in case mail is re-injected with "postsuper -R". + * the smtpd Milter client for policy decisions. Mail that is + * requeued with "postsuper -r" is not subject to processing by + * the cleanup Milter client, because a) it has already been + * filtered, and b) we don't have sufficient information to + * reproduce the exact same SMTP events and Sendmail macros that + * the smtpd Milter client received when the message originally + * arrived in Postfix. */ rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_ACT_CLIENT_NAME, state->name); diff --git a/postfix/src/trivial-rewrite/resolve.c b/postfix/src/trivial-rewrite/resolve.c index 61f5bf7ea..454cd5ae5 100644 --- a/postfix/src/trivial-rewrite/resolve.c +++ b/postfix/src/trivial-rewrite/resolve.c @@ -511,7 +511,8 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr, && (relay = mail_addr_find(rp->snd_relay_info, *sender ? sender : var_null_relay_maps_key, (char **) 0)) != 0) - vstring_strcpy(nexthop, relay); + vstring_strcpy(nexthop, strcasecmp(relay, "DUNNO") == 0 ? + rcpt_domain : relay); else if (*RES_PARAM_VALUE(rp->relayhost)) vstring_strcpy(nexthop, RES_PARAM_VALUE(rp->relayhost)); else