Exim 4.10 Specification chapter 37

Previous Next Contents (Exim 4.10 Specification)

# 37. Access control lists

Access Control Lists (ACLs) are defined in a separate section of the run time configuration file, headed by ``begin acl''. Each ACL definition starts with a name, terminated by a colon. Here is a complete ACL section which contains just one very small ACL:

      begin acl

      small_acl:
        accept   hosts = one.host.only

You can have as many lists as you like in the ACL section, and the order in which they appear does not matter. The lists are self-terminating.

ACLs are used to control Exim's behaviour when it receives certain SMTP commands. This applies both to incoming TCP/IP connections, and when a local process submits a message over a pipe (using the -bs option). The most common use is for controlling which recipients are accepted in incoming messages. The default configuration file contains an example of a realistic ACL. This is discussed in chapter 7. The -bh command line option provides a way of testing your ACL configuration by running a fake SMTP session.

In order to cause an ACL to be used, you have to name it in one of the relevant options in the main part of the configuration. These options are:

``acl_smtp_auth`` | ACL for AUTH
``acl_smtp_data`` | ACL after DATA
``acl_smtp_etrn`` | ACL for ETRN
``acl_smtp_expn`` | ACL for EXPN
``acl_smtp_rcpt`` | ACL for RCPT
``acl_smtp_vrfy`` | ACL for VRFY

For example, if you set

      acl_smtp_rcpt = small_acl

the little ACL defined above is used whenever Exim receives a RCPT command in an SMTP dialogue. The majority of policy tests on incoming messages can be done when RCPT commands arrive. A rejection of RCPT should cause the sending MTA to give up on the recipient address contained in the RCPT command.

You cannot test the contents of the message, for example, to verify addresses in the headers, at RCPT time. Such tests have to appear in the ACL that is run after the message has been received, before the final response to the DATA command is sent. This is the ACL specified by `acl_smtp_data`. At this time, it is no longer possible to reject individual recipients. An error response should reject the entire message. Unfortunately, it is known that some MTAs do not treat hard (5xx) errors correctly at this point - they keep the message on their queues and try again later, but that is their problem, though it does waste some of your resources.

## 37.1. ACL return codes

The result of running an ACL is either ``accept'' or ``deny'', or, if some test cannot be completed (for example, if a database is down), ``defer''. These results cause 2xx, 5xx, and 4xx return codes, respectively, to be used in the SMTP dialogue. A fourth return, ``error'', occurs when there is an error such as invalid syntax in the ACL. This also causes a 4xx return code.

## 37.2. Unset ACL options

The default actions when any of the `acl_smtp_xxx` options are unset are not all the same. If `acl_smtp_auth` is not defined, AUTH is always accepted (and an attempt is made to authenticate the connection). If `acl_smtp_data` is not defined, no checks are done after a message has been received (at the end of the DATA phase).

However, if any of the other options are not defined, the relevant SMTP command is rejected. In particular, this means that `acl_smtp_rcpt` must be defined in order to receive any messages over an SMTP connection. The default configuration file contains a suggested ACL which is set up for `acl_smtp_rcpt`.

## 37.3. Data for message ACLs

When an ACL for RCPT or DATA is being run, the variables that contain information about the host and the message's sender (for example, `$sender_host_address` and `$sender_address`) are set, and can be used in ACL statements. In the case of RCPT (but not DATA), `$domain` and `$local_part` are set from the argument address.

The `$message_size` variable is set to the value of the SIZE parameter on the MAIL command at RCPT time, or -1 if that parameter was not given. Its value is updated to the true message size by the time the ACL after DATA is run.

The `$rcpt_count` variable increases by one for each RCPT command received. The `$recipients_count` variable increases by one each time a RCPT command is accepted, so while an ACL for RCPT is being processed, it contains the number of previously accepted recipients. At DATA time, `$rcpt_count` contains the total number of RCPT commands, and `$recipients_count` contains the total number of accepted recipients.

