The Exim FAQ

Contents   Previous   Next

3. ROUTING TO REMOTE HOSTS

Q0301:  What do lowest numbered MX record points to local host and remote host address is the local host mean?

A0301:  They mean exactly what they say. Exim expected to route an address to a remote host, but the IP address it obtained from a router was for the local host. If you really do want to send over TCP/IP to the local host (to a different version of Exim or another MTA, for example), see Q0206.

More commonly, these errors arise when Exim thinks it is routing some foreign domain. For example, the router configuration causes Exim to look up the domain in the DNS, but when Exim examines the DNS output, either the lowest numbered MX record points at the local host, or there are no MX records, and the address record for the domain contains an IP address that belongs to the local host.

There has been a rash of instances of domains being deliberately set up with MX records pointing to localhost (or other names with A records that specify 127.0.0.1), which causes this behaviour. You can use the ignore_target_hosts option to get Exim to ignore these records. The default contiguration does this. For other cases:

(1)  If the domain is meant to be handled as a local domain, there is a problem with the configuration, because it should not then have been looked up in the DNS. Check the domains settings on your routers.

(2)  If the domain is one for which the local host is providing a relaying service (called ``mail hubbing''), possibly as part of a firewall, you need to set up a router to tell Exim where to send messages addressed to this domain, because the DNS directs them to the local host. You should put a router like this one before the one that does DNS lookups:

   hubbed_hosts:
     driver = manualroute
     transport = remote_smtp
     route_list = see discussion below

The contents of the route_list option depend on how many hosts you are hubbing for, and how their names are related to the domain name. Suppose the local host is a firewall, and all the domains in *.foo.bar have MX records pointing to it, and each domain corresponds to a host of the same name. Then the setting could be

   route_list = *.foo.bar $domain

If there isn't a convenient relationship between the domain names and the host names, you either have to list each domain separately, or use a lookup expansion to look up the host from the domain, or put the routing information in a file and use the route_data option with a lookup expansion.

(3)  If neither (1) nor (2) is the case, the lowest numbered MX record or the address record for the domain should not be pointing to your host. You should arrange to get the DNS mended.

Q0302:  Why does Exim say all relevant MX records point to non-existent hosts when MX records point to IP addresses?

A0302:  MX records cannot point to IP addresses. They are defined to point to host names, so Exim always interprets them that way. (An IP address is a syntactically valid host name.) The DNS for the domain you are having problems with is misconfigured.

However, it appears that more and more DNS zones are breaking the rules and putting IP addresses on the RHS of MX records. Exim follows the rules and rejects this, but other MTAs do support it, so the allow_mx_to_ip was regretfully added at release 3.14 to permit this heinous activity.

Q0303:  How do I configure Exim to send all messages to a central server? I don't want to do any local deliveries at all on this host.

A0303:  Use this as your first and only router:

   send_to_gateway:
     driver = manualroute
     transport = remote_smtp
     route_list = * central.server.host

Q0304:  How do I configure Exim to send all non-local mail to a gateway host?

A0304:  Replace the dnslookup router in the default configuration with the following:

   send_to_gateway:
     driver = manualroute
     domains = !+local_domains
     transport = remote_smtp
     route_list = * gate.way.host

If there are several hosts you can send to, you can specify them as a colon-separated list.

Q0305:  How can I arrange for mail on my local network to be delivered directly to the relevant hosts, but all other mail to be sent to my ISP's mail server? The local hosts are all DNS-registered and behave like normal Internet hosts.

A0305:  Set up a first router to pick off all the domains for your local network. There are several ways you might do this. For example

   local_network:
     driver = dnslookup
     transport = remote_smtp
     domains = *.mydomain.com

