New way to send fancy template emails in ASP.NET MVC

SAMPATH DASSANAYAKE    MAR 01

In most web applications there are needs to send emails to users. And most of the time, these emails have to resemble the look and the feel of the web site, keeping the web site's branding and theme in the email messages as well.

On a recent web application that we were working on there were several emails that needed to be be sent and the client had done designs for the emails. The actual emails that were sent had to fill these templates with the users data and be sent out. These emails resembled the web pages that the user would see on the site.

After searching for the best way to send out templated emails, this is the solution we came up with. We wanted a solution that would stick to the MVC architecture that the site was using.

We created a Controller named EmailController. For each email that needed to be sent, we created an ActionResult method. Each ActionResult had a corresponding View. In this view we placed the HTML for the email template, and populated this View though the data passed to it by the ActionResult. Then using screen scraping, required method would populate the View, scrape the HTML and place it on the body of the email and send it out.

The application structure looked like the following. For brevity I have omitted the rest of the files in the application file structure and showing only the files related to sending the emails.

  • <Models>
  • <Controllers>
    • AccountController.cs
    • EmailController.cs
  • <Views>
    • WelcomeEmail.aspx

Let's consider the Welcome Email. The EmailController.cs will have the following ActionResult.

   1: public ActionResult WelcomeEmail(int id) {
   2:     if (Request.IsAuthenticated == false)
   3:         return View("AccessDenied");
   4:  
   5:     User u = new UserRepository().Get(HttpContext.User.Identity.Name);
   6:     if (u != null) {
   7:         ViewData["email"] = u.Email;
   8:         ViewData["pss"] = u.Password
   9:     }
  10:     return View();
  11: }
  12:  

This method first checks if the request is authenticated, which means the current users is logged in. Then it retrieves the user from the UserRepository by the user name saved in the HTTPContext and populates the ViewData fields for email and password.

The WelcomeEmail.aspx page is a ASPX page which is designed using a Table HTML layout with inline CSS. The reason for using a table layout is when it comes to emails the most assured way to ensure that your email will display as intended is to use the HTML table based layout. Some email clients will not render the DIV's as intended. Also, the CSS has to be inline as most email clients tend to ignore the references to external CSS files.

Then on the Account Controller, which is the actual controller that handles the user registration, we call the WelcomeEmail ActionResult.

   1: [AcceptVerbs(HttpVerbs.Post)]
   2:  
   3: public ActionResult Register(User user) {
   4:  
   5:     // Validate inputs and create the User Account
   6:  
   7:     //Add an Auth Cookie
   8:  
   9:     //Send email
  10:  
  11:     string subject = "Welcome To Our Site";
  12:  
  13:     Helpers.Email.SendTemplatedEmail(
  14:         System.Configuration.ConfigurationManager.AppSettings["emailAddress"], 
  15:         user.Email, 
  16:         subject, 
  17:         Url.Action("WelcomeEmail", "Email", 0, "http") + "/" +u.UserID);
  18:  
  19:     Return View();
  20:  
  21: }
  22:  

The actual email sending is handled by a Helper Method.

   1: public static void SendTemplatedEmail(string from, 
   2:                                     string to, 
   3:                                     string subject, 
   4:                                     string templatePath){   
   5:  
   6:     MailMessage mm = new MailMessage(from, to);   
   7:     mm.Subject = subject;   
   8:     mm.Body = GetEmailBody(templatePath);   
   9:     
  10:     if (mm.Body != "") {  
  11:         mm.IsBodyHtml = true;  
  12:         SmtpClient smtp = new SmtpClient();  
  13:         smtp.Send(mm);  
  14:     }  
  15: }
  16:  
  17: public static string GetEmailBody(string templatePath){
  18:      System.Net.WebClient objWebClient = new System.Net.WebClient();
  19:      byte[] aRequestedHTML = null;  
  20:      string strRequestedHTML = null;
  21:  
  22:      aRequestedHTML = objWebClient.DownloadData(templatePath);
  23:      System.Text.UTF8Encoding objUTF8 = new System.Text.UTF8Encoding();     
  24:      strRequestedHTML = objUTF8.GetString(aRequestedHTML);
  25:  
  26:      return strRequestedHTML;
  27: }
 
