2. Installing and Configuring Exim4

Installation of Exim4 from the latest Debian GNU/Linux packages is easy. The installation is now based around debconf. If you are upgrading from a simple Exim3 configuration, you can use exim_convert4r4 to convert your configuration file to the new format. If you used the previous version of this guide, which covered Exim3, the conversion should succeed without incident. I intend to discuss configuration via debconf, including setting up local delivery to Maildir format, handling local domain email, and configuring smarthosting for outbound email.

2.1. Installing and Configuring Exim4 Packages

First, install Exim4 using the standard and exciting Debian procedure you know and love.


jasonb@nebula:~$ su -
nebula:~# apt-get update
nebula:~# apt-get install exim4

Fetching the meta package will result in the installation of exim4-base, exim4-config, and exim4-daemon-light, all version 4.34 as of this writing.

During installation, debconf will appear and ask you some questions about your shiny new Exim4 installation. If you are upgrading From Exim3, your configuration in /etc/exim/exim.conf will be parsed for appropriate default values. If you intend to convert your existing Exim3 configuration, you can go through the debconf screens, accepting the defaults, skip the rest of this section. (If you haven't made many modifications to your old Exim3 configuration, I encourage you to use the debconf generated configuration, as it's simpler.)

What follows is a discussion of each option presented by debconf. If you do not walk through the debconfig screens now or before continuing, the following discussion may not make much sense. If you accidentally broke out of debconfig, you can always run the following to restart the configuration process.


nebula:~# dpkg-reconfigure exim4-config

For the duration of this guide I assume you have chosen to use the monolithic configuration file, which is the default. Let's walk through the debconf questions on at a time.

First, if your host has a static IP address that is not located in your ISP's dynamic range, you should be able to initiate SMTP connections to remote sites directly and you do not need to use a smarthost. If such is the case, select "internet site; mail is sent and received directly using SMTP". For the rest of us, select "mail sent by smarthost; received via SMTP or fetchmail" as your mail configuration. The system mail name should be your fully qualified domain name. If you have not deployed DNS at your site, you may opt for using your system's /etc/hosts file to give your host such a name as demonstrated below. (If you choose the first option and you do not have DNS configured, you will probably encounter difficulties receiving email.)


nebula:~# cat >> /etc/hosts
127.0.0.1    mail.example.com
^D

Next, if the machine you are configuring is your only host, you should accept the default address, 127.0.0.1, as the IP address to listen on. If you intend to connect to Exim4 from other hosts, on the local network or elsewhere, you should either include additional specific addresses for your mail host (e.g. 192.168.33.5), separated by a colon, or delete the suggested value and leave it blank to have Exim4 listen on all available network interfaces.

Now, you need to decide what other destinations this host is the final destination for. If you have no other hosts, you can leave this at its default setting. If you have or intend to have an actual DNS domain across your local network, enter that domain name here. Don't include any hostnames, just the domain itself and its associated top level domain (TLD).

If you indicated your host will be sending and receiving email directly, next you will be asked for which domains you wish to accept email that are not considered local domains. Enter any appropriate domain names that apply to your configuration. If you selected the smarthosting option earlier, then you will not be prompted about which domains you which to relay for.

Next, you are prompted for the address ranges for which this mail host should accept connections for relaying mail elsewhere. For example, for my local network I used the address range 192.168.33.0/24. Include any additional ranges you want, separated by colons. Any hosts in the defined ranges will be allowed to send mail off site. You most definitely want to include hosts on your local network that you wish to send mail to the Internet from.

Now, enter the address of the smarthost through which you relay outgoing mail. Usually this will be your Internet service provider's outbound SMTP server, the server you are probably using to send email from the email client of your choice. You will not be prompted for a smarthost if you have chosen to send and receive mail directly.

Finally, if you are using a smarthost to relay mail, you can opt to have the outgoing address rewritten in the envelope header, if you would prefer your mail appear to have originated from a fully Internet connected host. Enter whatever fully qualified domain you would prefer, or accept the default if you don't care.

Last, you will be asked if you wish to minimize the number of DNS queries performed if you are in a dial-on-demand situation, perhaps with a leased line with metered usage. Ordinarily you can select the default, which is not to minimize DNS queries.

Upon completion of debconf configuration, your shiny new configuration file will be placed in /var/lib/exim4/config.autogenerated. As the filename implies, this is generated from your selections in /etc/exim4/update-exim4.conf.conf and /etc/exim4/exim4.conf.template. Any changes to the actual configuration, such as adding other routers or tweaking existing ones, must be done in the latter file.

