Setting up multidomain DKIM with Exim

Update November 2018:

A reader contacted me and pointed out that removing the {} around DKIM_DOMAIN solves the errors in the original example I found and had problems using. I’ve updated the code below (line 8) to reflect those changes in case anyone ends up here via google.

He also shared a nifty way to make selector rollovers easier by adding them to the filename:

And last but not least an elegant way to populate the  DKIM_DOMAIN variable:

Original Posting:

I was recently setting up SPF, DKIM and DMARC for multiple domains and was having trouble getting Exim to sign emails for the different domains. I found an article here explaining the steps. But I kept getting the following error in my exim logs:

failed to expand dkim_private_key: missing or misplaced { or }

The suggested configuration was the following:

I’m not quite sure why, but Exim was having trouble using the macros in the following macros, so I ended up changing it to the following snippet instead. If you don’t use DKIM_FILE you can omit it. Also you might want to set DKIM_STRICT to true if you published a DMARC policy that will reject or quarantine email failing the DKIM tests (unset, or “false” tells Exim to send the message unsigned if it ran into problems signing the email). The default setting for DKIM_CANON is “relaxed“, so it also can be omitted.

Other than that, just make sure the exim process has permissions to access the dkim directory and certificate files and everything should work nicely.

Playing around with Exim, Spamassassin, DKIM and SPF

I was playing around with my mail server today and decided to have a look at DKIM and SPF. Jump to the bottom for some useful links. You will have to be able to change TXT entries for your domain/subdomains to do any of this. Sending a mail to will generate an auto-reply with the result of your mail servers settings. I also noticed that Exim wasn’t listening to the IPv6 interface and promptly fixed that, and have received my first mail via IPv6.

Some spamassassin scores for your local/user settings:

Tools & Information:

Exim walkthrough:
Domain specific settings:

Moving Exim/Spamassassin/Cyrus -> Debian config

I’ve been putting off moving my mail system to the new server for a few weeks now since the old system was configured from scratch using the original config files and not the debian style config files. The differences in the Exim config are extreme. Debian splits the one large config file into lots of smaller files. This is great if: you never worked with exim before, you aren’t trying to migrate an existing configuration that is in one large file, and you don’t have all kinds of custom stuff like imap, spamassassin, greylisting mixed in. Yeah, not me. Even though I find the “one large file” a whole lot faster and easier to read, the Debian way has one big advantage: it is way easier for external scripts and packages to drop their custom config into exim. They just add a file to the right directory and thats it.

So I decided to go for it and merge my custom stuff into the Debain config. Greylisting worked out-of-the-box, spamassassin needed some minor tweaks, exim was (more or less) easy. The p.i.t.a. with exim is when you know exactly what is missing and where it would be configured, but because of “smart debian scripts” you have to find some config in an unrelated script and put the value there so it gets put in the right placeholder.

Here is a little summary in case I ever do this again and need to see if I forgot something:
– cyrus: copy /var/spool/cyrus/mail/ , /var/lib/cyrus/user/ , use cyradm to add the user.blargh account and /usr/sbin/cyrreconstruct -rf user (don’t forget the sieve filters)
– getmail: nothing special here, just copy config and add cronjob
– spamassassin: alter exim acl to set noscan for auth’d connections and have spamassassin scan everything not “noscan” (because per default local mail isn’t scanned, that includes everything we pick up via getmail)
– exim: check update-exim4.conf.conf for stupid entries, remember to turn on TLS (imap can use the same certificates), since we are using sasl for imap, have smtp auth use the same database (plain_saslauthd_server), turn on TLS by creating a file conf.d/main/00_exim4-config_localmacros with “MAIN_TLS_ENABLE = true” in it

Now that I’m done I found a pretty detailed German website with steps to set up such a system E-Mail-Server mit Debian, Exim und Cyrus. I did the exim router/transports a bit differently to have a bit more control over what goes where when. Still, defiantly worth reading if you are thinking about building such a system.

Email Server

I’m not a big fan of using greylisting to cut down on email spam, since it tends to big a big pain in the ass when I run into it running on other email servers. On the other hand the amount of incomming spam has risen to a level where I decided it’s time to really do something about it (not that Spamassassin was doing a bad job, but it shouldn’t have to go through hundreds of mails each day to sort out the 15-20 real mails).

So I did a quick google what packages were recommended for greylisting with exim, and ended up using “greylistd” which came with a nice example config for exim. I went through the config and loosened up the settings a bit. And after letting it run for 2 days, the stats say that a bit over 96% of incoming mail was never retried (e.g. either spam, or a crappy MTA sending me mail).

Next thing I’m having a look at is SPF. I’ve got it up and running, but it only throws warnings to the log right now, doesn’t block anything (same goes for messed up DNS entries of servers sending me mail).

Something positive I noted was that the number of MTA servers supporting TLS connections seems to be rising. Server <-> Server encryption of data is a good thing. Having users view and send mail via secure HTTPS/SSL/TLS cconnections is pretty useless if the mails gets forwarded to the destination in plaintext.