Simple Mail Service

Keep it SimpleOver the past years, I’ve found myself having to write down a mailing component for the projects that I’ve been involved… but none like this one that I decided to post.

First of all, I want to set the disclaimer that I do not think this is a revolutionary design or even unique in any sort… it is just the product of me designing a new application right after I finished reading this book. Amongst many things I read in this book, which by the way, I think it’s a MUST read for every ASP.NET MVC developer, was the concept (in practice) of Dependency Injection.

Up until now, I had thought of Dependency Injection as a simple matter of filling dependencies of other objects (and indeed, that’s what it is!!) but never really realized the power of it until I saw a DI Factory working on Steven Sanderson‘s book samples… and I trust you’ll too catch a glimpse of it through this example.

The Mail Service

Let’s get to the good stuff now (after that boring intro ). The first thing to start with, and isn’t really a breakthrough is the fact of thinking of the Mail Service as a “Service” (duhh!), instead of a helper class or extension methods or whatever other ideas you may have had or found. It’s a business (more application really) layer in it’s whole… and we should treat it with the isolation it deserves.

But wait!!, before we go any further, let me break your mind if you are already thinking that because you are building a service, then the service will know how to construct and send EACH and EVERY single Email that your application needs to send… WRONG!! I’ve gone that path before, and believe me… it’s no sunshine when it comes to maintain it.

So, what we are really building here, is a simple Email SMTP Sender service. Let’s start off by a simple interface:

public interface IMailService
{
    void Send(IMailTemplate template);
}

Simple enough, it’s all we really need for a Simple Mail Service. Feel free to extend and share if you find it useful and make further improvements. But if you noticed, and this is the beauty of the simplicity Dependency Injection provides… this mail sender doesn’t know anything (or very few) about the emails it is sending… it is, again, a SENDER… not a builder.

The Mail Template

Who really handles the content being delivered is (in concept) this IMailTemplate interface:

public interface IMailTemplate
{
    string From { get; }
    IEnumerable<string> To { get; }
    IEnumerable<string> Cc { get; }
    IEnumerable<string> Bcc { get; }

    string Subject { get; } 
    string Content { get; }
    bool IsContentHTML { get; }

    IEnumerable<Attachment> Attachments { get; }
}

This Mail Template is nothing but a builder of a single purpose message. It’s an interface! so you can implement it as many times as you like, with as many different purposes, formats, attachments and even embedded images in HTML as you like.

Concrete Implementations

To show you what the concrete (and probably most common) implementation of IMailService would be, here’s my simple SmtpMailService:

public class SmtpMailService : IMailService
{
    #region IMailService Members

    public void Send(IMailTemplate template)
    {
        try
        {
            SmtpClient client = new SmtpClient();

            MailMessage mailMessage = new MailMessage();

            foreach (var toMail in template.To)
            {
                mailMessage.To.Add(toMail);
            }

            foreach (var ccMail in template.Cc)
            {
                mailMessage.CC.Add(ccMail);
            }

            foreach (var bccMail in template.Bcc)
            {
                mailMessage.Bcc.Add(bccMail);
            }

            mailMessage.Subject = template.Subject;
            mailMessage.Body = template.Content;
            mailMessage.IsBodyHtml = template.IsContentHTML;

            foreach (var attachment in template.Attachments)
            {
                mailMessage.Attachments.Add(attachment);
            }

            client.Send(mailMessage);
        }
        catch { throw; }
    }

    #endregion
}

While leaving plenty of room for improvement, it pulls the job. So all we have to do now, is create our own implementation of the IMailTemplate interface, and we should be ready to start spamming .

I got the following template from a personal project I’m working on… so forgive me if it doesn’t compile out of the box:

public class SuccessfulRegistrationMailTemplate : name.space.IMailTemplate
{
    private User _User;
    private Person _Person;

    public SuccessfulRegistrationMailTemplate(User registeredUser, Person person)
    {
        this._User = registeredUser;
        this._Person = person;
    }

    #region IMailTemplate Members

    public string From { get { return null; } }

