Some people believe that configured address rewriting is a Mortal Sin. Others believe that life is not possible without it. Exim provides the facility; you do not have to use it. There are two cases that are commonly encountered:
In general, rewriting addresses from one's own system or domain has some legitimacy. Rewriting other addresses should be done only with great care and in special circumstances.
Address rewriting can be applied both to envelope addresses and addresses in header lines. Exim's rewriting rules specify to which addresses they apply.
Exim's rewriting configuration appears as the sixth part of the runtime
configuration file. It can be tested by the `-brw' command line option. This
takes an address (which can be a full RFC 822 address) as its argument. The
output is a list of how the address would be transformed by the rewriting rules
for each of the different places it might appear, that is, for each different
header and for the envelope sender and recipient fields.
For example,
might produce the output
which shows that rewriting has been set up for that address when used in any of
the source fields, but not when it appears as a recipient address.
exim -brw ph10@exim.work.shop
sender: Philip.Hazel@exim.work.shop
from: Philip.Hazel@exim.work.shop
to: ph10@exim.work.shop
cc: ph10@exim.work.shop
bcc: ph10@exim.work.shop
reply-to: Philip.Hazel@exim.work.shop
env-from: Philip.Hazel@exim.work.shop
env-to: ph10@exim.work.shop
The rewriting configuration consists of lines of rewriting rules in the form
<source pattern> <replacement> <flags>
For each address that could potentially be rewritten, the rules are scanned in order, and replacements from earlier rules can themselves be replaced as a result of later rules (but see the `q' and `r' flags).
The order in which header and envelope addresses are rewritten is undefined, may change between releases, and must not be relied on. For example, the replacement string for a header rewrite must not assume that the message's envelope sender address has (or has not) already been rewritten.
Long rules can be split over several lines by terminating all but the last with a backslash character. Leading white space on continuation lines is ignored. If the replacement string contains spaces, which can happen for certain forms of expansion expression, it must be enclosed in double quotes, and the normal quoting conventions apply inside them.
`$local_part' and `$domain' can be used in the replacement string to refer the address that is being rewritten. Note that complete lookup-driven rewriting can be done by a line of the form
*@* ${lookup ...
where the lookup key is derived from `$1' and `$2' or `$local_part' and `$domain'.
The source pattern can be in one of the following forms. Note that it is not enclosed in quotes, and there is no special processing of any characters. In particular, if it is a regular expression, backslash characters should not be doubled.
*@orchestra-land.fict.bookIf the domain is specified as a single @ character, it matches the primary host name.
root@lsearch;/special/domainsIf there is an asterisk in the local part, the value of the wild part is placed in the first numerical variable. If the lookup is a partial one, the wild part of the domain is placed in the next numerical variable, the fixed part of the domain is placed in the succeeding variable. Thus, for example, if the address `foo@bar.baz.com' is processed by a rewriting rule of the form
*@partial-dbm;/some/dbm/file <replacement string>and the key in the file that matches the domain is `*.baz.com', then
$1 = `foo' $2 = `bar' $3 = `baz.com'If the address `foo@baz.com' is looked up, this matches the same wildcard file entry, and in this case `$2' is set to the empty string, but `$3' is still set to `baz.com'. If a non-wild key is matched in a partial lookup, then again `$2' is set to the empty string and `$3' is set to the whole domain. For non-partial lookups, no numerical variables are set.
partial-dbm;/rewrite/databaseThis works as for an address-list configuration item -- the domain is first looked up, possibly partially, and if that fails, the whole address is then looked up (not partially). When a partial lookup succeeds, the numerical variable `$1' contains the wild part of the domain, and `$2' contains the fixed part. The `@@' form of address-list lookup can also be used.
The replacement is a string which is expanded. If the expansion is forced to fail by the presence of `fail' in a conditional item or lookup, the rewrite rule is abandoned, and subsequent ones are tried. Any other expansion failure causes the entire rewriting operation to be abandoned, and an entry written to the panic log.
Within the expansion, the variables `$local_part' and `$domain' refer to the address that is being rewritten. If the pattern is a regular expression, the numerical variables refer to the bracketed sub-expressions therein, with `$0' referring to the entire address. For example, if the pattern
^(red|white).king@(wonderland|lookingglass).fict.book$
is matched against the address `red.king@lookingglass.fict.book' then
`$0' is `red.king@lookingglass.fict.book' `$1' is `red' `$2' is `lookingglass'
If the pattern is not a regular expression, the numerical variables refer to the character strings matched by asterisks, with `$1' associated with the first asterisk. Once again, `$0' refers to the entire address. For example, if the pattern
*queen@*.fict.book
is matched against the address `hearts-queen@wonderland.fict.book' then
`$0' is `hearts-queen@wonderland.fict.book' `$1' is `hearts-' `$2' is `wonderland'
Note that if the local part does not start with an asterisk, but the domain does, then it is `$1' that contains the wild part of the domain.
The flags are single characters which may appear in any order. Spaces and tabs between them are ignored.
The flags field may be empty, in which case the rewriting rule applies to all headers and to both the sender and recipient fields of the envelope. Otherwise, one or more of the following letters can be given to control which addresses are rewritten:
E rewrite all envelope fields F rewrite the envelope From field T rewrite the envelope To field b rewrite the `Bcc:' header c rewrite the `Cc:' header f rewrite the `From:' header h rewrite all headers r rewrite the `Reply-to:' header s rewrite the `Sender:' header t rewrite the `To:' header
You should be particularly careful about rewriting `Sender:' headers, and restrict this to special known cases in your own domains.
The rewrite flag `S' specifies a rewrite at SMTP time, as soon as an address is received and before any other processing; even before syntax checking. The pattern is required to be a regular expression. This applies to both sender and recipient addresses, and allows for the handling of addresses that are not compliant with RFC 822 (for example, in batched SMTP input). Because of this, the variables `$local_part' and `$domain' are not available during the expansion of the replacement string.
There are four flags which control the way the rewriting process works:
From: Ford Prefect <fp42@restaurant.hitch.fict.book>into
From: Ford Prefect <prefectf@hitch.fict.book>Sometimes there is a need to replace the whole address item, and this can be done by adding the flag letter `w' to a rule. If this is set on a rule that causes an address in a header to be rewritten, the entire address is replaced, not just the working part. The replacement must be a complete RFC 822 address, including the angle brackets if necessary. When the `w' flag is set on a rule that causes an envelope address to be rewritten, all but the working part of the replacement address is discarded.
The `X' flag is a slightly strange oddity that adds additional checking to `sender_address_relay'. Whenever an address passes the `sender_address_relay' check, if there are any rewriting rules with the `X' flag set, the address is rewritten and if this makes any change to the address, it must verify successfully for the relaying to be permitted.
We use this in Cambridge as follows: users have a centrally registered address in the virtual domain `cam.ac.uk', but there are a number of different hosts where they actually have their accounts and from which they can read mail using IMAP or POP. It is desirable to prevent them using hosts other than those on which they have accounts as outgoing relays, and yet to permit the sending addresses to contain the `cam.ac.uk' domain. Since the user names are the same on the relay hosts as in the `cam.ac.uk' domain, a rewriting rule of the form
*@cam.ac.uk $1@${qualify_domain}.cam.ac.uk X
means that any sender address of the form `user@cam.ac.uk' is acceptable only if `user' has an account on the local host. This also has the virtue of detecting typos in the configurations of users' MUAs.
Here is an example of the two common rewriting paradigms:
*@*.hitch.book.fict $1@hitch.book.fict *@hitch.book.fict ${lookup{$1}dbm{/etc/realnames}\ {$value}fail}@hitch.book.fict bcfrF
Note the use of `fail' in the lookup expansion. This causes the string expansion to fail, and in this context it has the effect of leaving the original address unchanged, but Exim goes on to consider subsequent rewriting rules, if any, since the `q' flag is not present in that rule. An alternative to `fail' would be to supply `$1' explicitly, which would cause the rewritten address to be the same as before, at the cost of a small bit of processing. Not supplying either of these is an error, since the rewritten address would then contain no local part.
Exim does not handle addresses in the form of `bang paths'. If it sees such an address it treats it as an unqualified local part which it qualifies with the local qualification domain (if the source of the message is local or if the remote host is permitted to send unqualified addresses). Rewriting can sometimes be used to handle simple bang paths with a fixed number of components. For example, the rule
^([^!]+)!(.*)@your\.domain$ $2@$1
rewrites a two-component bang path `host.name!user' as the domain address `user@host.name'.
Go to the first, previous, next, last section, table of contents.