This does a perfectly conventional DNS routing operation, but only for the domains that match *.mydomain.com. Follow this with a `smart host' router:

   internet:
     driver = manualroute
     domains = !+local_domains
     transport = remote_smtp
     route_list = * mail.isp.net

This routes any other non-local domains to the smart host.

Q0306:  How do I configure Exim to send all non-local mail to a central server if it cannot be immediately delivered by my host? I don't want to have queued mail waiting on my host.

A0306:  Add to the remote_smtp transport the following:

   fallback_hosts = central.server.name(s)

If there are several names, they must be separated by colons.

Q0307:  The route_list setting ^foo$:^bar$ $domain in a manualroute router does not work.

A0307:  The first thing in a route_list item is a single pattern, not a list of patterns. You need to write that as ^(foo|bar)$ $domain. Alternatively, you could use several items and write

   route_list = foo $domain; bar $domain

Note the semicolon separator. This is because the second thing in each item can itself be a list - of hosts.

Q0308:  I have a domain for which some local parts must be delivered locally, but the remainder are to be treated like any other remote addresses.

A0308:  One possible way of doing this is as follows: Assuming you are using a configuration that is similar to the default one, first exclude your domain from the first router by changing it to look like this:

   non_special_remote:
     driver = dnslookup
     domains = ! +local_domains : ! special.domain
     transport = remote_smtp
     ignore_target_hosts = 127.0.0.0/8
     no_more

Then add a second router which handles the local parts that are not to be delivered locally:

   special_remote:
     driver = dnslookup
     domains = special.domain
     local_parts = ! lsearch;/list/of/special/localparts
     transport = remote_smtp
     ignore_target_hosts = 127.0.0.0/8
     no_more

The remaining local parts will fall through to the remaining routers, which can delivery them locally.

Q0309:  How can I configure Exim on a firewall machine so that if mail arrives addressed to a domain whose MX points to the firewall, it is forwarded to the internal mail server, without having to have a list of all the domains involved?

A0309:  As your first router, have the standard dnslookup router from the default configuration, with the added option

   self = pass

This will handle all domains whose lowest numbered MX records do not point to your host. Because of the no_more setting, if it encounters an unknown domain, routing will fail. However, if it hits a domain whose lowest numbered MX points to your host, the self option comes into play, and overrides no_more. The pass setting causes it to pass the address on to the next router. (The default causes it to generate an error.)

The only non-local domains that reach the second router are those with MX records pointing to the local host. Set it up to send them to the internal mail server like this:

   internal:
     driver = manualroute
     domains = ! +local_domains
     transport = remote_smtp
     route_list = * internal.server

Q0310:  If a DNS lookup returns no MX records why doesn't Exim just bin the message?

A0310:  If a DNS lookup returns no MXs, Exim looks for an address record, in accordance with the rules that are defined in the RFCs. If you want to break the rules, you can set mx_domains in the dnslookup router, but you will cut yourself off from those sites (and there still seem to be plenty) who do not set up MX records.

Q0311:  When a DNS lookup for MX records fails to complete, why doesn't Exim send the messsage to the host defined by the A record?

A0311:  The RFCs are quite clear on this. Only if it is known that there are no MX records is an MTA allowed to make use of the A record. When an MX lookup fails to complete, Exim does not know whether there are any MX records or not. There seem to be some name servers (or some configurations of some name servers) that give a ``server fail'' error when asked for a non-existent MX record. Exim uses standard resolver calls, which unfortunately do not distinguish between this case and a timeout, so all Exim can do is try again later.

Q0312:  Is it possible to use a conditional expression for the host item in a route_list for manualroute router? I tried the following, but it doesn't work:

   route_list = * ${if match{$header_from:}{\N.*\.usa\.net$\N} \
                {<smarthost1>}{<smarthost2>}

A0312:  The problem is that the second item in route_list contains white space, which means that it gets terminated prematurely. To avoid this, you must put the second item in quotes:

   route_list = * "${if match{$header_from:}{\N.*\.usa\.net$\N} \
                {<smarthost1>}{<smarthost2>}}"

Q0313:  I send all external mail to a smart host, but this means that bad addresses also get passed to the smart host. Can I avoid this?

A0313:  Assuming you have DNS availability, set up a conventional dnslookup router to do the routing, but in the remote_smtp transport set this:

   hosts = your.smart.host
   hosts_override

This will override the hosts that the router finds so that everything goes to the smart host, but any non-existent domains will be failed by the router.

Q0314:  I have a really annoying intermittent problem where attempts to mail to valid sites are rejected with unknown mail domain. This only happens a few times a day and there is no particular pattern to the sites it rejects. If I try to lookup the same domain a few minutes later then it is OK.

A0314:  This is almost certainly a problem with the DNS resolver or the the domain's name servers.

(1)  Have you linked Exim against the newest DNS resolver library that comes with Bind? If you are using SunOS4 that may be your problem, as the resolver that comes with that OS is known to be buggy and to give intermittent false negatives.

(2)  Effects like this are sometimes seen if a domain's name servers get out of step with each other.

Q0315:  I'd like route all mail with addresses that can't be resolved (the DNS lookup times out) to a relay machine.

A0315:  Set pass_on_timeout on your dnslookup router, and add below it a manualroute router that routes all relevant domains to the relay.

Q0316:  I would like to forward all incoming email for a particular domain to another host via SMTP. Whereabouts would I configure that?

A0316:  Use this as your first router:

   special:
     driver = manualroute
     transport = remote_smtp
     route_list = the.particular.domain the.other.host

You will also need to adjust the ACL for incoming SMTP so that this domain is accepted for relaying. If you are using the default configuration, there is a domain list called relay_domains that is set up for this.

Q0317:  What I'd like to do is have alternative smart hosts, where the one to be used is determined by which ISP I'm connected to.

A0317:  The simplest way to do this is to arrange for the name of the smart host du jour to be placed in a file when you connect, say /etc/smarthost. Then you can read this file from a manualroute router like this:

   smarthost:
     driver = manualroute
     transport = remote_smtp
     route_list = * ${readfile{/etc/smarthost}{}}

The second argument of the readfile item is a string that replaces any newline characters in the file (in this case, with nothing). By keeping the data out of the main configuration file, you avoid having to HUP the daemon when it changes.

Q0318:  Exim won't route to a host with no MX record.

A0318:  More than one thing may cause this.

(1)  Are you sure there really is no MX record? Sometimes a typo results in a malformed MX record in the zone file, in which case some name servers give a SERVFAIL error rather than NXDOMAIN. Exim has to treat this as a temporary error, so it can't go on to look for address records. You can check for this state using one of the DNS interrogation commands, such as nslookup, host, or dig.

(2)  Is there a wildcard MX record for your domain? Is the search_parents option on in your dnslookup router? If the answer to both these questions is ``yes'', that is the cause of the problem. When the DNS resolver fails to find the MX record, it tries adding on your domain if search_parents is true, and thereby finds your wildcard MX record. For example:

. There is a wildcard MX record for *.a.b.c.

. There is a host called x.y.z that has an A record and no MX record.

. Somebody on the host m.a.b.c domain tries to mail to user@x.y.z.

. Exim calls the DNS to look for an MX record for x.y.z.

. The DNS doesn't find any MX record. Because search_parents is true, it then tries searching the current host's parent domain, so it looks for x.y.z.a.b.c and picks up the wildcard MX record.

Setting search_parents false makes this case work while retaining the wildcard MX record. However, anybody on the host m.a.b.c who mails to user@n.a (expecting it to go to user@n.a.b.c) now has a problem. The widen_domains option of the dnslookup router may be helpful in this circumstance.

Q0319:  I have some mails on my queues that are sticking around longer than the retry time indicates they should. They are all getting frozen because some remote admin has set their MX record to 127.0.0.1.

A0319:  The admin in question is an idiot. Exim will always freeze such messages because they are apparently routed to the local host. To bounce these messages immediately, set

   ignore_target_hosts = 127.0.0.1

on the dnslookup router. This causes Exim to completely ignore any hosts with that IP address.

Q0320:  How can I arrange for all mail to user@some.domain to be forwarded to user@other.domain?

A0320:  Put this as your first router:

   forward:
     driver = redirect
     domains = some.domain
     data = ${quote:$local_part}@other.domain


Contents   Previous   Next