    public IEnumerable<string> To
    {
        get { return new string[] { this._User.Email }; }
    }

    public IEnumerable<string> Cc
    {
        get { return new string[0]; }
    }

    public IEnumerable<string> Bcc
    {
        get { return new string[0]; }
    }

    public string Subject
    {
        get { return "Successful Registration - MyWebSite.com"; }
    }

    public string Content
    {
        get
        {
            StringBuilder content = new StringBuilder();
            content.Append("<html><body>");
            content.AppendFormat("<h1>Welcome {0}</h1>", this._Person.FirstName + " " + this._Person.LastName1 + (this._Person.LastName2 ?? ""));
            content.AppendFormat("<p>Welcome to MyWebSite.com.</p>");

            HttpContextWrapper contextWrapper = new HttpContextWrapper(HttpContext.Current);
            UrlHelper helper = new UrlHelper(new RequestContext(contextWrapper, RouteTable.Routes.GetRouteData(contextWrapper)));
            content.AppendFormat("<p>Your Account {0} has been created successfully. Click <a href='{1}'>here</a> to start your session.</p>", this._User.Email, helper.Action("Index", new { controller = "Home" }));
            content.Append("</body></html>");

            return content.ToString();
        }
    }

    public bool IsContentHTML
    {
        get { return true; }
    }

    public IEnumerable<System.Net.Mail.Attachment> Attachments
    {
        get { return new System.Net.Mail.Attachment[0]; }
    }

    #endregion
}

So you can easily send this email like this:

this.MailService.Send(new SuccessfulRegistrationMailTemplate(newUser, newPerson));

And that’s it!

Where is the Dependency Injection part?

In case you missed it, the Dependency Injection comes when the sender receives the IMailTemplate, and asks it for the actual content to construct the MailMessage object with. This is basically “Injecting” the mail addresses, content and attachments into the IMailService sending logic. You can even put DB queries in there! or other Web Service or REST calls!

The Benefits

I’ve tried before constructing these huge moster service or components that would basically know how to build and mail each and every single mail that the system needs to mail out… and end up with an engine, so generic and flexible, that is almost imposible to understand the outcome when you look at the business layer that wants to send the email. So in this approach, I’ve managed to simplify the sending layer, and leave the specifics of each different message to it’s own implementation class.

Another benefit from this is the fact that this is refactorable and redistributable in different projects, as the format and content details are all outside the MailService itself. When I refactor it myself, I’ll make sure I publish it here so everyone can download it’s source and binaries.

Improvements (TODO list)

Well, here’s the list of things that I know you can and may want to put in there… but I just haven’t justified the time to do it.

  • HTML Templating: This kind of beats the “simple is better” approach cause introducing HTML templating with String token replacements will most likely turn this simple Mail Service into an obscure unmaintaineable monster… but hey, who am I to judge? I do grant the fact that in very simple and small applications, it’s probably easier to have HTML token replacements than dynamic HTML construction. Perhaps you are considering this for a CMS… you never know…
  • Asynchronous Programming Model (APM): There’s a single “Send” method on the Mail Service, but it’d be great if it had a BeginSend and EndSend for asynchronous mail sending. It’s all possible!
  • Queuing and Retrying: Though this is way beyond the features of a Simple Mail Service, handling mail sending using a Queue and Retrying whenever the error can be picked up during an SMTP send can turn very beneficial to largely loaded applications.
  • Non-SMTP delivery: You may verywell want to deliver messages not using SMTP. Perhaps a pickup folder of the local SMTP service, or an XML messaging model for console-geeks… whatever it is, this model actually applies to any construction of messages… not just Email messages.
  • View Engine Templates: I left this to the last, but highlighted it cause it’s far from being the least important. You can setup an IMailTemplate implementation that uses the View Engine of an ASP.NET MVC application (if you are building an MVC web site, of course :)) to generate your mail contents using the Controller-View architecture. This is similar to what MvcMailer and ActionMailer do.

Hope you enjoyed this post, and please leave your feedback on your way out!