Mocking out an email server

I am currently looking at automation of acceptance testing for workflows and a common task is to make sure an email has been sent. To do this in a TDD style I have been using the mock SMTP server nDumbster.

Now this was a port from Java in the the days of .NET 1.1 and does not seem to have had any development since. This can be seen because the following test using the .Net 1.1 System.Web.Mail call works beautifully, returning in a second or so

[TestMethod]
public void CanRecieveSingleWebMail()
{
System.Web.Mail.SmtpMail.SmtpServer = "localhost";
System.Web.Mail.SmtpMail.Send("somebody@foo.com", "everybody@bar.com", "This is the subject", "This is the body.");
Assert.AreEqual(1, smtpServer.ReceivedEmail.Length);
}

However the test using the .Net 2.0 System.Net.Mail is not so good

[TestMethod]
public void CanRecieveSingleNetMail()
{
System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient("localhost");
System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage("somebody@foo.com", "everybody@bar.com", "This is the subject", "This is the body.");
client.Send(msg);
Assert.AreEqual(1, smtpServer.ReceivedEmail.Length);
}

It does work but takes 100 seconds to return, a bit of a pain for TDD!

After a bit of debugging I found the problem was the final input.ReadLine(); in HandleSmtpTranslation which we expect to get a null at the end of a message, for Systsem.Web.Mail this returns instantly, but for System.Net.Mail this takes 100 second, but then is fine.

As a work round I have put in the logic

string line = null;
if (smtpState != SmtpState.QUIT)
{
    line = input.ReadLine();
}
if (line == null)
{
    break;
}

This works fine for single mail messages, using both the old and new API.

There is still a problem, with the System.Web.Mail API you can send multiple emails in a test, but this still fails for System.Net.Mail – the first goes OK, but the second fails saying the server is not present.

By the way I have ruled anti virus and anything specific to port 25 causing the problem. I suspect a threading issue as I believe System.Web.Mail was single threaded wrapper for COM and System.Net.Mail is multi threaded pure .Net logic.

If I get a better solution I will post about it, but I have enough functionality for me at present.

Update 28th Sep – Got an email today via the SourceForge forum that pointed me at the freeware LumiSoft mail server. On a first look this certainly appears to do the job. You just need to wire it into your tests in a wrapper class of your own.