From: Wietse Venema Date: Mon, 28 Jun 2004 05:00:00 +0000 (-0500) Subject: postfix-2.2-20040628 X-Git-Tag: v2.2.0-RC1~51 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=94a16728a993ab0e41453d5cf309144656133752;p=thirdparty%2Fpostfix.git postfix-2.2-20040628 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 9c442ceed..5d1e4644d 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -9422,14 +9422,14 @@ Apologies for any names omitted. explicit "multiple sessions per delivery request" model. This uncovered ESMTP and SASL missing re-initialization problems that were fixed in past week. Design by Victor - and Wietse, initial implementation by Victor Duchovny. + and Wietse, initial implementation by Victor Duchovni. 20040620 Future proofing: after the reorganization of SMTP request state and session state, added code to the smtp client error handling routines to more consistently deal with the - possibility that session information is not be available. + possibility that session information is not available. 20040621 @@ -9448,6 +9448,19 @@ Apologies for any names omitted. Support for external command execution directory. Files: global/pipe_command.[hc]. +20040622 + + Safety: when mail is delivered to a transport with per-delivery + recipient limit of 1, split the recipient address on the + recipient delimiter if one is defined, so that extended + addresses don't get extra delivery concurrency slots. + Files: *qmgr/qmgr_message.c. + +20040623 + + Workaround for fragile clients: add microsecond time to + maildir filename. Files: virtual/maildir.c, local/maildir.c. + Open problems: Low: make sure CCARGS -I options come at the end. diff --git a/postfix/README_FILES/BACKSCATTER_README b/postfix/README_FILES/BACKSCATTER_README index 86e8aa8e1..bee27caf9 100644 --- a/postfix/README_FILES/BACKSCATTER_README +++ b/postfix/README_FILES/BACKSCATTER_README @@ -53,8 +53,9 @@ Thus, if returned mail has a Received: message header like this: Received: from porcupine.org ... -Then I know that this is almost certainly forged mail. Mail that is really sent -by my systems looks like this: +Then I know that this is almost certainly forged mail (almost; see next section +for the fly in the ointment). Mail that is really sent by my systems looks like +this: Received: from hostname.porcupine.org ... @@ -66,6 +67,13 @@ result of forgery: Received: from host.example.com (HELO porcupine.org) ... Received: from host.example.com (EHLO porcupine.org) ... +Another frequent sign of forgery is the Message-ID: header. My systems produce +a Message-ID: of . The following are forgeries, +especially the first one: + + Message-ID: <1cb479435d8eb9.2beb1.qmail@porcupine.org> + Message-ID: + To block such backscatter I use header_checks and body_checks patterns like this: @@ -79,6 +87,8 @@ this: /^Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +) (porcupine\.org)\)/ reject forged client name in Received: header: $2 + /^Message-ID:.*@(porcupine\.org)/ + reject forged domain name in Message-ID: header: $1 /etc/postfix/body_checks: /^[> ]*Received: +from +(porcupine\.org) / @@ -86,6 +96,8 @@ this: /^[> ]*Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +) (porcupine\.org)\)/ reject forged client name in Received: header: $2 + /^[> ]*Message-ID:.*@(porcupine\.org)/ + reject forged domain name in Message-ID: header: $1 Notes: @@ -135,11 +147,11 @@ mail is obviously forged and is very easy to stop. /etc/postfix/header_checks: /^(From|Return-Path):.*[[:<:]](user@domain\.tld)[[:>:]]/ - reject forged sender address in $1: message header: $2 + reject forged sender address in $1: header: $2 /etc/postfix/body_checks: /^[> ]*(From|Return-Path):.*[[:<:]](user@domain\.tld)[[:>:]]/ - reject forged sender address in $1: message header: $2 + reject forged sender address in $1: header: $2 Notes: diff --git a/postfix/html/BACKSCATTER_README.html b/postfix/html/BACKSCATTER_README.html index f2889feaf..0af36f398 100644 --- a/postfix/html/BACKSCATTER_README.html +++ b/postfix/html/BACKSCATTER_README.html @@ -104,8 +104,9 @@ Received: from porcupine.org ... -

Then I know that this is almost certainly forged mail. Mail -that is really sent by my systems looks like this:

+

