cygwin+exim: setting up a local SMTP server for testing email applications

This is mainly a ref­er­ence for myself in case I forget how to do it later, as it took me a good deal of time to figure out.


I want to unit test appli­ca­tions that send emails. Obvi­ously I don’t want to be open­ing a dozen of real email accounts just to test this thing out. Nat­u­rally I would want to install an SMTP/POP3/IMAP server on Win­dows, and there is one free (open source) option that is quite promis­ing – hMailServer. How­ever, it still involves 2 (quite major) incon­ve­niences for my use case:

  • I have to go through the con­fig­u­ra­tion screens to create new users. i.e. if I want to send email to [email protected] I’d have to create the user account alice manually
  • I have to use an email client (like Out­look Express) to con­nect to the local POP3 server to view the emails. This seems redun­dant to me, since the files are already stored in my disks, why can’t I just view them?

The Solution

Then I came across exim on cygwin. exim is (as it claims to be) a vast improve­ment over the good ol’ send­mail. So I gave it a shot – man, that was awe­some! I can now direct my appli­ca­tion to send to arbi­trary address like [email protected], [email protected] and I can view the results imme­di­ately in a text file, solv­ing the two prob­lems men­tioned above. Here’s what I did:

  • Install exim using cygwin installer
  • Run exim-config
  • Edit /etc/exim.conf
  • Uncom­ment primary_hostname and set it to mail.local
  • Edit the router localuser, com­ment out the line check_local_user (If you don’t know what that means, just search for the line localuser:)
  • Edit %WINDIR%\system32\drivers\etc\hosts, add the line mail.local
  • Finally, reboot the exim service

And there you go! You can now send mail to *@mail.local. To view the mail, go to /var/spool/mail which con­tains all the mail in text files. A simple tail -f /var/spool/mail/foobar can mon­i­tor the mail sent to [email protected]

A simple test to make sure everything’s working:

$ exim -bt [email protected]
[email protected]
  router = localuser, transport = local_delivery
# If something is wrong in your config, it would say "Unrouteable address"
# Now let's try sending an email
$ exim -v -odf [email protected]
Hello World!
  <= [email protected] U=Chris P=local S=296
delivering KEQKED-0002RS-A7
  => foobar <[email protected]> R=localuser T=local_delivery
# Cool, let's see if it really delivered
$ tail /var/spool/mail/foobar
Received: from Chris by mail.local with local (Exim 4.69)
        (envelope-from <[email protected]>)
        id KEQKED-0002RS-A7
        for [email protected]; Sun, 08 Feb 2009 15:20:39 +0800
Message-Id: <[email protected]>
From: Chris <[email protected]>
Date: Sun, 08 Feb 2009 15:20:39 +0800
Hello World

8 Responses to “cygwin+exim: setting up a local SMTP server for testing email applications”

  • Nice. You men­tion Eclipse here and there, so I assume you also do stuff in Java. Here is one useful library for unit-​testing send­ing emails via SMTP: http://​code.​google.​com/​p​/​s​u​b​e​t​h​a​s​m​t​p​/​w​i​k​i​/​Wiser It acts as SMTP server, and let’s you check received mes­sages in Java code.

  • Interesting. Thanks for the link!

  • How do i use exim to send email with attachment?

  • @Mahesh:

    I don’t know how you can do it from the com­mand line. You prob­a­bly need to use a proper MUA for that, try mutt (avail­able from Cygwin installer). Or you could achieve the same thing with a Perl or Ruby script (more complicated)

  • @Mahesh:

    To send a non-​trivial mail with exim, first format it to a proper rfc822/rfc2822/rfc5322 format mail with the attach­ments done accord­ing to mime (lots of other tools to do that, take your pick), then pass it as input to exim some­thing like this:

    exim -some-options-here-forgot-which < your-message.rfc822

    Exim would do the rest

  • Unfortunatly exim now requires strange per­mis­sion set­tings and refuses to even start “LOG: MAIN PANIC DIE” “unable to set gid” “setuid for log-​file cre­ation failed, aborting”… I don’t actu­ally care about the log file… there should be no need for chang­ing users/groups it should just open a socket and write emails to files, every­thing else should be an exter­nal OS per­mis­sion issue… this is basic soft­ware devel­op­ment 101… sorry for the rant… just tired of simple pro­grams designed to be impos­si­ble to use.

  • Quality arti­cles is the impor­tant to inter­est the users to visit the web­site, that’s what this site is providing.

Leave a Reply