The Problem
Did you ever have to send a professional looking HTML email from your ASP.NET MVC APP? Say, to welcome a newly signed up user or to send a password reset link? I am sure at some point you had to! Well, at some point, we all have to send out emails from our app, be it for the sake of a notification or the "tell a friend" feature or anything... the sad part is, constructing HTML emails with personalized text, images and styles is at least a pain in the neck (or somewhere else for that matter)! To visualize, this is how it often looks in the code:
StringBuilder mailBody = new StringBuilder();
mailBody.Append("<html><head><style type=\"text\css\">...</style></head>");
mailBody.Append("<body>")
mailBody.AppendFormat("Hi {0}<br/>", user.FirstName);
...
... XX lines of similar Appending unless it its done!
...
mailBody.Append("</body></html>");
A Desired Solution
Wait a minute! We are already creating complex HTML views with all the styling, master paging and dynamic content from our MVC view files. This is exactly what we need in the HTML emails! So, to me, a desired solution will be like the following:
/* Layout: ~Views/Notifier/_Layout.cshtml */
<html>
<head>
<style type="text\css">
...
</style>
</head>
<body>
<div class="banner"></div>
<div class="mailBody">
Hello @user.FirstName:<br/>
@RenderBody()
Thank you.
--
The Team!
</div>
<body>
</html>
/* WecomeMessage: ~Views/Notifier/WelcomeMessage.cshtml */
Welcome to the Team Site. Please click the following link to complete your account signup!
@Html.ActivationLink(user.ActivationUrl)
Isn't this cleaner?
Introducing MvcMailer NuGet package
MvcMailer
is available here. To install this, just open up your Package Manager Console and run "Install-Package MvcMailer" (without the quotes) and you are done! If you are new to NuGet, I would recommend you to install it to utilize free libraries out there as a plugin to your app just like MvcMailer
!
Using MvcMailer
Once you install MvcMailer
NuGet package, it adds the following to your project:
- A reference to Mvc.Mailer.dll
- Notifier.cs to Mailers
- _Layout.cshtml and WelcomeMessage.cshtml to Views/Notifier
system.net mailSettings
to web.config
If you open Mailers/Notifier.cs, you will find an example of how to send emails using the MvcMailer
library. You can follow this list to get up and running in 3 minutes:
- Open up web.config and replace the placeholders with appropriate values for the following section:
<smtp from="some-email@gmail.com">
<network enableSsl="true" host="smtp.gmail.com"
port="587" userName="some-email@gmail.com" password="valid-password"/>
</smtp>
- Open Mailers/Notifier.cs and replace the recipient with an appropriate email address:
mailMessage.To.Add("some-email@gmail.com");
- Now, add the following code to send an email in your controller, model or anywhere else:
using Mvc.Mailer;
using YourAppRootNamespace.Mailers;
...
new Notifier().WelcomeMessage().Send();
...
You can also send asynchronous email by using the following:
new Notifier().WelcomeMessage().SendAsync();
So, all in all, just 1 line of code on top of its 2 lines of standard .NET Mail configuration to send email utilizing the power of all MVC Views! Sounds good, huh?
How Does This Work?
If you look in the WelcomeMessage()
method inside Mailers/Notifier.cs, you will see this line:
mailMessage.Body = PopulateBody(mailMessage: mailMessage,
viewName: "WelcomeMessage")
The above line populates the mailMessage.body
with the string
containing the compiled HTML from the view as it would be in the case of a regular MVC view! So, you get full power of your view engine to build the email body instead of the ugly looking string
concats all over the place!
As you can see, it uses the same view engine as your rest of the views do. So, it just reuses the components from the existing ASP.NET MVC framework and extends on top of it. It extends the ViewResult
class of ASP.NET MVC with a new class called StringResult
. StringResult
does exactly what ViewResult
does with one exception: instead of writing to the HTTP Response Output Stream, it simply writes to a StringBuilder
! So, the HTML generation is exactly the same, but the rendering is different.
Now that the view, along with its master pages and dynamic contents are compiled into a string
, it can be used as the email's body. This is how it works. Apart from this, it leverages the standard MailMessage
class of System.Net.Mail namespace
. So, it doesn't really have any learning curve for someone who already knows about the ASP.NET emailing libraries.
To simplify things, Mvc.Mailer
namespace has an extension class for MailMessage
that adds two handy methods to it - namely, Send() and SendAsync()
. These methods simply relay to an instance of the SmtpClient
class. So that your code doesn't need to deal with all these transport layer details and can stay at a fairly high level similar to the Controller Actions
, you simply fire the view and forget about how it is actually sent to the output stream!
A Few Interesting Points
- The idea to implement
MvcMailer
actually came while I was browsing ASP.NET MVC source code.
- The idea originates from my Ruby on Rails background.
- NuGet packaging seems to be a good way of releasing plugins for .NET applications!
- The source code for
MvcMailer
has only tens of lines, if you want, you can take a look at this github page!
Interesting Updates
- Jan 28, 2011 -
MvcMailer
0.7 is released. This version adds automated test support for code that use MvcMailer
to send emails.
- Jan 28, 2011 - MvcMailer-Example project is pushed to github. Use the example project to get up and running with
MvcMailer
even more quickly!