Then I know that this is almost certainly forged mail (almost; +see next section for the fly in the ointment). Mail that is really +sent by my systems looks like this:

@@ -125,6 +126,18 @@ Received: from host.example.com (EHLO porcupine.org) ...
 
+

Another frequent sign of forgery is the Message-ID: header. My +systems produce a Message-ID: of +<stuff@hostname.porcupine.org>. The following +are forgeries, especially the first one: + +

+
+Message-ID: <1cb479435d8eb9.2beb1.qmail@porcupine.org>
+Message-ID: <yulszqocfzsficvzzju@porcupine.org>
+
+
+

To block such backscatter I use header_checks and body_checks patterns like this:

@@ -139,12 +152,16 @@ patterns like this:

reject forged client name in Received: header: $1 /^Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/ reject forged client name in Received: header: $2 + /^Message-ID:.*@(porcupine\.org)/ + reject forged domain name in Message-ID: header: $1 /etc/postfix/body_checks: /^[> ]*Received: +from +(porcupine\.org) / reject forged client name in Received: header: $1 /^[> ]*Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/ reject forged client name in Received: header: $2 + /^[> ]*Message-ID:.*@(porcupine\.org)/ + reject forged domain name in Message-ID: header: $1 @@ -213,11 +230,11 @@ and is very easy to stop. /etc/postfix/header_checks: /^(From|Return-Path):.*[[:<:]](user@domain\.tld)[[:>:]]/ - reject forged sender address in $1: message header: $2 + reject forged sender address in $1: header: $2 /etc/postfix/body_checks: /^[> ]*(From|Return-Path):.*[[:<:]](user@domain\.tld)[[:>:]]/ - reject forged sender address in $1: message header: $2 + reject forged sender address in $1: header: $2 diff --git a/postfix/html/local.8.html b/postfix/html/local.8.html index 0ca93411d..aaf1769c9 100644 --- a/postfix/html/local.8.html +++ b/postfix/html/local.8.html @@ -49,8 +49,8 @@ LOCAL(8) LOCAL(8) $user (recipient username), $home (recipient home direc- tory), $shell (recipient shell), $recipient (complete recipient address), $extension (recipient address exten- - sion), $domain (recipient domain), local (entire recipient - address localpart) and $recipient_delimiter. The forms + sion), $domain (recipient domain), $local (entire recipi- + ent address localpart) and $recipient_delimiter. The forms ${name?value} and ${name:value} expand conditionally to value when $name is (is not) defined. Characters that may have special meaning to the shell or file system are @@ -154,7 +154,7 @@ LOCAL(8) LOCAL(8) (recipient home directory), $shell (recipient shell), $recipient (complete recipient address), $extension (recipient address extension), $domain (recipient domain), - local (entire recipient address localpart) and $recipi- + $local (entire recipient address localpart) and $recipi- ent_delimiter. The forms ${name?value} and ${name:value} expand conditionally to value when $name is (is not) defined. Characters that may have special meaning to the diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index e91f74924..3edff6d40 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -607,6 +607,11 @@ NOTE: if mail to the BCC address bounces it will be returned to the sender.

+

NOTE: automatic BCC recipients are produced only for new mail. +To avoid mailer loops, automatic BCC recipients are not generated +for mail that Postfix forwards internally, nor for mail that Postfix +generates itself.

+ @@ -4539,6 +4544,11 @@ NOTE: if mail to the BCC address bounces it will be returned to the sender.

+

NOTE: automatic BCC recipients are produced only for new mail. +To avoid mailer loops, automatic BCC recipients are not generated +for mail that Postfix forwards internally, nor for mail that Postfix +generates itself.

+

Example:

@@ -4948,6 +4958,11 @@ NOTE: if mail to the BCC address bounces it will be returned to the sender.

+

NOTE: automatic BCC recipients are produced only for new mail. +To avoid mailer loops, automatic BCC recipients are not generated +for mail that Postfix forwards internally, nor for mail that Postfix +generates itself.

+

Example:

diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index a60c2b9b1..c473165cd 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -326,6 +326,11 @@ that is received by the Postfix mail system. .PP NOTE: if mail to the BCC address bounces it will be returned to the sender. +.PP +NOTE: automatic BCC recipients are produced only for new mail. +To avoid mailer loops, automatic BCC recipients are not generated +for mail that Postfix forwards internally, nor for mail that Postfix +generates itself. .SH anvil_rate_time_unit (default: 60s) The time unit over which client connection rates and other rates are calculated. @@ -2328,6 +2333,11 @@ run "\fBpostmap /etc/postfix/recipient_bcc\fR". NOTE: if mail to the BCC address bounces it will be returned to the sender. .PP +NOTE: automatic BCC recipients are produced only for new mail. +To avoid mailer loops, automatic BCC recipients are not generated +for mail that Postfix forwards internally, nor for mail that Postfix +generates itself. +.PP Example: .PP .nf @@ -2579,6 +2589,11 @@ run "\fBpostmap /etc/postfix/sender_bcc\fR". NOTE: if mail to the BCC address bounces it will be returned to the sender. .PP +NOTE: automatic BCC recipients are produced only for new mail. +To avoid mailer loops, automatic BCC recipients are not generated +for mail that Postfix forwards internally, nor for mail that Postfix +generates itself. +.PP Example: .PP .nf diff --git a/postfix/man/man8/local.8 b/postfix/man/man8/local.8 index a7c20e364..6d56a7727 100644 --- a/postfix/man/man8/local.8 +++ b/postfix/man/man8/local.8 @@ -51,7 +51,7 @@ The \fBforward_path\fR parameter is subject to interpolation of \fB$user\fR (recipient username), \fB$home\fR (recipient home directory), \fB$shell\fR (recipient shell), \fB$recipient\fR (complete recipient address), \fB$extension\fR (recipient address -extension), \fB$domain\fR (recipient domain), \fBlocal\fR +extension), \fB$domain\fR (recipient domain), \fB$local\fR (entire recipient address localpart) and \fB$recipient_delimiter.\fR The forms \fI${name?value}\fR and \fI${name:value}\fR expand conditionally to \fIvalue\fR when @@ -165,7 +165,7 @@ to interpolation of \fB$user\fR (recipient username), \fB$home\fR (recipient home directory), \fB$shell\fR (recipient shell), \fB$recipient\fR (complete recipient address), \fB$extension\fR (recipient address extension), -\fB$domain\fR (recipient domain), \fBlocal\fR (entire +\fB$domain\fR (recipient domain), \fB$local\fR (entire recipient address localpart) and \fB$recipient_delimiter.\fR The forms \fI${name?value}\fR and \fI${name:value}\fR expand conditionally to \fIvalue\fR when \fI$name\fR is (is not) diff --git a/postfix/proto/BACKSCATTER_README.html b/postfix/proto/BACKSCATTER_README.html index 069bf60e1..258d85fde 100644 --- a/postfix/proto/BACKSCATTER_README.html +++ b/postfix/proto/BACKSCATTER_README.html @@ -104,8 +104,9 @@ Received: from porcupine.org ... -

Then I know that this is almost certainly forged mail. Mail -that is really sent by my systems looks like this:

+

Then I know that this is almost certainly forged mail (almost; +see next section for the fly in the ointment). Mail that is really +sent by my systems looks like this:

@@ -125,6 +126,18 @@ Received: from host.example.com (EHLO porcupine.org) ...
 
+

Another frequent sign of forgery is the Message-ID: header. My +systems produce a Message-ID: of +<stuff@hostname.porcupine.org>. The following +are forgeries, especially the first one: + +

+
+Message-ID: <1cb479435d8eb9.2beb1.qmail@porcupine.org>
+Message-ID: <yulszqocfzsficvzzju@porcupine.org>
+
+
+

To block such backscatter I use header_checks and body_checks patterns like this:

@@ -139,12 +152,16 @@ patterns like this:

reject forged client name in Received: header: $1 /^Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/ reject forged client name in Received: header: $2 + /^Message-ID:.*@(porcupine\.org)/ + reject forged domain name in Message-ID: header: $1 /etc/postfix/body_checks: /^[> ]*Received: +from +(porcupine\.org) / reject forged client name in Received: header: $1 /^[> ]*Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/ reject forged client name in Received: header: $2 + /^[> ]*Message-ID:.*@(porcupine\.org)/ + reject forged domain name in Message-ID: header: $1 @@ -213,11 +230,11 @@ and is very easy to stop. /etc/postfix/header_checks: /^(From|Return-Path):.*[[:<:]](user@domain\.tld)[[:>:]]/ - reject forged sender address in $1: message header: $2 + reject forged sender address in $1: header: $2 /etc/postfix/body_checks: /^[> ]*(From|Return-Path):.*[[:<:]](user@domain\.tld)[[:>:]]/ - reject forged sender address in $1: message header: $2 + reject forged sender address in $1: header: $2 diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 80dfd2a39..a71bccf55 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -535,6 +535,11 @@ NOTE: if mail to the BCC address bounces it will be returned to the sender.

+

NOTE: automatic BCC recipients are produced only for new mail. +To avoid mailer loops, automatic BCC recipients are not generated +for mail that Postfix forwards internally, nor for mail that Postfix +generates itself.

+ %PARAM berkeley_db_create_buffer_size 16777216

@@ -2827,6 +2832,11 @@ NOTE: if mail to the BCC address bounces it will be returned to the sender.

+

NOTE: automatic BCC recipients are produced only for new mail. +To avoid mailer loops, automatic BCC recipients are not generated +for mail that Postfix forwards internally, nor for mail that Postfix +generates itself.

+

Example:

@@ -3094,6 +3104,11 @@ NOTE: if mail to the BCC address bounces it will be returned to the sender.

+

NOTE: automatic BCC recipients are produced only for new mail. +To avoid mailer loops, automatic BCC recipients are not generated +for mail that Postfix forwards internally, nor for mail that Postfix +generates itself.

+

Example:

diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 23b742184..0ab9ea1e9 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only. */ -#define MAIL_RELEASE_DATE "20040621" +#define MAIL_RELEASE_DATE "20040628" #define MAIL_VERSION_NUMBER "2.2" #define VAR_MAIL_VERSION "mail_version" diff --git a/postfix/src/local/local.c b/postfix/src/local/local.c index 4fb88a99d..3cc7dc011 100644 --- a/postfix/src/local/local.c +++ b/postfix/src/local/local.c @@ -43,7 +43,7 @@ /* \fB$user\fR (recipient username), \fB$home\fR (recipient home /* directory), \fB$shell\fR (recipient shell), \fB$recipient\fR /* (complete recipient address), \fB$extension\fR (recipient address -/* extension), \fB$domain\fR (recipient domain), \fBlocal\fR +/* extension), \fB$domain\fR (recipient domain), \fB$local\fR /* (entire recipient address localpart) and /* \fB$recipient_delimiter.\fR The forms \fI${name?value}\fR and /* \fI${name:value}\fR expand conditionally to \fIvalue\fR when @@ -151,7 +151,7 @@ /* \fB$home\fR (recipient home directory), \fB$shell\fR /* (recipient shell), \fB$recipient\fR (complete recipient /* address), \fB$extension\fR (recipient address extension), -/* \fB$domain\fR (recipient domain), \fBlocal\fR (entire +/* \fB$domain\fR (recipient domain), \fB$local\fR (entire /* recipient address localpart) and \fB$recipient_delimiter.\fR /* The forms \fI${name?value}\fR and \fI${name:value}\fR expand /* conditionally to \fIvalue\fR when \fI$name\fR is (is not) diff --git a/postfix/src/local/maildir.c b/postfix/src/local/maildir.c index e2d20cb42..5d0ab04af 100644 --- a/postfix/src/local/maildir.c +++ b/postfix/src/local/maildir.c @@ -41,6 +41,7 @@ #include "sys_defs.h" #include +#include #include #include #include @@ -86,7 +87,9 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr, char *path) int deliver_status; int copy_flags; struct stat st; - time_t starttime = time((time_t *) 0); + struct timeval starttime; + + GETTIMEOFDAY(&starttime); /* * Make verbose logging easier to understand. @@ -166,7 +169,8 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr, char *path) * filesystem: a maildir has to be within a single UNIX device for link() * and rename() to work.) * - * [...] + * Mn, where n is (in decimal) the microsecond counter from the same + * gettimeofday() used for the left part of the unique name. * * Pn, where n is (in decimal) the process ID. * @@ -176,7 +180,7 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr, char *path) set_eugid(usr_attr.uid, usr_attr.gid); vstring_sprintf(buf, "%lu.P%d.%s", - (unsigned long) starttime, var_pid, get_hostname()); + (unsigned long) starttime.tv_sec, var_pid, get_hostname()); tmpfile = concatenate(tmpdir, STR(buf), (char *) 0); newfile = 0; if ((dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0 @@ -187,9 +191,12 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr, char *path) } else if (fstat(vstream_fileno(dst), &st) < 0) { vstring_sprintf(why, "create %s: %m", tmpfile); } else { - vstring_sprintf(buf, "%lu.V%lxI%lx.%s", - (unsigned long) starttime, (unsigned long) st.st_dev, - (unsigned long) st.st_ino, get_hostname()); + vstring_sprintf(buf, "%lu.V%lxI%lxM%lu.%s", + (unsigned long) starttime.tv_sec, + (unsigned long) st.st_dev, + (unsigned long) st.st_ino, + (unsigned long) starttime.tv_usec, + get_hostname()); newfile = concatenate(newdir, STR(buf), (char *) 0); if ((mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), dst, copy_flags, "\n", why)) == 0) { diff --git a/postfix/src/oqmgr/qmgr_message.c b/postfix/src/oqmgr/qmgr_message.c index a722d0908..658d1d74e 100644 --- a/postfix/src/oqmgr/qmgr_message.c +++ b/postfix/src/oqmgr/qmgr_message.c @@ -936,10 +936,9 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) * agent resources. We use recipient@nexthop as queue name rather * than the actual recipient domain name, so that one recipient in * multiple equivalent domains cannot evade the per-recipient - * concurrency limit. XXX Should split the address on the recipient - * delimiter if one is defined, but doing a proper job requires - * knowledge of local aliases. Yuck! I don't want to duplicate - * delivery-agent specific knowledge in the queue manager. + * concurrency limit. Split the address on the recipient delimiter if + * one is defined, so that extended addresses don't get extra + * delivery slots. * * Fold the result to lower case so that we don't have multiple queues * for the same name. @@ -947,18 +946,32 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) * Important! All recipients in a queue must have the same nexthop * value. It is OK to have multiple queues with the same nexthop * value, but only when those queues are named after recipients. + * + * The single-recipient code below was written for local(8) like + * delivery agents, and assumes that all domains that deliver to the + * same (transport + nexthop) are aliases for $nexthop. Delivery + * concurrency is changed from per-domain into per-recipient, by + * changing the queue name from nexthop into localpart@nexthop. + * + * XXX This assumption is incorrect when different destinations share + * the same (transport + nexthop). In reality, such transports are + * rarely configured to use single-recipient deliveries. The fix is + * to decouple the per-destination recipient limit from the + * per-destination concurrency. */ vstring_strcpy(queue_name, STR(reply.nexthop)); if (strcmp(transport->name, MAIL_SERVICE_ERROR) != 0 && transport->recipient_limit == 1) { + /* Copy the recipient localpart. */ at = strrchr(STR(reply.recipient), '@'); len = (at ? (at - STR(reply.recipient)) : strlen(STR(reply.recipient))); - VSTRING_SPACE(queue_name, len + 2); - memmove(STR(queue_name) + len + 1, STR(queue_name), - LEN(queue_name) + 1); - memcpy(STR(queue_name), STR(reply.recipient), len); - STR(queue_name)[len] = '@'; + vstring_strncpy(queue_name, STR(reply.recipient), len); + /* Remove the address extension from the recipient localpart. */ + if (*var_rcpt_delim && split_addr(STR(queue_name), *var_rcpt_delim)) + vstring_truncate(queue_name, strlen(STR(queue_name))); + /* Assume the recipient domain is equivalent to nexthop. */ + vstring_sprintf_append(queue_name, "@%s", STR(reply.nexthop)); } lowercase(STR(queue_name)); diff --git a/postfix/src/qmgr/qmgr_message.c b/postfix/src/qmgr/qmgr_message.c index 708f48923..724cbd1ab 100644 --- a/postfix/src/qmgr/qmgr_message.c +++ b/postfix/src/qmgr/qmgr_message.c @@ -980,10 +980,9 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) * agent resources. We use recipient@nexthop as queue name rather * than the actual recipient domain name, so that one recipient in * multiple equivalent domains cannot evade the per-recipient - * concurrency limit. XXX Should split the address on the recipient - * delimiter if one is defined, but doing a proper job requires - * knowledge of local aliases. Yuck! I don't want to duplicate - * delivery-agent specific knowledge in the queue manager. + * concurrency limit. Split the address on the recipient delimiter if + * one is defined, so that extended addresses don't get extra + * delivery slots. * * Fold the result to lower case so that we don't have multiple queues * for the same name. @@ -991,18 +990,32 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) * Important! All recipients in a queue must have the same nexthop * value. It is OK to have multiple queues with the same nexthop * value, but only when those queues are named after recipients. + * + * The single-recipient code below was written for local(8) like + * delivery agents, and assumes that all domains that deliver to the + * same (transport + nexthop) are aliases for $nexthop. Delivery + * concurrency is changed from per-domain into per-recipient, by + * changing the queue name from nexthop into localpart@nexthop. + * + * XXX This assumption is incorrect when different destinations share + * the same (transport + nexthop). In reality, such transports are + * rarely configured to use single-recipient deliveries. The fix is + * to decouple the per-destination recipient limit from the + * per-destination concurrency. */ vstring_strcpy(queue_name, STR(reply.nexthop)); if (strcmp(transport->name, MAIL_SERVICE_ERROR) != 0 && transport->recipient_limit == 1) { + /* Copy the recipient localpart. */ at = strrchr(STR(reply.recipient), '@'); len = (at ? (at - STR(reply.recipient)) : strlen(STR(reply.recipient))); - VSTRING_SPACE(queue_name, len + 2); - memmove(STR(queue_name) + len + 1, STR(queue_name), - LEN(queue_name) + 1); - memcpy(STR(queue_name), STR(reply.recipient), len); - STR(queue_name)[len] = '@'; + vstring_strncpy(queue_name, STR(reply.recipient), len); + /* Remove the address extension from the recipient localpart. */ + if (*var_rcpt_delim && split_addr(STR(queue_name), *var_rcpt_delim)) + vstring_truncate(queue_name, strlen(STR(queue_name))); + /* Assume the recipient domain is equivalent to nexthop. */ + vstring_sprintf_append(queue_name, "@%s", STR(reply.nexthop)); } lowercase(STR(queue_name)); diff --git a/postfix/src/virtual/maildir.c b/postfix/src/virtual/maildir.c index c51a4e7c5..b7f46bddd 100644 --- a/postfix/src/virtual/maildir.c +++ b/postfix/src/virtual/maildir.c @@ -36,6 +36,8 @@ #include "sys_defs.h" #include +#include +#include #include #include @@ -84,7 +86,9 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr) int deliver_status; int copy_flags; struct stat st; - time_t starttime = time((time_t *) 0); + struct timeval starttime; + + GETTIMEOFDAY(&starttime); /* * Make verbose logging easier to understand. @@ -163,7 +167,8 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr) * filesystem: a maildir has to be within a single UNIX device for link() * and rename() to work.) * - * [...] + * Mn, where n is (in decimal) the microsecond counter from the same + * gettimeofday() used for the left part of the unique name. * * Pn, where n is (in decimal) the process ID. * @@ -173,7 +178,7 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr) set_eugid(usr_attr.uid, usr_attr.gid); vstring_sprintf(buf, "%lu.P%d.%s", - (unsigned long) starttime, var_pid, get_hostname()); + (unsigned long) starttime.tv_sec, var_pid, get_hostname()); tmpfile = concatenate(tmpdir, STR(buf), (char *) 0); newfile = 0; if ((dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0 @@ -184,9 +189,12 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr) } else if (fstat(vstream_fileno(dst), &st) < 0) { vstring_sprintf(why, "create %s: %m", tmpfile); } else { - vstring_sprintf(buf, "%lu.V%lxI%lx.%s", - (unsigned long) starttime, (unsigned long) st.st_dev, - (unsigned long) st.st_ino, get_hostname()); + vstring_sprintf(buf, "%lu.V%lxI%lxM%lu.%s", + (unsigned long) starttime.tv_sec, + (unsigned long) st.st_dev, + (unsigned long) st.st_ino, + (unsigned long) starttime.tv_usec, + get_hostname()); newfile = concatenate(newdir, STR(buf), (char *) 0); if ((mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), dst, copy_flags, "\n", why)) == 0) {