## 37.4. Data for non-message ACLs

When an ACL for AUTH, ETRN, EXPN, or VRFY is being run, the remainder of the SMTP command line is placed in `$smtp_command_argument`. This can be tested using a `condition` condition. For example, here is an ACL for use with AUTH, which insists that either the session is encrypted, or the CRAM-MD5 authentication method is used. In other words, it does not permit authentication methods that use cleartext passwords on unencrypted connections.

      acl_check_auth:
        accept encrypted = *
        accept condition = ${if eq{${uc:$smtp_command_argument}}\
                            {CRAM-MD5}{yes}{no}}
        deny   message   = TLS encryption or CRAM-MD5 required

## 37.5. Use of the ACL selection options

The value of an `acl_smtp_xxx` option is expanded before use, so you can use different ACLs in different circumstances, and in fact the resulting string does not have to be the name of a configured list. Having expanded the string, Exim searches for an ACL as follows:

- If the string begins with a slash, Exim attempts to open the file and read its contents as an ACL. If the file does not exist or cannot be read, an error occurs (typically causing a temporary failure of whatever caused the ACL to be run). If an ACL is successfully read from a file, it is retained in memory, so that it can be re-used without actually having to re-read the file. For example:

        acl_smtp_data = /etc/acls/\
          ${lookup{$sender_host_address}lsearch\
          {/etc/acllist}{$value}{default}}

  This looks up an ACL file to use on the basis of the host's IP address, falling back to a default if the lookup fails.

- If the string does not start with a slash, and does not contain any spaces, Exim searches the ACL section of the configuration for a list whose name matches the string.

- If no named ACL is found, or if the string contains spaces, Exim parses the string as an inline ACL. This can save typing in cases where you just want to have something like

        acl_smtp_vrfy = accept

  in order to allow free use of the VRFY command.

## 37.6. Format of an ACL

An individual ACL consists of a number of statements. Each statement starts with a verb, optionally followed by a number of conditions and other modifiers. If all the conditions are met, the verb is obeyed. If there are no conditions, the verb is always obeyed. What happens if any of the conditions are not met depends on the verb (and in one case, on a special modifier). Not all the conditions make sense at every testing point. For example, you cannot test a sender address in the ACL that is run for a VRFY command.

The verbs are as follows:

- `accept`: If all the conditions are met, the ACL returns ``accept''. If any of the conditions are not met, what happens depends on whether `endpass` appears among the conditions (for syntax see below). If the failing condition precedes `endpass`, control is passed to the next ACL statement; if it follows `endpass`, the ACL returns ``deny''. Consider this statement, used to check a RCPT command:

        accept domains = +local_domains
               endpass
               verify = recipient

  If the recipient domain does not match the `domains` condition, control passes to the next statement. If it does match, the recipient is verified, and the command is accepted if verification succeeds. However, if verification fails, the ACL yields ``deny'', because the failing condition is after `endpass`.

- `deny`: If all the conditions are met, the ACL returns ``deny''. If any of the conditions are not met, control is passed to the next ACL statement. For example,

        deny dnslists = blackholes.mail-abuse.org

  rejects commands from hosts that are on a DNS black list.

- `require`: If all the conditions are met, control is passed to the next ACL statement. If any of the conditions are not met, the ACL returns ``deny''. For example, when checking a RCPT command,

        require verify = sender

  passes control to subsequent statements only if the message's sender can be verified. Otherwise, it rejects the command.

