ASP.NET VERSIONS: 2.0
SMTP in .NET 2.0
New Features and Functionality
By Josef Finsel
The next version of Visual Studio has some interesting changes in how and what you can do in sending e-mail. (Note: This column was written using the November Technology Preview of VS2005 and some things may not be available until Beta 2.)
What Is SMTP?
SMTP stands for Simple Mail Transport Protocol and is the Internet protocol used to deliver e-mail. Without going into all the technical details, the SMTP server sits and monitors a specific TCP/IP port, much like the HTTP server does. And it responds to those requests. These requests could be from an e-mail client, such as the one that we are going to build, or they could come from other SMTP servers that are delivering mail.
The first difference between .NET 2.0 and earlier versions is the introduction of the System.Net.Mailspace namespace, but this is not a simple move of methods and properties from one namespace to another. Rather, it is a rebuilding of how SMTP is implemented. One good example of this is demonstrated by looking at an e-mail address. In its simplest form an e-mail address is:
But there is more to it than that, isn t there. After all, most e-mail shows a real name, not an e-mail address. But what s the correct format? Is it:
Josef Finsel <[email protected]>
<[email protected]> Josef Finsel
Neither. It s simply:
The name is applied to the e-mail address within the text of the raw e-mail. Fortunately, this no longer matters because there is now a MailAddress object that takes care of that. The table in Figure 1 shows a list of all the classes in the System.Net.Mail namespace.
The base class used for the AlternateView, Attachment, and LinkedResource classes.
Used to provide a different format of the e-mail. If you send the e-mail as HTML, you can include a plain-text version using the AlternateView.
A class for adding attachments to the e-mail.
Used to embed external resources such as an image in an e-mail.
Used to define mail addresses and display names.
Used to create the actual e-mail.
Several classes that enable great control over interacting with an SMTP server.
Figure 1: Classes in System.Net.Mail.
Creating an E-mail
For this example we are going to build a simple Web page that will allow the user to enter their name and e-mail address, select a subject from a dropdown list, then enter the body of the message to send; this represents a typical customer service-type Email Us page. The page will then create a formatted e-mail to send to customer service and a copy to the user.
At first glance, the code in Listing One may seem like a more complicated way to create and send e-mails than it used to be, but it offers more control. We ll begin by creating three MailAddress objects, one each for the from address, the to address, and the CC to send a copy to the person sending the e-mail. This is as simple as creating new instances of the objects and passing in the e-mail address and the display name. Once these addresses are created, we can use the to and from addresses when we instantiate the MailMessage object. Although it may seem like overkill, creating objects for such a simple thing as e-mail addresses, the real power of these new objects comes out in the creation of collections of these objects. Sending an e-mail to multiple people is as easy as adding new items to the collection. This is how CC addresses are added.
All e-mails use MIME, Multipurpose Internet Mail Extensions (RFC 1341). This enables attachments to be rendered into a standardized format. If you use Notepad to open the .eml file included in the code download, you ll find that it contains blocks of encrypted text with headers defining what type of data those blocks contain. If you ve ever received an Unsolicited Commercial Email where the text of the message displayed the HTML elements instead of rendering the HTML, it s because the person sending the e-mail forgot to set the MIME content to say it was HTML and your mail program assumed it was text and displayed it as such. To avoid having this happen, we are going to define the MimeContentType for our e-mail.
Because not all e-mail programs can display HTML content, we ll add two versions of the e-mail, one in HTML and one in plain text. To do this, we ll use the AlternateView class to add the two messages, one with HTML and one without. While the AlternateView class is based on the AttachmentBase class, these two versions of the e-mail will not show up as attachments because the AlternateView defines the data as content-type: multipart/alternative. This informs the e-mail client that there are multiple ways to view the message and it can decide which one to display. In addition, including the HTML as an alternate view for the e-mail rather than as an attachment prevents the client from blocking the e-mail attachment as a potentially dangerous element.
The last thing to look at before digging into the code itself is attaching a graphic for use in the e-mail. Although it is possible to reference an image on the Web with the appropriate url, most e-mail clients will show broken images and the user will need to right-click to download the actual image. Rather than that, we are going to attach an image to the e-mail. As long as the html doesn t reference a location for the image, it will display the attachment as appropriate. Based on the documentation, it seems as though the LinkedResource would be the best method for adding such an image. However, being not quite Beta software, not everything is working and the LinkedResource is not available, so I am using the Attachment class instead. This means that the image will show up with a paperclip in most e-mail clients but that shouldn t be a problem.
The default.aspx page contains a couple of textboxes to allow for input of a name and e-mail address and the body of the e-mail. In addition, there is a dropdown box that contains a number of potential subjects about which someone might want to contact a company: Broken Link, Missing Image, etc. I m using these subjects for more than just offering the user a choice of subjects, I am using them to select what information goes into the e-mail message.
I have built a very simple HTML file called MailFormat.htm. This file uses two IMG tags to display the goldbar.gif image as a fancy separator. In addition, it has three text sections that serve as placeholders. Once the html file has been loaded into a string, these place holders can be replaced with the text of our response, the user s query, and the subject line. In addition, there are several text files that contain the response to the various subject lines. Now, to the code!
Putting the Pieces Together
We ll start by assembling the text of the messages. The first few lines show nothing out of the ordinary, defining a few string variables to hold the file path and names and two to hold the text we ll be using. The first new element comes when we read the files into the string variables. Opening a file and reading the entire thing into a string variable is as easy as using My.Computer.Filesystem.ReadAllText. The My.Computer, available in VB.NET, is a handy shorthand to reference many of the items related to the computer, such as the Clipboard, audio, registry, files, etc. Not all of these are available to server applications, but Filesystem is, so we ll take advantage of it to read the files in.
With the files loaded and ready, it s time to make the e-mail addresses: toAddress, ccAddress, and fromAddress. Creating the e-mail address allows us to use the to and from addresses, but not the CC. For that, we ll add the e-mail address to the CC collection. Next, define the MimeContentTypes and add the alternate view messages, one html and one plain text. The last thing to do before sending the e-mail is to attach the goldbar.gif image. In most instances, the Attachment class will take care of determining the correct MimeContentType, as it does in this case. And now we can set up the SmtpClient.
The SmtpClient class handles the actual sending of the e-mail. If you don t want to get fancy and do HTML e-mail and use names to mask the e-mail addresses, you can pass the to, from, subject, and text of the body directly to the SmtpClient s overloaded send method. Because we ve gone through all of this work to define the e-mail message, we ll pass that to the send method and we re done at least we are as soon as the e-mail has been dropped off to the server. If that s taking too long, due to a heavy volume of mail, you can use SendAsync to send the message asynchronously. An example of that can be found in the MSDN documentation.
All in all I like the new features and functionality for SMTP in .NET 2.0. But there is a caveat to mention here. The inner workings of configuring security for the SmtpClient are not quite finished, so it s not quite possible to define a user id and password for the SmtpClient to use when sending an e-mail. If you are connecting to an Exchange server, you can set it up to allow outbound e-mail from specific IP addresses or from computers within your domain without having to log in.
For more information on SMTP visit http://www.ietf.org/rfc/rfc0821.txt?number=821.
The sample code accompanying this article is available for download.
Josef Finsel is a software consultant with Strategic Data Solutions (http://www.sds-consulting.com). He has published a number of VB and SQL Server-related articles and is currently working with VS 2005. He s also author of The Handbook for Reluctant Database Administrators (Apress, 2001).
Protected Sub sendEmail_Click(ByVal sender As Object, ByVal e _
As System.EventArgs) Handles sendEmail.Click
Dim sBody As String
Dim fileReaderBody As String
Dim fileReaderFormat As String
Dim WebDirectory As String = Server.MapPath(".") & "\"
Dim fileName As String = WebDirectory
Dim htmlEmailFormat As String = WebDirectory & "MailFormat.htm"
Select Case Subject.Text
Case "Broken Link"
fileName = fileName & "BrokenLink.txt"
Case "Missing Picture"
fileName = fileName & "MissingPicture.txt"
Case "Typographical Error"
fileName = fileName & "TypoError.txt"
Case "Deal on Rolexes"
fileName = fileName & "Rolexes.txt"
fileName = fileName & "other.txt"
fileReaderBody = My.Computer.FileSystem.ReadAllText(fileName)
fileReaderFormat = _
sBody = fileReaderFormat.Replace("BODYGOESHERE", _
sBody = sBody.Replace("CONTENTGOESHERE", fileReaderBody)
sBody = sBody.Replace("SUBJECTGOESHERE", Subject.Text)
Dim toAddress As MailAddress = New _
MailAddress("[email protected]", "Customer Support")
Dim ccAddress As MailAddress = New _
Dim fromAddress As MailAddress = New _
Dim eMail As MailMessage = New _
eMail.Subject = Subject.Text
Dim htmlType As System.Net.Mime.ContentType = _
Dim txtType As System.Net.Mime.ContentType = _
& vbCrLf & messageBody.Text, htmlType))
Dim attchment As Attachment = New _
Attachment(WebDirectory & "goldbar.gif")
Dim client As SmtpClient = New SmtpClient("smtp.finsel.com")
End Listing One