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);