From 030e4ddd54d134a3583793bf85a3cf6eb4b2e08e Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Fri, 5 Apr 2013 00:00:00 -0500 Subject: [PATCH] postfix-2.11-20130405 --- postfix/HISTORY | 21 ++++++ postfix/RELEASE_NOTES | 13 ++++ postfix/html/local.8.html | 4 +- postfix/html/pipe.8.html | 4 +- postfix/html/postconf.5.html | 57 ++++++++++++++--- postfix/html/smtpd.8.html | 4 +- postfix/html/trivial-rewrite.8.html | 4 +- postfix/man/man5/postconf.5 | 64 ++++++++++++++++--- postfix/man/man8/local.8 | 3 +- postfix/man/man8/pipe.8 | 3 +- postfix/man/man8/smtpd.8 | 3 +- postfix/man/man8/trivial-rewrite.8 | 3 +- postfix/proto/postconf.proto | 61 ++++++++++++++---- postfix/src/global/mail_addr_find.c | 2 +- postfix/src/global/mail_params.c | 2 +- postfix/src/global/mail_version.h | 2 +- postfix/src/global/split_addr.c | 17 +++-- postfix/src/global/split_addr.h | 2 +- postfix/src/global/strip_addr.c | 46 ++++++++----- postfix/src/global/strip_addr.h | 2 +- postfix/src/global/strip_addr.ref | 2 + postfix/src/local/bounce_workaround.c | 2 +- postfix/src/local/local.c | 3 +- postfix/src/local/local_expand.c | 6 +- postfix/src/local/recipient.c | 2 +- postfix/src/local/resolve.c | 6 +- postfix/src/oqmgr/qmgr_message.c | 2 +- postfix/src/pipe/pipe.c | 7 +- postfix/src/qmgr/qmgr_message.c | 2 +- postfix/src/smtpd/smtpd.c | 3 +- postfix/src/smtpd/smtpd_check.c | 2 +- postfix/src/trivial-rewrite/transport.c | 2 +- postfix/src/trivial-rewrite/trivial-rewrite.c | 3 +- postfix/src/util/dict.c | 5 ++ 34 files changed, 278 insertions(+), 86 deletions(-) diff --git a/postfix/HISTORY b/postfix/HISTORY index b2e474cd6..e885287b7 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -18410,3 +18410,24 @@ Apologies for any names omitted. Documentation: in smtpd.c, the comment that justifies the 454 reply for "TLS unavailable" cited the wrong RFC. + +20130404 + + Human factors: warning when a main.cf parameter has multiple + entries with different values. File: util/dict.c. + +20130405 + + Feature: the recipient_delimiter parameter can now specify + a set of characters. A user name is now separated from its + address extension by the first character that matches the + recipient_delimiter set. Files: proto/postconf.proto, + src/global/mail_addr_find.c, src/global/mail_params.c, + src/global/split_addr.c, src/global/split_addr.h, + src/global/strip_addr.c, src/global/strip_addr.h, + src/global/strip_addr.ref, src/local/bounce_workaround.c, + src/local/local.c, src/local/local_expand.c, src/local/recipient.c, + src/local/resolve.c, src/oqmgr/qmgr_message.c, src/pipe/pipe.c, + src/qmgr/qmgr_message.c, src/smtpd/smtpd.c, + src/smtpd/smtpd_check.c, src/trivial-rewrite/transport.c, + src/trivial-rewrite/trivial-rewrite.c. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 765651348..593f1d7c3 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -14,6 +14,19 @@ specifies the release date of a stable release or snapshot release. If you upgrade from Postfix 2.9 or earlier, read RELEASE_NOTES-2.10 before proceeding. +Major changes with snapshot 20130405 +==================================== + +The recipient_delimiter parameter can now specify a set of characters. +A user name is now separated from its address extension by the first +character that matches the recipient_delimiter set. + +For example, specify "recipient_delimiter = +-" to support both the +Postfix-style "+" and the qmail-style "-" extension delimiter. + +As before, this implementation recognizes one delimiter character +per email address, and one address extension per email address. + Major changes with snapshot 20130319 ==================================== diff --git a/postfix/html/local.8.html b/postfix/html/local.8.html index e2cfed120..ee4dff4de 100644 --- a/postfix/html/local.8.html +++ b/postfix/html/local.8.html @@ -608,8 +608,8 @@ LOCAL(8) LOCAL(8) tory. recipient_delimiter (empty) - The separator between user names and address exten- - sions (user+foo). + The set of characters that can separate a user name + from its address extension (user+foo). require_home_directory (no) Require that a local(8) recipient's home directory diff --git a/postfix/html/pipe.8.html b/postfix/html/pipe.8.html index 94be20a98..afe2b5a2e 100644 --- a/postfix/html/pipe.8.html +++ b/postfix/html/pipe.8.html @@ -481,8 +481,8 @@ PIPE(8) PIPE(8) tory. recipient_delimiter (empty) - The separator between user names and address exten- - sions (user+foo). + The set of characters that can separate a user name + from its address extension (user+foo). syslog_facility (mail) The syslog facility of Postfix logging. diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 1c7b27b8e..09d0cf166 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -1451,7 +1451,9 @@ with the character set that is specified with the
$recipient_delimiter
-
The system-wide recipient address extension delimiter.
+
The address extension delimiter that was found in the recipient +address (Postfix 2.11 and later), or the system-wide recipient +address extension delimiter (Postfix 2.10 and earlier).
${name?value}
@@ -3254,7 +3256,9 @@ filtered with the character set that is specified with the
$recipient_delimiter
-
The system-wide recipient address extension delimiter.
+
The address extension delimiter that was found in the recipient +address (Postfix 2.11 and later), or the system-wide recipient +address extension delimiter (Postfix 2.10 and earlier).
${name?value}
@@ -5308,7 +5312,9 @@ The following $name expansions are done on $recipient_delimiter -
The system-wide recipient address extension delimiter.
+
The address extension delimiter that was found in the recipient +address (Postfix 2.11 and later), or the system-wide recipient +address extension delimiter (Postfix 2.10 and earlier).
$shell
@@ -8498,22 +8504,53 @@ Example:
recipient_delimiter (default: empty)
-

