This is mainly a reference for myself in case I forget how to do it later, as it took me a good deal of time to figure out.
Situation
I want to unit test applications that send emails. Obviously I don’t want to be opening a dozen of real email accounts just to test this thing out. Naturally I would want to install an SMTP/POP3/IMAP server on Windows, and there is one free (open source) option that is quite promising – hMailServer. However, it still involves 2 (quite major) inconveniences for my use case:
- I have to go through the configuration screens to create new users. i.e. if I want to send email to alice@localhost I’d have to create the user account alice manually
- I have to use an email client (like Outlook Express) to connect to the local POP3 server to view the emails. This seems redundant 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 improvement over the good ol’ sendmail. So I gave it a shot – man, that was awesome! I can now direct my application to send to arbitrary address like alice@mail.local, foobar@mail.local and I can view the results immediately in a text file, solving the two problems mentioned above. Here’s what I did:
- Install exim using cygwin installer
- Run
exim-config - Edit /etc/exim.conf
- Uncomment
primary_hostnameand set it tomail.local - Edit the router
localuser, comment out the linecheck_local_user(If you don’t know what that means, just search for the linelocaluser:) - Edit %WINDIR%\system32\drivers\etc\hosts, add the line
1 | 127.0.0.1 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 contains all the mail in text files. A simple tail -f /var/spool/mail/foobar can monitor the mail sent to foobar@mail.local
A simple test to make sure everything’s working:
$ exim -bt foobar@mail.local
foobar@mail.local
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 foobar@mail.local
Hello World!
.
LOG: MAIN
<= Chris@mail.local U=Chris P=local S=296
delivering KEQKED-0002RS-A7
LOG: MAIN
=> foobar <foobar@mail.local> R=localuser T=local_delivery
LOG: MAIN
Completed
# 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 <Chris@mail.local>)
id KEQKED-0002RS-A7
for foobar@mail.local; Sun, 08 Feb 2009 15:20:39 +0800
Message-Id: <EKEQKED-0002RS-A7@mail.local>
From: Chris <Chris@mail.local>
Date: Sun, 08 Feb 2009 15:20:39 +0800
Hello World


Nice. You mention Eclipse here and there, so I assume you also do stuff in Java. Here is one useful library for unit-testing sending emails via SMTP: http://code.google.com/p/subethasmtp/wiki/Wiser It acts as SMTP server, and let’s you check received messages 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 command line. You probably need to use a proper MUA for that, try
@Mahesh:
To send a non-trivial mail with exim, first format it to a proper rfc822/rfc2822/rfc5322 format mail with the attachments done according to mime (lots of other tools to do that, take your pick), then pass it as input to exim something like this:
exim -some-options-here-forgot-which < your-message.rfc822
Exim would do the rest