Go to the first, previous, next, last section, table of contents.


34. Address rewriting

There are some circumstances in which Exim automatically rewrites domains in addresses. The two most common are when an address is given without a domain (for addresses in envelopes, this is permitted only for locally submitted messages, or messages from hosts that match sender_unqualified_hosts or receiver_unqualified_hosts) or when an address contains an abbreviated domain that is expanded by DNS lookup.

One situation in which Exim does not rewrite a domain is when it is the name of a CNAME record in the DNS. The older RFCs suggest that such a domain should be rewritten using the `canonical' name, and some MTAs do this. The new draft RFCs do not contain this suggestion.

This chapter is about address rewriting that is explicitly specified in the configuration. Some people believe that configured 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.

In general, rewriting addresses from your own system or domain has some legitimacy. Rewriting other addresses should be done only with great care and in special circumstances. The author of Exim believes that rewriting should be used sparingly, and mainly for `regularizing' addresses in your own domains. Although it can be used as a routing tool, this is definitely not recommended.

There are two commonly encountered circumstances where rewriting is used, as illustrated by these examples:

Configured address rewriting can take place at several different stages of a message's processing. The main rewriting happens when a message is received, but it can also happen when a new address is generated during directing or routing (for example, by aliasing), and when a message is transported.

The rewriting rules that appear in the rewriting section of the configuration file (the sixth section) apply to addresses in incoming messages, and to addresses that are generated from the envelope recipients by aliasing or forwarding, unless no_rewrite is set on the relevant directors. Basically, they apply to each address the first time Exim sees it. These rules operate both on envelope addresses and on addresses in header lines. Each rule specifies to which types of address it applies.

At transport time, rewriting addresses in header lines can be specified by setting the generic headers_rewrite option on a transport. This option contains rules that are identical in form to those in the rewrite section of the configuration file. In addition, the outgoing envelope sender can be rewritten by means of the return_path transport option, but it is not possible to rewrite envelope recipients at transport time.

Rewriting of addresses in header lines applies only to those headers that were received with the message, or, in the case of transport rewriting, those that were added by a system filter. That is, it applies only to those headers that are common to all copies of the message. Header lines that are added by individual drivers (and which are therefore specific to individual recipient addresses) are not rewritten.

Unqualified addresses (those without a domain) in header lines are qualified and then rewritten if they are in locally submitted messages, or messages from hosts that are permitted to send unqualified envelope addresses. Otherwise, unqualified addresses in header lines are neither qualified nor rewritten.

The remainder of this chapter describes the rewriting rules that are used in the rewriting section of the configuration file, and also in the generic headers_rewrite option that can be set on any transport.

34.1 Testing the rewriting rules that apply on input

Exim's input rewriting configuration appears as the sixth part of the run time 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 in an incoming message, that is, for each different header and for the envelope sender and recipient fields. For example,

exim -brw ph10@exim.work.shop

might produce the output

  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

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.

34.2 Rewriting rules

The rewriting section of the configuration file consists of lines of rewriting rules in the form

<source pattern>  <replacement>  <flags>

The flags are single characters which may appear in any order. Spaces and tabs between them are ignored.

Rewriting rules that are specified for the headers_rewrite generic transport option are given as a colon-separated list; each item in the list takes the same format as a line in the main rewriting configuration.

The formats of source patterns and replacement strings are described below. Each is terminated by white space. If a 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.

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, with one exception: when a message is received, the envelope sender is always rewritten first, before any header lines are rewritten. For example, the replacement string for a rewrite of an address in To: must not assume that the message's address in From: has (or has not) already been rewritten. However, a rewrite of From: may assume that the envelope sender has already been rewritten.

$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 rule of the form

*@*   ${lookup ...

where the lookup key is derived from $1 and $2 or $local_part and $domain.

34.3 Rewriting patterns

The source pattern can be in one of the following forms. It is not enclosed in quotes, and there is no special processing of any characters. It is not expanded. If it is a regular expression, backslash characters should not be doubled.

34.4 Rewriting replacements

If the replacement string for a rule is a single asterisk, addresses that match the pattern and flags are not rewritten, and no subsequent rewriting rules are scanned. For example,

hatta@lookingglass.fict.book  *  f

specifies that hatta@lookingglass.fict.book is never to be rewritten in From: headers.

Otherwise, the replacement string is expanded and must yield a fully qualified address. Within the expansion, the variables $local_part and $domain refer to the address that is being rewritten. Any letters they contain retain their original case -- they are not lower cased. The numerical variables are set up according to the type of pattern that matched the address, as described above. If the expansion is forced to fail by the presence of `fail' in a conditional or lookup item, rewriting by the current rule is abandoned. Any other expansion failure causes the entire rewriting operation to be abandoned, and an entry written to the panic log.

34.5 Rewriting flags

There are four different kinds of flag that may appear on rewriting rules:

For rules that are part of the headers_rewrite generic transport option, E, F, T, S, and X are not permitted.

34.6 Flags specifying which headers and envelope addresses to rewrite

If none of the following flag letters, nor the `S' flag (see section 34.7) are present, a main rewriting rule applies to all headers and to both the sender and recipient fields of the envelope, whereas a transport-time rewriting rule just applies to all headers. Otherwise, the rewriting rule is skipped unless the relevant addresses are being processed.

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.

34.7 The SMTP-time rewriting flag

The rewrite flag `S' specifies a rewrite of incoming envelope addresses at SMTP time, as soon as an address is received in a MAIL or RCPT command, and before any other processing; even before syntax checking. The pattern is required to be a regular expression, and it is matched against the whole of the data for the command, including any surrounding angle brackets. This form of rewrite rule allows for the handling of addresses that are not compliant with RFCs 821 and 822 (for example, `bang paths' in batched SMTP input). Because the input is not required to be a syntactically valid address, the variables $local_part and $domain are not available during the expansion of the replacement string. The result of rewriting replaces the original address in the MAIL or RCPT command.

34.8 Flags controlling the rewriting process

There are four flags which control the way the rewriting process works. These take effect only when a rule is invoked, that is, when the address is of the correct type (matches the flags) and matches the pattern.

34.9 The additional relay checking flag

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

34.10 Rewriting examples

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 bctfrF

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.

The first example above replaces the domain with a superior, more general domain. This may not be desirable for certain local parts. If the rule

root@*.hitch.book.fict  *

were inserted as the first rule, rewriting would be suppressed for the local part root at any domain ending in hitch.book.fict.

Rewriting can be made conditional on a number of tests, by making use of ${if in the expansion item. For example, to apply a rewriting rule only to messages that originate outside the local host:

*@*.hitch.book.fict  "${if !eq {$sender_host_address}{}\
                      {$1@hitch.book.fict}fail}"

The replacement string is quoted in this example because it contains white space.

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'. However, there is a security implication in doing this as a normal rewriting rule for envelope addresses. It can provide a backdoor method for using your system as a relay, since the incoming addresses appear to be local. If the bang path addresses are received via SMTP, it is safer to use the `S' flag to rewrite them as they are received, so that relay checking can be done on the rewritten addresses.


Go to the first, previous, next, last section, table of contents.