You can revisit the debconf configuration at any time by running the following:


nebula:~# dpkg-reconfigure exim4-config

2.2. Converting Your Exim3 Configuration for Exim4

If you would rather recycle your old configuration using the exim_convert4r4, read on. Otherwise, you can skip this section. If you already configured Exim3 with support for delivering to Maildir style directories, after the conversion you should be good to go. If not, you may wish to simply go with the debconf generated configuration discussed above, since it will be a lot easier to enable Maildir style directories with that.


nebula:~# cat /etc/exim/exim.conf | exim_convert4r4 > /etc/exim4/exim4.conf
Runtime configuration file converter for Exim release 4.

** The following comments describe problems that have been encountered
   while converting an Exim 3 runtime file for Exim 4. More detail can
   be found in the file doc/Exim4.upgrade.

** The receiver_try_verify option no longer exists, and has no equivalent
   in Exim 4.

*******************************************************
***** Please review the generated file carefully. *****
*******************************************************

By default, if the file /etc/exim4/exim4.conf exists, the Debian Exim4 initialization scripts will start the daemon using that configuration file and ignore the file in /var/lib/exim4/config.autogenerated completely. If you are happy with your converted configuration, you may wish to disable debconf management of your configuration files entirely by editing /etc/exim4/update-exim4.conf.conf.


# /etc/exim4/update-exim4.conf.conf
#
# Edit this file and /etc/mailname by hand and execute update-exim4.conf
# yourself or use 'dpkg-reconfigure exim4-config'

dc_eximconfig_configtype='none'

Finally, restart the daemon.


nebula:~# invoke-rc.d exim4 reload
Reloading exim4 configuration files

2.3. Configuring Exim4 for Maildir Delivery

Unlike configuring Exim3 for Maildir, the configuration for Exim4 is straightforward. If you choose to use the debconf generated configuration file, you need merely open /etc/exim4/update-exim4.conf.conf and make a single edit. Add the option dc_localdelivery to the end of the file with a value of maildir_home, or change its value if it already exists, as shown below. (Future versions of debconf configuration will likely include this as a configuration time option for the Debian package of Exim4.)


dc_localdelivery=maildir_home

Now, restart the daemon.


nebula:~# invoke-rc.d exim4 reload
Reloading exim4 configuration files

If you recycled a previous Exim3 configuration with Maildir already configured, discussed above, then you need not do anything. You're done.

2.4. Testing your new Exim4 configuration

It's important that your configuration work correctly before proceeding further. Send yourself an email from another account somewhere on the Internet, or from another user on your own machine. (root works for this.) You might do the following:


nebula:/home/jasonb# echo "my test" | mail -s "test message" jasonb

The purpose of this exercise is two fold. First, you'll find out if Exim4 is configured properly. Second, and equally as important, Exim will create the Maildir hierarchy in your home directory, ~/Maildir, which Courier IMAP craves and requires to function. More on that later.


 nebula:~# tail -f /var/log/exim4/mainlog
2004-09-14 16:58:00 1C7KNE-0006w8-NZ <= root@nebula.internal.foo U=root P=local S=336
2004-09-14 16:58:00 1C7KNE-0006w8-NZ => tester <tester@nebula.internal.foo> R=local_user T=maildir_home
2004-09-14 16:58:00 1C7KNE-0006w8-NZ Completed

Success!


 nebula:~# ls -ltr /home/tester/
total 0
drwx------  5 tester tester 120 Sep 14 16:57 Maildir
nebula:~# ls -1 /home/tester/Maildir/new
/home/tester/Maildir/new:
1095195480.H806891P26670.nebula.internal.foo

nebula:~# cat /home/tester/Maildir/new/1095195480.H806891P26670.nebula.internal.foo
Return-path: <root@nebula.internal.foo>
Envelope-to: tester@nebula.internal.foo
Delivery-date: Tue, 14 Sep 2004 16:58:00 -0400
Received: from root by nebula.internal.foo with local (Exim 4.34)
        id 1C7KNE-0006w8-NZ
        for tester@nebula.internal.foo; Tue, 14 Sep 2004 16:58:00 -0400
To: tester@nebula.internal.foo
Subject: tester
Message-Id: <E1C7KNE-0006w8-NZ@nebula.internal.foo>
From: root <root@nebula.internal.foo>
Date: Tue, 14 Sep 2004 16:58:00 -0400

