Debian: Configuring exim4 for local mail delivery

5 minute read Published: 2023-01-18

In a previous article I did an overview of how I learned a few tools to tune my emails storage (mostly how to classify them based on their provenance). Today we will do a quick dive into how to tweak a bit the configuration for exim4 for local mail delivery.

exim4 is one of those old UNIX services that exists since the dawn of time: it's a mail server service and an MTA (basically it can process emails and transfer them from A to B, whatever "A" and "B" are).

I suspect virtually any Linux box has a mail delivery service active by default since it's so ingrained since the UNIX days (when the idea of being networked terminals was in the DNA of these workstations) and I guess we often ignore we have this thing running in our laptops in the background, mostly idling.

Historically these agents will save emails in a mbox format (that is: a single text file with all the mails concatenated). This mbox file usually resides in /var/mail/$USER and can be inspected with something like less +G /var/mail/$USER. To handle this mailbox either use the command mail (from GNU mailutils) or delete the file altogether, it will be recreated.

Today, it is suggested to use the Maildir format (creates a hierarchy of directories and each mail is a single file). I use the $MAILDIR env var to let everyone know where my maildir is.

The task at hand today will be telling exim4 to save them in our maildir directory.

Important note: since I am using Debian, most of content explained here is specific to Debian. The exim4 package has some Debian maintainer scripts that makes things a little bit more opaque. I ignore why but I guess they had good reasons.

§ Configure exim4

exim4 configuration sits in /etc/exim4. We can start by looking at /etc/exim4/update-exim4.conf.conf. This is a Debian maintainer script which proxies the real exim4 configuration and it's still unclear to me how exim4 is actually configured on Debian. The config file will probably have this line:

dc_localdelivery='mail_spool'

This instructs exim4 to save messages in a single mbox file, as per man 5 update-exim4.conf.conf:

dc_localdelivery
   name  of  the default transport for local mail delivery. Defaults to
   mail_spool if unset, use maildir_home for  delivery  to  ~/Maildir/.
   Sets macro LOCAL_DELIVERY.

Let's change it! Reconfigure exim4 with:

dpkg-reconfigure exim4-config

choose the profile "local delivery only; not on a network" and "Maildir format in home directory":

1. internet site; mail is sent and received directly using SMTP 
2. mail sent by smarthost; received via SMTP or fetchmail
3. mail sent by smarthost; no local mail
4. local delivery only; not on a network
5. no configuration at this time

    General type of mail configuration: 4

1. mbox format in /var/mail/
2. Maildir format in home directory
   
   Delivery method for local mail: 2

(documentation online or read /usr/share/doc/exim4-base/README.Debian.html). The Debian maintainer script /etc/exim4/update-exim4.conf.conf will be updated. The line above will now be:

dc_localdelivery='maildir_home'

As mentioned in the man page, it will also set the macro LOCAL_DELIVERY=maildir_home: this indicates that exim4 will use a Maildir and will save emails in ~/Maildir.

However, we want our mail delivered to another maildir so we will leverage another feature of the exim config file for customizations: macros.

You'll notice that in /etc/exim4.conf is it defined the maildir_home configuration block:

maildir_home:
  debug_print = "T: maildir_home for $local_part@$domain"
  driver = appendfile
  .ifdef MAILDIR_HOME_MAILDIR_LOCATION
  directory = MAILDIR_HOME_MAILDIR_LOCATION
  .else
  directory = $home/Maildir
  .endif

MAILDIR_HOME_MAILDIR_LOCATION is the macro we need to override. Let's create a file /etc/exim4/conf.d/main/00_localmacros with the following line:

MAILDIR_HOME_MAILDIR_LOCATION = $home/.local/mail/.system

Please note the path /.system (with a dot!).

This will tell exim4 about our custom maildir. Let's regenerate the configuration with:

update-exim4.conf --keepcomments --output /etc/exim4/exim4.conf 

And it's done. Now at the beginning of /etc/exim4/exim4.conf we will find the content of our 00_localmacros that will overwrite the default maildir.

Let's test that emails are delivered in the right place (no need to restart exim4) by triggering a security alert and execute sudo ls then CTRL+C at the password prompt. Let's check where we expect the emails to be stored:

$ find -f system $MAILDIR
/home/$USER/.local/mail/.system/
/home/$USER/.local/mail/.system/tmp
/home/$USER/.local/mail/.system/cur
/home/$USER/.local/mail/.system/new
/home/$USER/.local/mail/.system/new/1673815837.M248507P3365656.hostname.localdomain

Yay, it worked! The new maildir has been created automatically thanks to the directive create_directory in /etc/exim4/exim4.conf and we have a nice email about a failed sudo command :)

exim4 logs are at /var/log/exim4/mainlog.

§ Conclusions

I now receive in my mailbox a couple of useful emails from my Debian installation (such as important news about updated packages or CVEs), which before I was missing (I was just blindly updating packages).

It took a good deal of time to figure out the above but the documentation is stellar, just not very easily discoverable.

Some minor issues I can think of:

  1. I cannot have a local override config file, exim4 has only a global system file (kind of makes sense)

  2. Is this solution complete? Will all applications obey these settings? I have no idea.