(Print this page)

Using System.Net.Mail
Published date: Sunday, September 23, 2007
On: Moer and Éric Moreau's web site

Sending an e-mail with classes of the .Net Framework is pretty easy. Michel Fournier wrote an article titled Sending email from VB.Net in the April 2006 edition of the Level Extreme .Net magazine providing you a good wrapper that does most operations you need when an application needs to send an e-mail. I want to cover some topics that were not covered at that time.

A note on the namespace

In the era of .Net Framework 1.0 and 1.1, the namespace that developers needed to use to send e-mail from an application was System.Web.Mail. It was confusing for some Windows application developers asking why reference a Web assembly when creating a Windows application. When Microsoft released the version 2 of the .Net Framework, they renamed that namespace to System.Net.Mail for more clarity.

Another huge difference between both versions is that the first version (System.Web.Mail) was built on top of the CDO/CDOSYS librairies (through COM interop). The later version was rewritten entirely without any interop.

Sending a simple message

Before jumping into the new topics I want to introduce you, and because we need to be able to send a simple message before adding new features to it, here are the basics of sending an e-mail.

Figure 1: The demo application

You first need to create a MailMessage object (available in the System.Net.Mail namespace) and feed it with some values like the following code:

Dim strAddresses As String

'Prepare the message
Dim objMessage As New MailMessage
With objMessage
    .From = New MailAddress(txtFrom.Text)

    'able to handle more then a single recipient 
    strAddresses = txtTo.Text.Replace(",", ";")
    For Each strX As String In strAddresses.Split(";"c)
        If strX.Trim.Length > 0 Then
            .To.Add(New MailAddress(strX))
        End If
    Next

    .Subject = txtSubject.Text
    .Body = txtBody.Text
    .IsBodyHtml = (chkIsHTML.Checked)
End With
Your TextBox controls (From and To) must contain a valid e-mail address. You can also provide a proper display name if you use this format:
txtFrom.Text = "Eric Moreau"
Notice that you can also support the CC (Carbon copy) and the BCC (Blind Carbon Copy) using exactly the same code as for the To property. You may consider sending a separate copy of your e-mail to as many recipients you need instead of using the BCC option because many spam filters are blocking BCCs e-mails.

Now that we have a MailMessage object ready, we can now send it using this code:

Dim objSMTPClient As New SmtpClient()
Try
    objSMTPClient.Host = "Your SMTP provider URL or IP goes here"
    objSMTPClient.Send(objMessage)
    MessageBox.Show("E-Mail sent successfully")
Catch ex As Exception
    MessageBox.Show("Error occured sending e-mail." + _
                    Environment.NewLine + Environment.NewLine + _
                    ex.Message)
End Try
If you provided valid e-mail addresses and a valid host URL, your e-mail should be sent.

Attaching a file to the message

Adding a file as an attachment to the message is really simple. It is much like adding recipients to the message.

Here is an example of that code:

Dim strFiles As String = txtAttachments.Text.Replace(",", ";")
For Each strX As String In strFiles.Split(";"c)
    If strX.Trim.Length > 0 Then
        objMessage.Attachments.Add(New Attachment(strX))
    End If
Next
That code let you attach 1 or more file (separated by commas and/or semi-colons) to your message.

Attaching a stream as an attachment

If you have a stream of any kind in your application that you would like to send as an attachment to your e-mail, you might think that you first need to save it as a file and then attach it but you don’t have to.

When you create a new attachment, you can pass either a filename or a stream. If you are using the second option, you should set the name you the attachment to have and also specify a content type like the following example:

'1. Get some binary data
Dim data As Byte() = GetData()
'save the data to a memory stream
Dim ms As New IO.MemoryStream(data)

'2. create the attachment from a stream. 
'   Be sure to name the data with a file and 
'   media type that is respective of the data
objMessage.Attachments.Add(New Attachment(ms, "example.txt", "text/plain"))

Sending a HTML message

If you want nice looking message, you will have to format them using HTML.

There are 2 differences from a simple e-mail:

  • The Body property must contain a valid HTML string.
  • The IsBodyHtml property must be set to True.

Nothing else changes. You can still continue to use the other properties such as the subject and the attachments the same way.

For example, here is an example of a HTML formatted body:

txtBody.Text = "<h1>This is the title</h1>" + _
               "<br/><br/>" + _
               "<b>This is the <u>body</u> of a very dummy HTML message!</b>"

Providing an alternate view

You may encounter some problems when you send a HTML body as not every client supports it. For those e-mail clients, you can provide an alternate view so that they should at least be able to read some text.

If you want to provide this feature, you cannot use the Body property of the MailMessage object. Instead, you have to add views to the MailMessage object in the format you want using this code:

Dim objAVText As AlternateView
objAVText = AlternateView.CreateAlternateViewFromString( _
                    txtAlternateView.Text, Nothing, "text/plain")

Dim objAVHTML As AlternateView
objAVHTML = AlternateView.CreateAlternateViewFromString( _
                    txtBody.Text, Nothing, "text/html")

objMessage.AlternateViews.Add(objAVText)
objMessage.AlternateViews.Add(objAVHTML)

Embedding an image into a HTML body

If you would like to embed an image into your e-mail (instead of having the user to download it), you need to use the LinkedResources collection from the AlternateView object. You need to provide your image to the LinkedResources collection like if it was an attachment and reference it from your HTML body like this.

The code you need to add your picture to the LinkedResources collection is:

Dim objPicture As LinkedResource
objPicture = New LinkedResource("moon.jpg")
objPicture.ContentId = "PictureOfMoon"
objAVHTML.LinkedResources.Add(objPicture)
Now you need to link this resource somewhere into your HTML body. The key here is the ContentId property you have set in your LinkedResource. You need to use the same word with the keyword cid so it will look into the resources instead of trying to download it:
txtBody.Text = "<h1>This is the title</h1>" + _
               "<br/><br/>" + _
               "<b>This is the <u>body</u> of a HTML message with a picture!</b>" + _
               "<br/><br/>" + _
               "<img src=""cid:PictureOfMoon"">"

A good reference

There is a really good web site that provides a good FAQ compilation on the System.Net.Mail (.Net FrameWork 2.0) available from www.SystemNetMail.com http://www.systemnetmail.com/. If you are still using the older System.Web.Mail (.Net Framework 1.x) namespace, you should visit www.SystemWebMail.com.

Conclusion

If you download the demo application included with this article, don’t forget to set your own provider’s URL into the SendMessage method otherwise you will never be able to send any e-mails.

With those new tricks, I think that you can now easily create much fancier e-mails directly from your application.

I hope you appreciated the topic and see you next month.


(Print this page)