- `warn`: If all the conditions are met, some warning action is taken. In all cases, control passes to the next ACL statement. In the case of testing an incoming message, the warning action consists of adding header lines to the message, and/or writing an entry in the main log. Additional header lines are specified by the `message` modifier, as in this example:

        warn message = X-blacklisted-at: $dnslist_domain
             dnslists = blackholes.mail-abuse.org : \
                        dialup.mail-abuse.org

  If the same header line is requested several times (provoked, for example, by multiple RCPT commands), only one copy is actually added to the message. Header lines that are added by an ACL at RCPT time are visible in string expansions in the ACL that is run after DATA.

  Log lines are specified by the `log_message` modifier. For ACLs that are not concerned with incoming messages, only the logging action is available.

  If any condition on a `warn` statement cannot be completed (that is, there is some sort of defer), the warning action does not take place. The incident is logged, but the ACL continues to be processed.

At the end of each ACL there is an implicit unconditional `deny`.

As you can see from the examples above, the conditions and modifiers are written one to a line, with the first one on the same line as the verb, and subsequent ones on following lines. If you have a very long condition, you can continue it onto several physical lines by the usual \ continuation mechanism. It is conventional to align the conditions vertically.

## 37.7. Condition and modifier processing

An exclamation mark preceding a condition negates its result. For example,

      deny   domains = *.dom.example
            !verify = recipient

causes the ACL to return ``deny'' if the recipient domain ends in dom.example, but the recipient address cannot be verified.

The arguments of conditions and modifiers are expanded. A forced failure of an expansion causes a condition to be ignored, that is, it behaves as if the condition is true. Consider these two statements:

      accept  senders = ${lookup{$host_name}lsearch\
                        {/some/file}{$value}fail}
      accept  senders = ${lookup{$host_name}lsearch\
                        {/some/file}{$value}{}}

Each attempts to look up a list of acceptable senders. If the lookup succeeds, the returned list is searched, but if the lookup fails the behaviour is different in the two cases. The `fail` in the first statement causes the condition to be ignored, leaving no further conditions. The `accept` verb therefore succeeds. The second statement, however, generates an empty list when the lookup fails. No sender can match an empty list, so the condition fails and therefore the `accept` also fails.

## 37.8. ACL modifiers

The ACL modifiers are `endpass`, `log_message`, and `message`. They operate as follows:

endpass

This modifier, which has no argument, is recognized only in `accept` statements. It marks the boundary between the conditions whose failure causes control to pass to the next statement, and the conditions whose failure causes the ACL to return ``deny''. See the description of `accept` above.

log_message = <text>

This modifier sets up a message which is used as part of the log message if the ACL denies access because of a subsequent condition in the current statement. For example:

      require log_message = wrong cipher suite $tls_cipher
              encrypted   = DES-CBC3-SHA

`log_message` adds to any underlying error message that may exist because of the condition. For example, while verifying a recipient address, a :fail: redirection might have already set up a message. Although the message is defined before the conditions to which it applies, the expansion does not happen until after a condition has failed. This means that any variables that are set by the condition are available for inclusion in the message. For example, the `$dnslist_<xxx>` variables are set after a DNS black list lookup succeeds. If `log_message` is used with a `warn` statement, ``Warning:'' is added to the start of the message.

message = <text>

This modifier sets up a message which is used as an error message if a subsequent condition in the current statement causes the ACL to deny access. The message is returned as part of the SMTP response. For example:

      deny message = Relaying denied
           domains = !+relay_domains

The text is literal; any quotes are taken as literals, but because it is expanded, backslash escapes are processed anyway. If the message contains newlines, this gives rise to a multi-line SMTP response. Like `log_message`, the contents of `message` are not expanded until after a condition has failed.

If `message` is used on a statement that verifies an address, the message specified overrides any message that is generated by the verification process. However, the original message is available in the variable `$acl_verify_message`, so you can incorporate it into your message if you wish. In particular, if you want the text from `:fail:` items in redirect routers to be passed back as part of the SMTP response, you should either not use a `message` modifier, or make use of `$acl_verify_message`.

If `message` is used with `warn`, it causes a header line to be added an incoming message; for non-message ACLs, it has no effect with `warn`.

