Home About

March 3rd, 2009

Using C# and .NET to send an e-mail through SMTP - 5

Sending an e-mail using .NET

Sending an e-mail is pretty old news by now so it should come as no surprise that .NET contains a significant SMTP mail client. One old programming truth still holds: All programs will expand to eventually include sending (and receiving) e-mails. So how about adding e-mail to your program ? This post explores how we can use the System.Mail.SmtpClient to send formatted e-mails. There are plenty of options available and we will explore most of them.

In another lifetime together with friends I wrote a massive e-mail parser for the then popular FidoNet, and the (for us) new RFC822 based Internet. Written in Pascal for DOS it chewed its way through megabytes of modem downloaded Usenet groups and e-mail for our local BBS, night after night. It was fun and I learned that when it comes to e-mail that there are no real standards, just broken implementations.

Some 15 years later things have become quite a bit easier. Sending an e-mail is as straightforward as calling a few basic library functions and .NET of course includes a solid implementation.

Quickly sending an e-mail

If you are in a hurry then the following constructor will create a simple mail message from just 4 string parameters:

// public client.Send(string from,string to,string subject,string body)
using System.Net.Mail;
SmtpClient client = new SmtpClient();
client.Send("martijn@dijksterhuis.org","test@dijksterhuis.org","Testing!","If this break again,.. I won't know what to do");

In the above example the e-mail is send using the system default settings as discovered by the .NET framework. If you are curious which system acted as the Default SMTP server you can query SmtpClient.Host

Console.WriteLine(“Default SMTP Server: {0}”,client.Host);

Note that there is a good chance that the .NET libraries are unable to work out the SMTP host and will fail with an System.InvalidOperationException (The SMTP host was not specified) when you attempt to send the e-mail.

Sending a proper e-mail

An basic e-mail is build up out of a sender, one or more recipients, a message body and one or more attachments. And of course the e-mail is probably encoded in an outdated Russian font.

The e-mail sender and receiver are represented by the MailAddress class. So of course you need an e-mail address, optionally a name, and in case you really want to send a Russian formatted name, a proper encoding format.

MailAddress toUser = new MailAddress("martijn@dijksterhuis.org");
MailAddress toUser2 = new MailAddress("martijn@dijksterhuis.org","Martijn Dijksterhuis");
MailAddress toUser3 = new MailAddress("martijn@dijksterhuis.org","Martijn Dijksterhuis", System.Text.Encoding.UTF8);

My name doesn’t include any funky characters so I specified the default UTF-8 encoding.

Sending an e-mail with only a single sender and receiver

If your e-mail only contains a single sender and a single receiver the MailMessage(MailAddress From,MailAddress To) constructor provides all you need. It creates a new e-mail message structure, assigning the sending and receiver in the constructor.

MailAddress toUser = new MailAddress("myfriend@yahoo.com");
MailAddress fromUser = new MailAddress("martijn@dijksterhuis.org");
MailMessage msg  = new MailMessage(fromUser,toUser);

Adding more receivers to the same e-mail

A single recipient is probably not sufficient. Not to worry, you can add as many To’s, CC’s, BCC’s etc to the e-mail as you would like:

msg.To.Add( new MailAddress("second_to@dijksterhuis.org") );
msg.CC.Add( new MailAddress("first_cc@dijksterhuis.org") );
msg.CC.Add( new MailAddress("second_cc@dijksterhuis.org") );
msg.Bcc.Add( new MailAddress("first_bcc@dijksterhuis.org") );

Setting the E-mail subject and body content

Setting the subject of the e-mail is not hard, just set it from Msg.Subject. And if you would like to encode that in a format other the Unicode, say BIG-5 Chinese:

msg.Subject = "一分鐘換一年"
msg.SubjectEncoding = Encoding.GetEncoding("big5");

(The above Chinese came from my junk box and to the best of my knowledge its harmless)

Setting the actual message body works in a very similar fashion:

msg.Body = "Dear Customer, " + Environment.NewLine + Environment.NewLine;
msg.Body += "Because of repeated violations of our terms and conditions we had no choice but to";
msg.Body += "terminate your account with us." + Environment.NewLine + Environment.NewLine;
msg.Body += "The Management";
msg.BodyEncoding = System.Text.Encoding.UTF8;

Adding an attachment to the e-mail

An e-mail can have more than one attachment, and each attachment is represented by the System.Net.Mail.Attachment class. You can add them to the attachment collection of the message by calling “Attachments.Add()”

using System.Net.Mime;
Attachment firstAttachment = new Attachment("document.doc",MediaTypeNames.Application.Octet);
MailMessage msg  = new MailMessage(fromUser,toUser);
msg.Attachments.Add(firstAttachement);

The first parameter passed to the constructor is the path to the attachment to include. If no full path is given, the current working directory is tried. The file type is defined in System.Net.Mime — available options are:

MediaTypeNames Application Octet
PDF
RTF
Soap
Zip
Image Gif
JPEG
Tiff
Text HTML
Plain
RichText
XML

If the type of file is not specified use MediaTypesNames.Application.Octet , which stands for “data is not interpreted”.

Adding custom e-mail headers to your e-mail

The Msg.Header property allows you to query and add to the e-mail headers set  by the .NET framework. A brand new e-mail will only contain a single header: “Mime: 1.0″. Adding your own custom header to this is trivial as is shown in the following code example:


