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

Verification of incoming mail

Exim always checks the syntax of SMTP commands, and rejects any that are invalid. There are a number of options that cause Exim to verify the semantic validity of the data in an incoming SMTP message. Verification failures can cause the message to be rejected, or they can just be logged. Other types of control over incoming mail are discussed in subsequent chapters. The `-bh' command line option can be used to run fake SMTP sessions for the purpose of testing verification options.

Host verification

The name of the sending host is looked up using `gethostbyaddr()' if its IP address matches one of the networks specified in `host_lookup_nets' (which is unset in the Exim binary, but in the default configuration file is set to match all hosts). In some environments this might involve an expensive DNS lookup, so some sites may wish to disable it. However, an SMTP server for local desktop systems (which are frequently misconfigured) can normally look up their host names cheaply. This improves the contents of Exim's logs by including the correct host names.

Even if its address doesn't match `host_lookup_nets', a sending host's real name is looked up from its IP address if the argument it provides for the HELO or EHLO command is the local host's own name, or the name of one of its local domains, which seems to be a fairly common misconfiguration.

A host name that is obtained from looking up the sender's IP address is placed in the `$sender_host_name' variable. If no lookup was done, or if the lookup failed, that variable is left empty. Failure to look up the sending host's name is not of itself an error, nor is it by default an error for the name given in the HELO or EHLO command (which is placed in `$sender_helo_name') to be different.

The RFCs specifically state that mail should not be refused on the basis of the the content of the HELO or EHLO commands. However, there are installations that do want to be strict in this area, and to support them, Exim has the `helo_verify' option. Even when this is not set, Exim checks the syntax of the commands, and rejects them if there are syntax errors. It can be made less strict by unsetting `helo_strict_syntax' (which allows underscores to get through) or by setting `helo_accept_junk_hosts' or `helo_accept_junk_nets' (which permit certain hosts to send any old junk).

When `helo_verify' is set, a HELO or EHLO command must precede any MAIL commands in an incoming SMTP connection. If there wasn't one, all MAIL commands are rejected with a permanent error code. In addition, the argument supplied by HELO or EHLO is verified. If it is in the form of a literal IP address in square brackets, it must match the actual IP address of the sending host. If it is a domain name, then the sending host's name is looked up from its IP address (whether or not it matches `host_lookup_nets') and compared against it. If the comparison fails, the IP addresses associated with the HELO or EHLO name are looked up using `gethostbyname()' and compared against the sending host's IP address. If none of them match, the HELO or EHLO command is rejected with a permanent error code, and an entry is written in the main and reject logs.

Sender verification

When the `sender_verify' configuration option is set, Exim checks the senders of incoming SMTP messages, that is, the addresses given in the SMTP MAIL FROM commands. This applies to batch as well as normal SMTP input, unless `sender_verify_batch' is set false.

The check is performed by running the same verification code as is used then Exim is called with the `-bv' option. The check is performed when the MAIL FROM command is received. If the address cannot immediately be verified (typically because of DNS timeouts), a temporary failure error response (code 451) is given to the MAIL FROM command, unless `sender_try_verify' is set, in which case the message is accepted with a warning message.

What happens if verification fails depends on the setting of the `sender_verify_reject' option. If it is set (the default) then the message is rejected. Otherwise a warning message is logged, and processing continues.

Because remote postmasters always want to see the message headers when there is a problem, Exim does not give an error response immediately a sender address fails (permanently or temporarily), but instead it reads the data for the message first. The headers of rejected messages are written to the reject log, for use in tracking down the problem or tracing mail abusers. Up to three envelope recipients are also logged with the headers.

Unfortunately, there are a number of mailers in use that treat any SMTP error response given after the data has been transmitted as a temporary failure. Exim sends code 554 when it rejects a message because of a bad sender, and RFC 821 is quite clear in stating that all codes starting with 5 are always `permanent negative completion' replies. However, it does not give any guidance as to what should be done on receiving such replies, and some mailers persist in trying to send messages when they receive such a code at the end of the data.

To get round this, Exim keeps a database in which it remembers the bad sender address and host name when it rejects a message. If the same host sends the same bad sender address within 24 hours, Exim rejects the message at the MAIL FROM stage, before it reads the data for the message. This should prevent the sender from trying to send the message again, but there seem to be plenty of broken mailers out there that do keep on trying, sometimes for days on end.

