Portability: AIX 5.1/GCC.
-20041014-21
+20041014-23
Postfix no longer appends the local domain to header
addresses from remote clients. Instead, Postfix either
with the new local_header_rewrite_clients parameter (default:
permit_mynetworks, permit_sasl_authenticated).
+ These changes affect the SMTP server (including XFORWARD
+ support), the cleanup server (do or don't rewrite headers),
+ the trivial-rewrite server (append local domain or surrogate
+ remote domain to incomplete addresses), the queue manager
+ (send additional attributes to delivery agents), the LMTP
+ and SMTP clients (XFORWARD support), and the local delivery
+ agent (preserve XFORWARD attributes when forwarding mail).
+
20041016
Bugfix: attr_clnt_request() did not properly skip hash
Topics covered in this document:
+ * To rewrite or not to rewrite, or to label as invalid
* Postfix address rewriting overview
* Address rewriting when mail is received
* Debugging your address manipulations
+T\bTo\bo r\bre\bew\bwr\bri\bit\bte\be o\bor\br n\bno\bot\bt t\bto\bo r\bre\bew\bwr\bri\bit\bte\be,\b, o\bor\br t\bto\bo l\bla\bab\bbe\bel\bl a\bas\bs i\bin\bnv\bva\bal\bli\bid\bd
+
+Postfix versions 2.1 and earlier always rewrite message header addresses, and
+append Postfix's own domain information to incomplete addresses. While
+rewriting message headers is OK for mail with a local origin, it is undesirable
+for remote mail:
+
+ * Header mangling is frowned upon by mail standards,
+ * Appending Postfix's own domain information produces incorrect results with
+ remote incomplete addresses,
+ * Appending Postfix's own domain information sometimes creates the appearance
+ that spam is sent by local users.
+
+Postfix versions 2.2 give you the option to either not rewrite message headers
+from remote SMTP clients at all, or to label incomplete addresses in such
+message headers as invalid. Here is how it works:
+
+ * Postfix does not rewrite message headers from remote SMTP clients at all
+ when the remote_header_rewrite_domain parameter value is empty.
+ * Otherwise, Postfix appends the specified domain name to incomplete
+ addresses in message headers from remote SMTP clients. This feature can be
+ used to append a reserved domain such as "domain.invalid", so that
+ incomplete addresses cannot be mistaken for local addresses.
+
+The local_header_rewrite_clients parameter controls what SMTP clients Postfix
+considers local instead of remote.
+
P\bPo\bos\bst\btf\bfi\bix\bx a\bad\bdd\bdr\bre\bes\bss\bs r\bre\bew\bwr\bri\bit\bti\bin\bng\bg o\bov\bve\ber\brv\bvi\bie\bew\bw
The figure below zooms in on those parts of Postfix that are most involved with
of Postfix components expect that all addresses have the form
"user@domain".
- Postfix versions 2.2 and later do not rewrite message headers from
- remote SMTP clients at all, or they append the domain name specified
- with the remote_header_rewrite_domain configuration parameter.
+ Postfix versions 2.2 and later either do not rewrite message headers
+ from remote SMTP clients at all, or they append the domain name
+ specified with the remote_header_rewrite_domain configuration
+ parameter.
If your machine is not the main machine for $myorigin and you wish to
have some users delivered locally without going via that main machine,
(default: yes). The purpose is to get consistent treatment of different
forms of the same hostname.
- Postfix versions 2.2 and later do not rewrite message headers from
- remote clients at all, or they append the domain name specified with
- the remote_header_rewrite_domain configuration parameter.
+ Postfix versions 2.2 and later either do not rewrite message headers
+ from remote clients at all, or they append the domain name specified
+ with the remote_header_rewrite_domain configuration parameter.
Some will argue that rewriting "host" to "host.domain" is bad. That is
- why it can be turned off. Others like the convenience of having the
- local domain appended automatically.
+ why it can be turned off. Others like the convenience of having
+ Postfix's own domain appended automatically.
Rewrite "user@site." to "user@site" (without the trailing dot).
A single trailing dot is silently removed. However, an address that
xforward-command = XFORWARD 1*( SP attribute-name"="attribute-value )
- attribute-name = ( NAME | ADDR | PROTO | HELO )
+ attribute-name = ( NAME | ADDR | PROTO | HELO | SOURCE )
* The NAME attribute specifies the up-stream hostname, or [UNAVAILABLE] when
the information is unavailable. The hostname may be a non-DNS hostname.
when the information is unavailable. The hostname may be a non-DNS
hostname.
+ * The SOURCE attribute specifies LOCAL when the message was received from a
+ source that is local with respect to the up-stream host, REMOTE for mail
+ from a remote source, or [UNAVAILABLE] when the information is unavailable.
+ The down-stream MTA may decide to enable header munging and address
+ qualification with mail from local sources.
+
Note 1: Attribute values must not be longer than 255 characters (specific
attributes may impose shorter lengths), must not contain control characters,
non-ASCII characters, whitespace, or other characters that are special in
and change the patchlevel and the release date. Patches are never
issued for snapshot releases.
-Incompatible changes with snapshot Postfix-2.2-20041022
+Incompatible changes with snapshot Postfix-2.2-20041023
=======================================================
You must reload or stop/start Postfix, because the queue manager
Errors-To: is non-standard, there was no guarantee that it would
have effect with other MTAs.
-Major changes with snapshot Postfix-2.2-20041022
+Major changes with snapshot Postfix-2.2-20041023
================================================
The NIS+ client by Geoff Gibbs is now part of the Postfix source
tree. Details are given in the nisplus_table(5) manual page.
-By default, Postfix no longer appends the local domain to addresses
+By default, Postfix no longer appends the its own domain to addresses
in message headers from remote clients. Thus, spam from poorly
written software no longer looks like it came from a local user.
it rewrites headers and appends the domain name that is specified
with the remote_header_rewrite_domain parameter (like "domain.invalid").
-To get the behavior of earlier Postfix versions specify
+To get the behavior of earlier Postfix versions (always append
+Postfix's own domain to incomplete addresses in message headers)
+specify:
/etc/postfix/main.cf:
local_header_rewrite_clients = static:all
-Postfix always appends local domain information in message headers
-from Postfix sendmail and from local clients.
+Postfix always appends its own domain information to addresses in
+message headers from Postfix sendmail and from local SMTP clients.
-By default, Postfix considers a client local when its address
-matches mynetworks, or when it is SASL or TLS authenticated. If
-you want to include a pop-before-smtp table, then you have to
-specify that via the new local_header_rewrite_clients parameter:
+By default, Postfix considers an SMTP client local (and thus updates
+message header addresses with the Postfix's own domain) when the
+client IP address matches mynetworks, or when the client is SASL
+or TLS authenticated.
+
+If you want to include other clients via a pop-before-smtp table,
+then you have to specify that via the new local_header_rewrite_clients
+parameter:
/etc/postfix/main.cf:
local_header_rewrite_clients = permit_mynetworks,
check_address_map hash:/etc/postfix/pop-before-smtp
As before, Postfix appends local domain information to envelope
-addresses, because an unqualified address is effectively local when
-someone attempts to reply to it.
+addresses (as opposed to header addresses), because an unqualified
+envelope address is effectively local for the purpose of delivery,
+and for the purpose of replying to it.
+
+Full details are given in ADDRESS_REWRITING_README, and in the
+postconf(5) manual. For best results, point your browser at the
+ADDRESS_REWRITING_README.html file and navigate to the section
+titled "To rewrite or not to rewrite, or to label as invalid".
Incompatible changes with snapshot Postfix-2.2-20041009
=======================================================
<ul>
+<li> <a href="#william"> To rewrite or not to rewrite, or to label
+as invalid </a>
+
<li> <a href="#overview"> Postfix address rewriting overview </a>
<li> <a href="#receiving"> Address rewriting when mail is received</a>
</ul>
+<h2> <a name="william"> To rewrite or not to rewrite, or to label
+as invalid </a> </h2>
+
+<p> Postfix versions 2.1 and earlier always rewrite message header
+addresses, and append Postfix's own domain information to incomplete
+addresses. While rewriting message headers is OK for mail with a
+local origin, it is undesirable for remote mail: </p>
+
+<ul>
+
+<li> Header mangling is frowned upon by mail standards,
+
+<li> Appending Postfix's own domain information produces incorrect
+results with remote incomplete addresses,
+
+<li> Appending Postfix's own domain information sometimes creates
+the appearance that spam is sent by local users.
+
+</ul>
+
+<p> Postfix versions 2.2 give you the option to either not rewrite
+message headers from remote SMTP clients at all, or to label
+incomplete addresses in such message headers as invalid. Here is
+how it works: </p>
+
+<ul>
+
+<li> Postfix does not rewrite message headers from remote SMTP
+clients at all when the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter
+value is empty.
+
+<li> Otherwise, Postfix appends the specified domain name to
+incomplete addresses in message headers from remote SMTP clients.
+This feature can be used to append a reserved domain such as
+"domain.invalid", so that incomplete addresses cannot be mistaken
+for local addresses.
+
+</ul>
+
+<p> The <a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> parameter controls what SMTP
+clients Postfix considers local instead of remote. </p>
+
<h2> <a name="overview"> Postfix address rewriting overview </a> </h2>
<p> The figure below zooms in on those parts of Postfix that are most
</blockquote>
-
-<h2> <a name="receiving"> Address rewriting when mail is received</a> </h2>
+<h2> <a name="receiving"> Address rewriting when mail is received</a>
+</h2>
<p> The <a href="cleanup.8.html">cleanup(8)</a> server receives mail from outside of Postfix as
well as mail from internal sources such as forwarded mail,
because a lot of Postfix components expect that all addresses have
the form "user@domain". </p>
-<p> Postfix versions 2.2 and later do not rewrite message headers
-from remote SMTP clients at all, or they append the domain name
-specified with the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> configuration
+<p> Postfix versions 2.2 and later either do not rewrite message
+headers from remote SMTP clients at all, or they append the domain
+name specified with the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> configuration
parameter. </p>
<p> If your machine is not the main machine for $<a href="postconf.5.html#myorigin">myorigin</a> and you
parameter (default: yes). The purpose is to get consistent treatment
of different forms of the same hostname. </p>
-<p> Postfix versions 2.2 and later do not rewrite message headers
-from remote clients at all, or they append the domain name specified
-with the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> configuration parameter. </p>
+<p> Postfix versions 2.2 and later either do not rewrite message
+headers from remote clients at all, or they append the domain name
+specified with the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> configuration
+parameter. </p>
<p> Some will argue that rewriting "host" to "host.domain"
is bad. That is why it can be turned off. Others like the convenience
-of having the <a href="ADDRESS_CLASS_README.html#local_domain_class">local domain</a> appended automatically. </p> </dd>
+of having Postfix's own domain appended automatically. </p> </dd>
<dt>Rewrite "user@site." to "user@site" (without the trailing dot).</dt>
xforward-command = XFORWARD 1*( SP attribute-name"="attribute-value )
</p>
<p>
- attribute-name = ( NAME | ADDR | PROTO | HELO )
+ attribute-name = ( NAME | ADDR | PROTO | HELO | SOURCE )
</p>
</blockquote>
SMTP HELO command), or [UNAVAILABLE] when the information is
unavailable. The hostname may be a non-DNS hostname. </p>
+ <li> <p> The SOURCE attribute specifies LOCAL when the message
+ was received from a source that is local with respect to the
+ up-stream host, REMOTE for mail from a remote source, or
+ [UNAVAILABLE] when the information is unavailable. The down-stream
+ MTA may decide to enable header munging and address qualification
+ with mail from local sources. </p>
+
</ul>
<p> Note 1: Attribute values must not be longer than 255 characters
What addresses are subject to <a href="postconf.5.html#sender_canonical_maps">sender_canonical_maps</a>
address mapping.
+ <b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
+ Don't rewrite message headers from remote clients
+ at all when this parameter is empty; otherwise,
+ rewrite remote message headers and append the spec-
+ ified domain name to incomplete addresses.
+
<b>RESOURCE AND RATE CONTROLS</b>
<b><a href="postconf.5.html#duplicate_filter_limit">duplicate_filter_limit</a> (1000)</b>
- The maximal number of addresses remembered by the
- address duplicate filter for <a href="aliases.5.html">aliases(5)</a> or vir-
+ The maximal number of addresses remembered by the
+ address duplicate filter for <a href="aliases.5.html">aliases(5)</a> or vir-
tual(5) alias expansion, or for <a href="showq.8.html">showq(8)</a> queue dis-
plays.
message header.
<b><a href="postconf.5.html#hopcount_limit">hopcount_limit</a> (50)</b>
- The maximal number of Received: message headers
+ The maximal number of Received: message headers
that is allowed in the primary message headers.
<b><a href="postconf.5.html#in_flow_delay">in_flow_delay</a> (1s)</b>
- Time to pause before accepting a new message, when
+ Time to pause before accepting a new message, when
the message arrival rate exceeds the message deliv-
ery rate.
<b><a href="postconf.5.html#message_size_limit">message_size_limit</a> (10240000)</b>
- The maximal size in bytes of a message, including
+ The maximal size in bytes of a message, including
envelope information.
Available in Postfix version 2.0 and later:
will handle.
<b><a href="postconf.5.html#queue_file_attribute_count_limit">queue_file_attribute_count_limit</a> (100)</b>
- The maximal number of (name=value) attributes that
+ The maximal number of (name=value) attributes that
may be stored in a Postfix queue file.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#virtual_alias_expansion_limit">virtual_alias_expansion_limit</a> (1000)</b>
- The maximal number of addresses that virtual alias
+ The maximal number of addresses that virtual alias
expansion produces from each original recipient.
<b><a href="postconf.5.html#virtual_alias_recursion_limit">virtual_alias_recursion_limit</a> (1000)</b>
- The maximal nesting depth of virtual alias expan-
+ The maximal nesting depth of virtual alias expan-
sion.
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix main.cf and
+ The default location of the Postfix main.cf and
master.cf configuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
- How much time a Postfix daemon process may take to
- handle a request before it is terminated by a
+ How much time a Postfix daemon process may take to
+ handle a request before it is terminated by a
built-in watchdog timer.
<b><a href="postconf.5.html#delay_warning_time">delay_warning_time</a> (0h)</b>
- The time after which the sender receives the mes-
+ The time after which the sender receives the mes-
sage headers of mail that is still queued.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
over an internal communication channel.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
- The maximum amount of time that an idle Postfix
- daemon process waits for the next service request
+ The maximum amount of time that an idle Postfix
+ daemon process waits for the next service request
before exiting.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
- The maximal number of connection requests before a
+ The maximal number of connection requests before a
Postfix daemon process terminates.
<b><a href="postconf.5.html#myhostname">myhostname</a> (see 'postconf -d' output)</b>
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
The domain name that locally-posted mail appears to
- come from, and that locally posted mail is deliv-
+ come from, and that locally posted mail is deliv-
ered to.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
- The process ID of a Postfix command or daemon pro-
+ The process ID of a Postfix command or daemon pro-
cess.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
- The location of the Postfix top-level queue direc-
+ The location of the Postfix top-level queue direc-
tory.
<b><a href="postconf.5.html#soft_bounce">soft_bounce</a> (no)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
- The mail system name that is prepended to the pro-
+ The mail system name that is prepended to the pro-
cess name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> (yes)</b>
- Enable support for the X-Original-To message
+ Enable support for the X-Original-To message
header.
<b>FILES</b>
<a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a> Postfix address manipulation
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
<a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> = static:all
</pre>
+<p> The purist setting: rewrite headers only in mail from Postfix
+sendmail and in SMTP mail from this machine. </p>
+
+<pre>
+ <a href="postconf.5.html#mynetworks_style">mynetworks_style</a> = host
+ <a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>
+</pre>
+
<p> The default setting: rewrite headers and append my own domain
-only with mail from local or authorized clients. </p>
+only with mail from Postfix sendmail and from local or authorized
+SMTP clients. </p>
<pre>
<a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,
<a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a> <a href="postconf.5.html#permit_tls_clientcerts">permit_tls_clientcerts</a>
</pre>
-<p> Include clients that are pop-before-smtp authenticated: </p>
+<p> The ISP setting: include clients that are pop-before-smtp
+authenticated. </p>
<pre>
<a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,
<p> Don't rewrite message headers from remote clients at all when
this parameter is empty; otherwise, rewrite remote message headers
-and append the specified domain name to incomplete addresses. </p>
+and append the specified domain name to incomplete addresses. The
+<a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> parameter controls what clients Postfix
+considers local. </p>
<p> Examples: </p>
<li> <a href="spawn.8.html">spawn(8)</a>, run non-Postfix server
+<li> <a href="trivial-rewrite.8.html">trivial-rewrite(8)</a>, Postfix address rewriting
+
<li> <a href="verify.8.html">verify(8)</a>, Postfix address verification
<li> <a href="virtual.8.html">virtual(8)</a>, Postfix virtual delivery agent
port to.
<b>ADDRESS REWRITING CONTROLS</b>
+ See the <a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a> document for a detailed
+ discussion of Postfix address rewriting.
+
<b><a href="postconf.5.html#receive_override_options">receive_override_options</a> (empty)</b>
- Enable or disable recipient validation, built-in
+ Enable or disable recipient validation, built-in
content filtering, or address mapping.
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> (see 'postconf -d' output)</b>
Append the domain name in $<a href="postconf.5.html#myorigin">myorigin</a> or $<a href="postconf.5.html#mydomain">mydomain</a> to
- message header addresses from these clients only;
- either don't rewrite message headers from other
+ message header addresses from these clients only;
+ either don't rewrite message headers from other
clients at all, or append the domain specified with
the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter.
- <b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
- Don't rewrite message headers from remote clients
- at all when this parameter is empty; otherwise,
- rewrite remote message headers and append the spec-
- ified domain name to incomplete addresses.
-
<b>AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS</b>
As of version 1.0, Postfix can be configured to send new
mail to an external content filter AFTER the mail is
<b>README FILES</b>
<a href="ADDRESS_CLASS_README.html">ADDRESS_CLASS_README</a>, blocking unknown hosted or relay recipients
+ <a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a> Postfix address manipulation
<a href="FILTER_README.html">FILTER_README</a>, external after-queue content filter
<a href="LOCAL_RECIPIENT_README.html">LOCAL_RECIPIENT_README</a>, blocking unknown local recipients
<a href="SMTPD_ACCESS_README.html">SMTPD_ACCESS_README</a>, built-in access policies
.ad
.ft R
.PP
+The purist setting: rewrite headers only in mail from Postfix
+sendmail and in SMTP mail from this machine.
+.PP
+.nf
+.na
+.ft C
+ mynetworks_style = host
+ local_header_rewrite_clients = permit_mynetworks
+.fi
+.ad
+.ft R
+.PP
The default setting: rewrite headers and append my own domain
-only with mail from local or authorized clients.
+only with mail from Postfix sendmail and from local or authorized
+SMTP clients.
.PP
.nf
.na
.ad
.ft R
.PP
-Include clients that are pop-before-smtp authenticated:
+The ISP setting: include clients that are pop-before-smtp
+authenticated.
.PP
.nf
.na
.SH remote_header_rewrite_domain (default: empty)
Don't rewrite message headers from remote clients at all when
this parameter is empty; otherwise, rewrite remote message headers
-and append the specified domain name to incomplete addresses.
+and append the specified domain name to incomplete addresses. The
+local_header_rewrite_clients parameter controls what clients Postfix
+considers local.
.PP
Examples:
.PP
.IP "\fBsender_canonical_classes (envelope_sender, header_sender)\fR"
What addresses are subject to sender_canonical_maps address
mapping.
+.IP "\fBremote_header_rewrite_domain (empty)\fR"
+Don't rewrite message headers from remote clients at all when
+this parameter is empty; otherwise, rewrite remote message headers
+and append the specified domain name to incomplete addresses.
.SH "RESOURCE AND RATE CONTROLS"
.na
.nf
.nf
.ad
.fi
+See the ADDRESS_REWRITING_README document for a detailed
+discussion of Postfix address rewriting.
.IP "\fBreceive_override_options (empty)\fR"
Enable or disable recipient validation, built-in content
filtering, or address mapping.
header addresses from these clients only; either don't rewrite
message headers from other clients at all, or append the domain
specified with the remote_header_rewrite_domain parameter.
-.IP "\fBremote_header_rewrite_domain (empty)\fR"
-Don't rewrite message headers from remote clients at all when
-this parameter is empty; otherwise, rewrite remote message headers
-and append the specified domain name to incomplete addresses.
.SH "AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS"
.na
.nf
.na
.nf
ADDRESS_CLASS_README, blocking unknown hosted or relay recipients
+ADDRESS_REWRITING_README Postfix address manipulation
FILTER_README, external after-queue content filter
LOCAL_RECIPIENT_README, blocking unknown local recipients
SMTPD_ACCESS_README, built-in access policies
/^[A-Z].*:$/ { print ul "<h2>", $0, "</h2>\n\n<ul>\n\n"; ul = "</ul>\n\n" }
-/^[a-z][a-z0-9_]+\(/ { print "<li>", $0, "\n" }
+/^[a-z][-a-z0-9_]+\(/ { print "<li>", $0, "\n" }
' | sed 's;: </h2>$; </h2>;'
<ul>
+<li> <a href="#william"> To rewrite or not to rewrite, or to label
+as invalid </a>
+
<li> <a href="#overview"> Postfix address rewriting overview </a>
<li> <a href="#receiving"> Address rewriting when mail is received</a>
</ul>
+<h2> <a name="william"> To rewrite or not to rewrite, or to label
+as invalid </a> </h2>
+
+<p> Postfix versions 2.1 and earlier always rewrite message header
+addresses, and append Postfix's own domain information to incomplete
+addresses. While rewriting message headers is OK for mail with a
+local origin, it is undesirable for remote mail: </p>
+
+<ul>
+
+<li> Header mangling is frowned upon by mail standards,
+
+<li> Appending Postfix's own domain information produces incorrect
+results with remote incomplete addresses,
+
+<li> Appending Postfix's own domain information sometimes creates
+the appearance that spam is sent by local users.
+
+</ul>
+
+<p> Postfix versions 2.2 give you the option to either not rewrite
+message headers from remote SMTP clients at all, or to label
+incomplete addresses in such message headers as invalid. Here is
+how it works: </p>
+
+<ul>
+
+<li> Postfix does not rewrite message headers from remote SMTP
+clients at all when the remote_header_rewrite_domain parameter
+value is empty.
+
+<li> Otherwise, Postfix appends the specified domain name to
+incomplete addresses in message headers from remote SMTP clients.
+This feature can be used to append a reserved domain such as
+"domain.invalid", so that incomplete addresses cannot be mistaken
+for local addresses.
+
+</ul>
+
+<p> The local_header_rewrite_clients parameter controls what SMTP
+clients Postfix considers local instead of remote. </p>
+
<h2> <a name="overview"> Postfix address rewriting overview </a> </h2>
<p> The figure below zooms in on those parts of Postfix that are most
</blockquote>
-
-<h2> <a name="receiving"> Address rewriting when mail is received</a> </h2>
+<h2> <a name="receiving"> Address rewriting when mail is received</a>
+</h2>
<p> The cleanup(8) server receives mail from outside of Postfix as
well as mail from internal sources such as forwarded mail,
because a lot of Postfix components expect that all addresses have
the form "user@domain". </p>
-<p> Postfix versions 2.2 and later do not rewrite message headers
-from remote SMTP clients at all, or they append the domain name
-specified with the remote_header_rewrite_domain configuration
+<p> Postfix versions 2.2 and later either do not rewrite message
+headers from remote SMTP clients at all, or they append the domain
+name specified with the remote_header_rewrite_domain configuration
parameter. </p>
<p> If your machine is not the main machine for $myorigin and you
parameter (default: yes). The purpose is to get consistent treatment
of different forms of the same hostname. </p>
-<p> Postfix versions 2.2 and later do not rewrite message headers
-from remote clients at all, or they append the domain name specified
-with the remote_header_rewrite_domain configuration parameter. </p>
+<p> Postfix versions 2.2 and later either do not rewrite message
+headers from remote clients at all, or they append the domain name
+specified with the remote_header_rewrite_domain configuration
+parameter. </p>
<p> Some will argue that rewriting "host" to "host.domain"
is bad. That is why it can be turned off. Others like the convenience
-of having the local domain appended automatically. </p> </dd>
+of having Postfix's own domain appended automatically. </p> </dd>
<dt>Rewrite "user@site." to "user@site" (without the trailing dot).</dt>
xforward-command = XFORWARD 1*( SP attribute-name"="attribute-value )
</p>
<p>
- attribute-name = ( NAME | ADDR | PROTO | HELO )
+ attribute-name = ( NAME | ADDR | PROTO | HELO | SOURCE )
</p>
</blockquote>
SMTP HELO command), or [UNAVAILABLE] when the information is
unavailable. The hostname may be a non-DNS hostname. </p>
+ <li> <p> The SOURCE attribute specifies LOCAL when the message
+ was received from a source that is local with respect to the
+ up-stream host, REMOTE for mail from a remote source, or
+ [UNAVAILABLE] when the information is unavailable. The down-stream
+ MTA may decide to enable header munging and address qualification
+ with mail from local sources. </p>
+
</ul>
<p> Note 1: Attribute values must not be longer than 255 characters
<p> Don't rewrite message headers from remote clients at all when
this parameter is empty; otherwise, rewrite remote message headers
-and append the specified domain name to incomplete addresses. </p>
+and append the specified domain name to incomplete addresses. The
+local_header_rewrite_clients parameter controls what clients Postfix
+considers local. </p>
<p> Examples: </p>
local_header_rewrite_clients = static:all
</pre>
+<p> The purist setting: rewrite headers only in mail from Postfix
+sendmail and in SMTP mail from this machine. </p>
+
+<pre>
+ mynetworks_style = host
+ local_header_rewrite_clients = permit_mynetworks
+</pre>
+
<p> The default setting: rewrite headers and append my own domain
-only with mail from local or authorized clients. </p>
+only with mail from Postfix sendmail and from local or authorized
+SMTP clients. </p>
<pre>
local_header_rewrite_clients = permit_mynetworks,
permit_sasl_authenticated permit_tls_clientcerts
</pre>
-<p> Include clients that are pop-before-smtp authenticated: </p>
+<p> The ISP setting: include clients that are pop-before-smtp
+authenticated. </p>
<pre>
local_header_rewrite_clients = permit_mynetworks,
cleanup_addr.o: ../../include/maps.h
cleanup_addr.o: ../../include/dict.h
cleanup_addr.o: ../../include/argv.h
-cleanup_addr.o: ../../include/rewrite_clnt.h
+cleanup_addr.o: ../../include/mail_proto.h
+cleanup_addr.o: ../../include/iostuff.h
+cleanup_addr.o: ../../include/attr.h
cleanup_addr.o: cleanup.h
cleanup_addr.o: ../../include/nvtable.h
cleanup_addr.o: ../../include/htable.h
cleanup_envelope.o: ../../include/mail_proto.h
cleanup_envelope.o: ../../include/iostuff.h
cleanup_envelope.o: ../../include/attr.h
-cleanup_envelope.o: ../../include/rewrite_clnt.h
cleanup_envelope.o: cleanup.h
cleanup_envelope.o: ../../include/argv.h
cleanup_envelope.o: ../../include/maps.h
cleanup_message.o: ../../include/attr.h
cleanup_message.o: ../../include/mime_state.h
cleanup_message.o: ../../include/lex_822.h
-cleanup_message.o: ../../include/rewrite_clnt.h
cleanup_message.o: cleanup.h
cleanup_message.o: ../../include/maps.h
cleanup_message.o: ../../include/dict.h
cleanup_rewrite.o: ../../include/tok822.h
cleanup_rewrite.o: ../../include/resolve_clnt.h
cleanup_rewrite.o: ../../include/rewrite_clnt.h
+cleanup_rewrite.o: ../../include/mail_proto.h
+cleanup_rewrite.o: ../../include/vstream.h
+cleanup_rewrite.o: ../../include/iostuff.h
+cleanup_rewrite.o: ../../include/attr.h
cleanup_rewrite.o: ../../include/quote_822_local.h
cleanup_rewrite.o: ../../include/quote_flags.h
cleanup_rewrite.o: cleanup.h
-cleanup_rewrite.o: ../../include/vstream.h
cleanup_rewrite.o: ../../include/argv.h
cleanup_rewrite.o: ../../include/nvtable.h
cleanup_rewrite.o: ../../include/htable.h
cleanup_state.o: ../../include/mail_params.h
cleanup_state.o: ../../include/mime_state.h
cleanup_state.o: ../../include/header_opts.h
-cleanup_state.o: ../../include/rewrite_clnt.h
-cleanup_state.o: cleanup.h
+cleanup_state.o: ../../include/mail_proto.h
cleanup_state.o: ../../include/vstream.h
+cleanup_state.o: ../../include/iostuff.h
+cleanup_state.o: ../../include/attr.h
+cleanup_state.o: cleanup.h
cleanup_state.o: ../../include/argv.h
cleanup_state.o: ../../include/nvtable.h
cleanup_state.o: ../../include/maps.h
/* .IP "\fBsender_canonical_classes (envelope_sender, header_sender)\fR"
/* What addresses are subject to sender_canonical_maps address
/* mapping.
+/* .IP "\fBremote_header_rewrite_domain (empty)\fR"
+/* Don't rewrite message headers from remote clients at all when
+/* this parameter is empty; otherwise, rewrite remote message headers
+/* and append the specified domain name to incomplete addresses.
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
NVTABLE *attr; /* queue file attribute list */
MIME_STATE *mime_state; /* MIME state engine */
int mime_errs; /* MIME error flags */
- char *rewrite_context_name; /* address rewrite context */
+ char *hdr_rewrite_context; /* header rewrite context */
char *filter; /* from header/body patterns */
char *redirect; /* from header/body patterns */
} CLEANUP_STATE;
#include <mail_addr.h>
#include <canon_addr.h>
#include <mail_addr_find.h>
-#include <rewrite_clnt.h>
+#include <mail_proto.h>
/* Application-specific. */
const char *bcc;
/*
- * Note: an unqualified username is for all practical purposes equivalent
- * to a fully qualified local address, if only because a reply to an
- * incomplete address will be sent to a local recipient. Having to
- * support both forms is error prone, therefore an incomplete envelope
- * address is rewritten to fully qualified form in the local domain
- * context.
+ * Note: an unqualified envelope address is for all practical purposes
+ * equivalent to a fully qualified local address, both for delivery and
+ * for replying. Having to support both forms is error prone, therefore
+ * an incomplete envelope address is rewritten to fully qualified form in
+ * the local domain context.
*/
- cleanup_rewrite_internal(REWRITE_LOCAL, clean_addr, buf);
+ cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, buf);
if (strncasecmp(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@",
sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) {
canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON);
const char *bcc;
/*
- * Note: an unqualified username is for all practical purposes equivalent
- * to a fully qualified local address, if only because a reply to an
- * incomplete address will be sent to a local recipient. Having to
- * support both forms is error prone, therefore an incomplete envelope
- * address is rewritten to fully qualified form in the local domain
- * context.
+ * Note: an unqualified envelope address is for all practical purposes
+ * equivalent to a fully qualified local address, both for delivery and
+ * for replying. Having to support both forms is error prone, therefore
+ * an incomplete envelope address is rewritten to fully qualified form in
+ * the local domain context.
*/
- cleanup_rewrite_internal(REWRITE_LOCAL,
+ cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL,
clean_addr, *buf ? buf : var_empty_addr);
if (state->flags & CLEANUP_FLAG_MAP_OK) {
if (cleanup_rcpt_canon_maps
VSTRING *clean_addr = vstring_alloc(100);
/*
- * Note: BCC addresses are supplied locally, andmust be rewritten in the
+ * Note: BCC addresses are supplied locally, and must be rewritten in the
* local address rewriting context.
*/
- cleanup_rewrite_internal(REWRITE_LOCAL, clean_addr, bcc);
+ cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, bcc);
if (state->flags & CLEANUP_FLAG_MAP_OK) {
if (cleanup_rcpt_canon_maps
&& (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
#include <mymalloc.h>
#include <stringops.h>
#include <nvtable.h>
-#include <name_code.h>
/* Global library. */
#include <mail_params.h>
#include <verp_sender.h>
#include <mail_proto.h>
-#include <rewrite_clnt.h>
/* Application-specific. */
#include "cleanup.h"
#define STR vstring_str
+#define STREQ(x,y) (strcmp((x), (y)) == 0)
static void cleanup_envelope_process(CLEANUP_STATE *, int, const char *, int);
char *attr_value;
const char *error_text;
int extra_opts;
- NAME_CODE rewrite_context_names[] = {
- REWRITE_LOCAL, 1,
- REWRITE_REMOTE, 1,
- REWRITE_NONE, 1,
- 0, 0,
- };
if (msg_verbose)
msg_info("initial envelope %c %.*s", type, len, buf);
myfree(sbuf);
return;
}
- if (strcmp(attr_name, MAIL_ATTR_RWR_CTXT_NAME) == 0) {
- if (name_code(rewrite_context_names, NAME_CODE_FLAG_STRICT_CASE,
- attr_value) == 0) {
- msg_warn("%s: message rejected: bad rewriting context: %.100s",
- state->queue_id, attr_value);
- state->errs |= CLEANUP_STAT_BAD;
- return;
+ if (strcmp(attr_name, MAIL_ATTR_RWR_CONTEXT) == 0) {
+ /* Choose header rewriting context. See also cleanup_addr.c. */
+ if (STREQ(attr_value, MAIL_ATTR_RWR_LOCAL)) {
+ state->hdr_rewrite_context = MAIL_ATTR_RWR_LOCAL;
+ } else if (STREQ(attr_value, MAIL_ATTR_RWR_REMOTE)) {
+ state->hdr_rewrite_context =
+ (*var_remote_rwr_domain ? MAIL_ATTR_RWR_REMOTE : 0);
} else {
- myfree(state->rewrite_context_name);
- state->rewrite_context_name = mystrdup(attr_value);
+ msg_warn("%s: message rejected: bad rewriting context: %.100s",
+ state->queue_id, attr_value);
+ state->errs |= CLEANUP_STAT_BAD;
+ return;
}
}
nvtable_update(state->attr, attr_name, attr_value);
int var_body_check_len; /* when to stop body scan */
char *var_send_bcc_maps; /* sender auto-bcc maps */
char *var_rcpt_bcc_maps; /* recipient auto-bcc maps */
+char *var_remote_rwr_domain; /* header-only surrogate */
CONFIG_INT_TABLE cleanup_int_table[] = {
VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0,
VAR_MASQ_CLASSES, DEF_MASQ_CLASSES, &var_masq_classes, 0, 0,
VAR_SEND_BCC_MAPS, DEF_SEND_BCC_MAPS, &var_send_bcc_maps, 0, 0,
VAR_RCPT_BCC_MAPS, DEF_RCPT_BCC_MAPS, &var_rcpt_bcc_maps, 0, 0,
+ VAR_REM_RWR_DOMAIN, DEF_REM_RWR_DOMAIN, &var_remote_rwr_domain, 0, 0,
0,
};
#include <mail_proto.h>
#include <mime_state.h>
#include <lex_822.h>
-#include <rewrite_clnt.h>
/* Application-specific. */
var_token_limit);
addr_list = tok822_grep(tree, TOK822_ADDR);
for (tpp = addr_list; *tpp; tpp++) {
- cleanup_rewrite_tree(state->rewrite_context_name, *tpp);
+ cleanup_rewrite_tree(state->hdr_rewrite_context, *tpp);
if (state->flags & CLEANUP_FLAG_MAP_OK) {
if (cleanup_send_canon_maps
&& (cleanup_send_canon_flags & CLEANUP_CANON_FLAG_HDR_FROM))
var_token_limit);
addr_list = tok822_grep(tree, TOK822_ADDR);
for (tpp = addr_list; *tpp; tpp++) {
- cleanup_rewrite_tree(state->rewrite_context_name, *tpp);
+ cleanup_rewrite_tree(state->hdr_rewrite_context, *tpp);
if (state->flags & CLEANUP_FLAG_MAP_OK) {
if (cleanup_rcpt_canon_maps
&& (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_HDR_RCPT))
if (hdr_opts->flags & HDR_OPT_RR)
state->resent = "Resent-";
if ((hdr_opts->flags & HDR_OPT_SENDER)
- && strcmp(state->rewrite_context_name, REWRITE_NONE) != 0) {
+ && state->hdr_rewrite_context) {
cleanup_rewrite_sender(state, hdr_opts, header_buf);
} else if ((hdr_opts->flags & HDR_OPT_RECIP)
- && strcmp(state->rewrite_context_name, REWRITE_NONE) != 0) {
+ && state->hdr_rewrite_context) {
cleanup_rewrite_recip(state, hdr_opts, header_buf);
} else if ((hdr_opts->flags & HDR_OPT_DROP) == 0) {
cleanup_out_header(state, header_buf);
#include <been_here.h>
#include <mail_params.h>
#include <mime_state.h>
-#include <rewrite_clnt.h>
+#include <mail_proto.h>
/* Application-specific. */
state->attr = nvtable_create(10);
state->mime_state = 0;
state->mime_errs = 0;
- state->rewrite_context_name = mystrdup(REWRITE_LOCAL);
+ state->hdr_rewrite_context = MAIL_ATTR_RWR_LOCAL;
state->filter = 0;
state->redirect = 0;
return (state);
myfree(state->filter);
if (state->redirect)
myfree(state->redirect);
- if (state->rewrite_context_name)
- myfree(state->rewrite_context_name);
myfree((char *) state);
}
canon_addr.o: ../../include/vbuf.h
canon_addr.o: ../../include/mymalloc.h
canon_addr.o: rewrite_clnt.h
+canon_addr.o: mail_proto.h
+canon_addr.o: ../../include/vstream.h
+canon_addr.o: ../../include/iostuff.h
+canon_addr.o: ../../include/attr.h
canon_addr.o: canon_addr.h
cfg_parser.o: cfg_parser.c
cfg_parser.o: ../../include/sys_defs.h
tok822_rewrite.o: ../../include/vbuf.h
tok822_rewrite.o: ../../include/msg.h
tok822_rewrite.o: rewrite_clnt.h
+tok822_rewrite.o: mail_proto.h
+tok822_rewrite.o: ../../include/vstream.h
+tok822_rewrite.o: ../../include/iostuff.h
+tok822_rewrite.o: ../../include/attr.h
tok822_rewrite.o: tok822.h
tok822_rewrite.o: resolve_clnt.h
tok822_tree.o: tok822_tree.c
ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, request->sasl_method,
ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, request->sasl_username,
ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, request->sasl_sender,
- ATTR_TYPE_STR, MAIL_ATTR_RWR_CTXT_NAME, request->rewrite_context,
+ ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, request->rewrite_context,
ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, offs,
ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orcpt,
ATTR_TYPE_STR, MAIL_ATTR_RECIP, addr,
ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, sasl_method,
ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, sasl_username,
ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, sasl_sender,
- ATTR_TYPE_STR, MAIL_ATTR_RWR_CTXT_NAME, rewrite_context,
+ ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, rewrite_context,
ATTR_TYPE_END) != 19) {
msg_warn("%s: error receiving common attributes", myname);
return (-1);
char *sasl_method; /* SASL method */
char *sasl_username; /* SASL user name */
char *sasl_sender; /* SASL sender */
- char *rewrite_context; /* header rewrite context */
+ char *rewrite_context; /* address rewrite context */
} DELIVER_REQUEST;
/*
#define MAIL_ATTR_SASL_USERNAME "sasl_username"
#define MAIL_ATTR_SASL_SENDER "sasl_sender"
#define MAIL_ATTR_DUMMY "dummy"
-#define MAIL_ATTR_RWR_CTXT_NAME "rewrite_context_name"
+#define MAIL_ATTR_RWR_CONTEXT "rewrite_context"
+
+#define MAIL_ATTR_RWR_LOCAL "local"
+#define MAIL_ATTR_RWR_REMOTE "remote"
#define MAIL_ATTR_TTL "ttl"
#define MAIL_ATTR_LABEL "label"
#define XFORWARD_PROTO "PROTO" /* client protocol */
#define XFORWARD_HELO "HELO" /* client helo */
#define XFORWARD_IDENT "IDENT" /* message identifier */
-#define XFORWARD_DOMAIN "DOMAIN" /* origin type */
+#define XFORWARD_DOMAIN "SOURCE" /* origin type */
#define XFORWARD_DOM_LOCAL "LOCAL" /* local origin */
#define XFORWARD_DOM_REMOTE "REMOTE" /* remote origin */
* Patches change the patchlevel and the release date. Snapshots change the
* release date only.
*/
-#define MAIL_RELEASE_DATE "20041022"
+#define MAIL_RELEASE_DATE "20041023"
#define MAIL_VERSION_NUMBER "2.2"
#define VAR_MAIL_VERSION "mail_version"
{
VSTREAM *stream;
- /*
- * Sanity check.
- */
- if (strcmp(rule, REWRITE_NONE) == 0)
- msg_panic("rewrite_clnt: bad rewrite context: \"%s\"", rule);
-
/*
* One-entry cache.
*/
#include <vstring.h>
/*
- * External interface.
+ * Global library.
*/
-#define REWRITE_ADDR "rewrite"
-#define REWRITE_CANON REWRITE_LOCAL /* backwards compatibility */
+#include <mail_proto.h> /* MAIL_ATTR_RWR_LOCAL */
/*
- * XXX These should be moved to mail_proto.h because they appear as
- * attribute values in queue file records and delivery requests.
+ * External interface.
*/
-#define REWRITE_LOCAL "local"
-#define REWRITE_REMOTE "remote"
-#define REWRITE_NONE "none"
+#define REWRITE_ADDR "rewrite"
+#define REWRITE_CANON MAIL_ATTR_RWR_LOCAL /* backwards compatibility */
extern VSTRING *rewrite_clnt(const char *, const char *, VSTRING *);
extern VSTRING *rewrite_clnt_internal(const char *, const char *, VSTRING *);
/* scache_clnt_size - dummy */
-static void scache_clnt_size(SCACHE *scache, SCACHE_SIZE *size)
+static void scache_clnt_size(SCACHE *unused_scache, SCACHE_SIZE *size)
{
/* XXX Crap in a hurry. */
size->dest_count = 0;
#include <mark_corrupt.h>
#include <quote_821_local.h>
#include <mail_proto.h>
-#include <rewrite_clnt.h>
/* Application-specific. */
LMTP_RESP *resp;
RECIPIENT *rcpt;
VSTRING *next_command = vstring_alloc(100);
- int *NOCLOBBER survivors = 0;
+ int *NOCLOBBER survivors = 0;
NOCLOBBER int next_state;
NOCLOBBER int next_rcpt;
NOCLOBBER int send_rcpt;
vstring_sprintf_append(next_command, " %s=%s",
XFORWARD_HELO, DEL_REQ_ATTR_AVAIL(request->client_helo) ?
request->client_helo : XFORWARD_UNAVAILABLE);
- if (state->features & LMTP_FEATURE_XFORWARD_DOMAIN)
- vstring_sprintf_append(next_command, " %s=%s", XFORWARD_DOMAIN,
- DEL_REQ_ATTR_AVAIL(request->rewrite_context) == 0 ?
- XFORWARD_UNAVAILABLE :
- strcmp(request->rewrite_context, REWRITE_LOCAL) ?
- XFORWARD_DOM_REMOTE : XFORWARD_DOM_LOCAL );
+ if (state->features & LMTP_FEATURE_XFORWARD_DOMAIN)
+ vstring_sprintf_append(next_command, " %s=%s", XFORWARD_DOMAIN,
+ DEL_REQ_ATTR_AVAIL(request->rewrite_context) == 0 ?
+ XFORWARD_UNAVAILABLE :
+ strcmp(request->rewrite_context, MAIL_ATTR_RWR_LOCAL) ?
+ XFORWARD_DOM_REMOTE : XFORWARD_DOM_LOCAL);
next_state = LMTP_STATE_MAIL;
break;
resolve.o: ../../include/vstream.h
resolve.o: ../../include/iostuff.h
resolve.o: ../../include/attr.h
-resolve.o: ../../include/resolve_clnt.h
resolve.o: ../../include/rewrite_clnt.h
+resolve.o: ../../include/resolve_clnt.h
resolve.o: ../../include/tok822.h
resolve.o: ../../include/mail_params.h
resolve.o: ../../include/defer.h
/* forward_open - open connection to cleanup service */
-static FORWARD_INFO *forward_open(char *sender)
+static FORWARD_INFO *forward_open(DELIVER_REQUEST *request, char *sender)
{
VSTRING *buffer = vstring_alloc(100);
FORWARD_INFO *info;
* designated sender: mailing list owner, posting user, whatever.
*/
rec_fprintf(cleanup, REC_TYPE_TIME, "%ld", (long) info->posting_time);
+ rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
+ MAIL_ATTR_CLIENT_NAME, request->client_name);
+ rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
+ MAIL_ATTR_CLIENT_ADDR, request->client_addr);
+ rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
+ MAIL_ATTR_PROTO_NAME, request->client_proto);
+ rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
+ MAIL_ATTR_HELO_NAME, request->client_helo);
+ rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
+ MAIL_ATTR_SASL_METHOD, request->sasl_method);
+ rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
+ MAIL_ATTR_SASL_USERNAME, request->sasl_username);
+ rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
+ MAIL_ATTR_SASL_SENDER, request->sasl_sender);
+ rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
+ MAIL_ATTR_RWR_CONTEXT, request->rewrite_context);
rec_fputs(cleanup, REC_TYPE_FROM, sender);
vstring_free(buffer);
htable_enter(forward_dt, attr.delivered, (char *) table_snd);
}
if ((info = (FORWARD_INFO *) htable_find(table_snd, attr.sender)) == 0) {
- if ((info = forward_open(attr.sender)) == 0)
+ if ((info = forward_open(attr.request, attr.sender)) == 0)
return (-1);
htable_enter(table_snd, attr.sender, (char *) info);
}
state.msg_attr.sender = rqst->sender;
state.msg_attr.relay = service;
state.msg_attr.arrival_time = rqst->arrival_time;
+ state.msg_attr.request = rqst;
RESET_OWNER_ATTR(state.msg_attr, state.level);
RESET_USER_ATTR(usr_attr, state.level);
state.loop_info = delivered_init(state.msg_attr); /* delivered-to */
char *sender; /* taken from envelope */
char *orig_rcpt; /* from submission */
char *recipient; /* taken from resolver */
- long rcpt_offset; /* taken from resolver */
+ long rcpt_offset; /* taken from resolver */
char *domain; /* recipient domain */
char *local; /* recipient full localpart */
char *user; /* recipient localpart, base name */
long arrival_time; /* arrival time */
int exp_type; /* expansion type. see below */
char *exp_from; /* expanded_from */
+ DELIVER_REQUEST *request; /* the kitchen sink */
} DELIVER_ATTR;
extern void deliver_attr_init(DELIVER_ATTR *);
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, message->client_proto,
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, message->client_helo,
ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, message->sasl_method,
- ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
+ ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender,
- ATTR_TYPE_STR, MAIL_ATTR_RWR_CTXT_NAME, message->rewrite_context,
+ ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, message->rewrite_context,
ATTR_TYPE_END);
if (sender_buf != 0)
vstring_free(sender_buf);
msg_warn("%s: ignoring multiple %s attribute: %s",
message->queue_id, MAIL_ATTR_SASL_SENDER, value);
}
- if (strcmp(name, MAIL_ATTR_RWR_CTXT_NAME) == 0) {
+ if (strcmp(name, MAIL_ATTR_RWR_CONTEXT) == 0) {
if (message->rewrite_context == 0)
message->rewrite_context = mystrdup(value);
else
msg_warn("%s: ignoring multiple %s attribute: %s",
- message->queue_id, MAIL_ATTR_RWR_CTXT_NAME, value);
+ message->queue_id, MAIL_ATTR_RWR_CONTEXT, value);
}
/* Optional tracing flags. */
else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
pickup.o: ../../include/rec_type.h
pickup.o: ../../include/lex_822.h
pickup.o: ../../include/input_transp.h
-pickup.o: ../../include/rewrite_clnt.h
pickup.o: ../../include/mail_server.h
#include <rec_type.h>
#include <lex_822.h>
#include <input_transp.h>
-#include <rewrite_clnt.h> /* XXX */
/* Single-threaded server skeleton. */
rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_ORIGIN, MAIL_ATTR_ORG_LOCAL);
rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
- MAIL_ATTR_RWR_CTXT_NAME, REWRITE_LOCAL);
+ MAIL_ATTR_RWR_CONTEXT, MAIL_ATTR_RWR_LOCAL);
/*
* Copy the message envelope segment. Allow only those records that we
ATTR_TYPE_STR, MAIL_ATTR_PROTO_NAME, message->client_proto,
ATTR_TYPE_STR, MAIL_ATTR_HELO_NAME, message->client_helo,
ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD, message->sasl_method,
- ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
+ ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender,
- ATTR_TYPE_STR, MAIL_ATTR_RWR_CTXT_NAME, message->rewrite_context,
+ ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, message->rewrite_context,
ATTR_TYPE_END);
if (sender_buf != 0)
vstring_free(sender_buf);
msg_warn("%s: ignoring multiple %s attribute: %s",
message->queue_id, MAIL_ATTR_SASL_SENDER, value);
}
- if (strcmp(name, MAIL_ATTR_RWR_CTXT_NAME) == 0) {
+ if (strcmp(name, MAIL_ATTR_RWR_CONTEXT) == 0) {
if (message->rewrite_context == 0)
message->rewrite_context = mystrdup(value);
else
msg_warn("%s: ignoring multiple %s attribute: %s",
- message->queue_id, MAIL_ATTR_RWR_CTXT_NAME, value);
+ message->queue_id, MAIL_ATTR_RWR_CONTEXT, value);
}
/* Optional tracing flags. */
else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
#include <quote_821_local.h>
#include <mail_proto.h>
#include <mime_state.h>
-#include <rewrite_clnt.h>
/* Application-specific. */
vstring_sprintf_append(next_command, " %s=%s", XFORWARD_DOMAIN,
DEL_REQ_ATTR_AVAIL(request->rewrite_context) == 0 ?
XFORWARD_UNAVAILABLE :
- strcmp(request->rewrite_context, REWRITE_LOCAL) ?
- XFORWARD_DOM_REMOTE : XFORWARD_DOM_LOCAL );
+ strcmp(request->rewrite_context, MAIL_ATTR_RWR_LOCAL) ?
+ XFORWARD_DOM_REMOTE : XFORWARD_DOM_LOCAL);
next_state = SMTP_STATE_MAIL;
break;
smtpd_check.o: ../../include/domain_list.h
smtpd_check.o: ../../include/mail_params.h
smtpd_check.o: ../../include/rewrite_clnt.h
+smtpd_check.o: ../../include/mail_proto.h
+smtpd_check.o: ../../include/iostuff.h
smtpd_check.o: ../../include/resolve_clnt.h
smtpd_check.o: ../../include/mail_error.h
smtpd_check.o: ../../include/name_mask.h
smtpd_check.o: ../../include/cleanup_user.h
smtpd_check.o: ../../include/record.h
smtpd_check.o: ../../include/rec_type.h
-smtpd_check.o: ../../include/mail_proto.h
-smtpd_check.o: ../../include/iostuff.h
smtpd_check.o: ../../include/mail_addr.h
smtpd_check.o: ../../include/verify_clnt.h
smtpd_check.o: ../../include/deliver_request.h
/* ADDRESS REWRITING CONTROLS
/* .ad
/* .fi
+/* See the ADDRESS_REWRITING_README document for a detailed
+/* discussion of Postfix address rewriting.
/* .IP "\fBreceive_override_options (empty)\fR"
/* Enable or disable recipient validation, built-in content
/* filtering, or address mapping.
/* header addresses from these clients only; either don't rewrite
/* message headers from other clients at all, or append the domain
/* specified with the remote_header_rewrite_domain parameter.
-/* .IP "\fBremote_header_rewrite_domain (empty)\fR"
-/* Don't rewrite message headers from remote clients at all when
-/* this parameter is empty; otherwise, rewrite remote message headers
-/* and append the specified domain name to incomplete addresses.
/* AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS
/* .ad
/* .fi
/* .na
/* .nf
/* ADDRESS_CLASS_README, blocking unknown hosted or relay recipients
+/* ADDRESS_REWRITING_README Postfix address manipulation
/* FILTER_README, external after-queue content filter
/* LOCAL_RECIPIENT_README, blocking unknown local recipients
/* SMTPD_ACCESS_README, built-in access policies
#include <anvil_clnt.h>
#endif
#include <flush_clnt.h>
-#include <rewrite_clnt.h>
/* Single-threaded server skeleton. */
#endif
-char *var_remote_rwr_domain;
char *var_local_rwr_clients;
/*
if (*var_filter_xport)
rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
- MAIL_ATTR_RWR_CTXT_NAME, FORWARD_DOMAIN(state));
+ MAIL_ATTR_RWR_CONTEXT, FORWARD_DOMAIN(state));
#ifdef USE_SASL_AUTH
if (var_smtpd_sasl_enable) {
if (state->sasl_method)
0, 0,
};
static char *context_name[] = {
- REWRITE_LOCAL, /* Postfix internal form */
- 0, /* filled in on the fly */
+ MAIL_ATTR_RWR_LOCAL, /* Postfix internal form */
+ MAIL_ATTR_RWR_REMOTE, /* Postfix internal form */
};
static NAME_CODE xforward_to_context[] = {
XFORWARD_DOM_LOCAL, 0, /* XFORWARD representation */
case SMTPD_STATE_XFORWARD_DOMAIN:
if (STREQ(attr_value, XFORWARD_UNAVAILABLE))
attr_value = XFORWARD_DOM_LOCAL;
- context_name[1] = *var_remote_rwr_domain ?
- REWRITE_REMOTE : REWRITE_NONE;
if ((context_code = name_code(xforward_to_context,
NAME_CODE_FLAG_NONE,
attr_value)) < 0) {
#ifdef SNAPSHOT
VAR_SMTPD_HOGGERS, DEF_SMTPD_HOGGERS, &var_smtpd_hoggers, 0, 0,
#endif
- VAR_REM_RWR_DOMAIN, DEF_REM_RWR_DOMAIN, &var_remote_rwr_domain, 0, 0,
VAR_LOC_RWR_CLIENTS, DEF_LOC_RWR_CLIENTS, &var_local_rwr_clients, 0, 0,
0,
};
off_t msg_size; /* MAIL FROM message size */
int junk_cmds; /* counter */
int rcpt_overshoot; /* counter */
- char *rewrite_context_name; /* address rewriting context */
+ char *rewrite_context; /* address rewriting context */
/*
* SASL specific.
#define FORWARD_DOMAIN(s) \
(((s)->xforward.flags & SMTPD_STATE_XFORWARD_DOMAIN) ? \
- (s)->xforward.domain : (s)->rewrite_context_name)
+ (s)->xforward.domain : (s)->rewrite_context)
extern void smtpd_xforward_init(SMTPD_STATE *);
extern void smtpd_xforward_preset(SMTPD_STATE *);
#include <verify_clnt.h>
#include <input_transp.h>
#include <is_header.h>
+#include <rewrite_clnt.h>
/* Application-specific. */
/*
* Resolve the address.
*/
- rewrite_clnt_internal(REWRITE_LOCAL, addr, query);
+ rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL, addr, query);
resolve_clnt_query(STR(query), reply);
lowercase(STR(reply->recipient));
continue;
}
if (status == SMTPD_CHECK_OK) {
- if (state->rewrite_context_name)
- myfree(state->rewrite_context_name);
- state->rewrite_context_name = mystrdup(REWRITE_LOCAL);
+ state->rewrite_context = MAIL_ATTR_RWR_LOCAL;
return;
}
}
- state->rewrite_context_name = mystrdup(*var_remote_rwr_domain ?
- REWRITE_REMOTE : REWRITE_NONE);
+ state->rewrite_context = MAIL_ATTR_RWR_REMOTE;
}
/* smtpd_check_client - validate client name or address */
if (*recipient) {
if (canon_verify_sender == 0) {
canon_verify_sender = vstring_alloc(10);
- rewrite_clnt_internal(REWRITE_LOCAL,
+ rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL,
var_verify_sender,
canon_verify_sender);
}
char *var_relay_rcpt_maps;
char *var_verify_sender;
char *var_smtpd_sasl_opts;
-char *var_remote_rwr_domain;
char *var_local_rwr_clients;
typedef struct {
VAR_VERIFY_SENDER, DEF_VERIFY_SENDER, &var_verify_sender,
VAR_MAIL_NAME, DEF_MAIL_NAME, &var_mail_name,
VAR_SMTPD_SASL_OPTS, DEF_SMTPD_SASL_OPTS, &var_smtpd_sasl_opts,
- VAR_REM_RWR_DOMAIN, DEF_REM_RWR_DOMAIN, &var_remote_rwr_domain,
VAR_LOC_RWR_CLIENTS, DEF_LOC_RWR_CLIENTS, &var_local_rwr_clients,
0,
};
default:
if (strcasecmp(args->argv[0], "check_rewrite") == 0) {
smtpd_check_rewrite(&state);
- resp = state.rewrite_context_name;
+ resp = state.rewrite_context;
break;
}
resp = "Commands...\n\
#include <mail_params.h>
#include <rec_type.h>
#include <mail_proto.h>
-#include <rewrite_clnt.h>
/* Application-specific. */
FORWARD_PROTO(state))))
&& (!(state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_DOMAIN)
|| !(bad = smtpd_xforward(state, buf, XFORWARD_DOMAIN, 1,
- STREQ(FORWARD_DOMAIN(state), REWRITE_LOCAL) ?
+ STREQ(FORWARD_DOMAIN(state), MAIL_ATTR_RWR_LOCAL) ?
XFORWARD_DOM_LOCAL : XFORWARD_DOM_REMOTE))))
bad = smtpd_xforward_flush(state, buf);
vstring_free(buf);
state->saved_flags = 0;
state->instance = vstring_alloc(10);
state->seqno = 0;
- state->rewrite_context_name = 0;
+ state->rewrite_context = 0;
#ifdef USE_SASL_AUTH
if (SMTPD_STAND_ALONE(state))
vstring_free(state->proxy_buffer);
if (state->instance)
vstring_free(state->instance);
- if (state->rewrite_context_name)
- myfree(state->rewrite_context_name);
#ifdef USE_SASL_AUTH
if (var_smtpd_sasl_enable)
resolve.o: ../../include/mail_proto.h
resolve.o: ../../include/iostuff.h
resolve.o: ../../include/attr.h
-resolve.o: ../../include/rewrite_clnt.h
resolve.o: ../../include/resolve_local.h
resolve.o: ../../include/mail_conf.h
resolve.o: ../../include/quote_822_local.h
rewrite.o: ../../include/tok822.h
rewrite.o: ../../include/resolve_clnt.h
rewrite.o: ../../include/mail_conf.h
-rewrite.o: ../../include/rewrite_clnt.h
rewrite.o: trivial-rewrite.h
transport.o: transport.c
transport.o: ../../include/sys_defs.h
trivial-rewrite.o: ../../include/attr.h
trivial-rewrite.o: ../../include/resolve_local.h
trivial-rewrite.o: ../../include/mail_conf.h
-trivial-rewrite.o: ../../include/resolve_clnt.h
trivial-rewrite.o: ../../include/rewrite_clnt.h
+trivial-rewrite.o: ../../include/resolve_clnt.h
trivial-rewrite.o: ../../include/tok822.h
trivial-rewrite.o: ../../include/mail_addr.h
trivial-rewrite.o: ../../include/mail_server.h
#include <mail_params.h>
#include <mail_proto.h>
-#include <rewrite_clnt.h>
#include <resolve_local.h>
#include <mail_conf.h>
#include <quote_822_local.h>
#include <resolve_local.h>
#include <tok822.h>
#include <mail_conf.h>
-#include <rewrite_clnt.h>
/* Application-specific. */
ATTR_TYPE_END) != 2)
return (-1);
- if (strcmp(vstring_str(ruleset), REWRITE_LOCAL) == 0)
+ if (strcmp(vstring_str(ruleset), MAIL_ATTR_RWR_LOCAL) == 0)
context = &local_context;
- else if (strcmp(vstring_str(ruleset), REWRITE_REMOTE) == 0)
+ else if (strcmp(vstring_str(ruleset), MAIL_ATTR_RWR_REMOTE) == 0)
context = &remote_context;
else {
msg_warn("unknown context: %s", vstring_str(ruleset));