-The separator between user names and address extensions (user+foo). -See canonical(5), local(8), relocated(5) and virtual(5) for the -effects this has on aliases, canonical, virtual, relocated and -on .forward file lookups. Basically, the software tries user+foo -and .forward+foo before trying user and .forward. +

The set of characters that can separate a user name from its +address extension (user+foo). See canonical(5), local(8), relocated(5) +and virtual(5) for the effects this has on aliases, canonical, +virtual, and relocated lookups. Basically, the software tries +user+foo and .forward+foo before trying user and .forward.

+ +

This implementation recognizes one delimiter character per email +address, and one address extension per email address.

+ +

When the recipient_delimiter set contains multiple characters +(Postfix 2.11 and later), a user name is separated from its address +extension by the first character that matches the recipient_delimiter +set.

+ +

When used in forward_path, ${recipient_delimiter} is replaced +with the recipient delimiter that was found in the recipient email +address (Postfix 2.11 and later), or it is replaced with the main.cf +recipient_delimiter parameter value (Postfix 2.10 and earlier).

+

The recipient_delimiter is not applied to the mailer-daemon +address, the postmaster address, or the double-bounce address. With +the default "owner_request_special = yes" setting, the recipient_delimiter +is also not applied to addresses with the special "owner-" prefix +or the special "-request" suffix.

+

-Example: +Examples:

+# Handle Postfix-style extensions.
 recipient_delimiter = +
 
