Life, the Universe, and Software EngineeringLife, the Universe, and Software Engineering

Corporate Ready HTML and Plain Text Email with SmtpClient

Main Image

Here is a new email template library that makes it dead easy for your web application to send the most professional looking email using as little as three lines of code.

Sending plain text email from your web application has always been relatively easy using the SmtpClient, but most web applications end up with a lot of hard coding to do this.  Changing email address and messages can require a site recompile.  Of course, one can pull in a format template from a text file but that again requires additional code and gains only minor improvements to flexibility.

Here is an example of the type of email that can be produced with the email template library:

Email4

 

and the code used to produce this email: 

EmailTemplate emailTemplate =EmailTemplate.Load(Server.MapPath("./EmailTemplates/EmailTemplate4.xml"));

WebEmailArgumentList argumentList = newWebEmailArgumentList();

argumentList.AddExtensionObject("cart", shoppingCart);

SmtpClient smtpClient = newSmtpClient();

smtpClient.Send(emailTemplate.CreateMailMessage(argumentList));

You can see that I cheated and used 5 lines of code.  A simpler email, that does not use rich data, such as the shopping cart above could actual be sent with a SINGLE line of code:

newSmtpClient().Send(EmailTemplate.Load(Server.MapPath("./EmailTemplate1.xml")).CreateMailMessage());

Now I wouldn’t recommend that you collapse things to just one line of code, as it makes reading code a lot more difficult, but I did it here to highlight the simplicity of using the this email library to send, not just plain text, but HTML email with attachments and embedded resources.

Historic SmtpClient Code

For those of you who have not used the SmtpClient provided in the System.Net namespace of the .NET object library, below is an example of the typical coding need to sent a plain text email:

SmtpClient smtpClient = newSmtpClient();

smtpClient.Host = "mail.bobsbigburgers.com"

;

MailMessage mailMessage = new MailMessage();

mailMessage.From = new MailAddress("webteam@bobsbigburgers.com");

mailMessage.To.Add(new MailAddress(txtEmail.Text, txtFirstName.Text + " " + txtLastName.Text));

mailMessage.CC.Add("bob@bobsbigburgers.com");

mailMessage.Subject = "Old style email message send test";

