This site's name is dot net tricks (dotNetTricks.com), so I guess I have to show a trick first. I'm taking some advice from Craig on Picking Low Hanging Fruit first, so I can get into a rhythm and hopefully have a couple posts a week.
In the spirit of all things 2.0, I think I want to show how to leverage the built in email template functionality in ASP.net 2.0, called MailDefintion. I don't believe I've ever seen a post on this, so this is sort of a good place to leverage some useful functionality that's really easy to use and you can build a pretty decent emailing templating system in a short time.
The basis of this stems from the controls such as the CreateUserWizard Controls, which can send emails based on templates you define within the control. I see it as a useful feature and really wished that this was exposed a bit more for consumption.
<asp:CreateUserWizard ID="CreateUserWizard1" Runat="server">
<MailDefinition
BodyFileName="~/RegistrationEmail.txt"
From="http://nettiers.com"
Subject="Thanks for registering!">
</MailDefinition>
</asp:CreateUserWizard>
|
So, I took a look at that and said, hey, why are the membership controls the only ones that can define a MailDefinition, I want to use that in my controls too. So, a few minutes with
Reflector told me how the controls levered the functionality that I wanted as well.
The calling code ends up looking this:
ListDictionary replacements = new ListDictionary();
replacements.Add("<%UserName%>", userName);
replacements.Add("<%TeamMember%>", teamMember);
// it can only be used in the context of a control, so I usually send over the control responsible for the tirggering event.
bool emailSent = WebNotificationManager.SendMessage(btnSubmitEmail, MessageTemplate.DownloadInstructions, replacements,
userEmail, Resources.MailSubject.DownloadSubject);
|
Then the control automagically fires off that email based on settings you put in the web.config.
<system.net>
<mailSettings>
<smtp from=“info@nettiers.com”>
<network host=“mail.nettiers.com” userName=email@name.com password="somepass" />
</smtp>
</mailSettings>
</system.net>
|
For ease of use, I created a MessageTemplate enumeration to hold all of the templates that exists in the application, this could live in the DB as well, it didn't make sense in the application I was writing at the time.
/// <summary>
/// Summary description for MessageTemplate
/// </summary>
public enum MessageTemplate
{
None,
ThankYouForVisiting,
DownloadInstructions
}
|
For this example I'm going to use the DownloadInstructions template which looks like this.
~/App_Data/DownloadInstructions.txt
Hi <%UserName%>,
Please download .netTiers at www.nettiers.com.
Thank you,
<%TeamMember%>
.netTiers Team
|
Really now you get it to work by creating a MailDefinition in code based on your template you provide.
public static bool SendMessage(WebControl owner, MessageTemplate messageTemplate, ListDictionary replacements, string to, string subject)
{
MailMessage mailMessage = CreateMessage(owner, messageTemplate, replacements, to, null, null, subject);
return InternalSend(mailMessage);
}
|
private static System.Net.Mail.MailMessage CreateMessage(WebControl owner, MessageTemplate messageTemplate, ListDictionary replacements, string to, string from, string cc, string subject)
{
string physicalPath = HttpContext.Current.Server.MapPath("~/App_Data/messages/" + messageTemplate.ToString() + ".txt");
if (!File.Exists(physicalPath))
{
throw new ArgumentException("Invalid MailTemplate Passed into the NotificationManager", "messageTemplate");
}
MailDefinition md = new MailDefinition();
md.BodyFileName = physicalPath;
md.Subject = subject;
md.From = from;
md.CC = cc;
md.IsBodyHtml = false;
System.Net.Mail.MailMessage mailMessage; //this actually processes all of the replacement vars that you've included.
mailMessage = md.CreateMailMessage(to, replacements, owner);
return mailMessage;
}
|
There are many ways to sending the actual email, it's not that glamorous, but i'm including the code anyway so that this example will be feature complete.
private static bool InternalSend(MailMessage mailMessage, bool isAsync)
{
try
{
if (!isAsync) // blocks current thread
WebMailSender.SendMailMessage(mailMessage);
else // does not block current thread
WebMailSender.SendMailMessageAsync(mailMessage);
}
catch (Exception exc)
{
//handle, log, do something
throw;
}
return true;
}
|
public static bool SendMailMessage(MailMessage mailMessage)
{
try
{
SmtpClient client = new SmtpClient();
client.Send(mailMessage);
}
catch (Exception exc)
{
// Log
throw;
}
return true;
}
public static void SendMailMessageAsync(MailMessage mailMessage)
{
try
{
SmtpClient client = new SmtpClient();
client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
client.SendAsync(mailMessage, mailMessage.To.ToString());
}
catch (Exception)
{
//Log
throw;
}
}
|