A Lesson in SMTP

Formatting Mail Messages with Plain Text, HTML, Attachments, and more…

8 Min Read
ITPro Today logo

ASP.NET Under the Hood

LANGUAGES: VB.NET | C#

ASP.NETVERSIONS: 2.0

 

A Lesson in SMTP

Formatting Mail Messages with Plain Text, HTML,Attachments, and more

 

By Michele Leroux Bustamante

 

Greetings ASP.NET architects and developers! I hope youenjoy this second installment of the ASP.NET Under the Hood column. I inviteyou to send your questions and requests to [email protected] let me unravel some mysteries for you!

 

Q. I need to send formatted HTML e-mails with one or moreattachments from my ASP.NET 2.0 application, as well as supply a plain-textversion for users who use text-based mail clients. Do you have any advice onhow to do this with System.Net.Mail? Accomplishing the same with System.Web.Mailseemed overly complex. What other things should I know about sending e-mailprogrammatically?

 

A. A few years ago I remember building a newsletter enginewith the mail functionality provided by System.Web.Mail only to find that Ihad to dig into the MIME specification to manually generatemultipart/alternative messages. The good news is that System.Net.Mailcompletely surpasses the functionality provided previously in System.Web.Mail,so you don t have to build a custom SMTP client with sockets and learn morethan you really wanted to know about the MIME standard just to send attachmentsand dual formatted e-mail.

 

In fact, functionality formerly provided bySystem.Web.Mail in .NET 1.x is now obsolete. .NET 2.0 introduces a good amountof new functionality in the System.Net.Mailnamespace, including:

  • A better object model for formatting HTML e-mail,providing e-mail alternatives, and adding MIME-encoded attachments.

  • Support for asynchronous calls.

  • The ability to easily send SMTP server credentialswithout hacking field values.

 

Now, let s get back to the specific question.

 

Sending Plain-text E-mail

It s easy enough to send a simple e-mail using the SmtpClienttype; just create an instance of the type, set the Host property, and call Send,as shown here:

 

SmtpClient smtp = new SmtpClient();

smtp.Host = www.mysmtpserver.com ;

smtp.Send([email protected],[email protected],

 "Plain Text Email",

"This e-mail is just a bunch of plain text, no formatting ");

 

In this example,Send passes parameters indicating the sender s address, the recipient saddress, the subject, and the actual text content of the e-mail. This generatesa simple, plain-text e-mail without attachments, without specifyingcredentials, and without any extended recipient lists. The resulting SMTP message looks something likethis:

 

mime-version: 1.0

From: [email protected]

to: [email protected]

date: 16 Jan 200602:08:09 -0800

subject: Plain Text Email

content-type: text/plain; charset=us-ascii

content-transfer-encoding: quoted-printable

This e-mail is just a bunch of plain text,

no formatting

 

Message headers are automatically generated from theparameters passed, or they carry default values. Note that the Content-Type defaultsto text/plain; charset=us-ascii because we are sending a simple characterstream following the headers.

 

Sending HTML-formatted E-mail

SmtpClient also provides another method signature for Send that lets you supply amore tailored MailMessage type.This gives you additional control over the message details. Figure 1 shows anexample that sends an HTML-formatted message.

 

MailMessage msg = new MailMessage();

msg.From = new MailAddress("[email protected]",

"Michele Leroux Bustamante");

msg.To.Add("[email protected]");

msg.Subject = "HTML Formatted Email";

msg.IsBodyHtml = true;

msg.Body = "Coolness! This email is

much more interesting.";

msg.CC.Add("[email protected]");

msg.Bcc.Add("[email protected]");

SmtpClient smtp = new SmtpClient();

smtp.Host = "www.mysmtpserver.com"

smtp.Send(msg);

Figure 1: Sendingan HTML-formatted message.

 

You can see from the example in Figure 1 that the MailMessageclass exposes a rich object model for building the message. In particular,providing a friendly name for the From address willhelp you avoid landing in spam folders! Setting IsBodyHtml to true also causesthe Content-Type to default to text/html .

 

Adding Attachments to E-mail

Adding attachments is also easy using the Attachmentsproperty of MailMessage (see Figure 2).

 

MailMessage msg = new MailMessage();

msg.From = new MailAddress("[email protected]", "MicheleLeroux Bustamante");

msg.To.Add("[email protected]");

msg.Subject = "HTML with Attachments";

msg.IsBodyHtml = true;

msg.Body = "Coolness! This email ismuch more interesting.";

Attachment att = new Attachment("data.zip",

MediaTypeNames.Application.Octet);

msg.Attachments.Add(att);

SmtpClient smtp = new SmtpClient();

smtp.Host = "www.mysmtpserver.com"

smtp.Send(msg);

Figure 2: Usingthe Attachments property of MailMessage.

 

This was also possible with System.Web.Mail, but finally mediatype names are much easier to specify (and find!). The new MediaTypeNames type savesyou from scouring the Web for a reminder of the valid media types for variousattachments.

 

Supporting Multiple E-mail Clients

This is where things used to get interesting with thedeprecated System.Web.Mail object model. Previously, it was not possible togenerate HTML e-mail that also supplies a plain text version for text-basedmail clients. Before, you had to dig in and generate the MIME-encoded messageyourself!

 