MailMessage Msg = new MailMessage(new               MailAddress("martijn@dijksterhuis.org"),new MailAddress("martijn@dijksterhuis.org"));

// Add a custom header to the e-mail
Msg.Headers.Add("X-Header","2.0");

// Display all the message headers.
string[] Keys = Msg.Headers.AllKeys;
foreach (string s in Keys)

Console.WriteLine("{0}: {1}", s,Msg.Headers[s]);

Sending your e-mail with SmtpClient

The hard work of delivering the e-mail is done through the SmtpClient class and the most basic delivery only takes two lines:

SmtpClient client = new SmtpClient();
client.Send(Msg);

It might be wise to catch exceptions at this point because sending an SMTP e-mail can throw a number:


  1. SmtpFailedRecipientsException: The message could not be delivered to one or more of the recipients in To, CC, or Bcc.

  2. SmtpException : Connection failed, authentication failed or a time-out

  3. ArgumentNullException / ArgumentOutOfRangeException / InvalidOperationException : Something wrong with the input fields of the e-mail

If you do not specify any parameters the default SmtpClient constructor will lookup the SMTP server to use through the .NET environment.

You can specify a specific server and optional port through the second constructor:

SmtpClient client = new SmtpClient(“mail.dijksterhuis.org”,3000);

The above SmtpClient.Send call is a blocking call — your application halts while the e-mail is being send. Naturally there is also an asynchronous call: SmtpClient.SendAsync.

Using SmtpClient.SendAsync is a little more work. How to do this is shown in the following example:

using System;
using System.Net.Mail;
using System.Threading;
using System.ComponentModel;

namespace SnmpMailer
{
    class MainClass
    {
        static Semaphore mailSendSemaphore;
                
        private static void MailSendCallback(object sender, AsyncCompletedEventArgs arg)
        {
            // Get our unique token for this asynchronous operation.
            String token = (string) arg.UserState;

            // Did the user abort the sent ?
            if (arg.Cancelled)
                Console.WriteLine("[{0}] Send canceled.", token);
            // Did an error occur during the send?
            if (arg.Error != null)
                 Console.WriteLine("[{0}] {1}", token, arg.Error.ToString());
            else
                Console.WriteLine("Message sent succesfully!");

            // Release the main thread
            mailSendSemaphore.Release();
        }
        
        public static void Main(string[] args)
        {
            mailSendSemaphore = new Semaphore(0,1);
            
            /* Create the mail message with to & from */
            MailMessage Msg = new MailMessage(new MailAddress("noreply@dijksterhuis.org"),
                                              new MailAddress("martijn@dijksterhuis.org"));

            Msg.Body = "Dear Customer, " + Environment.NewLine + Environment.NewLine;
            Msg.Body += "Because of repeated violations of our terms and conditions we had no choice but to";
            Msg.Body += "terminate your account with us." + Environment.NewLine + Environment.NewLine;
            Msg.Body += "The Management";
            Msg.BodyEncoding = System.Text.Encoding.UTF8;

            /* Set the subject */
            Msg.Subject = "Termination of service notice";

            /* Add our own header */
            Msg.Headers.Add("X-Deliverator","Terminator");

            /* Deliver the message in an asynchronous fashion */
            SmtpClient Deliverator = new SmtpClient("mymailserver.com");

            /* Print the default client */
            Console.WriteLine("Default SMTP Server: {0}",Deliverator.Host);

            /* Specify the call back function */
            Deliverator.SendCompleted += new SendCompletedEventHandler(MailSendCallback);

            /* For an asyncronous call we can pass a token to help us determine the message being send */
            Deliverator.SendAsync(Msg,"Msg ID 1212");

            /* Because we have little else to do, we set a semaphore and wait */
            mailSendSemaphore.WaitOne();

            Console.WriteLine("Mail delivery finished");
        }
    }
}

Image credit: Mzelle Biscotte

Be Sociable, Share!

Tags: ,

5 Responses to “Using C# and .NET to send an e-mail through SMTP”

  1. Romain Tartière Says:

    Hi!

    Small typo at the beginning:
    using System.Net.Mail; // instead of System.Mail

  2. Martijn Says:

    Hi Romain,

    Thanks for the comment! I fixed it in the post.

    Martijn

  3. Savanna Says:

    Is it possible to send message to many contacts by use put email addresses into To and Cc and when the reciepients get the message, they can not see who recieve this message just his email address? Do you know the source code to not show email reciepients in content To and Cc?
    Please help me.
    Thanks in advance.
    Savanna

  4. Kolorowanki Says:

    Great tutorial, I will try your way. I only drawing so I will pass your post address to my programmer.
    Thanks for sharing.
    Regards,
    Matt Kolorowanki,
    Illustrator

  5. MIQmiq Says:

    To Savanna, just put the email adresses into bcc instead og to and cc. bbc stands for blind copy, and the receiver wil not see all the other email adresses.


Most popular
Recent Comments
  • ARS: great plugin! I love it! but, it will be so nice if you can add attribute ‘title’ as one of...
  • Nelson: Saved me from doing it myself. Good article.
  • andy: i am currently playing taiwanese server wow in 奈辛瓦里(PVP) and i would like to realm transfer to somewhere there...
  • berties: any english speaking playing on a taiwanese server?
  • web application development: has C# search volume really so constant over the years? really surprising.