Exim Mail Transport Agent

Daniel Allen

Prescient Code Solutions

da (at) coder.com

Monday, 12 August, 2002

I've added my talking notes to the slides. The page formatting was set to display properly on my browser window at 800x600, though the notes will mess up the paging. Oh well.

Choosing a Mail Transport Agent

Choosing a Mail Transport Agent

Why do you Care?

Choosing a Mail Transport Agent

Why do you Care?

A Mail Transport Agent is the generic name for any program that gets mail from one address to another, in contrast with a Mail User Agent like Pine or Eudora. If you don't run a mail server yourself because your full-service ISP handles all your mail needs, or if you only run a server with one domain with low administration needs, you probably won't care.

Choosing a Mail Transport Agent

Why do you Care?

If you run mailing lists or multiple domains on your servers, you'll have some amount of configuration of your own mail transport agent. Sometimes the choice of Mail Transport Agents is made for you. For example if you want to run the mailing list manager 'ezmlm' you'll have to use qmail. If 'sendmail compatbility' is mandatory, you might need to run sendmail, but maybe not because all of the other Mail Transport Agents mentioned here besides qmail are also largely sendmail compatible. Finally, if you're paranoid about security and are worried about somebody breaking into your server via your mail transport agent, you will care.

Initial Comparisons

When I made this decision, my highest priorities were features, maturity, ease of use, and performance. It turns out that mostly, Mail Transport Agents score the same (within a tolerable range), except for ease of use. I'll try to justify that below.

Sendmail

There is a macro language, m4, which makes sendmail configuration somewhat easier; but doing anything specialized is still an intimidating task for many. Sendmail is the granddaddy of Mail Transport Agents, and is still used on over 50% of all mail servers worldwide. Most of which aren't customized very much from the defaults.

qmail

qmail was written to be security-obsessive. There are different sub-systems (daemons) to handle such tasks as queueing mail, sending mail from the queue, handling errors, etc. Each sub-system was written to not trust the others, in case there is a compromise. This makes excellent security, but more difficult configuration; among other user concerns, there are many places where you have to repeat your configuration changes in multiple files. There do exist some front-end interfaces to make administration simpler. There are also third-party addons to make qmail act more like Sendmail, so it will be more-or-less compatible with other programs that expect Sendmail compatibility.

Exim

Exim was written to be efficient and easy to configure. It was also written to have all of the features of sendmail and more. How easy? Let's look at a moderately tough example ...

Example: Email to unknown users

Here is an example situation. Perhaps you run a user-friendly domain and you want custom email to be sent to people whose email bounces. This requires processing all email that should be delivered locally but hasn't successfully been routed to a local user. You might send back an error message that includes the best guess at a valid address. (Yes, that's insecure, but it might make sense within a company intranet.)

Here's the exim recipe to add to the configuration file:
# add a director at the bottom of the director section of the config file

unknownuser:
  driver = smartuser
  transport = unknownuser_pipe
  no_verify

# add a transport

unknownuser_pipe:
  driver = pipe
  command = /opt/exim/util/baduser.sh
  ignore_status
  return_output
  user = nobody

baduser.sh could run any commands you like, such a soundex search on the name part of the address, or listing the addresses that alphabetically come before or after the bad address.

Doing this in sendmail could be painful

In fact the sendmail expert in the room during the talk was not convinced it was possible.

Explanation of how Exim works

In exim, there are three logical subcomponents that handle incoming and outgoing email:
An email address is local or remote. An address is local if exim is told to handle email delivery for the domain part of the address. Otherwise it is remote. Exim is handed all incoming and outgoing email. If a recipient is local, exim steps through the directors until it finds one that matches (such as by looking up addresses in the user database, via a LDAP search, or an alias file.) The director selectively hands the mail off to a transport which can save the mail to the tail end of a file, save as a file in a directory, pipe to a script, or send an autoreply without storing the email.

If the recipient email address is remote, exim hands it to the routers which generally do a DNS lookup on the hostname and validate it exists. The router hands the mail to a transport, which typically sends it to a queue directory and sends it in a SMTP transmission. The transport also keeps the message in the queue if the remote host refuses the mail initially or the host is unavailable.

More Comparisons

comparison with other MTAs (stolen from www.lifewithqmail.org/lwq.html#comparison)

MTA Maturity Security Features Performance Sendmail Compatibility Modular
qmail medium high high high addons yes
Sendmail high low high low yes no
Postfix medium high medium high yes yes
exim medium low high medium yes no
Courier low medium high medium optional yes

Maturity depends on the number of years it has had popular acceptance; for all of these open-source Mail Transport Agents, it also suggests how many eyes have been looking for bugs in the source code.

Security is a function of whether the Mail Transport Agent was designed for potential security problems from the outset. Exim's low rating is because the author expressly said he isn't a security expert and as such hasn't performed a complete audit; there haven't been any security holes found, unlike in sendmail, but if there ever were, there was the potential for a worse hole than in qmail.

The Features column only marks down Postfix, because Postfix is young and the focus has been on security and basic features. However, if your main requirement is the fastest Mail Transport Agent, postfix is a good choice.

Sendmail Compatibility refers to whether you can 'drop in' a new Mail Transport Agent and programs which expect the '/usr/bin/sendmail' binary will work with no other changes.

Performance depends entirely on your needs; sendmail can do just fine on many thousands of email messages daily, perhaps up to a few thousands an hour. Exim has been used on hosts sending more than 10,000 emails hourly; qmail and postfix at least twice that and probably much more.

In the balance, for my servers, I was most interested in a Mail Transport Agent that wouldn't drive me up the wall when I wanted to make changes, since I'm a bear with little brain (or memory for what I did six months ago when I last changed something). So far I've been entirely happy with Exim.

The End

Rover was just over six weeks old when these pictures were taken. Rest assured, she's still just as cute.

refs

Example Exim Configuration File

This is a complete exim configuration file, slightly simplified and minus most of the comments that describe how it works.
#                    MAIN CONFIGURATION SETTINGS

primary_hostname = coder.com
local_domains = "matrix.coder.com :\
                 engine.coder.com"
local_domains_include_host = true
never_users = root
host_accept_relay = localhost
relay_domains = "matrix.coder.com :\
                 engine.coder.com"
sender_verify
trusted_users = mail:coder
end

#                      TRANSPORTS CONFIGURATION

remote_smtp:
  driver = smtp

local_delivery:
  driver = appendfile
  file = /var/mail/${local_part}
  delivery_date_add
  envelope_to_add
  return_path_add
  group = mail
  mode = 0660

address_pipe:
  driver = pipe
  return_output

address_file:
  driver = appendfile
  delivery_date_add
  envelope_to_add
  return_path_add

address_reply:
  driver = autoreply
end

#                      DIRECTORS CONFIGURATION 
#             Specifies how local addresses are handled 

system_aliases:
  driver = aliasfile
  file = /etc/aliases
  search_type = lsearch
  user = coder
  group = mail
  file_transport = address_file
  pipe_transport = address_pipe

userforward:
  driver = forwardfile
  file = .forward
  no_verify
  no_expn
  check_ancestor
  file_transport = address_file
  pipe_transport = address_pipe
  reply_transport = address_reply

localuser:
  driver = localuser
  transport = local_delivery
end

#                      ROUTERS CONFIGURATION
#            Specifies how remote addresses are handled

lookuphost:
  driver = lookuphost
  transport = remote_smtp
end

                      RETRY CONFIGURATION
*                      *           F,2h,15m; G,16h,1h,1.5; F,4d,8h

#                      REWRITE CONFIGURATION
end
#                   AUTHENTICATION CONFIGURATION
end