Generate HTML e-mail body in C# using templates

Almost a year ago, I answered a question on StackOverflow, about if there’s a better way to generate HTML e-mails in C# than using a StringBuilder and just appending strings one by one.

I think that any modern piece of software today, needs to send e-mail. Whether it being password recovery e-mails, rich reports, newsletters or anything else – being able to easily see and customize the look and feel of your e-mails is vital.

So, the worst way I could think of is having your HTML hidden away in some StringBuilder.Append() hell. The best solution (in my opinion) would be, if you could have plain old HTML files with parameters like <#FirstName#> so you could dynamically replace those at runtime.

The MailDefinition class

Luckily, there’s a class for that! If you read the comments on my answer on StackOverflow, you’ll notice that none of them was familiar with that class and it came as a bit of a surprise. It did for me too, I actually wrote my own “MailDefinition” class that did just about the same thing. A complete waste of time, and it only tells me that us, developers, are sometimes too trigger happy on the keyboard instead of doing some research first. A quick search in the MSDN documentation would have saved me some work here and there.

Using the MailDefinition class is pretty straight forward. You use the MailDefinition class to create an instance of MailMessage, which you can send straightaway:

MailDefinition md = new MailDefinition();
md.From = "test@domain.com";
md.IsBodyHtml = true;
md.Subject = "Test of MailDefinition";

ListDictionary replacements = new ListDictionary();
replacements.Add("<%Name%>", "Martin");
replacements.Add("<%Country%>", "Denmark");

string body = "
Hello <%Name%>

You're from <%Country%>.
"; MailMessage msg = md.CreateMailMessage("you@anywhere.com", replacements, body, new System.Web.UI.Control());

Instead of having the HTML inside the code, you could easily have it in your database or as a file on the computer. That will also enable you to edit the look and feel of the HTML template at any time, without having to rebuild and deploy your application.

MailDefinition is located in the System.Web assembly, so don’t forget to add reference to that from your project.

  • Pingback: How to Send HTML E-mail from an ASP.NET MVC Controller | Martin Normark's blog

  • bri

    Bad choice of <% tags above. I had to view the source to see what you meant in your code snippet.

  • http://www.milkshakecommerce.com/ecommerce-blog Martin H. Normark

    It doesn’t seem to mess things up in my browser, but I do have problems with code formatting occasionally – I’m thinking about hosting code snippets using Github.

  • Geiger

    Why not just use string.format?

    string body =  Server.HtmlEncode(string.Format(@”Hello {0}

     

    You’re from {1}.

     

     

    “,

     “Martin”,

     “Denmark”));

  • http://www.milkshakecommerce.com/ecommerce-blog Martin H. Normark

    You could easily do that. But then you lose the ability to have HTML templates with named replacement-tokens – which is kind of the point. Editing the templates would be very hard, if all tokens were {0}…{n}, and there were quite a few of them.

    Much easier to see what each parameter is with the tokens.

  • Paul King

    That is awesome. Thank you so much.

  • Avinash

    I’m curious to Know how to Insert the HTML content from a file.
    I mean , I have the HTML file in the system, I just need to insert this as body

  • http://www.milkshakecommerce.com/ecommerce-blog Martin H. Normark

    This is how you read the body from a file on disk: 
    https://gist.github.com/1668751

  • JM

    Thanks Martin! This blog helped me a lot! =)

  • Jeffclark

    I am interested in this article.  I have looked to send HTML through email on the web and only found stringbuilder solutions.  What I want to find out is if I have an HTML document on disk and I want to read that into the body of my email and then replacing information into original HTML file in the email.  So not to confuse you.  I have an HTML form that I want to populate and email from my website.  Can you direct me on how to go about this?

  • http://www.milkshakecommerce.com/ecommerce-blog Martin H. Normark

    Hi

    Look at this for reading files from disk: http://msdn.microsoft.com/en-us/library/db5x7c0d.aspx

    And this for writing the output back to disk: http://msdn.microsoft.com/en-us/library/6ka1wd3w.aspx

    After calling CreateMailMessage you should be able to get the body, by reading the Body property on the MailMessage returned.

  • http://www.facebook.com/Rettungsschirm Федя Михайлович Сумкин

    MailDefinition is actually a strange class, which uses ViewState to save property velues. And it forces you to create an instance of new System.Web.UI.Control(), what I don’t like to do. The only usefull thing it does – it appends an “AlternateView” to msg.AlternateViews:
    AlternateView alternateView = AlternateView.CreateAlternateViewFromString(body, null, “text/html”);
    msg.AlternateViews.Add(alternateView);
    this peace of code is what you actually need. Well, this ist true for me, but if you really want to read a file from disk each time before sending an e-mail, using MailDefinition class may be fine.

  • http://www.milkshakecommerce.com/ecommerce-blog Martin H. Normark

    Hi

    You don’t have to read the content from disk. In my example I pass in the body via a string: MailMessage msg = md.CreateMailMessage(“you@anywhere.com”, replacements, body, new System.Web.UI.Control());

  • lbytesxk

    Hello
    Does this only work with web based emails or can I use it with System.Net.Mail class? (need to send HTML email via exchange server)
    thanks

  • http://www.milkshakecommerce.com/ecommerce-blog Martin H. Normark

    It does work with System.Net.Mail — when you call CreateMailMessage on the MailDefinition, it returns an instance of System.Net.Mail.MailMessage for you to sent: http://msdn.microsoft.com/en-us/library/ms156159.aspx

  • Thando Khumalo

    Great staff!! It works even if you use the MailMessage(): System.Net.Mail class. I was missing the message.IsBodyHtml = true par, thanks Martin

  • http://www.milkshakecommerce.com/ecommerce-blog Martin H. Normark

    You’re welcome!

    Glad you liked it.

    / Martin


    Sent from Mailbox for iPhone

  • Pingback: Generating HTML email body in C# - C# Solution - Developers Q & A

  • http://blog.benpowell.co.uk Ben Powell

    This looked so promising, but I find it sad that this class is so tightly bound to System.Web.

    Often you want to send email from applications other than a website, or the business logic is buried outside the website in an enterprise solution and you don’t want to add a reference to System .Web from your business logic (often you can’t since you’d create a circular reference).

    Looks like an opportunity to build something similar without this dependency.

  • http://martinnormark.com/ Martin H. Normark

    Hi Ben

    I’ve actually moved entirely away from this approach, and instead I use MvcMailer for rendering/generating HTML e-mails.

    https://github.com/smsohan/MvcMailer

    Regarding business logic, I’ve added a dedicated MailController to my MVC project that provides a set of action that can be called via simple HTTP GET/POST request from other backend services etc. so I always have e-mail templates in the same place, and they’re always sent from the same place as well.

  • Pingback: [RESOLVED]Email a page | ASP Questions & Answers

  • Pingback: [RESOLVED]Email a page | ASP Web Form Data Control

  • Pingback: [RESOLVED]Email a page | ASP.NET MVC

  • Rajmohan G

    This really useful. Can I pass array value to template and use it?

  • http://martinnormark.com/ Martin H. Normark

    For more complex models, you’ll be better off using something like MvcMailer: https://github.com/smsohan/MvcMailer

    Then you can create a view, just as if it was a view for any controller action and you can iterate through the items in the array.