my test 

You can see above Exim4 happily creates Maildir/ directory and sticks your new mail message in the Maildir/new/ directory.

It's necessary for each user to have this directory before Courier IMAP can successfully access a user's mail, otherwise your mail client will return an error. With that in mind, there are a few ways you can ensure that this directory exists. For future users, you can modify your /etc/skel directory and add a Maildir/ directory there. Thusly as root:


maildirmake /etc/skel/Maildir

All future users will now have a Maildir/ with the proper permissions and subdirectories. It's important to note that maildirmake is only available after you install the courier-base package.

That still leaves existing users, though. You can mail everyone on the system about the new IMAP setup and in doing so, Exim4 will create the very Maildir structure you seek. Or you can write a script to add a Maildir for each existing user with the maildirmake command like we did above for /etc/skel. It's up to you.

You cannot proceed with the next step successfully, in any case, without at least building a Maildir for yourself. So if you didn't send a test message, run the following as your own user:


tester@nebula:~$ cd ~
tester@nebula:~$ maildirmake Maildir

2.5. Configuring New Mail Notification

If you'd like to continue to receive the notification "You have new mail.", you need to modify several files.

First, /etc/login.defs. You will want to locate the QMAIL_DIR and MAIL_FILE environment variables and uncomment them. Then, comment out the MAIL_DIR environment variable. The value of MAIL_FILE will be appended to the user's home directory, such that the MAIL environment variable becomes defined as MAIL=$HOME/$MAIL_FILE, which is what you want. An example follows.


QMAIL_DIR    Maildir/
#MAIL_DIR    /var/mail
MAIL_FILE    Maildir/

Second, modify your /etc/pam.d/login to receive new mail notifications when you login on the console. Your /etc/pam.d/login with the correction options for pam_mail.so should look like the example below.


session    optional   pam_mail.so standard noenv dir=~/Maildir

Last, you need to make a similar modification to /etc/pam.d/ssh so you receive new mail notifications when you login via ssh. In order for the MAIL environment variable to be set correctly, you must ensure that the noenv is not passed to pam_mail.so.


# Print the status of the user's mailbox upon successful login.
session    optional     pam_mail.so standard dir=~/Maildir # [1]

Now you can enjoy mail notifications whenever you login to your mail server.

2.6. Configuring Exim4 dot forward Filtering

For a detail discussion of Exim's filter system, you should check out Exim's documentation itself. For just the short of it, read on.

In order for Exim to recognize a .forward as having Exim4 filter rules, the first non-whitespace entry must be:


# Exim filter

Character case and anything following it on the same line are ignored.

Next, you'll likely want some rules in your Exim4 filter .forward file. Using a simple if then elif else endif construct you can perform various tests against each incoming email before delivery (or discarding) it to a specified location. You can perform evaluations against any existing entry in an email's header, like so:


# Match any email who's To: header contains "exim"
# and save it to .dir1
if $h_to: contains "exim" then save Maildir/.dir1/

# Match email with a From: header that's
# exactly "not@wanted.com" and save it to .SPAM
elif $h_from: is "not@wanted.com" then save Maildir/.SPAM/

endif

To access the email header of your choice, append $header_, or as abbreviated above, just $h_, to the full name of an email header, following by a colon (:). The keywords is and contains are self explanatory. The save keyword, when followed by a path that ends with a forward slash (/), will deliver the email being evaluated in Maildir format. As such, the trailing slash is crucial. Don't omit it.

In Courier's IMAP hierarchy, directories beneath the root are dot directories. In addition, all subdirectories are denoted by periods, not additional forward slashes. So, lists/Debian/User/ is actually .Lists.Debian.User/ on the filesystem and should be referred to in Exim filters as "save Maildir/.Lists.Debian.User/" for things to be saved the way you expect.

My own personal working Exim filter file looks like this:


# Exim filter

# Save yourselves
if error_message then finish endif

# Let's make use of pipes
# The script accepts input on STDIN and does stuff with the mail
if $h_Subject: contains "uptime report"
then
       pipe "$home/bin/uptime.pl"
endif

# Handle mailing lists

if $h_List-Id: contains "leaplist"
  then save Maildir/.mailinglists.leap.linux/
elif $h_from: contains "ebay.com"
  then save Maildir/.Ebay/
elif $h_Sender: contains "LINUX-L"
  then save Maildir/.mailinglists.LUG/
endif