If `log_message` is not present but `message` is present, the `message` text is used for logging. However, if it contains newlines, only the first line of the text is logged. In the absence of both `log_message` and `message`, a default built-in message is used. Neither `log_message` nor `message` are used if they are empty strings, or if their expansions fail.

## 37.9. ACL conditions

Not all conditions are relevant in all circumstances. For example, testing senders and recipients does not make sense in an ACL that is being run as the result of the arrival of an ETRN command, and checks on message headers can be done only in the ACL specified by `acl_smtp_data`.

The conditions are:

acl = <name of acl or ACL string or file name >

The possible values of the argument are the same as for the `acl_smtp_xxx` options. The named or inline ACL is run. If it returns ``accept'' the condition is true; if it returns ``deny'' the condition is false; if it returns ``defer'', the current ACL returns ``defer''. ACLs may be nested up to 20 deep; the limit exists purely to catch runaway loops.

This condition allows you to use different ACLs in different conditions. For example, different ACLs can be used to handle RCPT commands for different local users or different local domains.

authenticated = <string list>

If the SMTP connection is not authenticated, the condition is false. Otherwise, the name of the authenticator is tested against the list. To test for authentication by any authenticator, you can set

      authenticated = *

condition = <string>

This feature allows you to make up custom conditions. If the result of expanding the string is an empty string, the number zero, or one of the strings ``no'' or ``false'', the condition is false. If the result is any non-zero number, or one of the strings ``yes'' or ``true'', the condition is true. For any other values, some error is assumed to have occured, and the ACL returns ``defer''.

dnslists = <list of domain names and other data>

This condition checks for entries in DNS black lists. These are also known as ``RBL lists'', after the original Realtime Blackhole List, but note that the use of the lists at mail-abuse.org now carries a charge. In its simplest form, the `dnslists` condition tests whether the calling host is on a DNS black list by looking up the inverted IP address in one or more DNS domains. For example, if the calling host's IP address is 192.168.62.43, and the ACL statement is

      deny dnslists = blackholes.mail-abuse.org : \
                      dialups.mail-abuse.org

the following domains are looked up:

      43.62.168.192.blackholes.mail-abuse.org
      43.62.168.192.dialups.mail-abuse.org

If a DNS lookup times out or otherwise fails to give a decisive answer, Exim behaves as if the host is not on the relevant list. This is usually the required action when `dnslists` is used with `deny` (which is the most common usage), because it prevents a DNS failure from blocking mail. However, you can change this behaviour by putting one of the following special items in the list:

`` `+include_unknown` behave as if the item is on the list
`` `+exclude_unknown` behave as if the item is not on the list (default)
`` `+defer_unknown` give a temporary error

Each of these applies to any subsequent items on the list. For example:

      deny dnslists = +defer_unknown : foo.bar.example

Testing the list of domains stops as soon as a match is found. If you want to warn for one list and block for another, you can use two different statements:

      deny  dnslists = blackholes.mail-abuse.org
      warn  dnslists = dialups.mail-abuse.org

