From: Wietse Venema Date: Sat, 23 Oct 2004 05:00:00 +0000 (-0500) Subject: postfix-2.2-20041023 X-Git-Tag: v2.2.0-RC1~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a80a65ded2966f4bdc8d62f84bd415f34bab49e;p=thirdparty%2Fpostfix.git postfix-2.2-20041023 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 96384d9f7..d20167c55 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -9774,7 +9774,7 @@ Apologies for any names omitted. 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 @@ -9787,6 +9787,14 @@ Apologies for any names omitted. 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 diff --git a/postfix/README_FILES/ADDRESS_REWRITING_README b/postfix/README_FILES/ADDRESS_REWRITING_README index 502891cc1..f1497a327 100644 --- a/postfix/README_FILES/ADDRESS_REWRITING_README +++ b/postfix/README_FILES/ADDRESS_REWRITING_README @@ -35,6 +35,7 @@ document gives an introduction to Postfix lookup tables. 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 @@ -55,6 +56,33 @@ Topics covered in this document: * Debugging your address manipulations +TToo rreewwrriittee oorr nnoott ttoo rreewwrriittee,, oorr ttoo llaabbeell aass iinnvvaalliidd + +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. + PPoossttffiixx aaddddrreessss rreewwrriittiinngg oovveerrvviieeww The figure below zooms in on those parts of Postfix that are most involved with @@ -199,9 +227,10 @@ address manipulations: 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, @@ -214,13 +243,13 @@ address manipulations: (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 diff --git a/postfix/README_FILES/XFORWARD_README b/postfix/README_FILES/XFORWARD_README index 91a145277..bd7fc0dce 100644 --- a/postfix/README_FILES/XFORWARD_README +++ b/postfix/README_FILES/XFORWARD_README @@ -41,7 +41,7 @@ are in fact case insensitive. 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. @@ -59,6 +59,12 @@ are in fact case insensitive. 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 diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 07d1948d1..38080ab09 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -7,7 +7,7 @@ snapshot release). Patches are issued for the official release 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 @@ -19,13 +19,13 @@ It was already disabled by default with Postfix version 2.1. Since 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. @@ -33,18 +33,24 @@ Postfix either does not rewrite remote message headers at all, or 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, @@ -52,8 +58,14 @@ specify that via the new local_header_rewrite_clients parameter: 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 ======================================================= diff --git a/postfix/html/ADDRESS_REWRITING_README.html b/postfix/html/ADDRESS_REWRITING_README.html index ece7cac24..25ba8bdeb 100644 --- a/postfix/html/ADDRESS_REWRITING_README.html +++ b/postfix/html/ADDRESS_REWRITING_README.html @@ -63,6 +63,9 @@ tables.

+

To rewrite or not to rewrite, or to label +as invalid

+ +

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:

+ + + +

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:

+ + + +

The local_header_rewrite_clients parameter controls what SMTP +clients Postfix considers local instead of remote.

+

Postfix address rewriting overview

The figure below zooms in on those parts of Postfix that are most @@ -296,8 +341,8 @@ none - -

Address rewriting when mail is received

+

Address rewriting when mail is received +

The cleanup(8) server receives mail from outside of Postfix as well as mail from internal sources such as forwarded mail, @@ -383,9 +428,9 @@ parameter (default: yes). You should never turn off this feature, because a lot 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 +

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 @@ -404,13 +449,14 @@ Rewrite "user@host" to "user@host.$mydomain -

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.

+of having Postfix's own domain appended automatically.

Rewrite "user@site." to "user@site" (without the trailing dot).
diff --git a/postfix/html/XFORWARD_README.html b/postfix/html/XFORWARD_README.html index e5b450fda..c1f02d821 100644 --- a/postfix/html/XFORWARD_README.html +++ b/postfix/html/XFORWARD_README.html @@ -69,7 +69,7 @@ names are shown in upper case, they are in fact case insensitive. xforward-command = XFORWARD 1*( SP attribute-name"="attribute-value )

- attribute-name = ( NAME | ADDR | PROTO | HELO ) + attribute-name = ( NAME | ADDR | PROTO | HELO | SOURCE )

