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.
192.168.0.1/32 : require_ssl="true" type="cram" user="myuser" pass="mypass"
72.14.221.109/32: require_ssl="true" type="login,plain" user="myuser@googlemail.com" pass="mypass"
72.14.221.111/32: require_ssl="true" type="login,plain" user="myuser@googlemail.com" 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_USERNAME = ${extract{user}{AUTH_CLIENT_SEND_DATA}}
AUTH_CLIENT_PASSWORD = ${extract{pass}{AUTH_CLIENT_SEND_DATA}}
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}}
AUTH_CLIENT_SEND_CRAM_USER = AUTH_CLIENT_USERNAME
AUTH_CLIENT_SEND_CRAM_PASS = AUTH_CLIENT_PASSWORD
AUTH_CLIENT_SEND_LOGIN = : AUTH_CLIENT_USERNAME : AUTH_CLIENT_PASSWORD
AUTH_CLIENT_SEND_PLAIN = ^AUTH_CLIENT_USERNAME^AUTH_CLIENT_PASSWORD
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.
remote_smtp:
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.
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
LOGIN:
driver = plaintext
client_condition = AUTH_CLIENT_ENABLED_LOGIN
client_send = AUTH_CLIENT_SEND_LOGIN
PLAIN:
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 192.168.0.1. Because there’s an entry for 192.168.0.1 in the file you created at the beginning, remote_smtp would know to use authentication and ssl.
smart_route:
driver = manualroute
domains = !+local_domains
transport = remote_smtp
route_data = 192.168.0.1
Job done.
Want to leave a tip?You can follow this Blog using RSS. To read more, visit my blog index.