Exim Client Authentication Recipe

Written 15 years ago by Mike Cardwell

In the past I had a fairly complex setup with Exim, where it routed email out via various smart hosts which use authenticated SMTP. I don’t have that setup any more, but the configuration I used is still in place, so I thought I’d share it. I wanted a simple setup where I could drop a list of ip:username:password combinations into a file, and Exim would do the rest. Here’s how to do it:

First of all, create a file containing the following details about each of your smart hosts.  : require_ssl="true" type="cram"        user="myuser"                pass="mypass" require_ssl="true" type="login,plain" user="" pass="mypass" require_ssl="true" type="login,plain" user="" pass="mypass"

I think the contents of that file are fairly self explanatory. You must always provide all 4 options, require_ssl, type, user and pass. Make sure there is no whitespace adjecent to the equals symbols, as per my example.

At the top of your Exim configuration, add a macro which defines the path to the file you’ve just created called AUTH_CLIENT_DATA

AUTH_CLIENT_DATA = /etc/exim4/client_smtp_auth.txt

You’ll obviously want to change that to point to the location of your own file. Copy and paste the following list of macros, unchanged, below the AUTH_CLIENT_DATA macro. You don’t need to know what these do, they just make the transport and authenticator changes very simple.

AUTH_CLIENT_REQUIRED       = ${filter{${readfile{AUTH_CLIENT_DATA}{:}}}{match{$item}{\N^\s*\d{1,3}(?:\.\d{1,3}){3}(?:/[0-9]{1,2})?\s*$\N}}}
AUTH_CLIENT_REQUIRE_SSL    = ${filter{${sg{${filter{<\n${readfile{AUTH_CLIENT_DATA}}}{match{${extract{require_ssl}{$item}}}{\N^(?i)\s*(true|yes|1)\s*$\N}}}}{\N\n\N}{:}}}{match{$item}{\N^\s*\d{1,3}(?:\.\d{1,3}){3}\s*$\N}}}
AUTH_CLIENT_SEND_DATA      = ${lookup{$host_address}iplsearch{AUTH_CLIENT_DATA}}
AUTH_CLIENT_ENABLED_PLAIN  = ${if match{${extract{type}{AUTH_CLIENT_SEND_DATA}}}{\N^(?i)(.+,)*plain(,.+)*$\N}{true}{false}}
AUTH_CLIENT_ENABLED_LOGIN  = ${if match{${extract{type}{AUTH_CLIENT_SEND_DATA}}}{\N^(?i)(.+,)*login(,.+)*$\N}{true}{false}}
AUTH_CLIENT_ENABLED_CRAM   = ${if match{${extract{type}{AUTH_CLIENT_SEND_DATA}}}{\N^(?i)(.+,)*cram(,.+)*$\N}{true}{false}}

To inform your remote_smtp transport about when it should use authentication and when it should require ssl, add hosts_require_tls and hosts_require_auth options as follows.

    driver             = smtp
    hosts_require_tls  = AUTH_CLIENT_REQUIRE_SSL
    hosts_require_auth = AUTH_CLIENT_REQUIRED

In the authenticators section of your Exim config, create three authenticators for plain, login and cram.

    driver           = cram_md5
    public_name      = CRAM-MD5
    client_condition = AUTH_CLIENT_ENABLED_CRAM
    client_name      = AUTH_CLIENT_SEND_CRAM_USER
    client_secret    = AUTH_CLIENT_SEND_CRAM_PASS

    driver           = plaintext
    client_condition = AUTH_CLIENT_ENABLED_LOGIN
    client_send      = AUTH_CLIENT_SEND_LOGIN

    driver           = plaintext
    client_condition = AUTH_CLIENT_ENABLED_PLAIN
    client_send      = AUTH_CLIENT_SEND_PLAIN

Finally, create a manualroute router to define which messages should be routed out via a smarthost. Here’s an example which would route out all non local messages via Because there’s an entry for in the file you created at the beginning, remote_smtp would know to use authentication and ssl.

    driver     = manualroute
    domains    = !+local_domains
    transport  = remote_smtp
    route_data =

Job done.

Want to leave a tip?BitcoinMoneroZcashPaypalYou can follow this Blog using RSS. To read more, visit my blog index.