2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-22 09:57:34 +00:00

postfix-2.11-20130405

This commit is contained in:
Wietse Venema 2013-04-05 00:00:00 -05:00 committed by Viktor Dukhovni
parent 46a1d9a44f
commit 030e4ddd54
34 changed files with 278 additions and 86 deletions

View File

@ -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.

View File

@ -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
====================================

View File

@ -608,8 +608,8 @@ LOCAL(8) LOCAL(8)
tory.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
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).
<b><a href="postconf.5.html#require_home_directory">require_home_directory</a> (no)</b>
Require that a <a href="local.8.html"><b>local</b>(8)</a> recipient's home directory

View File

@ -481,8 +481,8 @@ PIPE(8) PIPE(8)
tory.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
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).
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.

View File

@ -1451,7 +1451,9 @@ with the character set that is specified with the
<dt><b>$<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a></b></dt>
<dd>The system-wide recipient address extension delimiter. </dd>
<dd>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). </dd>
<dt><b>${name?value}</b></dt>
@ -3254,7 +3256,9 @@ filtered with the character set that is specified with the
<dt><b>$<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a></b></dt>
<dd>The system-wide recipient address extension delimiter. </dd>
<dd>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). </dd>
<dt><b>${name?value}</b></dt>
@ -5308,7 +5312,9 @@ The following $name expansions are done on <a href="postconf.5.html#luser_relay"
<dt><b>$<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a></b></dt>
<dd>The system-wide recipient address extension delimiter. </dd>
<dd>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). </dd>
<dt><b>$shell</b></dt>
@ -8498,22 +8504,53 @@ Example:
<DT><b><a name="recipient_delimiter">recipient_delimiter</a>
(default: empty)</b></DT><DD>
<p>
The separator between user names and address extensions (user+foo).
See <a href="canonical.5.html">canonical(5)</a>, <a href="local.8.html">local(8)</a>, <a href="relocated.5.html">relocated(5)</a> and <a href="virtual.5.html">virtual(5)</a> 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.
<p> The set of characters that can separate a user name from its
address extension (user+foo). See <a href="canonical.5.html">canonical(5)</a>, <a href="local.8.html">local(8)</a>, <a href="relocated.5.html">relocated(5)</a>
and <a href="virtual.5.html">virtual(5)</a> 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. </p>
<p> This implementation recognizes one delimiter character per email
address, and one address extension per email address. </p>
<p> When the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> 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 <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a>
set. </p>
<p> When used in <a href="postconf.5.html#forward_path">forward_path</a>, ${<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a>} 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 <a href="postconf.5.html">main.cf</a>
<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> parameter value (Postfix 2.10 and earlier).
</p>
<p> The <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is not applied to the mailer-daemon
address, the postmaster address, or the double-bounce address. With
the default "<a href="postconf.5.html#owner_request_special">owner_request_special</a> = yes" setting, the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a>
is also not applied to addresses with the special "owner-" prefix
or the special "-request" suffix. </p>
<p>
Example:
Examples:
</p>
<pre>
# Handle Postfix-style extensions.
<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> = +
</pre>
<pre>
# Handle both Postfix and qmail extensions (Postfix 2.11 and later).
recipient_delimiters = +-
</pre>
<pre>
# Use .forward for mail without address extension, and for mail with
# an unrecognized address extension.
<a href="postconf.5.html#forward_path">forward_path</a> = $home/.forward${<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a>}${extension},
$home/.forward,
</pre>
</DD>

View File

@ -1293,8 +1293,8 @@ SMTPD(8) SMTPD(8)
tory.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
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).
<b><a href="postconf.5.html#smtpd_banner">smtpd_banner</a> ($<a href="postconf.5.html#myhostname">myhostname</a> ESMTP $<a href="postconf.5.html#mail_name">mail_name</a>)</b>
The text that follows the 220 status code in the

View File

@ -133,8 +133,8 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
information.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
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).
<b><a href="postconf.5.html#swap_bangpath">swap_bangpath</a> (yes)</b>
Enable the rewriting of "site!user" into

View File

@ -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.

View File

@ -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.

View File

@ -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"

View File

@ -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.

View File

@ -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

View File

@ -1609,7 +1609,9 @@ execution_directory_expansion_filter parameter. </p>
<dt><b>$recipient_delimiter</b></dt>
<dd>The system-wide recipient address extension delimiter. </dd>
<dd>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). </dd>
<dt><b>${name?value}</b></dt>
@ -1670,7 +1672,9 @@ forward_expansion_filter parameter. </p>
<dt><b>$recipient_delimiter</b></dt>
<dd>The system-wide recipient address extension delimiter. </dd>
<dd>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). </dd>
<dt><b>${name?value}</b></dt>
@ -2404,7 +2408,9 @@ The following $name expansions are done on luser_relay:
<dt><b>$recipient_delimiter</b></dt>
<dd>The system-wide recipient address extension delimiter. </dd>
<dd>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). </dd>
<dt><b>$shell</b></dt>
@ -3495,22 +3501,53 @@ Example:
recipient_canonical_maps = hash:/etc/postfix/recipient_canonical
</pre>
%PARAM recipient_delimiter
%PARAM recipient_delimiter
<p>
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.
<p> 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. </p>
<p> This implementation recognizes one delimiter character per email
address, and one address extension per email address. </p>
<p> 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. </p>
<p> 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).
</p>
<p> 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. </p>
<p>
Example:
Examples:
</p>
<pre>
# Handle Postfix-style extensions.
recipient_delimiter = +
</pre>
<pre>
recipient_delimiter = +
# Handle both Postfix and qmail extensions (Postfix 2.11 and later).
recipient_delimiters = +-
</pre>
<pre>
# Use .forward for mail without address extension, and for mail with
# an unrecognized address extension.
forward_path = $home/.forward${recipient_delimiter}${extension},
$home/.forward,
</pre>
%PARAM reject_code 554

View File

@ -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);
}
/*

View File

@ -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,

View File

@ -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

View File

@ -6,12 +6,12 @@
/* SYNOPSIS
/* #include <split_addr.h>
/*
/* 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);
}
}

View File

@ -13,7 +13,7 @@
/* External interface. */
extern char *split_addr(char *, int);
extern char *split_addr(char *, const char *);
/* LICENSE
/* .ad

View File

@ -6,10 +6,10 @@
/* SYNOPSIS
/* #include <strip_addr.h>
/*
/* 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);
}

View File

@ -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

View File

@ -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

View File

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

View File

@ -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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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.

View File

@ -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) \

View File

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

View File

@ -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

View File

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