+
+# Handle both Postfix and qmail extensions (Postfix 2.11 and later).
+recipient_delimiters = +-
+
+ +
+# Use .forward for mail without address extension, and for mail with
+# an unrecognized address extension.
+forward_path = $home/.forward${recipient_delimiter}${extension},
+    $home/.forward,
+
+
diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index dc934bb90..b879d1418 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -1293,8 +1293,8 @@ SMTPD(8) SMTPD(8) tory. recipient_delimiter (empty) - The separator between user names and address exten- - sions (user+foo). + The set of characters that can separate a user name + from its address extension (user+foo). smtpd_banner ($myhostname ESMTP $mail_name) The text that follows the 220 status code in the diff --git a/postfix/html/trivial-rewrite.8.html b/postfix/html/trivial-rewrite.8.html index 6da7aced5..e47d39e0e 100644 --- a/postfix/html/trivial-rewrite.8.html +++ b/postfix/html/trivial-rewrite.8.html @@ -133,8 +133,8 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) information. recipient_delimiter (empty) - The separator between user names and address exten- - sions (user+foo). + The set of characters that can separate a user name + from its address extension (user+foo). swap_bangpath (yes) Enable the rewriting of "site!user" into diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 3f9814927..8d22aa22d 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -835,7 +835,9 @@ The recipient domain. The entire recipient localpart. .br .IP "\fB$recipient_delimiter\fR" -The system-wide recipient address extension delimiter. +The address extension delimiter that was found in the recipient +address (Postfix 2.11 and later), or the system-wide recipient +address extension delimiter (Postfix 2.10 and earlier). .br .IP "\fB${name?value}\fR" Expands to \fIvalue\fR when \fI$name\fR is non-empty. @@ -1919,7 +1921,9 @@ The recipient domain. The entire recipient localpart. .br .IP "\fB$recipient_delimiter\fR" -The system-wide recipient address extension delimiter. +The address extension delimiter that was found in the recipient +address (Postfix 2.11 and later), or the system-wide recipient +address extension delimiter (Postfix 2.10 and earlier). .br .IP "\fB${name?value}\fR" Expands to \fIvalue\fR when \fI$name\fR is non-empty. @@ -3068,7 +3072,9 @@ The entire recipient address localpart. The full recipient address. .br .IP "\fB$recipient_delimiter\fR" -The system-wide recipient address extension delimiter. +The address extension delimiter that was found in the recipient +address (Postfix 2.11 and later), or the system-wide recipient +address extension delimiter (Postfix 2.10 and earlier). .br .IP "\fB$shell\fR" The recipient's login shell. @@ -5095,21 +5101,61 @@ recipient_canonical_maps = hash:/etc/postfix/recipient_canonical .ad .ft R .SH recipient_delimiter (default: empty) -The separator between user names and address extensions (user+foo). -See \fBcanonical\fR(5), \fBlocal\fR(8), \fBrelocated\fR(5) and \fBvirtual\fR(5) for the -effects this has on aliases, canonical, virtual, relocated and -on .forward file lookups. Basically, the software tries user+foo -and .forward+foo before trying user and .forward. +The set of characters that can separate a user name from its +address extension (user+foo). See \fBcanonical\fR(5), \fBlocal\fR(8), \fBrelocated\fR(5) +and \fBvirtual\fR(5) for the effects this has on aliases, canonical, +virtual, and relocated lookups. Basically, the software tries +user+foo and .forward+foo before trying user and .forward. .PP -Example: +This implementation recognizes one delimiter character per email +address, and one address extension per email address. +.PP +When the recipient_delimiter set contains multiple characters +(Postfix 2.11 and later), a user name is separated from its address +extension by the first character that matches the recipient_delimiter +set. +.PP +When used in forward_path, ${recipient_delimiter} is replaced +with the recipient delimiter that was found in the recipient email +address (Postfix 2.11 and later), or it is replaced with the main.cf +recipient_delimiter parameter value (Postfix 2.10 and earlier). +.PP +The recipient_delimiter is not applied to the mailer-daemon +address, the postmaster address, or the double-bounce address. With +the default "owner_request_special = yes" setting, the recipient_delimiter +is also not applied to addresses with the special "owner-" prefix +or the special "-request" suffix. +.PP +Examples: .PP .nf .na .ft C +# Handle Postfix-style extensions. recipient_delimiter = + .fi .ad .ft R +.PP +.nf +.na +.ft C +# Handle both Postfix and qmail extensions (Postfix 2.11 and later). +recipient_delimiters = +- +.fi +.ad +.ft R +.PP +.nf +.na +.ft C +# Use .forward for mail without address extension, and for mail with +# an unrecognized address extension. +forward_path = $home/.forward${recipient_delimiter}${extension}, + $home/.forward, +.fi +.ad +.ft R .SH reject_code (default: 554) The numerical Postfix SMTP server response code when a remote SMTP client request is rejected by the "reject" restriction. diff --git a/postfix/man/man8/local.8 b/postfix/man/man8/local.8 index 5b6bc81b4..b872ce6fe 100644 --- a/postfix/man/man8/local.8 +++ b/postfix/man/man8/local.8 @@ -575,7 +575,8 @@ key to the lookup result. .IP "\fBqueue_directory (see 'postconf -d' output)\fR" The location of the Postfix top-level queue directory. .IP "\fBrecipient_delimiter (empty)\fR" -The separator between user names and address extensions (user+foo). +The set of characters that can separate a user name from its +address extension (user+foo). .IP "\fBrequire_home_directory (no)\fR" Require that a \fBlocal\fR(8) recipient's home directory exists before mail delivery is attempted. diff --git a/postfix/man/man8/pipe.8 b/postfix/man/man8/pipe.8 index ec088ac6b..a24a5ee48 100644 --- a/postfix/man/man8/pipe.8 +++ b/postfix/man/man8/pipe.8 @@ -412,7 +412,8 @@ The process name of a Postfix command or daemon process. .IP "\fBqueue_directory (see 'postconf -d' output)\fR" The location of the Postfix top-level queue directory. .IP "\fBrecipient_delimiter (empty)\fR" -The separator between user names and address extensions (user+foo). +The set of characters that can separate a user name from its +address extension (user+foo). .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index d6c8bce00..fd71de239 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -1012,7 +1012,8 @@ The process name of a Postfix command or daemon process. .IP "\fBqueue_directory (see 'postconf -d' output)\fR" The location of the Postfix top-level queue directory. .IP "\fBrecipient_delimiter (empty)\fR" -The separator between user names and address extensions (user+foo). +The set of characters that can separate a user name from its +address extension (user+foo). .IP "\fBsmtpd_banner ($myhostname ESMTP $mail_name)\fR" The text that follows the 220 status code in the SMTP greeting banner. diff --git a/postfix/man/man8/trivial-rewrite.8 b/postfix/man/man8/trivial-rewrite.8 index ca85bd36b..134c108be 100644 --- a/postfix/man/man8/trivial-rewrite.8 +++ b/postfix/man/man8/trivial-rewrite.8 @@ -130,7 +130,8 @@ addresses without domain information. With locally submitted mail, append the string ".$mydomain" to addresses that have no ".domain" information. .IP "\fBrecipient_delimiter (empty)\fR" -The separator between user names and address extensions (user+foo). +The set of characters that can separate a user name from its +address extension (user+foo). .IP "\fBswap_bangpath (yes)\fR" Enable the rewriting of "site!user" into "user@site". .PP diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index c42856f1b..9c8d9fd8c 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -1609,7 +1609,9 @@ execution_directory_expansion_filter parameter.

