Summary
The following article contains code to send data via a dictionary to a Mail Helper which builds an html email based on an Email template defined by a user control.
Premise
At work, I have had to build websites which send out html emails. We already had some code which loaded a user control into an html writer, which gave a html string to be placed in the html body for sending .Net mail. I wanted to abstract the logic out so that I could reuse it in any of my projects without having to modify all the parameters etc.
Essentially the things that were different were the HTML template, and the data to be bound to the template. Everything else; the building, the sending all had the same logic.
The Code
First we have the MailHelper class, which will build and send the email. We pass in the path of the email template, and basic email parameters such as to, from and subject. The dictionary is a string object pair for convenience. Use the string as a key to reference your objects similar to a ViewState or ViewModel.
Then you will see the EmailControl class which extends UserControl. We want to place a method there for setting the key value pairs. And then we want all Email templates to extend from this class.
public static class MailHelper
{
public static void SendEmail(string controlPath,
string to,
string from,
string subject,
Dictionary<string, object> keyValuePairs)
{
var body = GenerateContactEmailBody(controlPath, keyValuePairs);
var officeMessage = new MailMessage(from, to)
{
Subject = subject,
IsBodyHtml = true,
Body = body
};
var client = new SmtpClient();
client.Send(officeMessage);
}
private static string GenerateContactEmailBody(string path,
Dictionary<string, object> keyValuePairs)
{
Page pageHolder = new Page();
var emailControl = (EmailControl)pageHolder.LoadControl(path);
emailControl.SetKeyValuePairs(keyValuePairs);
var writer = new StringWriter(CultureInfo.CurrentCulture);
emailControl.RenderControl(new Html32TextWriter(writer));
return writer.ToString();
}
}
public class EmailControl : System.Web.UI.UserControl
{
public virtual void SetKeyValuePairs(Dictionary<string,object> value)
{
throw new NotImplementedException();
}
}
So now we can create a new HTML Email template. Create a new UserControl, make this extend EmailControl instead of extending UserControl directly. Then override the SetKeyValuePairs method. In my example below, I have a ContactUs email template where I accept values for Name, Email, Telephone, and Question. These are all strings but could have been other objects.
Then in my ascx file, I create the html template as per a design, and bind the properties where they are needed. The override for RenderControl is needed when we generate the html in the MailHelper.
public partial class ContactUs : EmailControl
{
public override void SetKeyValuePairs(Dictionary<string, object> value)
{
Name = value["Name"].ToString();
Email = value["Email"].ToString();
Telephone = value["Telephone"].ToString();
Question = value["Question"].ToString();
}
public string Name { get; set; }
public string Email { get; set; }
public string Telephone { get; set; }
public string Question { get; set; }
public override void RenderControl(HtmlTextWriter writer)
{
DataBind();
base.RenderControl(writer);
}
}
Finally, the bit of code which I call on my page which actually calls the MailHelper and sends out the email.
var kvp = new Dictionary<string, object>();
kvp.Add("Name", name);
kvp.Add("Email", email);
kvp.Add("Telephone", telephone);
kvp.Add("Question", question);
var to = ConfigurationManager.AppSettings["ContactTo"];
var from = ConfigurationManager.AppSettings["ContactFrom"];
var subject = ConfigurationManager.AppSettings["ContactSubject"];
MailHelper.SendEmail("~/ContactUs.ascx", to, from, subject, kvp);