is renamed to "generic", for consistency with "canonical"
and "virtual".
+20050212
+
+ Cleanup: remove old trace(8) logfile before attempting
+ delivery (and after locking the message file exclusively).
+ Files: *qmgr/qmgr_message.c.
+
+ Cleanup: don't parse-then-regenerate message headers when
+ no address is changed by address rewriting operations. This
+ behavior was copied from the SMTP client's generic mapping
+ code. Files: cleanup/cleanup_rewrite.c, cleanup/cleanup_map11.c,
+ cleanup/cleanup_masquerade.c, cleanup/cleanup_message.c..
+
Open problems:
- Low: 9kbyte memory leak when an expired in-memory session
- is removed by SSL_CTX_flush_sessions(). The occurrance of
- this is rare enough that it is a low priority.
+ Med: disable header address rewriting after XCLIENT?
+ Introduce a better concept of original submission?
- Med: local and remote source port and IP address for smtpd
- policy hook.
+ Low: 9kbyte memory leak when expired in-memory session
+ information is removed by SSL_CTX_flush_sessions(); found
+ by setting the expiry time shorter than the time to deliver
+ one or two messages. Postfix processes are short-lived,
+ and the occurrance of this leak is rare enough that it is
+ a low priority.
- Med: canonical/generic/virtual mapping always append
- myorigin/mydomain and never remote_header_rewrite_domain;
- this needs to be clear from documentation.
+ Low: configurable order of local(8) delivery methods.
- Med: disable address rewriting after XCLIENT? Introduce a
- better concept of original submission?
+ Med: local and remote source port and IP address for smtpd
+ policy hook.
Med: smtp_connect_timeout_budget (default: 3x smtp_connect_timeout)
to limit the total time spent trying to connect.
Low: make post-install a "postfix-only script" so it can
take data from the environment instead of main.cf.
- Low: qmgr should truncate trace logfile before attempting
- delivery.
-
Low: randomize deferred mail backoff.
Med: separate ulimit for delivery to command?
Med: postsuper -r should do something with recipients in
bounce logfiles.
- Low: qmgr_move should not reset time stamps on queue files
- without shared lock (i.e. not open by a delivery agent).
-
Low: postsuper re-run after renaming files, but only a
limited number of times.
Med: make qmgr recipient bounce/defer activity asynchronous
or add a multi-recipient operation that reduces overhead.
+ One possibility is to pass delivery requests to a retry(8)
+ delivery agent which is error(8) in disguise, and which
+ calls defer_append() instead of bounce_append().
Low: postmap/postalias should not try to open a bogus file
when given an unsupported dictionary type.
|mapping |SMTP |smtp(8) |smtp_generic_maps |none |
|table |mail | | | |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |Local alias |all mail|local(8)|alias_maps |none |
- |database | | | | |
+ |Local alias |local | | | |
+ |database |mail |local(8)|alias_maps |none |
+ | |only | | | |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |Local per- | | | | |
- |user |all mail|local(8)|forward_path |none |
- |.forward | | | | |
+ |Local per- |local | | | |
+ |user |mail |local(8)|forward_path |none |
+ |.forward |only | | | |
|files | | | | |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |Local catch-|all mail|local(8)|luser_relay |none |
- |all address | | | | |
+ |Local catch-|local | | | |
+ |all address |mail |local(8)|luser_relay |none |
+ | |only | | | |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
A\bAd\bdd\bdr\bre\bes\bss\bs r\bre\bew\bwr\bri\bit\bti\bin\bng\bg w\bwh\bhe\ben\bn m\bma\bai\bil\bl i\bis\bs r\bre\bec\bce\bei\biv\bve\bed\bd
/usr/sbin/sendmail -q (whenever the Internet link is up)
- The exact location of the sendmail command is system-specific. Use the
- command "p\bpo\bos\bst\btc\bco\bon\bnf\bf s\bse\ben\bnd\bdm\bma\bai\bil\bl_\b_p\bpa\bat\bth\bh" to find out where the Postfix sendmail
+ The exact location of the Postfix sendmail command is system-specific. Use
+ the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf s\bse\ben\bnd\bdm\bma\bai\bil\bl_\b_p\bpa\bat\bth\bh" to find out where the Postfix sendmail
command is located on your machine.
In order to find out if the mail queue is flushed, use something like:
Note: the following information is Postfix version dependent. To find out what
Postfix version you have, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf m\bma\bai\bil\bl_\b_v\bve\ber\brs\bsi\bio\bon\bn".
-P\bPo\bos\bst\btf\bfi\bix\bx v\bve\ber\brs\bsi\bio\bon\bn 2\b2.\b.2\b2 a\ban\bnd\bd l\bla\bat\bte\ber\br
+S\bSo\bol\blu\but\bti\bio\bon\bn 1\b1:\b: P\bPo\bos\bst\btf\bfi\bix\bx v\bve\ber\brs\bsi\bio\bon\bn 2\b2.\b.2\b2 a\ban\bnd\bd l\bla\bat\bte\ber\br
Postfix 2.2 uses the generic(5) address mapping to replace local fantasy email
addresses by valid Internet addresses. This mapping happens ONLY when mail
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/g\bge\ben\bne\ber\bri\bic\bc" whenever you change the
generic table.
-P\bPo\bos\bst\btf\bfi\bix\bx v\bve\ber\brs\bsi\bio\bon\bn 2\b2.\b.1\b1 a\ban\bnd\bd e\bea\bar\brl\bli\bie\ber\br
+S\bSo\bol\blu\but\bti\bio\bon\bn 2\b2:\b: P\bPo\bos\bst\btf\bfi\bix\bx v\bve\ber\brs\bsi\bio\bon\bn 2\b2.\b.1\b1 a\ban\bnd\bd e\bea\bar\brl\bli\bie\ber\br
The solution with older Postfix systems is to use valid Internet addresses
where possible, and to let Postfix map valid Internet addresses to local
and change the patchlevel and the release date. Patches are never
issued for snapshot releases.
+Major changes with snapshot Postfix-2.2-20050212
+================================================
+
+When header address rewriting is enabled, Postfix now updates a
+message header only when at least one address address in that header
+is modified. Older Postfix versions first parse and then unparse
+a header so that there may be subtle changes in formatting.
+
Major changes with snapshot Postfix-2.2-20050211
================================================
# README FILES
# Use "postconf readme_directory" or "postconf html_direc-
# tory" to locate this information.
-# DATABASE_README, Postfix lookup table overview
# ADDRESS_REWRITING_README, address rewriting guide
+# DATABASE_README, Postfix lookup table overview
+# STANDARD_CONFIGURATION_README, configuration examples
#
# LICENSE
# The Secure Mailer license must be distributed with this
</td> <td> none </td> </tr>
<tr> <td> <a href="#aliases"> Local alias database</a> </td> <td>
-all mail </td> <td> <a href="local.8.html">local(8)</a> </td> <td> <a href="postconf.5.html#alias_maps">alias_maps</a> </td> <td> none
+local mail only </td> <td> <a href="local.8.html">local(8)</a> </td> <td> <a href="postconf.5.html#alias_maps">alias_maps</a> </td> <td> none
</td> </tr>
<tr> <td> <a href="#forward"> Local per-user .forward files</a>
-</td> <td> all mail </td> <td> <a href="local.8.html">local(8)</a> </td> <td> <a href="postconf.5.html#forward_path">forward_path</a>
+</td> <td> local mail only </td> <td> <a href="local.8.html">local(8)</a> </td> <td> <a href="postconf.5.html#forward_path">forward_path</a>
</td> <td> none </td> </tr>
<tr> <td> <a href="#luser_relay"> Local catch-all address</a> </td>
-<td> all mail </td> <td> <a href="local.8.html">local(8)</a> </td> <td> <a href="postconf.5.html#luser_relay">luser_relay</a> </td> <td>
+<td> local mail only </td> <td> <a href="local.8.html">local(8)</a> </td> <td> <a href="postconf.5.html#luser_relay">luser_relay</a> </td> <td>
none </td> </tr>
</table>
/usr/sbin/sendmail -q (whenever the Internet link is up)
</pre>
-<p> The exact location of the sendmail command is system-specific.
+<p> The exact location of the Postfix sendmail command is system-specific.
Use the command "<b>postconf <a href="postconf.5.html#sendmail_path">sendmail_path</a></b>" to find out where the
Postfix sendmail command is located on your machine. </p>
To find out what Postfix version you have, execute the command
"<b>postconf <a href="postconf.5.html#mail_version">mail_version</a></b>". </p>
-<h3>Postfix version 2.2 and later </h3>
+<h3>Solution 1: Postfix version 2.2 and later </h3>
<p> Postfix 2.2 uses the <a href="generic.5.html">generic(5)</a> address mapping to replace
local fantasy email addresses by valid Internet addresses. This
<p> Execute the command "<b>postmap /etc/postfix/generic</b>"
whenever you change the generic table. </p>
-<h3>Postfix version 2.1 and earlier </h3>
+<h3>Solution 2: Postfix version 2.1 and earlier </h3>
<p> The solution with older Postfix systems is to use valid
Internet addresses where possible, and to let Postfix map valid
<a href="smtp.8.html">smtp(8)</a>, Postfix SMTP client
<b>README FILES</b>
- <a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
<a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a>, address rewriting guide
+ <a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
+ <a href="STANDARD_CONFIGURATION_README.html">STANDARD_CONFIGURATION_README</a>, configuration examples
<b>LICENSE</b>
The Secure Mailer license must be distributed with this
"\fBpostconf html_directory\fR" to locate this information.
.na
.nf
-DATABASE_README, Postfix lookup table overview
ADDRESS_REWRITING_README, address rewriting guide
+DATABASE_README, Postfix lookup table overview
+STANDARD_CONFIGURATION_README, configuration examples
.SH "LICENSE"
.na
.nf
</td> <td> none </td> </tr>
<tr> <td> <a href="#aliases"> Local alias database</a> </td> <td>
-all mail </td> <td> local(8) </td> <td> alias_maps </td> <td> none
+local mail only </td> <td> local(8) </td> <td> alias_maps </td> <td> none
</td> </tr>
<tr> <td> <a href="#forward"> Local per-user .forward files</a>
-</td> <td> all mail </td> <td> local(8) </td> <td> forward_path
+</td> <td> local mail only </td> <td> local(8) </td> <td> forward_path
</td> <td> none </td> </tr>
<tr> <td> <a href="#luser_relay"> Local catch-all address</a> </td>
-<td> all mail </td> <td> local(8) </td> <td> luser_relay </td> <td>
+<td> local mail only </td> <td> local(8) </td> <td> luser_relay </td> <td>
none </td> </tr>
</table>
/usr/sbin/sendmail -q (whenever the Internet link is up)
</pre>
-<p> The exact location of the sendmail command is system-specific.
+<p> The exact location of the Postfix sendmail command is system-specific.
Use the command "<b>postconf sendmail_path</b>" to find out where the
Postfix sendmail command is located on your machine. </p>
To find out what Postfix version you have, execute the command
"<b>postconf mail_version</b>". </p>
-<h3>Postfix version 2.2 and later </h3>
+<h3>Solution 1: Postfix version 2.2 and later </h3>
<p> Postfix 2.2 uses the generic(5) address mapping to replace
local fantasy email addresses by valid Internet addresses. This
<p> Execute the command "<b>postmap /etc/postfix/generic</b>"
whenever you change the generic table. </p>
-<h3>Postfix version 2.1 and earlier </h3>
+<h3>Solution 2: Postfix version 2.1 and earlier </h3>
<p> The solution with older Postfix systems is to use valid
Internet addresses where possible, and to let Postfix map valid
# "\fBpostconf html_directory\fR" to locate this information.
# .na
# .nf
-# DATABASE_README, Postfix lookup table overview
# ADDRESS_REWRITING_README, address rewriting guide
+# DATABASE_README, Postfix lookup table overview
+# STANDARD_CONFIGURATION_README, configuration examples
# LICENSE
# .ad
# .fi
/*
* cleanup_rewrite.c
*/
-extern void cleanup_rewrite_external(const char *, VSTRING *, const char *);
-extern void cleanup_rewrite_internal(const char *, VSTRING *, const char *);
-extern void cleanup_rewrite_tree(const char *, TOK822 *);
+extern int cleanup_rewrite_external(const char *, VSTRING *, const char *);
+extern int cleanup_rewrite_internal(const char *, VSTRING *, const char *);
+extern int cleanup_rewrite_tree(const char *, TOK822 *);
/*
* cleanup_map11.c
*/
-extern void cleanup_map11_external(CLEANUP_STATE *, VSTRING *, MAPS *, int);
-extern void cleanup_map11_internal(CLEANUP_STATE *, VSTRING *, MAPS *, int);
-extern void cleanup_map11_tree(CLEANUP_STATE *, TOK822 *, MAPS *, int);
+extern int cleanup_map11_external(CLEANUP_STATE *, VSTRING *, MAPS *, int);
+extern int cleanup_map11_internal(CLEANUP_STATE *, VSTRING *, MAPS *, int);
+extern int cleanup_map11_tree(CLEANUP_STATE *, TOK822 *, MAPS *, int);
/*
* cleanup_map1n.c
/*
* cleanup_masquerade.c
*/
-extern void cleanup_masquerade_external(VSTRING *, ARGV *);
-extern void cleanup_masquerade_internal(VSTRING *, ARGV *);
-extern void cleanup_masquerade_tree(TOK822 *, ARGV *);
+extern int cleanup_masquerade_external(VSTRING *, ARGV *);
+extern int cleanup_masquerade_internal(VSTRING *, ARGV *);
+extern int cleanup_masquerade_tree(TOK822 *, ARGV *);
/*
* cleanup_recipient.c
/* SYNOPSIS
/* #include <cleanup.h>
/*
-/* void cleanup_map11_external(state, addr, maps, propagate)
+/* int cleanup_map11_external(state, addr, maps, propagate)
/* CLEANUP_STATE *state;
/* VSTRING *addr;
/* MAPS *maps;
/* int propagate;
/*
-/* void cleanup_map11_internal(state, addr, maps, propagate)
+/* int cleanup_map11_internal(state, addr, maps, propagate)
/* CLEANUP_STATE *state;
/* VSTRING *addr;
/* MAPS *maps;
/* int propagate;
/*
-/* void cleanup_map11_tree(state, tree, maps, propagate)
+/* int cleanup_map11_tree(state, tree, maps, propagate)
/* CLEANUP_STATE *state;
/* TOK822 *tree;
/* MAPS *maps;
/* or until an unreasonable recursion level is reached.
/* An unmatched address extension is propagated when
/* \fIpropagate\fR is non-zero.
+/* These functions return non-zero when the address was changed.
/*
/* cleanup_map11_external() looks up the external (quoted) string
/* form of an address in the maps specified via the \fImaps\fR argument.
/* cleanup_map11_external - one-to-one table lookups */
-void cleanup_map11_external(CLEANUP_STATE *state, VSTRING *addr,
+int cleanup_map11_external(CLEANUP_STATE *state, VSTRING *addr,
MAPS *maps, int propagate)
{
int count;
int expand_to_self;
ARGV *new_addr;
char *saved_addr;
+ int did_rewrite = 0;
/*
* Produce sensible output even in the face of a recoverable error. This
msg_warn("%s: multi-valued %s entry for %s",
state->queue_id, maps->title, STR(addr));
saved_addr = mystrdup(STR(addr));
+ did_rewrite |= strcmp(new_addr->argv[0], STR(addr));
vstring_strcpy(addr, new_addr->argv[0]);
expand_to_self = !strcasecmp(saved_addr, STR(addr));
myfree(saved_addr);
argv_free(new_addr);
if (expand_to_self)
- return;
+ return (did_rewrite);
} else if (dict_errno != 0) {
msg_warn("%s: %s map lookup problem for %s",
state->queue_id, maps->title, STR(addr));
state->errs |= CLEANUP_STAT_WRITE;
- return;
+ return (did_rewrite);
} else {
- return;
+ return (did_rewrite);
}
}
msg_warn("%s: unreasonable %s map nesting for %s",
state->queue_id, maps->title, STR(addr));
+ return (did_rewrite);
}
/* cleanup_map11_tree - rewrite address node */
-void cleanup_map11_tree(CLEANUP_STATE *state, TOK822 *tree,
+int cleanup_map11_tree(CLEANUP_STATE *state, TOK822 *tree,
MAPS *maps, int propagate)
{
VSTRING *temp = vstring_alloc(100);
+ int did_rewrite;
/*
* Produce sensible output even in the face of a recoverable error. This
* the place.
*/
tok822_externalize(temp, tree->head, TOK822_STR_DEFL);
- cleanup_map11_external(state, temp, maps, propagate);
+ did_rewrite = cleanup_map11_external(state, temp, maps, propagate);
tok822_free_tree(tree->head);
tree->head = tok822_scan(STR(temp), &tree->tail);
vstring_free(temp);
+ return (did_rewrite);
}
/* cleanup_map11_internal - rewrite address internal form */
-void cleanup_map11_internal(CLEANUP_STATE *state, VSTRING *addr,
+int cleanup_map11_internal(CLEANUP_STATE *state, VSTRING *addr,
MAPS *maps, int propagate)
{
VSTRING *temp = vstring_alloc(100);
+ int did_rewrite;
/*
* Produce sensible output even in the face of a recoverable error. This
* the place.
*/
quote_822_local(temp, STR(addr));
- cleanup_map11_external(state, temp, maps, propagate);
+ did_rewrite = cleanup_map11_external(state, temp, maps, propagate);
unquote_822_local(addr, STR(temp));
vstring_free(temp);
+ return (did_rewrite);
}
/* SYNOPSIS
/* #include <cleanup.h>
/*
-/* void cleanup_masquerade_external(addr, masq_domains)
+/* int cleanup_masquerade_external(addr, masq_domains)
/* VSTRING *addr;
/* ARGV *masq_domains;
/*
-/* void cleanup_masquerade_internal(addr, masq_domains)
+/* int cleanup_masquerade_internal(addr, masq_domains)
/* VSTRING *addr;
/* ARGV *masq_domains;
/*
-/* void cleanup_masquerade_tree(tree, masq_domains)
+/* int cleanup_masquerade_tree(tree, masq_domains)
/* TOK822 *tree;
/* ARGV *masq_domains;
/* DESCRIPTION
/* below domain names that are listed in the masquerade_domains
/* configuration parameter, except for user names listed in the
/* masquerade_exceptions configuration parameter.
+/* These functions return non-zero when the address was changed.
/*
/* cleanup_masquerade_external() rewrites the external (quoted) string
/* form of an address.
/* cleanup_masquerade_external - masquerade address external form */
-void cleanup_masquerade_external(VSTRING *addr, ARGV *masq_domains)
+int cleanup_masquerade_external(VSTRING *addr, ARGV *masq_domains)
{
char *domain;
int domain_len;
int masq_len;
char *parent;
int truncate;
+ int did_rewrite = 0;
/* Stuff for excluded names. */
char *name;
* Find the domain part.
*/
if ((domain = strrchr(STR(addr), '@')) == 0)
- return;
+ return (0);
domain += 1;
domain_len = strlen(domain);
excluded = (string_list_match(cleanup_masq_exceptions, lowercase(name)) != 0);
myfree(name);
if (excluded)
- return;
+ return (0);
}
/*
msg_info("masquerade: %s -> %s", domain, masq);
vstring_truncate(addr, domain - STR(addr));
vstring_strcat(addr, masq);
+ did_rewrite = 1;
}
break;
}
}
}
+ return (did_rewrite);
}
/* cleanup_masquerade_tree - masquerade address node */
-void cleanup_masquerade_tree(TOK822 *tree, ARGV *masq_domains)
+int cleanup_masquerade_tree(TOK822 *tree, ARGV *masq_domains)
{
VSTRING *temp = vstring_alloc(100);
+ int did_rewrite;
tok822_externalize(temp, tree->head, TOK822_STR_DEFL);
- cleanup_masquerade_external(temp, masq_domains);
+ did_rewrite = cleanup_masquerade_external(temp, masq_domains);
tok822_free_tree(tree->head);
tree->head = tok822_scan(STR(temp), &tree->tail);
vstring_free(temp);
+ return (did_rewrite);
}
/* cleanup_masquerade_internal - masquerade address internal form */
-void cleanup_masquerade_internal(VSTRING *addr, ARGV *masq_domains)
+int cleanup_masquerade_internal(VSTRING *addr, ARGV *masq_domains)
{
VSTRING *temp = vstring_alloc(100);
+ int did_rewrite;
quote_822_local(temp, STR(addr));
- cleanup_masquerade_external(temp, masq_domains);
+ did_rewrite = cleanup_masquerade_external(temp, masq_domains);
unquote_822_local(addr, STR(temp));
vstring_free(temp);
+ return (did_rewrite);
}
/*
#include <vstream.h>
-char *var_masq_exceptions;
+char *var_masq_exceptions;
STRING_LIST *cleanup_masq_exceptions;
-int main(int argc, char **argv)
+int main(int argc, char **argv)
{
VSTRING *addr;
ARGV *masq_domains;
var_masq_exceptions = argv[1];
cleanup_masq_exceptions =
- string_list_init(MATCH_FLAG_NONE, var_masq_exceptions);
+ string_list_init(MATCH_FLAG_NONE, var_masq_exceptions);
masq_domains = argv_split(argv[2], " ,\t\r\n");
addr = vstring_alloc(1);
if (strchr(argv[3], '@') == 0)
TOK822 *tree;
TOK822 **addr_list;
TOK822 **tpp;
+ int did_rewrite = 0;
if (msg_verbose)
msg_info("rewrite_sender: %s", hdr_opts->name);
var_token_limit);
addr_list = tok822_grep(tree, TOK822_ADDR);
for (tpp = addr_list; *tpp; tpp++) {
- cleanup_rewrite_tree(state->hdr_rewrite_context, *tpp);
+ did_rewrite |= 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))
- cleanup_map11_tree(state, *tpp, cleanup_send_canon_maps,
+ did_rewrite |=
+ cleanup_map11_tree(state, *tpp, cleanup_send_canon_maps,
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
if (cleanup_comm_canon_maps
&& (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_HDR_FROM))
- cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps,
+ did_rewrite |=
+ cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps,
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
if (cleanup_masq_domains
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_FROM))
- cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
+ did_rewrite |=
+ cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
}
}
- vstring_sprintf(header_buf, "%s: ", hdr_opts->name);
- tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
+ if (did_rewrite) {
+ vstring_sprintf(header_buf, "%s: ", hdr_opts->name);
+ tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
+ }
myfree((char *) addr_list);
tok822_free_tree(tree);
- if ((hdr_opts->flags & HDR_OPT_DROP) == 0)
- cleanup_fold_header(state, header_buf);
+ if ((hdr_opts->flags & HDR_OPT_DROP) == 0) {
+ if (did_rewrite)
+ cleanup_fold_header(state, header_buf);
+ else
+ cleanup_out_header(state, header_buf);
+ }
}
/* cleanup_rewrite_recip - recipient address rewriting */
TOK822 *tree;
TOK822 **addr_list;
TOK822 **tpp;
+ int did_rewrite = 0;
if (msg_verbose)
msg_info("rewrite_recip: %s", hdr_opts->name);
var_token_limit);
addr_list = tok822_grep(tree, TOK822_ADDR);
for (tpp = addr_list; *tpp; tpp++) {
- cleanup_rewrite_tree(state->hdr_rewrite_context, *tpp);
+ did_rewrite |= 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))
- cleanup_map11_tree(state, *tpp, cleanup_rcpt_canon_maps,
+ did_rewrite |=
+ cleanup_map11_tree(state, *tpp, cleanup_rcpt_canon_maps,
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
if (cleanup_comm_canon_maps
&& (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_HDR_RCPT))
- cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps,
+ did_rewrite |=
+ cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps,
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
if (cleanup_masq_domains
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_RCPT))
- cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
+ did_rewrite |=
+ cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
}
}
- vstring_sprintf(header_buf, "%s: ", hdr_opts->name);
- tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
+ if (did_rewrite) {
+ vstring_sprintf(header_buf, "%s: ", hdr_opts->name);
+ tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
+ }
myfree((char *) addr_list);
tok822_free_tree(tree);
- if ((hdr_opts->flags & HDR_OPT_DROP) == 0)
- cleanup_fold_header(state, header_buf);
+ if ((hdr_opts->flags & HDR_OPT_DROP) == 0) {
+ if (did_rewrite)
+ cleanup_fold_header(state, header_buf);
+ else
+ cleanup_out_header(state, header_buf);
+ }
}
/* cleanup_act_log - log action with context */
/* SYNOPSIS
/* #include <cleanup.h>
/*
-/* void cleanup_rewrite_external(context_name, result, addr)
+/* int cleanup_rewrite_external(context_name, result, addr)
/* const char *context;
/* VSTRING *result;
/* const char *addr;
/*
-/* void cleanup_rewrite_internal(context_name, result, addr)
+/* int cleanup_rewrite_internal(context_name, result, addr)
/* const char *context;
/* VSTRING *result;
/* const char *addr;
/*
-/* void cleanup_rewrite_tree(context_name, tree)
+/* int cleanup_rewrite_tree(context_name, tree)
/* const char *context;
/* TOK822 *tree;
/* DESCRIPTION
/* This module rewrites addresses to canonical form, adding missing
/* domains and stripping source routes etc., and performs
/* \fIcanonical\fR map lookups to map addresses to official form.
+/* These functions return non-zero when the address was changed.
/*
/* cleanup_rewrite_init() performs one-time initialization.
/*
/* cleanup_rewrite_external - rewrite address external form */
-void cleanup_rewrite_external(const char *context_name, VSTRING *result,
+int cleanup_rewrite_external(const char *context_name, VSTRING *result,
const char *addr)
{
rewrite_clnt(context_name, addr, result);
+ return (strcmp(STR(result), addr) != 0);
}
/* cleanup_rewrite_tree - rewrite address node */
-void cleanup_rewrite_tree(const char *context_name, TOK822 *tree)
+int cleanup_rewrite_tree(const char *context_name, TOK822 *tree)
{
VSTRING *dst = vstring_alloc(100);
VSTRING *src = vstring_alloc(100);
+ int did_rewrite;
tok822_externalize(src, tree->head, TOK822_STR_DEFL);
- cleanup_rewrite_external(context_name, dst, STR(src));
+ did_rewrite = cleanup_rewrite_external(context_name, dst, STR(src));
tok822_free_tree(tree->head);
tree->head = tok822_scan(STR(dst), &tree->tail);
vstring_free(dst);
vstring_free(src);
+ return (did_rewrite);
}
/* cleanup_rewrite_internal - rewrite address internal form */
-void cleanup_rewrite_internal(const char *context_name,
+int cleanup_rewrite_internal(const char *context_name,
VSTRING *result, const char *addr)
{
VSTRING *dst = vstring_alloc(100);
VSTRING *src = vstring_alloc(100);
+ int did_rewrite;
quote_822_local(src, addr);
- cleanup_rewrite_external(context_name, dst, STR(src));
+ did_rewrite = cleanup_rewrite_external(context_name, dst, STR(src));
unquote_822_local(result, STR(dst));
vstring_free(dst);
vstring_free(src);
+ return (did_rewrite);
}
* Patches change the patchlevel and the release date. Snapshots change the
* release date only.
*/
-#define MAIL_RELEASE_DATE "20050211"
+#define MAIL_RELEASE_DATE "20050212"
#define MAIL_VERSION_NUMBER "2.2"
#define VAR_MAIL_VERSION "mail_version"
static void qmgr_message_oldstyle_scan(QMGR_MESSAGE *message)
{
VSTRING *buf;
- long orig_offset,
- extra_offset;
+ long orig_offset, extra_offset;
int rec_type;
char *start;
message->sasl_method = mystrdup(value);
else
msg_warn("%s: ignoring multiple %s attribute: %s",
- message->queue_id, MAIL_ATTR_SASL_METHOD, value);
+ message->queue_id, MAIL_ATTR_SASL_METHOD, value);
}
if (strcmp(name, MAIL_ATTR_SASL_USERNAME) == 0) {
if (message->sasl_username == 0)
message->sasl_username = mystrdup(value);
else
msg_warn("%s: ignoring multiple %s attribute: %s",
- message->queue_id, MAIL_ATTR_SASL_USERNAME, value);
+ message->queue_id, MAIL_ATTR_SASL_USERNAME, value);
}
if (strcmp(name, MAIL_ATTR_SASL_SENDER) == 0) {
if (message->sasl_sender == 0)
message->sasl_sender = mystrdup(value);
else
msg_warn("%s: ignoring multiple %s attribute: %s",
- message->queue_id, MAIL_ATTR_SASL_SENDER, value);
+ message->queue_id, MAIL_ATTR_SASL_SENDER, value);
}
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_CONTEXT, value);
+ message->queue_id, MAIL_ATTR_RWR_CONTEXT, value);
}
/* Optional tracing flags. */
else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
* queue file and *before* resolving new recipients. Since all those
* operations are encapsulated so nicely by this routine, the defer
* log reset has to be done here as well.
+ *
+ * Likewise remove a trace file with results from address verification,
+ * "what if" testing, or verbose delivery.
*/
if (mail_queue_remove(MAIL_QUEUE_DEFER, queue_id) && errno != ENOENT)
msg_fatal("%s: %s: remove %s %s: %m", myname,
queue_id, MAIL_QUEUE_DEFER, queue_id);
+ if (message->tflags != 0
+ && mail_queue_remove(MAIL_QUEUE_TRACE, queue_id) && errno != ENOENT)
+ msg_fatal("%s: %s: remove %s %s: %m", myname,
+ queue_id, MAIL_QUEUE_TRACE, queue_id);
qmgr_message_sort(message);
qmgr_message_resolve(message);
qmgr_message_sort(message);
static void qmgr_message_oldstyle_scan(QMGR_MESSAGE *message)
{
VSTRING *buf;
- long orig_offset,
- extra_offset;
+ long orig_offset, extra_offset;
int rec_type;
char *start;
message->sasl_method = mystrdup(value);
else
msg_warn("%s: ignoring multiple %s attribute: %s",
- message->queue_id, MAIL_ATTR_SASL_METHOD, value);
+ message->queue_id, MAIL_ATTR_SASL_METHOD, value);
}
if (strcmp(name, MAIL_ATTR_SASL_USERNAME) == 0) {
if (message->sasl_username == 0)
message->sasl_username = mystrdup(value);
else
msg_warn("%s: ignoring multiple %s attribute: %s",
- message->queue_id, MAIL_ATTR_SASL_USERNAME, value);
+ message->queue_id, MAIL_ATTR_SASL_USERNAME, value);
}
if (strcmp(name, MAIL_ATTR_SASL_SENDER) == 0) {
if (message->sasl_sender == 0)
message->sasl_sender = mystrdup(value);
else
msg_warn("%s: ignoring multiple %s attribute: %s",
- message->queue_id, MAIL_ATTR_SASL_SENDER, value);
+ message->queue_id, MAIL_ATTR_SASL_SENDER, value);
}
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_CONTEXT, value);
+ message->queue_id, MAIL_ATTR_RWR_CONTEXT, value);
}
/* Optional tracing flags. */
else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
* queue file and *before* resolving new recipients. Since all those
* operations are encapsulated so nicely by this routine, the defer
* log reset has to be done here as well.
+ *
+ * Likewise remove a trace file with results from address verification,
+ * "what if" testing, or verbose delivery.
*/
if (mail_queue_remove(MAIL_QUEUE_DEFER, queue_id) && errno != ENOENT)
msg_fatal("%s: %s: remove %s %s: %m", myname,
queue_id, MAIL_QUEUE_DEFER, queue_id);
+ if (message->tflags != 0
+ && mail_queue_remove(MAIL_QUEUE_TRACE, queue_id) && errno != ENOENT)
+ msg_fatal("%s: %s: remove %s %s: %m", myname,
+ queue_id, MAIL_QUEUE_TRACE, queue_id);
qmgr_message_sort(message);
qmgr_message_resolve(message);
qmgr_message_sort(message);
}
#ifdef USE_TLS
} else if (strcasecmp(word, "STARTTLS") == 0) {
+ /* Ignored later if we already sent STARTTLS. */
if ((discard_mask & EHLO_MASK_STARTTLS) == 0)
session->features |= SMTP_FEATURE_STARTTLS;
#endif