$recipient_delimiter
-
The system-wide recipient address extension delimiter.
+
The address extension delimiter that was found in the recipient +address (Postfix 2.11 and later), or the system-wide recipient +address extension delimiter (Postfix 2.10 and earlier).
${name?value}
@@ -1670,7 +1672,9 @@ forward_expansion_filter parameter.

$recipient_delimiter
-
The system-wide recipient address extension delimiter.
+
The address extension delimiter that was found in the recipient +address (Postfix 2.11 and later), or the system-wide recipient +address extension delimiter (Postfix 2.10 and earlier).
${name?value}
@@ -2404,7 +2408,9 @@ The following $name expansions are done on luser_relay:
$recipient_delimiter
-
The system-wide recipient address extension delimiter.
+
The address extension delimiter that was found in the recipient +address (Postfix 2.11 and later), or the system-wide recipient +address extension delimiter (Postfix 2.10 and earlier).
$shell
@@ -3495,22 +3501,53 @@ Example: recipient_canonical_maps = hash:/etc/postfix/recipient_canonical -%PARAM recipient_delimiter +%PARAM recipient_delimiter -

-The separator between user names and address extensions (user+foo). -See canonical(5), local(8), relocated(5) and virtual(5) for the -effects this has on aliases, canonical, virtual, relocated and -on .forward file lookups. Basically, the software tries user+foo -and .forward+foo before trying user and .forward. +

The set of characters that can separate a user name from its +address extension (user+foo). See canonical(5), local(8), relocated(5) +and virtual(5) for the effects this has on aliases, canonical, +virtual, and relocated lookups. Basically, the software tries +user+foo and .forward+foo before trying user and .forward.

+ +

This implementation recognizes one delimiter character per email +address, and one address extension per email address.

+ +

When the recipient_delimiter set contains multiple characters +(Postfix 2.11 and later), a user name is separated from its address +extension by the first character that matches the recipient_delimiter +set.

+ +

When used in forward_path, ${recipient_delimiter} is replaced +with the recipient delimiter that was found in the recipient email +address (Postfix 2.11 and later), or it is replaced with the main.cf +recipient_delimiter parameter value (Postfix 2.10 and earlier).

+

The recipient_delimiter is not applied to the mailer-daemon +address, the postmaster address, or the double-bounce address. With +the default "owner_request_special = yes" setting, the recipient_delimiter +is also not applied to addresses with the special "owner-" prefix +or the special "-request" suffix.

+

-Example: +Examples:

+ +
+# Handle Postfix-style extensions.
+recipient_delimiter = +
+
-recipient_delimiter = +
+# Handle both Postfix and qmail extensions (Postfix 2.11 and later).
+recipient_delimiters = +-
+
+ +
+# Use .forward for mail without address extension, and for mail with
+# an unrecognized address extension.
+forward_path = $home/.forward${recipient_delimiter}${extension},
+    $home/.forward,
 