@@ -94,6 +94,13 @@ names are shown in upper case, they are in fact case insensitive. SMTP HELO command), or [UNAVAILABLE] 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 diff --git a/postfix/html/cleanup.8.html b/postfix/html/cleanup.8.html index ad3718215..5c566ab12 100644 --- a/postfix/html/cleanup.8.html +++ b/postfix/html/cleanup.8.html @@ -234,10 +234,16 @@ CLEANUP(8) CLEANUP(8) What addresses are subject to sender_canonical_maps address mapping. + remote_header_rewrite_domain (empty) + 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. + RESOURCE AND RATE CONTROLS duplicate_filter_limit (1000) - The maximal number of addresses remembered by the - address duplicate filter for aliases(5) or vir- + The maximal number of addresses remembered by the + address duplicate filter for aliases(5) or vir- tual(5) alias expansion, or for showq(8) queue dis- plays. @@ -246,16 +252,16 @@ CLEANUP(8) CLEANUP(8) message header. hopcount_limit (50) - The maximal number of Received: message headers + The maximal number of Received: message headers that is allowed in the primary message headers. in_flow_delay (1s) - 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. message_size_limit (10240000) - 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: @@ -273,31 +279,31 @@ CLEANUP(8) CLEANUP(8) will handle. queue_file_attribute_count_limit (100) - 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: virtual_alias_expansion_limit (1000) - The maximal number of addresses that virtual alias + The maximal number of addresses that virtual alias expansion produces from each original recipient. virtual_alias_recursion_limit (1000) - The maximal nesting depth of virtual alias expan- + The maximal nesting depth of virtual alias expan- sion. MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and + The default location of the Postfix main.cf and master.cf configuration files. daemon_timeout (18000s) - 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. delay_warning_time (0h) - 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. ipc_timeout (3600s) @@ -305,12 +311,12 @@ CLEANUP(8) CLEANUP(8) over an internal communication channel. max_idle (100s) - 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. max_use (100) - The maximal number of connection requests before a + The maximal number of connection requests before a Postfix daemon process terminates. myhostname (see 'postconf -d' output) @@ -318,19 +324,19 @@ CLEANUP(8) CLEANUP(8) myorigin ($myhostname) 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. process_id (read-only) - The process ID of a Postfix command or daemon pro- + The process ID of a Postfix command or daemon pro- cess. process_name (read-only) - The process name of a Postfix command or daemon + The process name of a Postfix command or daemon process. queue_directory (see 'postconf -d' output) - The location of the Postfix top-level queue direc- + The location of the Postfix top-level queue direc- tory. soft_bounce (no) @@ -341,14 +347,14 @@ CLEANUP(8) CLEANUP(8) The syslog facility of Postfix logging. syslog_name (postfix) - 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: enable_original_recipient (yes) - Enable support for the X-Original-To message + Enable support for the X-Original-To message header. FILES @@ -371,7 +377,7 @@ CLEANUP(8) CLEANUP(8) ADDRESS_REWRITING_README Postfix address manipulation LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index d19f324b8..7265524fa 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -3132,15 +3132,25 @@ and always append my own domain to incomplete header addresses.

    local_header_rewrite_clients = static:all +

    The purist setting: rewrite headers only in mail from Postfix +sendmail and in SMTP mail from this machine.

    + +
    +    mynetworks_style = host
    +    local_header_rewrite_clients = permit_mynetworks
    +
    +

    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.

         local_header_rewrite_clients = permit_mynetworks,
             permit_sasl_authenticated permit_tls_clientcerts
     
    -

    Include clients that are pop-before-smtp authenticated:

    +

    The ISP setting: include clients that are pop-before-smtp +authenticated.

         local_header_rewrite_clients = permit_mynetworks,
    @@ -5069,7 +5079,9 @@ Examples:
     
     

    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.

    Examples:

    diff --git a/postfix/html/postfix-manuals.html b/postfix/html/postfix-manuals.html index 6956125a5..d066ba359 100644 --- a/postfix/html/postfix-manuals.html +++ b/postfix/html/postfix-manuals.html @@ -198,6 +198,8 @@ the following convention:

  • spawn(8), run non-Postfix server +
  • trivial-rewrite(8), Postfix address rewriting +
  • verify(8), Postfix address verification
  • virtual(8), Postfix virtual delivery agent diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index 5eaa0d80f..4fc7cd37b 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -104,25 +104,22 @@ SMTPD(8) SMTPD(8) port to. ADDRESS REWRITING CONTROLS + See the ADDRESS_REWRITING_README document for a detailed + discussion of Postfix address rewriting. + receive_override_options (empty) - 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: local_header_rewrite_clients (see 'postconf -d' output) Append the domain name in $myorigin or $mydomain 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 remote_header_rewrite_domain parameter. - remote_header_rewrite_domain (empty) - 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. - AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS As of version 1.0, Postfix can be configured to send new mail to an external content filter AFTER the mail is @@ -787,6 +784,7 @@ SMTPD(8) SMTPD(8) README FILES 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 diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 435a7468f..1eb814f51 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -1607,8 +1607,21 @@ and always append my own domain to incomplete header addresses. .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 @@ -1619,7 +1632,8 @@ only with mail from local or authorized clients. .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 @@ -2706,7 +2720,9 @@ relocated_maps = hash:/etc/postfix/relocated .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 diff --git a/postfix/man/man8/cleanup.8 b/postfix/man/man8/cleanup.8 index 3110a9c08..be120c5cd 100644 --- a/postfix/man/man8/cleanup.8 +++ b/postfix/man/man8/cleanup.8 @@ -200,6 +200,10 @@ mapping. .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 diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index 5c1fed6d3..01709f279 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -107,6 +107,8 @@ What SMTP clients Postfix will not offer AUTH support to. .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. @@ -117,10 +119,6 @@ Append the domain name in $myorigin or $mydomain to 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 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 @@ -647,6 +645,7 @@ Use "\fBpostconf readme_directory\fR" or .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 diff --git a/postfix/mantools/makemanidx b/postfix/mantools/makemanidx index 2e2725f90..543eae517 100755 --- a/postfix/mantools/makemanidx +++ b/postfix/mantools/makemanidx @@ -86,7 +86,7 @@ NR == 1,/SH "*SEE ALSO"*/ { next } /^[A-Z].*:$/ { print ul "

    ", $0, "

    \n\n
      \n\n"; ul = "
    \n\n" } -/^[a-z][a-z0-9_]+\(/ { print "
  • ", $0, "\n" } +/^[a-z][-a-z0-9_]+\(/ { print "
  • ", $0, "\n" } ' | sed 's;: $; ;' diff --git a/postfix/proto/ADDRESS_REWRITING_README.html b/postfix/proto/ADDRESS_REWRITING_README.html index 33d4a8c0d..b092d0c84 100644 --- a/postfix/proto/ADDRESS_REWRITING_README.html +++ b/postfix/proto/ADDRESS_REWRITING_README.html @@ -63,6 +63,9 @@ tables.

    +

    To rewrite or not to rewrite, or to label +as invalid

    + +

    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.

    +

    Postfix address rewriting overview

    The figure below zooms in on those parts of Postfix that are most @@ -296,8 +341,8 @@ none - -

    Address rewriting when mail is received

    +

    Address rewriting when mail is received +

    The cleanup(8) server receives mail from outside of Postfix as well as mail from internal sources such as forwarded mail, @@ -383,9 +428,9 @@ parameter (default: yes). You should never turn off this feature, because a lot 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 +

    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 @@ -404,13 +449,14 @@ Rewrite "user@host" to "user@host.$mydomain" parameter (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.

    +of having Postfix's own domain appended automatically.

    Rewrite "user@site." to "user@site" (without the trailing dot).
    diff --git a/postfix/proto/XFORWARD_README.html b/postfix/proto/XFORWARD_README.html index 1563815a4..a748447fa 100644 --- a/postfix/proto/XFORWARD_README.html +++ b/postfix/proto/XFORWARD_README.html @@ -69,7 +69,7 @@ names are shown in upper case, they are in fact case insensitive. xforward-command = XFORWARD 1*( SP attribute-name"="attribute-value )

    - attribute-name = ( NAME | ADDR | PROTO | HELO ) + attribute-name = ( NAME | ADDR | PROTO | HELO | SOURCE )

    @@ -94,6 +94,13 @@ names are shown in upper case, they are in fact case insensitive. SMTP HELO command), or [UNAVAILABLE] 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 diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index a985cae0b..f9040db33 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -7222,7 +7222,9 @@ physical endpoints.

    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.

    Examples:

    @@ -7300,15 +7302,25 @@ and always append my own domain to incomplete header addresses.

    local_header_rewrite_clients = static:all
  • +

    The purist setting: rewrite headers only in mail from Postfix +sendmail and in SMTP mail from this machine.

    + +
    +    mynetworks_style = host
    +    local_header_rewrite_clients = permit_mynetworks
    +
    +

    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.

         local_header_rewrite_clients = permit_mynetworks, 
             permit_sasl_authenticated permit_tls_clientcerts
     
    -

    Include clients that are pop-before-smtp authenticated:

    +

    The ISP setting: include clients that are pop-before-smtp +authenticated.

         local_header_rewrite_clients = permit_mynetworks, 
    diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in
    index f540446db..e2f2c8691 100644
    --- a/postfix/src/cleanup/Makefile.in
    +++ b/postfix/src/cleanup/Makefile.in
    @@ -130,7 +130,9 @@ cleanup_addr.o: ../../include/mail_addr_find.h
     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
    @@ -197,7 +199,6 @@ cleanup_envelope.o: ../../include/verp_sender.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
    @@ -384,7 +385,6 @@ cleanup_message.o: ../../include/iostuff.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
    @@ -455,10 +455,13 @@ cleanup_rewrite.o: ../../include/vbuf.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
    @@ -483,9 +486,11 @@ cleanup_state.o: ../../include/been_here.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
    diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c
    index d06458a7c..f72deda00 100644
    --- a/postfix/src/cleanup/cleanup.c
    +++ b/postfix/src/cleanup/cleanup.c
    @@ -176,6 +176,10 @@
     /* .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
    diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h
    index 8ec055ec2..f592df81e 100644
    --- a/postfix/src/cleanup/cleanup.h
    +++ b/postfix/src/cleanup/cleanup.h
    @@ -61,7 +61,7 @@ typedef struct CLEANUP_STATE {
         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;
    diff --git a/postfix/src/cleanup/cleanup_addr.c b/postfix/src/cleanup/cleanup_addr.c
    index ecc577812..32fb86470 100644
    --- a/postfix/src/cleanup/cleanup_addr.c
    +++ b/postfix/src/cleanup/cleanup_addr.c
    @@ -76,7 +76,7 @@
     #include 
     #include 
     #include 
    -#include 
    +#include 
     
     /* Application-specific. */
     
    @@ -93,14 +93,13 @@ void    cleanup_addr_sender(CLEANUP_STATE *state, const char *buf)
         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);
    @@ -140,14 +139,13 @@ void    cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf)
         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
    @@ -181,10 +179,10 @@ void    cleanup_addr_bcc(CLEANUP_STATE *state, const char *bcc)
         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))
    diff --git a/postfix/src/cleanup/cleanup_envelope.c b/postfix/src/cleanup/cleanup_envelope.c
    index a86236c96..a2063f984 100644
    --- a/postfix/src/cleanup/cleanup_envelope.c
    +++ b/postfix/src/cleanup/cleanup_envelope.c
    @@ -57,7 +57,6 @@
     #include 
     #include 
     #include 
    -#include 
     
     /* Global library. */
     
    @@ -68,13 +67,13 @@
     #include 
     #include 
     #include 
    -#include 
     
     /* 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);
     
    @@ -112,12 +111,6 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
         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);
    @@ -287,16 +280,18 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
     	    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);
    diff --git a/postfix/src/cleanup/cleanup_init.c b/postfix/src/cleanup/cleanup_init.c
    index c3b8459cb..f5d4c869e 100644
    --- a/postfix/src/cleanup/cleanup_init.c
    +++ b/postfix/src/cleanup/cleanup_init.c
    @@ -121,6 +121,7 @@ int     var_virt_expan_limit;		/* maximum virtual alias expansion */
     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,
    @@ -163,6 +164,7 @@ CONFIG_STR_TABLE cleanup_str_table[] = {
         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,
     };
     
    diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c
    index 71dd5472a..575e68426 100644
    --- a/postfix/src/cleanup/cleanup_message.c
    +++ b/postfix/src/cleanup/cleanup_message.c
    @@ -80,7 +80,6 @@
     #include 
     #include 
     #include 
    -#include 
     
     /* Application-specific. */
     
    @@ -176,7 +175,7 @@ static void cleanup_rewrite_sender(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts,
     			      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))
    @@ -221,7 +220,7 @@ static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts,
     			      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))
    @@ -499,10 +498,10 @@ static void cleanup_header_callback(void *context, int header_class,
     	    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);
    diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c
    index 3ffa5945b..3c761a572 100644
    --- a/postfix/src/cleanup/cleanup_state.c
    +++ b/postfix/src/cleanup/cleanup_state.c
    @@ -44,7 +44,7 @@
     #include 
     #include 
     #include 
    -#include 
    +#include 
     
     /* Application-specific. */
     
    @@ -85,7 +85,7 @@ CLEANUP_STATE *cleanup_state_alloc(void)
         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);
    @@ -123,7 +123,5 @@ void    cleanup_state_free(CLEANUP_STATE *state)
     	myfree(state->filter);
         if (state->redirect)
     	myfree(state->redirect);
    -    if (state->rewrite_context_name)
    -	myfree(state->rewrite_context_name);
         myfree((char *) state);
     }
    diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in
    index 1dd4f6c0a..09305f61b 100644
    --- a/postfix/src/global/Makefile.in
    +++ b/postfix/src/global/Makefile.in
    @@ -455,6 +455,10 @@ canon_addr.o: ../../include/vstring.h
     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
    @@ -1381,6 +1385,10 @@ tok822_rewrite.o: ../../include/vstring.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
    diff --git a/postfix/src/global/deliver_pass.c b/postfix/src/global/deliver_pass.c
    index c93aef143..e9a2b0807 100644
    --- a/postfix/src/global/deliver_pass.c
    +++ b/postfix/src/global/deliver_pass.c
    @@ -114,7 +114,7 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request,
     	       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,
    diff --git a/postfix/src/global/deliver_request.c b/postfix/src/global/deliver_request.c
    index b30fd0bee..f8a1fc7f8 100644
    --- a/postfix/src/global/deliver_request.c
    +++ b/postfix/src/global/deliver_request.c
    @@ -240,7 +240,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
     		  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);
    diff --git a/postfix/src/global/deliver_request.h b/postfix/src/global/deliver_request.h
    index 33f37afac..281b311be 100644
    --- a/postfix/src/global/deliver_request.h
    +++ b/postfix/src/global/deliver_request.h
    @@ -47,7 +47,7 @@ typedef struct DELIVER_REQUEST {
         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;
     
      /*
    diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h
    index 222e51e08..e48437381 100644
    --- a/postfix/src/global/mail_proto.h
    +++ b/postfix/src/global/mail_proto.h
    @@ -122,7 +122,10 @@ extern char *mail_pathname(const char *, const char *);
     #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"
    @@ -180,7 +183,7 @@ extern char *mail_pathname(const char *, const char *);
     #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 */
     
    diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
    index b6ada4c52..42f75c0a6 100644
    --- a/postfix/src/global/mail_version.h
    +++ b/postfix/src/global/mail_version.h
    @@ -20,7 +20,7 @@
       * Patches change the patchlevel and the release date. Snapshots change the
       * release date only.
       */
    -#define MAIL_RELEASE_DATE	"20041022"
    +#define MAIL_RELEASE_DATE	"20041023"
     #define MAIL_VERSION_NUMBER	"2.2"
     
     #define VAR_MAIL_VERSION	"mail_version"
    diff --git a/postfix/src/global/rewrite_clnt.c b/postfix/src/global/rewrite_clnt.c
    index db4545ea4..ac28d2546 100644
    --- a/postfix/src/global/rewrite_clnt.c
    +++ b/postfix/src/global/rewrite_clnt.c
    @@ -82,12 +82,6 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
     {
         VSTREAM *stream;
     
    -    /*
    -     * Sanity check.
    -     */
    -    if (strcmp(rule, REWRITE_NONE) == 0)
    -	msg_panic("rewrite_clnt: bad rewrite context: \"%s\"", rule);
    -
         /*
          * One-entry cache.
          */
    diff --git a/postfix/src/global/rewrite_clnt.h b/postfix/src/global/rewrite_clnt.h
    index 5611f9fd1..85c19f481 100644
    --- a/postfix/src/global/rewrite_clnt.h
    +++ b/postfix/src/global/rewrite_clnt.h
    @@ -17,18 +17,15 @@
     #include 
     
      /*
    -  * External interface.
    +  * Global library.
       */
    -#define REWRITE_ADDR	"rewrite"
    -#define REWRITE_CANON	REWRITE_LOCAL	/* backwards compatibility */
    +#include 			/* 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 *);
    diff --git a/postfix/src/global/scache_clnt.c b/postfix/src/global/scache_clnt.c
    index 3838294d7..9c1e482df 100644
    --- a/postfix/src/global/scache_clnt.c
    +++ b/postfix/src/global/scache_clnt.c
    @@ -308,7 +308,7 @@ static int scache_clnt_find_dest(SCACHE *scache, const char *dest_label,
     
     /* 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;
    diff --git a/postfix/src/lmtp/lmtp_proto.c b/postfix/src/lmtp/lmtp_proto.c
    index afdaf4a20..94551b3b1 100644
    --- a/postfix/src/lmtp/lmtp_proto.c
    +++ b/postfix/src/lmtp/lmtp_proto.c
    @@ -119,7 +119,6 @@
     #include 
     #include 
     #include 
    -#include 
     
     /* Application-specific. */
     
    @@ -314,7 +313,7 @@ static int lmtp_loop(LMTP_STATE *state, NOCLOBBER int send_state,
         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;
    @@ -420,12 +419,12 @@ static int lmtp_loop(LMTP_STATE *state, NOCLOBBER int send_state,
     		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;
     
    diff --git a/postfix/src/local/Makefile.in b/postfix/src/local/Makefile.in
    index 60b4c78dc..a76c1dfdf 100644
    --- a/postfix/src/local/Makefile.in
    +++ b/postfix/src/local/Makefile.in
    @@ -436,8 +436,8 @@ resolve.o: ../../include/mail_proto.h
     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
    diff --git a/postfix/src/local/forward.c b/postfix/src/local/forward.c
    index b50856000..81fab30b6 100644
    --- a/postfix/src/local/forward.c
    +++ b/postfix/src/local/forward.c
    @@ -111,7 +111,7 @@ int     forward_init(void)
     
     /* 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;
    @@ -152,6 +152,22 @@ static FORWARD_INFO *forward_open(char *sender)
          * 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);
    @@ -183,7 +199,7 @@ int     forward_append(DELIVER_ATTR attr)
     	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);
         }
    diff --git a/postfix/src/local/local.c b/postfix/src/local/local.c
    index c225e173f..f82f5928a 100644
    --- a/postfix/src/local/local.c
    +++ b/postfix/src/local/local.c
    @@ -608,6 +608,7 @@ static int local_deliver(DELIVER_REQUEST *rqst, char *service)
         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 */
    diff --git a/postfix/src/local/local.h b/postfix/src/local/local.h
    index a06a037ee..e2945e723 100644
    --- a/postfix/src/local/local.h
    +++ b/postfix/src/local/local.h
    @@ -72,7 +72,7 @@ typedef struct DELIVER_ATTR {
         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 */
    @@ -84,6 +84,7 @@ typedef struct DELIVER_ATTR {
         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 *);
    diff --git a/postfix/src/oqmgr/qmgr_deliver.c b/postfix/src/oqmgr/qmgr_deliver.c
    index 0c55ab300..058aa8a55 100644
    --- a/postfix/src/oqmgr/qmgr_deliver.c
    +++ b/postfix/src/oqmgr/qmgr_deliver.c
    @@ -162,9 +162,9 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
     	       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);
    diff --git a/postfix/src/oqmgr/qmgr_message.c b/postfix/src/oqmgr/qmgr_message.c
    index e1be5a490..090b0f24f 100644
    --- a/postfix/src/oqmgr/qmgr_message.c
    +++ b/postfix/src/oqmgr/qmgr_message.c
    @@ -551,12 +551,12 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
     		    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) {
    diff --git a/postfix/src/pickup/Makefile.in b/postfix/src/pickup/Makefile.in
    index 741bae6c4..8d832721e 100644
    --- a/postfix/src/pickup/Makefile.in
    +++ b/postfix/src/pickup/Makefile.in
    @@ -76,5 +76,4 @@ pickup.o: ../../include/record.h
     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
    diff --git a/postfix/src/pickup/pickup.c b/postfix/src/pickup/pickup.c
    index 090690407..a8ddf94a6 100644
    --- a/postfix/src/pickup/pickup.c
    +++ b/postfix/src/pickup/pickup.c
    @@ -138,7 +138,6 @@
     #include 
     #include 
     #include 
    -#include 		/* XXX */
     
     /* Single-threaded server skeleton. */
     
    @@ -295,7 +294,7 @@ static int pickup_copy(VSTREAM *qfile, VSTREAM *cleanup,
         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
    diff --git a/postfix/src/qmgr/qmgr_deliver.c b/postfix/src/qmgr/qmgr_deliver.c
    index 9616735fc..28463a0e6 100644
    --- a/postfix/src/qmgr/qmgr_deliver.c
    +++ b/postfix/src/qmgr/qmgr_deliver.c
    @@ -167,9 +167,9 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
     	       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);
    diff --git a/postfix/src/qmgr/qmgr_message.c b/postfix/src/qmgr/qmgr_message.c
    index 48052de60..17d2f2de2 100644
    --- a/postfix/src/qmgr/qmgr_message.c
    +++ b/postfix/src/qmgr/qmgr_message.c
    @@ -586,12 +586,12 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
     		    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) {
    diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c
    index 70184dc71..8b05780b1 100644
    --- a/postfix/src/smtp/smtp_proto.c
    +++ b/postfix/src/smtp/smtp_proto.c
    @@ -121,7 +121,6 @@
     #include 
     #include 
     #include 
    -#include 
     
     /* Application-specific. */
     
    @@ -645,8 +644,8 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
     		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;
     
    diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in
    index d29e4c49f..62a97aa53 100644
    --- a/postfix/src/smtpd/Makefile.in
    +++ b/postfix/src/smtpd/Makefile.in
    @@ -211,6 +211,8 @@ smtpd_check.o: ../../include/namadr_list.h
     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
    @@ -225,8 +227,6 @@ smtpd_check.o: ../../include/virtual8_maps.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
    diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c
    index 538590fab..ce1410fef 100644
    --- a/postfix/src/smtpd/smtpd.c
    +++ b/postfix/src/smtpd/smtpd.c
    @@ -89,6 +89,8 @@
     /* 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.
    @@ -99,10 +101,6 @@
     /*	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
    @@ -595,6 +593,7 @@
     /* .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
    @@ -680,7 +679,6 @@
     #include 
     #endif
     #include 
    -#include 
     
     /* Single-threaded server skeleton. */
     
    @@ -793,7 +791,6 @@ char   *var_smtpd_hoggers;
     
     #endif
     
    -char   *var_remote_rwr_domain;
     char   *var_local_rwr_clients;
     
      /*
    @@ -1074,7 +1071,7 @@ static void mail_open_stream(SMTPD_STATE *state)
     	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)
    @@ -2247,8 +2244,8 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
     	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 */
    @@ -2375,8 +2372,6 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
     	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) {
    @@ -2919,7 +2914,6 @@ int     main(int argc, char **argv)
     #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,
         };
    diff --git a/postfix/src/smtpd/smtpd.h b/postfix/src/smtpd/smtpd.h
    index e00b76382..232c3a02a 100644
    --- a/postfix/src/smtpd/smtpd.h
    +++ b/postfix/src/smtpd/smtpd.h
    @@ -88,7 +88,7 @@ typedef struct SMTPD_STATE {
         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.
    @@ -245,7 +245,7 @@ extern void smtpd_peer_reset(SMTPD_STATE *state);
     
     #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 *);
    diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c
    index e140c7cb1..f8e04a768 100644
    --- a/postfix/src/smtpd/smtpd_check.c
    +++ b/postfix/src/smtpd/smtpd_check.c
    @@ -212,6 +212,7 @@
     #include 
     #include 
     #include 
    +#include 
     
     /* Application-specific. */
     
    @@ -424,7 +425,7 @@ static void *resolve_pagein(const char *addr, void *unused_context)
         /*
          * 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));
     
    @@ -3429,14 +3430,11 @@ void    smtpd_check_rewrite(SMTPD_STATE *state)
     	    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 */
    @@ -3615,7 +3613,7 @@ char   *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
         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);
     	}
    @@ -4064,7 +4062,6 @@ char   *var_def_rbl_reply;
     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 {
    @@ -4106,7 +4103,6 @@ static STRING_TABLE string_table[] = {
         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,
     };
    @@ -4596,7 +4592,7 @@ int     main(int argc, char **argv)
     	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\
    diff --git a/postfix/src/smtpd/smtpd_proxy.c b/postfix/src/smtpd/smtpd_proxy.c
    index bede77c82..861f72d29 100644
    --- a/postfix/src/smtpd/smtpd_proxy.c
    +++ b/postfix/src/smtpd/smtpd_proxy.c
    @@ -157,7 +157,6 @@
     #include 
     #include 
     #include 
    -#include 
     
     /* Application-specific. */
     
    @@ -340,7 +339,7 @@ int     smtpd_proxy_open(SMTPD_STATE *state, const char *service,
     					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);
    diff --git a/postfix/src/smtpd/smtpd_state.c b/postfix/src/smtpd/smtpd_state.c
    index 388957d55..759f5ebfd 100644
    --- a/postfix/src/smtpd/smtpd_state.c
    +++ b/postfix/src/smtpd/smtpd_state.c
    @@ -114,7 +114,7 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream,
         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))
    @@ -171,8 +171,6 @@ void    smtpd_state_reset(SMTPD_STATE *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)
    diff --git a/postfix/src/trivial-rewrite/Makefile.in b/postfix/src/trivial-rewrite/Makefile.in
    index 84da86e67..f51117795 100644
    --- a/postfix/src/trivial-rewrite/Makefile.in
    +++ b/postfix/src/trivial-rewrite/Makefile.in
    @@ -73,7 +73,6 @@ resolve.o: ../../include/mail_params.h
     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
    @@ -107,7 +106,6 @@ rewrite.o: ../../include/resolve_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
    @@ -146,8 +144,8 @@ trivial-rewrite.o: ../../include/iostuff.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
    diff --git a/postfix/src/trivial-rewrite/resolve.c b/postfix/src/trivial-rewrite/resolve.c
    index 924b51e6a..3b345671d 100644
    --- a/postfix/src/trivial-rewrite/resolve.c
    +++ b/postfix/src/trivial-rewrite/resolve.c
    @@ -65,7 +65,6 @@
     
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/postfix/src/trivial-rewrite/rewrite.c b/postfix/src/trivial-rewrite/rewrite.c
    index 6bf8a4a52..675457cff 100644
    --- a/postfix/src/trivial-rewrite/rewrite.c
    +++ b/postfix/src/trivial-rewrite/rewrite.c
    @@ -78,7 +78,6 @@
     #include 
     #include 
     #include 
    -#include 
     
     /* Application-specific. */
     
    @@ -245,9 +244,9 @@ int     rewrite_proto(VSTREAM *stream)
     		  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));