The SendTemplateEmail method calls GetEmailBody method to scrape the HTML from the View. This line objWebClient.DownloadData(templatePath) when executed actually loads the View passed to it in the templatePath variable and passes the HTML which we encode and extract as HTML. Then this extracted HTML is set on the email body and the email is sent.

Comments

DotNetKicks.com   3/2/2010 6:46:47 AM #

New way to send fancy template emails in ASP.NET MVC

You've been kicked (a good thing) - Trackback from DotNetKicks.com


Bobby   3/3/2010 8:40:55 AM #

Hey there, are you having issues with your hosting? I needed to refresh the page about four times to get the page to load. You might want to change hosts. Or could the problem be from me?


chips zynga   3/3/2010 10:30:55 AM #

i am quite often surfing about the online world the majority of the week which means I have a tendency to peruse an awful lot, which isn't always a good factor as a large amount of the web pages I see are constructed of useless garbage copied from various other sites a million times, on the other hand I have to give you credit this blog is indeed not bad at all and also boasts a lot of original substance, for that reason thank you for helping to stop the phenomena of only replicating other people's blogs, in case you ever want to try a few hands of zynga poker with me just let me know - you have my e-mail Smile


dorian   3/3/2010 1:58:44 PM #

@Bobby - I don't think we're having issues.

@everybody - let me know if anybody else is having problems.

Subscribe to our feed - we're continually working with new ASP.NET technologies and will continue share our insights with you.


Sampath Dassanayake   3/3/2010 2:20:51 PM #

Thanks for all the comments. It is nice to get some feedback.

Like @dorian said, we will be posting new stuff we learn, the challenges we come across and how we solved them through this blog. We learn a lot from the knowledge on the Internet and are keen to share what we put together.

If you keep reading, we'll keep them coming Smile


Ian Mercer   3/4/2010 9:38:33 AM #

Using WebClient to scrape your own screens seems rather ugly.

www.brightmix.com/.../ has a good solution for rendering a View to a string so you can send it in email.

/// Static Method to render string - put somewhere of your choosing
public static string RenderPartialToString(string controlName, object viewData)
{
     ViewDataDictionary vd = new ViewDataDictionary(viewData);
     ViewPage vp = new ViewPage { ViewData = vd };
     Control control = vp.LoadControl(controlName);

     vp.Controls.Add(control);

     StringBuilder sb = new StringBuilder();
     using (StringWriter sw = new StringWriter(sb))
     {
         using (HtmlTextWriter tw = new HtmlTextWriter(sw))
         {
             vp.RenderControl(tw);
         }
     }

     return sb.ToString();
}


dorian   3/4/2010 9:45:12 AM #

@Ian Good suggestion! We'll take that into consideration and possibly change the code.

We like using views because it allows us to preview the populated template in a browser, and it clearly separates the building and sending of the template, but we shouldn't be using HTTP to scrape it before sending it. I believe your suggestion will increase performance and reliability.


Sökordsoptimering   3/5/2010 5:51:58 AM #

Hi. I just noticed that your blog looks like it has a few code problems at the very bottom of your website's page. I'm not sure if everybody is getting this same bugginess when browsing your website? I am employing a totally different browser than most people, referred to as Opera, so that is what might be causing it? I just wanted to make sure you know. Thanks for posting some great postings and I'll try to return back with a completely different browser to check things out!


Cadred (dotNET)   3/5/2010 8:23:23 AM #

.NET Pulse 3/5/2010

.NET Pulse 3/5/2010


RUTH BRANCH   3/12/2010 2:18:39 AM #

nice excellent blog yea nice job our website will soon be adding reviews on blogs and add them to our websites as the top best 1000 blogs to visit we also do reviews on Product Reviews  all types of reviews we will get back to you


Online Games   3/14/2010 8:44:25 PM #

Hi, just today discovered this blog but I have to say that it looks nice. I totally agree with you. Have a good day, keep up the great work and I will definitely come back.


Jodee Jericho   3/15/2010 1:15:42 AM #

Hi, I don't agree with everything in this write-up, but you do make some very good points. I'm very interested in this matter and I myself do alot of research as well. Either way it was a well thoughtout and nice read so I figured I would leave you a comment.


emma watson pics   3/23/2010 11:46:11 AM #

Good stuff on New way to send fancy template emails in ASP.NET MVC. I even agree with most of it!


Comments are closed