SMTP Settings for Local Testing Without a Mail Server

See if you've got mail, with actually sending it.

Posted by AgileCoder on March 12, 2012

I was recently working through some old code that my team generated. One common pattern that I have run into is a 'check' for whether or not to send email. See, typically we store a configuration variable named something like "DeliverEmail" and set it to false when the code is on a development or beta machine. Then, in our code we read the config setting in an if() statement and ignore the send mail code if it is false.

This has worked for us for years, but it's a kludge. So I spent some time on the internets and found this article on configuring ASP.Net and SMTP to save outgoing email to a directory, rather than process and send it.

There are actually several reasons why you might want to write your email to a local file rather than send it immediately.
  • Testing - You may be using cleansed/obfuscated data and not want to send the messages. Or you may want to read text from the email to verify that it is formatted correctly, without having to manually open and check email sent to a personal account.
  • Hassle of configuring SMTP in Vista and Win 7 (see this article). SMTP isn't on or even installed by default in several MS operating systems.
There are two steps to setting this up: the code to send the message, which should be nearly identical to your normal SendMail code; and SMTP settings stored in your config file.
 
The code I use to send email is shown below.  There are two things to note. First, none of the SMTP server details are in this code; they are read from the config file at runtime.  Second, the MailMessage and SmtpClient objects are instantiated with the .Net Using{} syntax. I've occasionally had trouble with the SMTP cache failing to flush in a timely manner.  Both of these object implement IDispose, and the garbage collection process seems to flush the cache consistently.
public void SomeAction()
{
     using (MailMessage email = new MailMessage())
     {
          email.From = new MailAddress("no-reply@test.com");
          email.To.Add("test@test.com");
          email.Subject = “Test email to file”;
          email.Body = “This is body text saved to a .eml file”;
                
          using (SmtpClient client = new SmtpClient())
          {
               client.Send(email);
          }
     }
}
 The more recent schema for web.config includes a "mailSettings" node in the system.net section.  Within that section you can set the values as shown here to force the .Net SmtpClient to send the message as a file to a local directory:
<system.net>
    <mailSettings>
      <smtp deliveryMethod="SpecifiedPickupDirectory">
        <network host="localhost" />
        <specifiedPickupDirectory pickupDirectoryLocation="c:\deleteme\test_email\"/>
      </smtp>
    </mailSettings>
  </system.net>
Two final things to note.  For this to work the directory listed in pickupDirectoryLocation must already exist (the process won't create it if it is missing), and the account under which your app is running must have write/modify access to that directory,