Setting Up Exim To Provide an Authenticated SMTP Relay ------------------------------------------------------ 1) Write a Perl script to do your actual authentication. It should have a function which expects a username and password as arguments, and returns 1 for successful auth, 0 for unsuccessful: sub authenticate { my ($username,$password) = @_; return 1 if $username eq 'ILike' && $password eq 'Pie'; return 0; } The script shouldn't do anything in the main body, just declare subs. It is also going to be the best place to implement anti-spam checks later on. 2) Build Exim, uncommenting the "EXIM_PERL=perl.o" line to enable embedded Perl support. Install to taste. 3) In your main Exim configuration ($PREFIX/etc/configure), include the following: perl_startup = do '/path/to/authentication/script.pl' perl_at_start = true This will load in your authentication script at Exim startup, preparing the authentication subroutine(s) for later use. 4) Set up your Exim Authenticators, also in "configure": begin authenticators # (should be in the stock config, add these after it) plain: driver = plaintext public_name = PLAIN server_prompts = : server_condition = ${perl{smtp_auth}{$2}{$3}} server_set_id = $2 login: driver = plaintext public_name = LOGIN server_prompts = Username:: : Password:: server_condition = ${perl{smtp_auth}{$1}{$2}} server_set_id = $1 ### CRAM-MD5 Untested Example cram-md5: driver = cram_md5 public_name = CRAM-MD5 server_secret = ${perl{cram_auth}{$1}} server_set_id = $1 Where "smtp_auth" is the name of the sub created for authentication earlier. cram_auth would be a subroutine that takes in the username and then returns the user's secret (which would have to be known in plaintext by the script), exim will then compare an MD5 of the secret against the MD5'd secret provided by the user. 5) Set up ACLs to actually make use of all this: # In the main config, near the perl lines from before will do: acl_smtp_rcpt = acl_check_rcpt # Anywhere after "begin acl" and before any other "begin"s acl_check_rcpt: require authenticate = * encrypted = * # if you want to require SSL verify = sender warn set acl_c0 = ${perl{antispam}} deny condition = ${if eq {$acl_c0}{0} {1}{0}} message = Blocked By Spam Check accept This assumes that you have a subroutine called "antispam" loaded which returns 1 if the message should be allowed, 0 otherwise. In that script, you can use Exim::expand_string('$local_part') and Exim::expand_string('$domain') to get the local part and domain of the recipient currently being processed (it'll be called for each recipient). You can expand all kinds of other variables as necessary, as well - everything Exim knows about the message is available to the Perl script. 6) To set up SSL, create a cert/privkey pair, and add the following to the main config: tls_advertise_hosts = * tls_certificate = /path/to/certificate.crt tls_privatekey = /path/to/privkey.key 7) If you want to restrict the number of recipients in each SMTP session, add something like: recipients_max = 100 To the main Exim config. That should just about meet the requirements. Feel free to e-mail tim (at) krellis.org with any questions. -- Tim Wilde (Krellis)