%PARAM reject_code 554 diff --git a/postfix/src/global/mail_addr_find.c b/postfix/src/global/mail_addr_find.c index ed8caab6d..e21dd3600 100644 --- a/postfix/src/global/mail_addr_find.c +++ b/postfix/src/global/mail_addr_find.c @@ -109,7 +109,7 @@ const char *mail_addr_find(MAPS *path, const char *address, char **extp) if (*var_rcpt_delim == 0) { bare_key = saved_ext = 0; } else { - bare_key = strip_addr(full_key, &saved_ext, *var_rcpt_delim); + bare_key = strip_addr(full_key, &saved_ext, var_rcpt_delim); } /* diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index 94ea155d7..5bc95c659 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -557,7 +557,7 @@ void mail_params_init() VAR_MAIL_VERSION, DEF_MAIL_VERSION, &var_mail_version, 1, 0, VAR_DB_TYPE, DEF_DB_TYPE, &var_db_type, 1, 0, VAR_HASH_QUEUE_NAMES, DEF_HASH_QUEUE_NAMES, &var_hash_queue_names, 1, 0, - VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim, 0, 1, + VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim, 0, 0, VAR_RELAY_DOMAINS, DEF_RELAY_DOMAINS, &var_relay_domains, 0, 0, VAR_FFLUSH_DOMAINS, DEF_FFLUSH_DOMAINS, &var_fflush_domains, 0, 0, VAR_EXPORT_ENVIRON, DEF_EXPORT_ENVIRON, &var_export_environ, 0, 0, diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index a869f257d..434e516e8 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 "20130403" +#define MAIL_RELEASE_DATE "20130405" #define MAIL_VERSION_NUMBER "2.11" #ifdef SNAPSHOT diff --git a/postfix/src/global/split_addr.c b/postfix/src/global/split_addr.c index 279ad4fb6..7e7cc27c8 100644 --- a/postfix/src/global/split_addr.c +++ b/postfix/src/global/split_addr.c @@ -6,12 +6,12 @@ /* SYNOPSIS /* #include /* -/* char *split_addr(localpart, delimiter) +/* char *split_addr(localpart, delimiter_set) /* char *localpart; -/* int delimiter; +/* const char *delimiter_set; /* DESCRIPTION /* split_addr() null-terminates \fIlocalpart\fR at the first -/* occurrence of the \fIdelimiter\fR character found, and +/* occurrence of the \fIdelimiter\fR character(s) found, and /* returns a pointer to the remainder. /* /* Reserved addresses are not split: postmaster, mailer-daemon, @@ -50,7 +50,7 @@ /* split_addr - split address with extreme prejudice */ -char *split_addr(char *localpart, int delimiter) +char *split_addr(char *localpart, const char *delimiter_set) { int len; @@ -67,7 +67,7 @@ char *split_addr(char *localpart, int delimiter) /* * Backwards compatibility: don't split owner-foo or foo-request. */ - if (delimiter == '-' && var_ownreq_special != 0) { + if (strchr(delimiter_set, '-') != 0 && var_ownreq_special != 0) { if (strncasecmp(localpart, "owner-", 6) == 0) return (0); if ((len = strlen(localpart) - 8) > 0 @@ -79,5 +79,10 @@ char *split_addr(char *localpart, int delimiter) * Safe to split this address. Do not split the address if the result * would have a null localpart. */ - return (delimiter == *localpart ? 0 : split_at(localpart, delimiter)); + if ((len = strcspn(localpart, delimiter_set)) == 0 || localpart[len] == 0) { + return (0); + } else { + localpart[len] = 0; + return (localpart + len + 1); + } } diff --git a/postfix/src/global/split_addr.h b/postfix/src/global/split_addr.h index 1c87fb99a..fa89faeae 100644 --- a/postfix/src/global/split_addr.h +++ b/postfix/src/global/split_addr.h @@ -13,7 +13,7 @@ /* External interface. */ -extern char *split_addr(char *, int); +extern char *split_addr(char *, const char *); /* LICENSE /* .ad diff --git a/postfix/src/global/strip_addr.c b/postfix/src/global/strip_addr.c index 803db87f8..6792d35f3 100644 --- a/postfix/src/global/strip_addr.c +++ b/postfix/src/global/strip_addr.c @@ -6,10 +6,10 @@ /* SYNOPSIS /* #include /* -/* char *strip_addr(address, extension, delimiter) +/* char *strip_addr(address, extension, delimiter_set) /* const char *address; /* char **extension; -/* int delimiter; +/* const char *delimiter_set; /* DESCRIPTION /* strip_addr() takes an address and either returns a null /* pointer when the address contains no address extension, @@ -25,8 +25,8 @@ /* that had to be chopped off. /* The copy includes the recipient address delimiter. /* The caller is expected to pass the copy to myfree(). -/* .IP delimiter -/* Recipient address delimiter. +/* .IP delimiter_set +/* Set of recipient address delimiter characters. /* SEE ALSO /* split_addr(3) strip extension from localpart /* LICENSE @@ -56,7 +56,7 @@ /* strip_addr - strip extension from address */ -char *strip_addr(const char *full, char **extension, int delimiter) +char *strip_addr(const char *full, char **extension, const char *delimiter_set) { char *ratsign; char *extent; @@ -66,16 +66,16 @@ char *strip_addr(const char *full, char **extension, int delimiter) /* * A quick test to eliminate inputs without delimiter anywhere. */ - if (delimiter == 0 || strchr(full, delimiter) == 0) { + if (*delimiter_set == 0 || full[strcspn(full, delimiter_set)] == 0) { stripped = saved_ext = 0; } else { stripped = mystrdup(full); if ((ratsign = strrchr(stripped, '@')) != 0) *ratsign = 0; - if ((extent = split_addr(stripped, delimiter)) != 0) { + if ((extent = split_addr(stripped, delimiter_set)) != 0) { extent -= 1; if (extension) { - *extent = delimiter; + *extent = full[strlen(stripped)]; saved_ext = mystrdup(extent); *extent = 0; } else @@ -105,17 +105,19 @@ int main(int unused_argc, char **unused_argv) { char *extension; char *stripped; - int delim = '-'; + char* delim = "+-"; + +#define NO_DELIM "" /* * Incredible. This function takes only three arguments, and the tests * already take more lines of code than the code being tested. */ - stripped = strip_addr("foo", (char **) 0, 0); + stripped = strip_addr("foo", (char **) 0, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 1"); - stripped = strip_addr("foo", &extension, 0); + stripped = strip_addr("foo", &extension, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 2"); if (extension != 0) @@ -131,11 +133,11 @@ int main(int unused_argc, char **unused_argv) if (extension != 0) msg_panic("strip_addr botch 6"); - stripped = strip_addr("foo@bar", (char **) 0, 0); + stripped = strip_addr("foo@bar", (char **) 0, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 7"); - stripped = strip_addr("foo@bar", &extension, 0); + stripped = strip_addr("foo@bar", &extension, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 8"); if (extension != 0) @@ -151,11 +153,11 @@ int main(int unused_argc, char **unused_argv) if (extension != 0) msg_panic("strip_addr botch 12"); - stripped = strip_addr("foo-ext", (char **) 0, 0); + stripped = strip_addr("foo-ext", (char **) 0, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 13"); - stripped = strip_addr("foo-ext", &extension, 0); + stripped = strip_addr("foo-ext", &extension, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 14"); if (extension != 0) @@ -178,11 +180,11 @@ int main(int unused_argc, char **unused_argv) myfree(stripped); myfree(extension); - stripped = strip_addr("foo-ext@bar", (char **) 0, 0); + stripped = strip_addr("foo-ext@bar", (char **) 0, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 19"); - stripped = strip_addr("foo-ext@bar", &extension, 0); + stripped = strip_addr("foo-ext@bar", &extension, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 20"); if (extension != 0) @@ -205,6 +207,16 @@ int main(int unused_argc, char **unused_argv) myfree(stripped); myfree(extension); + stripped = strip_addr("foo+ext@bar", &extension, delim); + if (stripped == 0) + msg_panic("strip_addr botch 25"); + if (extension == 0) + msg_panic("strip_addr botch 26"); + msg_info("wanted: foo+ext@bar -> %s %s", "foo@bar", "+ext"); + msg_info("strip_addr foo+ext@bar -> %s %s", stripped, extension); + myfree(stripped); + myfree(extension); + return (0); } diff --git a/postfix/src/global/strip_addr.h b/postfix/src/global/strip_addr.h index e99c6fdf8..19530e1ba 100644 --- a/postfix/src/global/strip_addr.h +++ b/postfix/src/global/strip_addr.h @@ -13,7 +13,7 @@ /* External interface. */ -extern char *strip_addr(const char *, char **, int); +extern char *strip_addr(const char *, char **, const char *); /* LICENSE /* .ad diff --git a/postfix/src/global/strip_addr.ref b/postfix/src/global/strip_addr.ref index 3068918ca..af218e5c0 100644 --- a/postfix/src/global/strip_addr.ref +++ b/postfix/src/global/strip_addr.ref @@ -6,3 +6,5 @@ unknown: wanted: foo-ext@bar -> foo@bar unknown: strip_addr foo-ext@bar -> foo@bar unknown: wanted: foo-ext@bar -> foo@bar -ext unknown: strip_addr foo-ext@bar -> foo@bar -ext +unknown: wanted: foo+ext@bar -> foo@bar +ext +unknown: strip_addr foo+ext@bar -> foo@bar +ext diff --git a/postfix/src/local/bounce_workaround.c b/postfix/src/local/bounce_workaround.c index 8d1670c80..e7211ec55 100644 --- a/postfix/src/local/bounce_workaround.c +++ b/postfix/src/local/bounce_workaround.c @@ -109,7 +109,7 @@ int bounce_workaround(LOCAL_STATE state) if (alias_maps->error == 0 && owner_expansion == 0 && (stripped_recipient = strip_addr(state.msg_attr.rcpt.address, (char **) 0, - *var_rcpt_delim)) != 0) { + var_rcpt_delim)) != 0) { myfree(owner_alias); FIND_OWNER(owner_alias, owner_expansion, stripped_recipient); myfree(stripped_recipient); diff --git a/postfix/src/local/local.c b/postfix/src/local/local.c index cec231263..32da88bca 100644 --- a/postfix/src/local/local.c +++ b/postfix/src/local/local.c @@ -531,7 +531,8 @@ /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" /* The location of the Postfix top-level queue directory. /* .IP "\fBrecipient_delimiter (empty)\fR" -/* The separator between user names and address extensions (user+foo). +/* The set of characters that can separate a user name from its +/* address extension (user+foo). /* .IP "\fBrequire_home_directory (no)\fR" /* Require that a \fBlocal\fR(8) recipient's home directory exists /* before mail delivery is attempted. diff --git a/postfix/src/local/local_expand.c b/postfix/src/local/local_expand.c index db5121ee8..612e68094 100644 --- a/postfix/src/local/local_expand.c +++ b/postfix/src/local/local_expand.c @@ -113,6 +113,7 @@ typedef struct { static const char *local_expand_lookup(const char *name, int mode, char *ptr) { LOCAL_EXP *local = (LOCAL_EXP *) ptr; + static char rcpt_delim[2]; #define STREQ(x,y) (*(x) == *(y) && strcmp((x), (y)) == 0) @@ -135,7 +136,10 @@ static const char *local_expand_lookup(const char *name, int mode, char *ptr) local->status |= LOCAL_EXP_EXTENSION_MATCHED; return (local->state->msg_attr.extension); } else if (STREQ(name, "recipient_delimiter")) { - return (*var_rcpt_delim ? var_rcpt_delim : 0); + rcpt_delim[0] = + local->state->msg_attr.local[strlen(local->state->msg_attr.user)]; + rcpt_delim[1] = 0; + return (rcpt_delim[0] ? rcpt_delim : 0); #if 0 } else if (STREQ(name, "client_hostname")) { return (local->state->msg_attr.request->client_name); diff --git a/postfix/src/local/recipient.c b/postfix/src/local/recipient.c index 192144493..8017942e5 100644 --- a/postfix/src/local/recipient.c +++ b/postfix/src/local/recipient.c @@ -270,7 +270,7 @@ int deliver_recipient(LOCAL_STATE state, USER_ATTR usr_attr) state.msg_attr.user = mystrdup(state.msg_attr.local); if (*var_rcpt_delim) { state.msg_attr.extension = - split_addr(state.msg_attr.user, *var_rcpt_delim); + split_addr(state.msg_attr.user, var_rcpt_delim); if (state.msg_attr.extension && strchr(state.msg_attr.extension, '/')) { msg_warn("%s: address with illegal extension: %s", state.msg_attr.queue_id, state.msg_attr.local); diff --git a/postfix/src/local/resolve.c b/postfix/src/local/resolve.c index 89c330325..a6aa9d035 100644 --- a/postfix/src/local/resolve.c +++ b/postfix/src/local/resolve.c @@ -90,6 +90,7 @@ int deliver_resolve_tree(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr int status; ssize_t ext_len; char *ratsign; + int rcpt_delim; /* * Make verbose logging easier to understand. @@ -130,8 +131,9 @@ int deliver_resolve_tree(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr * Splice in the optional unmatched address extension. */ if (state.msg_attr.unmatched) { + rcpt_delim = state.msg_attr.local[strlen(state.msg_attr.user)]; if ((ratsign = strrchr(STR(reply.recipient), '@')) == 0) { - VSTRING_ADDCH(reply.recipient, *var_rcpt_delim); + VSTRING_ADDCH(reply.recipient, rcpt_delim); vstring_strcat(reply.recipient, state.msg_attr.unmatched); } else { ext_len = strlen(state.msg_attr.unmatched); @@ -139,7 +141,7 @@ int deliver_resolve_tree(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr if ((ratsign = strrchr(STR(reply.recipient), '@')) == 0) msg_panic("%s: recipient @ botch", myname); memmove(ratsign + ext_len + 1, ratsign, strlen(ratsign) + 1); - *ratsign = *var_rcpt_delim; + *ratsign = rcpt_delim; memcpy(ratsign + 1, state.msg_attr.unmatched, ext_len); VSTRING_SKIP(reply.recipient); } diff --git a/postfix/src/oqmgr/qmgr_message.c b/postfix/src/oqmgr/qmgr_message.c index 71955d4f3..e2f923741 100644 --- a/postfix/src/oqmgr/qmgr_message.c +++ b/postfix/src/oqmgr/qmgr_message.c @@ -1175,7 +1175,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) : strlen(STR(reply.recipient))); 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)) + 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)); diff --git a/postfix/src/pipe/pipe.c b/postfix/src/pipe/pipe.c index 73e9978bb..b6329f02f 100644 --- a/postfix/src/pipe/pipe.c +++ b/postfix/src/pipe/pipe.c @@ -390,7 +390,8 @@ /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" /* The location of the Postfix top-level queue directory. /* .IP "\fBrecipient_delimiter (empty)\fR" -/* The separator between user names and address extensions (user+foo). +/* The set of characters that can separate a user name from its +/* address extension (user+foo). /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" @@ -717,7 +718,7 @@ static ARGV *expand_argv(const char *service, char **argv, msg_warn("no @ in recipient address: %s", rcpt_list->info[i].address); if (*var_rcpt_delim) - split_addr(STR(buf), *var_rcpt_delim); + split_addr(STR(buf), var_rcpt_delim); if (*STR(buf) == 0) continue; dict_update(PIPE_DICT_TABLE, PIPE_DICT_USER, STR(buf)); @@ -735,7 +736,7 @@ static ARGV *expand_argv(const char *service, char **argv, msg_warn("no @ in recipient address: %s", rcpt_list->info[i].address); if (*var_rcpt_delim == 0 - || (ext = split_addr(STR(buf), *var_rcpt_delim)) == 0) + || (ext = split_addr(STR(buf), var_rcpt_delim)) == 0) ext = ""; /* insert null arg */ dict_update(PIPE_DICT_TABLE, PIPE_DICT_EXTENSION, ext); } diff --git a/postfix/src/qmgr/qmgr_message.c b/postfix/src/qmgr/qmgr_message.c index 576fb2d6f..e6bbaf65c 100644 --- a/postfix/src/qmgr/qmgr_message.c +++ b/postfix/src/qmgr/qmgr_message.c @@ -1234,7 +1234,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) : strlen(STR(reply.recipient))); 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)) + 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)); diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 1f219e187..fae7358ba 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -956,7 +956,8 @@ /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" /* The location of the Postfix top-level queue directory. /* .IP "\fBrecipient_delimiter (empty)\fR" -/* The separator between user names and address extensions (user+foo). +/* The set of characters that can separate a user name from its +/* address extension (user+foo). /* .IP "\fBsmtpd_banner ($myhostname ESMTP $mail_name)\fR" /* The text that follows the 220 status code in the SMTP greeting /* banner. diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 52ebc66c1..3ee7ee12f 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -2866,7 +2866,7 @@ static int check_mail_access(SMTPD_STATE *state, const char *table, if (*var_rcpt_delim == 0) { bare_addr = 0; } else { - bare_addr = strip_addr(addr, (char **) 0, *var_rcpt_delim); + bare_addr = strip_addr(addr, (char **) 0, var_rcpt_delim); } #define CHECK_MAIL_ACCESS_RETURN(x) \ diff --git a/postfix/src/trivial-rewrite/transport.c b/postfix/src/trivial-rewrite/transport.c index 29720541c..61937ae42 100644 --- a/postfix/src/trivial-rewrite/transport.c +++ b/postfix/src/trivial-rewrite/transport.c @@ -286,7 +286,7 @@ int transport_lookup(TRANSPORT_INFO *tp, const char *addr, * partial lookup keys with regular expressions. */ if ((stripped_addr = strip_addr(addr, DISCARD_EXTENSION, - *var_rcpt_delim)) != 0) { + var_rcpt_delim)) != 0) { found = find_transport_entry(tp, stripped_addr, rcpt_domain, PARTIAL, channel, nexthop); diff --git a/postfix/src/trivial-rewrite/trivial-rewrite.c b/postfix/src/trivial-rewrite/trivial-rewrite.c index b8cc438c2..cafb1acee 100644 --- a/postfix/src/trivial-rewrite/trivial-rewrite.c +++ b/postfix/src/trivial-rewrite/trivial-rewrite.c @@ -110,7 +110,8 @@ /* With locally submitted mail, append the string ".$mydomain" to /* addresses that have no ".domain" information. /* .IP "\fBrecipient_delimiter (empty)\fR" -/* The separator between user names and address extensions (user+foo). +/* The set of characters that can separate a user name from its +/* address extension (user+foo). /* .IP "\fBswap_bangpath (yes)\fR" /* Enable the rewriting of "site!user" into "user@site". /* .PP diff --git a/postfix/src/util/dict.c b/postfix/src/util/dict.c index 8d77883f5..3c4a9b1b8 100644 --- a/postfix/src/util/dict.c +++ b/postfix/src/util/dict.c @@ -431,6 +431,7 @@ void dict_load_fp(const char *dict_name, VSTREAM *fp) VSTRING *buf; char *member; char *val; + const char *old; int old_lineno; int lineno; const char *err; @@ -455,6 +456,10 @@ void dict_load_fp(const char *dict_name, VSTREAM *fp) err, STR(buf)); if (msg_verbose > 1) msg_info("%s: %s = %s", myname, member, val); + if ((old = dict->lookup(dict, member)) != 0 + && strcmp(old, val) != 0) + msg_warn("%s, line %d: overriding earlier entry: %s=%s", + VSTREAM_PATH(fp), lineno, member, old); if (dict->update(dict, member, val) != 0) msg_fatal("%s, line %d: unable to update %s:%s", VSTREAM_PATH(fp), lineno, dict->type, dict->name);