mailMessage.Body = string.Format(@"{0},
Thank you for pressing the ""Send Email"" button.
Your participation is greatly appretiated,
Bob's Big Burgers
", txtFirstName.Text);

smtpClient.Send(mailMessage);

I starting working on this email template library a number of years ago in a effort to not have to recode the code you see above each time an email message was required on a web site.  Recently I took an other look at the library and decided to update it to handle more complex email message processing.  The result is the library you see now.   The email template library can now produce just about any data rich, corporate ready email with just a few lines of code.

So now lets dig a little deeper into the library and see what makes the magic happen,  and, of course, the catch… there always has to be a catch. 

A Simple Email Template

Lets take a look at a simple email first, just an acknowledgment that something happened on the web site,  one that does not need dynamic data, such as a user’s personal information, which may change, based on data entered on the page.  The need for this type of email message is fairly rare on a web site, but it will get us started exploring the library.

Below is an rendering of a simple HTML email message, and the 3 lines of hard coding necessary to sent it:

Simple Email

 

EmailTemplate emailTemplate =EmailTemplate.Load(Server.MapPath("./EmailTemplates/EmailTemplate1.xml"));

SmtpClient smtpClient = newSmtpClient();

smtpClient.Send(emailTemplate.CreateMailMessage());

Let’s examine the template file used to produce the above email.  This, of course, is the “catch”.  Simplifying the hard coding requirement moves the complexity of the email message into the template file.  The advantage of doing this though, is the complete flexibility of adjusting your email messages with out the need to involve the web site developer or recompile the site. 

<?xml version='1.0' encoding='utf-8'?>
<em:email-template

xmlns:em='http://daisley-harrison.com/namespaces/EmailTemplate'>
    <em:from>Bob's Big Burgers &lt;webteam@bobsbigburgers.com&gt;</em:from>
    <em:to>[settings:email-template1-to]</em:to>
    <em:cc>willam@bobsbigburgers.com, pebbles@bobsbigburgers</em:cc>
    <em:bcc>bob@bobsbigburgers.com</em:bcc>
    <em:subject>Way to go team!</em:subject>
    <em:body>
Someone just purchased a bunch of stuff!
    </em:body>
    <em:alternate-views>
       <em:alternate-view>
           <em:body>
                <html xmlns='http://www.w3.org/1999/xhtml'>
                    <body>
                        <div>
                            <a href='http://www.bobsbigburgers.com'>
                                <img src='[linked-resource:./Images/Logo.jpg]' alt='logo'/>
                            </a>
                        </div>
                        <h1>Bob's Big Burgers Did It Again</h1>
                        <p>
                             Someone just purchased a bunch of stuff!
                        </p>
                    </body>
               </html>
            </em:body>
        </em:alternate-view>
    </em:alternate-views>
</em:email-template>

 

Note that the above template is actual producing a fairly sophisticated email.  The message itself contains a plain text email, an alternate HTML view, and an embedded logo image. 

The Email Template root element

Lets examine the component parts of this template starting with the root element:

<?xmlversion='1.0'encoding='utf-8'?>
<em:email-template

xmlns:em='http://daisley-harrison.com/namespaces/EmailTemplate'>
        …
</em:email-template>

First, for those of you not too familar with XML, please note the email template namespace declared as xmlns:em='http://daisley-harrison.com/namespaces/EmailTemplate' and that all email template tags are prefix with “em:“.  This exact template namespace must be declared in order for the template to be loaded correctly by the library.  The prefix “em” can actual be any name you choose, or if you declare the namespace with xmlns='http://daisley-harrison.com/namespaces/EmailTemplate' you don’t need the prefix on any of the element names. For example:

<?xmlversion='1.0'encoding='utf-8'?>
<email-template

xmlns='http://daisley-harrison.com/namespaces/EmailTemplate'>
    <from>webteam@bobsbigburgers.com</from>
        …
</email-template>

In the case of our full sample email template we send HTML tags in the email body, so it is more convenient to specify a namespace prefix for the template elements.  This means we can write the HTML language elements without an namespace prefix making the HTML tags easier to read.

The Email Template address elements

Now lets look at the email address elements:

<?xmlversion='1.0'encoding='utf-8'?>
<em:email-template

xmlns:em='http://daisley-harrison.com/namespaces/EmailTemplate'>
    <em:from>Bob's Big Burgers &lt;webteam@bobsbigburgers.com&gt;</em:from>
    <em:to>[settings:email-template1-to]</em:to>
    <em:cc>willam@bobsbigburgers.com, pebbles@bobsbigburgers</em:cc>
    <em:bcc>bob@bobsbigburgers.com</em:bcc>
    …

</em:email-template>

Notice the template expression in between the <em:to>…</em:to> tags that reads “[settings:email-template1-to]”.  Template expressions are evaluated by the email template processing engine to include dynamic data in the resulting mail message.  Template expressions can appear inside any element or attribute value and are recognized by the email template processor when they are enclosed in square brackets ( “[” or “]” ).  In this case the expression looks up the value of the application settings key “email-template1-to” from the application configuration file, which in our case is the web.config file.

The email Template subject element

 

<?xmlversion='1.0'encoding='utf-8'?>
<em:email-template

xmlns:em='http://daisley-harrison.com/namespaces/EmailTemplate'>

    …

    <em:subject>Way to go team!</em:subject>

    …

</em:email-template>

This element is farly straight forward, it sets the value of the subject line of the email mesage.  This field, like most other can also contain template expressions. For example:

 

<?xmlversion='1.0'encoding='utf-8'?>
<em:email-template

xmlns:em='http://daisley-harrison.com/namespaces/EmailTemplate'>

    …

    <em:subject>The email was sent by [settings:WebMasterFirstName]</em:subject>

    …

</em:email-template>

Of course for this to work, your web.confing file needs to have an appSettings section similar to the following:

<?xml version="1.0"?>
<

configuration>    …
<appSettings>
   …
    <add key="email-template1-to" value="test1@bobsbigburgers.com"/>
    <add key="WebMasterFirstName" value="Fred"/>
    …
</appSettings>

   …


</configuration>

The template body element

The template body element can contain any type of text or xml markup that you want.  The template engine recognizes template expressions (closed in square brackets) as well as a fairly sophisticated set of process flow and conditional elements such as <em:if>...</em:if> <em:choose>...</em:choose> and <em:for-each>...</em:for-each> to name a few.  For more detalis see our support page titled Email Template Files

<?xml version='1.0' encoding='utf-8'?>
<em:email-template

xmlns:em='http://daisley-harrison.com/namespaces/EmailTemplate'>
    …
    <em:body>
Someone just purchased a bunch of stuff!
    </em:body>
    …
</em:email-template>

 It is possible to set just a plain text email by leaving out the <em:alternate-views>…</em:alternate-views> section entirely, just leaving the body section containing plain text.   It is also possible to send an HTML only email by also leaving off the alternate-view seciton and specifying html directly in the body.  For example:

 

<?xml version='1.0' encoding='utf-8'?>
<em:email-template

xmlns:em

='http://daisley-harrison.com/namespaces/EmailTemplate'>
    <em:from>Bob's Big Burgers &lt;webteam@bobsbigburgers.com&gt;</em:from>
    <em:to>[settings:email-template1-to]</em:to>
    <em:cc>willam@bobsbigburgers.com, pebbles@bobsbigburgers</em:cc>
    <em:bcc>bob@bobsbigburgers.com</em:bcc>
    <em:subject>Way to go team!</em:subject>
    <em:body>
        <html>
             <h1>Hello World</h1>
        </html>
    </em:body>
</em:email-template>

You can also include one or more template expression in the body text.  For example:

<?xml version='1.0' encoding='utf-8'?>
<em:email-template

xmlns:em

='http://daisley-harrison.com/namespaces/EmailTemplate'>
    <em:from>Bob's Big Burgers &lt;webteam@bobsbigburgers.com&gt;</em:from>
    <em:to>[settings:email-template1-to]</em:to>
    <em:cc>willam@bobsbigburgers.com, pebbles@bobsbigburgers</em:cc>
    <em:bcc>bob@bobsbigburgers.com</em:bcc>
    <em:subject>Way to go team!</em:subject>
    <em:body>
        <html>
            <body>
                 <div>Hello [session:FirstName] [session:LastName],</div>
                 <p>Welcome to this really cool site!</p>

             …

             </body>
        </html>
    </em:body>
</em:email-template>

In the above example the expression [session:FirstName] looks up the first name from the session state variable “FirstName”.  In order for these type of expression to work you will need to first set the session state variables appropriately. For example

EmailTemplate emailTemplate =EmailTemplate.Load(Server.MapPath("./EmailTemplates/EmailTemplate2.xml"));

SmtpClient smtpClient = newSmtpClient(); 

Session["FirstName"] ="Fred"; Session["LastName"] ="Flintstone";

smtpClient.Send(emailTemplate.CreateMailMessage(newWebEmailArgumentList()));

 

Note, to read IIS session state variables and other IIS related objects you must pass an instance of of WebEmailArgumentList to the CreateMailMessage method.

The Template alternate-view element

In our original email template we sent both plain text and HTML text email messages.  This is done so that the resulting email message if friendly to all types of email client.  Some email client can display plain text only, other prefer HTML messages.   To sent more that one type of email body in a single email message, you must to the alternate-view element.

<?xml version='1.0' encoding='utf-8'?>
<em:email-template

xmlns:em

='http://daisley-harrison.com/namespaces/EmailTemplate'>

     …

   <em:body>
Someone just purchased a bunch of stuff!
    </em:body>

    …


    <em:alternate-views>
        <em:alternate-view>
           <em:body>
                <html xmlns='http://www.w3.org/1999/xhtml'>
                    <body>
                        <div>
                            <a href='http://www.bobsbigburgers.com'>
                                <img src='[linked-resource:./Images/Logo.jpg]' alt='logo'/>
                            </a>
                        </div>
                        <h1>Bob's Big Burgers Did It Again</h1>
                        <p>
                             Someone just purchased a bunch of stuff!
                        </p>
                    </body>
               </html>
            </em:body>
        </em:alternate-view>
    </em:alternate-views>
</em:email-template>

In the case of our first email template the<em:body>…</em:body> element tags at the root contain plain text, so the <em:body>…</em:body> tags inside the <em:alternate-view>...</em:alternate-view> element tags contain the alternate HTML view of the same message.  Here though I like to draw you attention to the template expression inside the image tag: [linked-resource:./Images/Logo.jpg] The linked-resource expression embeds the resource, in this case ./Images/Logo.jpg  directly in the email message being sent to the client, an returns a valid linked resource url that can be used directly by the <img> tags src attribute.

Summary

Sending corporate ready emails from your SharePoint, ASP.NET or .NET application has never been easier.  I did not get to the explaination of my “teaser” email at the start of this article, which includes complete shopping cart data inside the email, however I do promise a Part Two of this article which will explain just how it was created.

The complete source for all of the templates explained in this article, including the shopping cart email, and sample code to create send them, can be found on the Email Library Download page.


The complete user guide from the Email Library can be found on the Email Library User Guide page.

© Copyright 2009 Aaron G. Daisley-Harrison – All rights reserved

Authors

All Categories

Archive