In an attempt to shut such MTAs up, if the same host sends the same bad sender for a third time within 24 hours, MAIL FROM is accepted, but all subsequent RCPT TO commands are rejected with a 550 error code. This means `unknown user' and if a remote mailer doesn't treat that as a hard error, it is very seriously broken.

The `sender_verify_except_hosts' and `sender_verify_except_nets' options can be used to specify hosts and RFC 1413 idents or IP networks for which sender verification is not applied. If a cluster of hosts all check incoming external messages, there is no need to waste effort checking mail sent between them. For example:

sender_verify_except_hosts = "*.ref.book:exim@mailer.fict.book"

Fixing bad senders

It is unfortunately the case that lots of messages are sent out onto the Internet with invalid senders. In some cases, the message itself contains a valid return address in one of its headers. If the `sender_verify_fixup' option is set as well as `sender_verify', Exim does not reject a message if the sender is invalid, provided it can find a `Sender:', `Reply-to:', or `From:' header containing a valid address. Instead, it replaces the sender with the valid address, and records the fact that it has done so by adding a header of the form:

X-BadReturnPath: <invalid address> rewritten using <name> header

If there are several occurrences of any of the relevant headers, they are all checked. If any `Resent-' headers exist, it is those headers that are checked rather than the original ones.

The fixup happens for both permanent and temporary errors. This covers the case when the bad addresses refer to some DNS zone whose nameservers are unreachable. This approach is, of course, fixing the symptom and not the disease.

If `sender_verify_fixup' is set when `sender_verify_reject' is false, Exim does not modify the message, but records in the log the fixup it would have made.

Header verification

Exim's sender verification options can be used to block messages with bad envelope senders. However, if a message arrives with a null envelope sender, that is, if the SMTP command was


then Exim has nothing to check, and is forced to accept the message (unless it fails another check, of course). If `headers_sender_verify_errmsg' is set, then for messages that have null senders (purporting to be mail delivery error messages), Exim does some checking of the RFC 822 headers. It looks for a valid address in the `Sender:', `Reply-to:', and `From:' headers, and if one cannot be found, the message is rejected, unless `headers_checks_fail' is false, in which case it just makes a warning entry in the reject log.

If there are several occurrences of any of the relevant headers, they are all checked. If any `Resent-' headers exist, it is those headers that are checked rather than the original ones.

Unfortunately, because it has to read the message before doing this check, the rejection happens after the end of the data, and it is known that some mailers do not treat hard (5xx) errors correctly at this point -- they keep the message on their spools and try again later, but that is their problem, though it does waste some resources.

The option `headers_sender_verify' is also available. It insists on there being a valid `Sender:', `Reply-to:', or `From:' header on all incoming SMTP messages, not just those with null senders.

The `sender_verify_except_hosts' and `sender_verify_except_nets' options provide a means of excepting hosts from sender verification checks. These exception lists apply both to checks on envelope senders and to sender addresses in headers.

A common spamming ploy is to send syntactically invalid headers such as

To: @

The option `headers_check_syntax' causes Exim to check the syntax of all headers that can contain lists of addresses (`Sender:', `From:', `Reply-to:', `To:', `Cc:', and `Bcc:') on all incoming messages (both local and SMTP). This is a syntax check only. Like the `headers_sender_verify' options, the rejection happens after the end of the data, and it is also controlled by `headers_checks_fail'; if that is false, a bad message is accepted, with a warning in the reject log.

Receiver verification

By default, Exim just checks the syntax of addresses given in the SMTP RCPT TO command. This minimizes the time required for an SMTP message transfer, and also makes it possible to provide special processing for unknown local parts in local domains, by using a `smartuser' director to pass messages with unknown local parts to a script or to another host.

Some installations prefer to check receiver addresses as they are received. If the `receiver_verify' option is set, the same code that is used by the `-bv' option is used to check incoming addresses, unless the remote host matches an entry in `receiver_verify_except_hosts' or `receiver_verify_except_nets'. If verification fails, a permanent negative response is given to the RCPT TO command. If there is a temporary failure, a temporary error is given, unless `receiver_try_verify' is set, in which case the address is accepted.

It is also possible to restrict the addresses that are verified to certain domains by setting `receiver_verify_addresses', and receiver verification can also be made conditional on the sender address by setting `receiver_verify_senders' and/or `receiver_verify_senders_except'. All of these options operate only when `receiver_verify' or `receiver_try_verify' is set.

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