Now, with the SmtpClient type, you can add alternativemessage views with the code shown in Figure 3.

 

MailMessage msg = new MailMessage();

set other properties

string s = "This e-mail is just a bunch of plain text, noformatting ";

byte[] text = Encoding.ASCII.GetBytes(s);

msg.AlternateViews.Add(new AlternateView(new MemoryStream(text),

"text/plain"));

msg.AlternateViews.Add(new AlternateView( htmlemail.html ,

"text/html"));

Figure 3: Addalternative message views using the SmtpClient type.

 

Notice that each alternative specifies its ownContent-Type in the AlternativeView constructor? That s because each messagepart will be separated by MIME-encoded boundaries (see the sidebar A Lesson inMIME on page XX) and will describe its own format. The overall message will besent as multipart/mixed or multipart/alternative using the former if thereare attachments included. Confused? Well, don t worry ... what s nice is thatnow you shouldn t really need to care about the details of MIME encoding you canbe off and running with just a few lines of code!

 

Additional Resources

For more details on SMTP, visit http://www.ietf.org/rfc/rfc0821.txt.For more details on MIME,visit http://www.ietf.org/rfc/rfc1521.txt?number=1521.

 

If you have additional questions or comments regardingthis column, or any other ASP.NET topics, please drop me a line at [email protected] for reading!

 

C# and VB.NET codeexamples are available for download.

 

MicheleLeroux Bustamante is Chief Architect at IDesign Inc., Microsoft RegionalDirector for San Diego, Microsoft MVP for XML Web services, and a BEA TechnicalDirector. At IDesign Michele provides training, mentoring, and high-endarchitecture consulting services, specializing in scalable and secure .NETarchitecture design, globalization, Web services, and interoperability withJava platforms. She is a board member for the International Association ofSoftware Architects (IASA), a frequent conference presenter, conference chairof SD s Web Services track, and a frequently published author. She is currentlywriting a book for O Reilly on the Windows Communication Foundation. Reach herat http://www.idesign.net or http://www.dasblonde.net.

 

A Lesson in MIME

Multipurpose Internet Mail Extensions, or MIME, specifiesa standard format for encapsulating multiple pieces of data into a singleInternet message. E-mail clients rely on MIME headers to display messagescorrectly. Plain-text messages are sent with the content type text/plain, andclients simply display the body of the message. HTML messages can be sent witha content type of text/html, which tells clients to respect HTML markup in themessage body. When attachments are part of the message, plain-text and HTMLmessages use the content type multipart/mixed.

 

Multipart content type indicates that the message includesone or more different parts separated by a unique string boundary. A multipartmessage stream consists first of headers, followed by a carriage return andlinefeed , and the content enclosed in an opening and closingboundary. The boundary is indicated in the Content-Type header, and e-mailclients expect the boundary string to appear prefixed with two hyphens (--) atthe beginning of the entire message content, and between each message part inthe content. A closing boundary must appear at the end of the message toindicate the final message part has been read. This closing boundary includes adouble-hyphen prefix and suffix. The following listing gives you an idea howthat looks:

 

Content-Type: multipart/mixed; boundary=mime_boundary1

--mime_boundary1

Content-Type: text/plain; charset=us-ascii

Content-Transfer-Encoding: 7bit

[text part]

--mime_boundary1

Content-Type: application/octet-stream

Content-Disposition: attachment; filename= data.zip

Content-Transfer-Encoding: base64

[binary part]

--mime_boundary1--

 

This listing illustrates sending a multipart/mixed messagethat contains two parts: the plain-text message and a zipped file attachment.The boundary string is mime_boundary1 in this example, but can be any uniquestring value. Headers are placed within each message part, following theseparation boundary, to specify things such as content type and transferencoding. In the above listing, the first part represents the content of themessage; the second part is a binary attachment. Content typeapplication/octet-stream is a generic sub type that indicates the data can beloaded by an application, but the sender is not specifying which application(such as Excel, Word, or PowerPoint). This allows the e-mail client to use therecommended filename indicated in the Content-Disposition header, to launch thecorrect application when the attachment is launched. Content-Disposition headeralso provides a means for the sender to indicate the file type, and a suggestedarchival name for the message part.

 

When you specify alternate versions of the message, theSmtpClient generates two versions of the message. The following code adds aplain-text and HTML version of the message:

 

mime-version: 1.0

From: [email protected]

to: [email protected]

date: 16 Jan 200602:08:09 -0800

subject: Multi-format EMail

content-type: multipart/alternative; boundary=mime_boundary1

--mime_boundary1

Content-Type: text/plain; charset=us-ascii

This e-mail is just a bunch of plain text,

no formatting

--mime_boundary1

Content-Type: text/html

Coolness! This email ismuch more interesting.

--mime_boundary1--

 

As you can see, multipart/alternative is packaged similarlyto multipart/mixed, except that each message part is interpreted as a differentversion of the same data. Content type helps distinguish the difference betweenthem, and e-mail clients usually try to use the last message part that theysupport. So, if the mail client supports HTML, the second message part isdisplayed; if not, the first part is displayed. This is why order is important.

 

 

 

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like