There are some lists which are keyed on domain names rather than inverted IP addresses (see for example the domain based zones link at http://www.rfc-ignorant.org/). You can change the name that is looked up by adding additional data to a `dnslists` item, introduced by a slash. For example,

      deny  message  = Sender's domain is listed at $dnslist_domain
            dnslists = dsn.rfc-ignorant.org/$sender_address_domain

This particular example is useful only in ACLs that are obeyed after the RCPT or DATA commands, when a sender address is available. If (for example) the message's sender is user@tld.example the name that is looked up is

      tld.example.dsn.rfc-ignorant.org

You can mix entries with and without additional data in the same `dnslists` condition.

When an entry is found in a DNS black list, the variable `$dnslist_domain` contains the name of the domain which matched, `$dnslist_value` contains the data from the entry, and `$dnslist_text` contains the contents of any associated TXT record. You can use these variables in `message` or `log_message` modifiers - although these appear before the condition in the ACL, they are not expanded until after it has failed. For example:

      deny    hosts = !+local_networks
              message = $sender_host_address is listed \
                        at $dnslist_domain
              dnslists = rbl-plus.mail-abuse.example

DNS black list lookups are cached by Exim for the duration of the SMTP session, so a lookup based on the IP address is done at most once for any incoming connection. Exim does not share information between multiple incoming connections (but your local name server cache should be active).

DNS black lists are constructed using address records in the DNS. The original RBL just used the address 127.0.0.1 on the right hand side of the records, but the RBL+ list and some other lists use a number of values with different meanings. The values used on the RBL+ list are:

127.1.0.1 | RBL
127.1.0.2 | DUL
127.1.0.3 | DUL and RBL
127.1.0.4 | RSS
127.1.0.5 | RSS and RBL
127.1.0.6 | RSS and DUL
127.1.0.7 | RSS and DUL and RBL

If you add an equals sign and an IP address after a `dnslists` domain name, you can restrict its action to DNS records with a matching right hand side. For example,

      deny dnslists = rblplus.mail-abuse.org=127.0.0.2

rejects only those hosts that yield 127.0.0.2. More than one address may be given, using a comma as a separator. These are alternatives - if any one of them matches, the RBL entry operates. If there are no addresses, any address record is considered to be a match.

If you want to specify a constraining address and also change the name that is looked up, the address list must be specified first. For example:

      deny dnslists = dsn.rfc-ignorant.org\
                      =127.0.0.2/$sender_address_domain

domains = <domain list>

This condition is relevant only after a RCPT command. It checks that the domain of the recipient address is in the domain list. If percent-hack processing is enabled, it is done before this test is done. If the check succeeds with a lookup, the result of the lookup is placed in `$domain_data` until the next `domains` test.

encrypted = <string list>

If the SMTP connection is not encrypted, the condition is false. Otherwise, the name of the cipher suite in use is tested against the list. To test for encryption without testing for any specific cipher suite(s), set

      encrypted = *

hosts = < host list>

This condition tests that the calling host matches the host list. If you have name lookups or wildcarded host names and IP addresses in the same host list, you should normally put the IP addresses first. For example, you could have:

      accept hosts = 10.9.8.7 : dbm;/etc/friendly/hosts

The reason for this lies in the left-to-right way that Exim processes lists. It can test IP addresses without doing any DNS lookups, but when it reaches an item that requires a host name, it fails if it cannot find a host name to compare with the pattern. If the above list is given in the opposite order, the `accept` statement fails for a host whose name cannot be found, even if its IP address is 10.9.8.7.

If you really do want to do the name check first, and still recognize the IP address even if the name lookup fails, you can rewrite the ACL like this:

      accept hosts = dbm;/etc/friendly/hosts
      accept hosts = 10.9.8.7

The default action on failing to find the host name is to assume that the host is not in the list, so the first `accept` statement fails. The second statement can then check the IP address.

local_parts = <local part list>

This condition is relevant only after a RCPT command. It checks that the local part of the recipient address is in the list. If percent-hack processing is enabled, it is done before this test. If the check succeeds with a lookup, the result of the lookup is placed in `$local_part_data` until the next `local_parts` test.

recipients = <address list>

This condition is relevant only after a RCPT command. It checks the entire recipient address against a list of recipients.

sender_domains = <domain list>

This condition tests the domain of the sender of the message against the given domain list.

senders = <address list>

This condition tests the sender of the message against the given list. To test for a bounce message, which has an empty sender, set

      senders = :

verify = certificate

This condition is true if the SMTP session is encrypted, and a certificate was received from the client, and the certificate was verified. The server requests a certificate only if the client matches `tls_verify_hosts` or `tls_try_verify_hosts` (see chapter 36).

verify = header_sender/<options>

This condition is relevant only in an ACL that is run after a message has been received, that is, in an ACL specified by `acl_smtp_data`. It checks that there is a verifiable sender address in at least one of the Sender:, Reply-To:, or From: header lines. Details of address verification and the options are given in the next section. You can combine this condition with the `senders` condition to restrict it to bounce messages only:

      deny    senders = :
              message = A valid sender header is required for bounces
             !verify  = header_sender

verify = header_syntax

This condition is relevant only in an ACL that is run after a message has been received, that is, in an ACL specified by `acl_smtp_data`. It checks the syntax of all header lines that can contain lists of addresses (Sender:, From:, Reply-To:, To:, Cc:, and Bcc:). This is a syntax check only. A common spamming ploy is to send syntactically invalid headers such as

      To: @

This condition can be used to reject such messages.

verify = helo

This condition is true if a HELO or EHLO command has been received from the client host, and its contents have been verified. Verification of these commands does not happen by default. See the description of the `helo_verify_hosts` and `helo_try_verify_hosts` options for details of how to request it.

verify = recipient/<options>

This condition is relevant only after a RCPT command. It verifies the current recipient. Details are given in the next section.

verify = reverse_host_lookup

This condition ensures that a verified host name has been looked up from the IP address of the client host. (This may have happened already if the host name was needed for checking a host list, or if the host matched `host_lookup`.) Verification ensures that the host name obtained from a reverse DNS lookup, or one of its aliases, does, when itself looked up in the DNS, yield the original IP address.

verify = sender/<options>

This condition is relevant only after a RCPT command, or after a message has been received. If the message's sender is empty (that is, this is a bounce message), the condition is true. Otherwise, the sender address is verified. Details of verification are given in the next section. Exim caches the result of sender verification, to avoid doing it more than once per message.

verify = sender=address/<options>

This is a variation of the previous option, in which a modified address is verified as a sender.

## 37.10. Address verification

Several of the `verify` conditions described in the previous section cause addresses to be verified. These conditions can be followed by a number of options that modify the verification process. The options are separated from the keyword and from each other by slashes. For example:

      verify = sender/callout
      verify = recipient/defer_ok/callout=10s/callout_defer_ok

The first stage of verification is to run the address through the routers, in ``verify mode''. Routers can detect the difference between verification and routing for delivery, and their actions can be varied by a number of generic options such as `verify` and `verify_only` (see chapter 14).

If there is a defer error while doing this verification routing, the ACL normally returns ``defer''. However, if you include `defer_ok` in the options, the condition is forced to be true instead.

For non-local addresses, routing verifies the domain, but is unable to do any checking of the local part. There are situations where some means of verifying the local part is desirable. One way this can be done is to make an SMTP callback to the sending host (for a sender address) or a callforward to a subsequent host (for a recipient address), to see if the host accepts the address. We use the term callout to cover both cases. This facility should be used with care, because it adds a lot of resource usage to the cost of verifying an address.

If the `callout` option is present on a condition that verifies an address, a second stage of verification occurs if the address is successfully routed to one or more remote hosts. Exim makes SMTP connections to the remote hosts, to test whether the address is acceptable. For a sender address, it behaves as if transmitting a bounce message and sends:

`` `HELO <primary host name>`
`` `MAIL FROM:<>`
`` `RCPT TO:<the address to be tested>`
`` `QUIT`

For a recipient address, the MAIL command contains the sender address of the message. If the response to the RCPT command is a 2xx code, the verification succeeds. If it is 5xx, the verification fails. For any other condition, Exim tries the next host, if any. If there is a problem with all the remote hosts, the ACL yields ``defer'', unless the `callout_defer_ok` option is given, in which case the condition is forced to succeed.

For SMTP callout connections, the port to connect to and the outgoing interface are taken from the transport to which address was routed, if it is a remote transport. Otherwise port 25 is used, and the interface is not specified.

The timeout that applies for the callout attempt to each host can be changed by specifying it on the `callout` option. For example:

      verify = sender/callout=5s

The default is 30 seconds.

## 37.11. Sender address verification reporting

When sender verification fails in an ACL, the details of the failure are given as additional output lines before the 550 response to the relevant SMTP command (RCPT or DATA). For example, if sender callout is in use, you might see:

      MAIL FROM:<xyz@abc.example>
      250 OK
      RCPT TO:<pqr@def.example>
      550-Verification failed for <xyz@abc.example>
      550-Called:   192.168.34.43
      550-Sent:     RCPT TO:<xyz@abc.example>
      550-Response: 550 Unknown local part xyz in <xyz@abc.example>
      550 Sender verification failed

If more than one RCPT command fails in the same way, the details are given only for the first of them. However, some administrators do not want to send out this much information. You can suppress the details by adding ``/no_details'' to the ACL statement that requests sender verification. For example:

      verify = sender/no_details

## 37.12. Redirection while verifying

A dilemma arises when a local address is redirected by aliasing or forwarding during verification: should the generated addresses themselves be verified, or should the successful expansion of the original address be enough to verify it? Exim takes the following pragmatic approach:

- When an incoming address is redirected to just one child address, verification continues with the child address, and if that fails to verify, the original verification also fails.

- When an incoming address is redirected to more than one child address, verification does not continue. A success result is returned.

This seems the most reasonable behaviour for the common use of aliasing as a way of redirecting different local parts to the same mailbox. It means, for example, that a pair of alias entries of the form

      A.Wol:   aw123
      aw123:   :fail: Gone away, no forwarding address

work as expected, with both local parts causing verification failure. When a redirection generates more than one address, the behaviour is more like a mailing list, where the existence of the alias itself is sufficient for verification to succeed.

## 37.13. Using an ACL to control relaying

An MTA is said to relay a message if it receives it from some host and delivers it directly to another host as a result of a remote address contained within it. Redirecting a local address via an alias or forward file and then passing the message on to another host is not relaying, but a redirection as a result of the ``percent hack'' is.

Two kinds of relaying exist, which are termed ``incoming'' and ``outgoing''. A host which is acting as a gateway or an MX backup is concerned with incoming relaying from arbitrary hosts to a specific set of domains. On the other hand, a host which is acting as a smart host for a number of clients is concerned with outgoing relaying from those clients to the Internet at large. Often the same host is fulfilling both functions, as illustrated in the diagram below, but in principle these two kinds of relaying are entirely independent. What is not wanted is the transmission of mail from arbitrary remote hosts through your system to arbitrary domains.

You can implement relay control by means of suitable statements in the ACL that runs for each RCPT command. For convenience, it is often easiest to use Exim's named list facility to define the domains and hosts involved. For example, suppose you want to do the following:

- Deliver a number of domains to mailboxes on the local host (or process them locally in some other way). Let's say these are my.dom1.example and my.dom2.example.

- Relay mail for a number of other domains for which you are the secondary MX. These might be friend1.example and friend2.example.

- Relay mail from the hosts on your local LAN, to whatever domains are involved. Suppose your LAN is 192.168.45.0/24.

In the main part of the configuration, you put the following definitions:

      domainlist local_domains = my.dom1.example : my.dom2.example
      domainlist relay_domains = friend1.example : friend2.example
      hostlist   relay_hosts   = 192.168.45.0/24

Now you can use these definitions in the ACL that is run for every RCPT command:

      acl_check_rcpt:
        accept domains = +local_domains : +relay_domains
        accept hosts   = +relay_hosts

The first statement accepts any RCPT command that contains an address in the local or relay domains. For any other domain, control passes to the second statement, which accepts the command only if it comes from one of the relay hosts. In practice, you will probably want to make your ACL more sophisticated than this, for example, by including sender and recipient verification. The default configuration includes a more comprehensive example, which is described in chapter 7.

Previous Next Contents (Exim 4.10 Specification)