Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

SMTP Client Supporting Implicit SSL Secure Sockets Layer with OAuth2 Open Authorization or Password Authorization (2.0)

5.00/5 (21 votes)
20 Jun 2019CPOL7 min read 58.9K   2.8K  
The attached open source C# .NET library is an SMTP client implementing implicit SSL and OAuth2 protocols. The library answers the question: how to send email message using Gmail as a server. Or, how to send email message using email server that implements implicit SSL and port 465.

Image of TestUziSecureSmtpClient

Introduction

The attached .NET library UziSecureSmtpClient allows you to send secure email from your .NET application. The class library is written in C# for .NET framework. This library was developed for MM Interplast. MM Interplast is a Myanmar based manufacturer providing customized PET preforms, HDPE closures and containers for the food, beverage and consumer industry produced on state of the art equipment. The library was developed because the current Microsoft Visual Studio SmtpClient class does not support implicit SSL connection security. It is important to note that using implicit SSL to communicate with the mail server implies that everything including the plain text password is encrypted between your computer and the mail server provider. The library was tested by sending mail messages using the following email server provides: Gmail, Yahoo, ATT, Rogers, HostGator and Network Solutions.

Version 2.0 supports subject line with non ASCII characters.

The class library supports three types of outgoing email servers.

  • Gmail: Connection security is SSL/TLS. Authentication method is OAuth2. For GMAIL, the outgoing host server is smtp.gmail.com and outgoing port is 465.
  • Servers such as Yahoo, ATT and Rogers: Connection security is SSL/TLS. The authentication method is plain text password. However, the password is encrypted as all other parts of the email message by SSL. Outgoing port number is normally is 465.
  • Servers with no connection security and plain text password. Outgoing port number is 587.

Authentication method OAuth2 was only tested with Gmail. In order to use OAuth2, one needs to create a refresh token file. Step 2 below describes the creation process for Gmail. I do not know if other providers of OAuth2 authentication outgoing email use the same process. I suspect that GmailRefreshToken program will have to be modified or rewritten.

Email message format is described in Wikipedia MIME entry. MIME is specified in six linked RFC memoranda: RFC 2045, RFC 2046, RFC 2047, RFC 4288, RFC 4289 and RFC 2049; with the integration with SMTP email specified in detail in RFC 1521 and RFC 1522.

Step 1- Email Account

Create an email account for your outgoing mail. Add it to your email program and make sure you can send and receive emails. Make note of the outgoing server settings:

  • Host or server name
  • Port
  • User name
  • User password
  • Authentication method
  • Connection Security

Step 2- Demo Folder

Create a new folder for testing the software. Extract the five files from the demo zip file into this folder.

  • GMailRefreshToken.exe
  • UziSecureSmtpClient.dll
  • TestSecureSmtpClient.exe
  • EmailImage.png
  • Rfc2045.pdf

Step 3- Create Authentication Refresh Token File (Only for Gmail)

If your email provider is not Gmail, skip this step.

Step 3A- Create a Client ID Token File

  • Go to the link: https://console.developers.google.com/apis/
  • If you are not logged into Google, it will ask you to login. Login with your Gmail account.
  • Select on the left the API manager Library tab.
  • Select Gmail API under Google Apps APIs.
  • Select on the left Credentials under API Manager.
  • Click on Create credentials combo-box.
  • Select OAuth Client ID.
  • Under Application type, select Other.
  • Change the Name to your email application.
  • Click on Create.
  • You will see OAuth Client box with Client ID and Client Secret random text data.
  • Click OK.
  • You will see a one line table with your OAuth 2.0 client ID.
  • At the end of this line, there is a down arrow icon. If you put the cursor on the icon, it will say Download JSON.
  • Click on this icon.
  • The browser will let you save a JSON file. Save the file to the demo folder from step 2. The default name is very long. You can change the name to a shorter name (i.e., SecureSmtpClientIDToken.json).

Step 3B- Create Refresh Token File

  • Run the GMailRefreshToken.exe program.
  • Click on the Browse button.
  • Find the JSON file that you saved in the demo folder (step 3A above). Click Open. The name will be displayed in the Gmail API Client ID text box.
  • Type the user email address into the Email address box.
  • Press Create Refresh Token button.
  • You will see a message box on the screen Email Authorization. Click OK.
  • Your default browser will open or a new tab will be added to your open browser.
  • You will need to log into your email account.
  • After login, you will see a message asking permission to View and manage your email.
  • Click Allow.
  • The browser screen will turn blue and will ask you to close the tab. And at the same time, you will get a Save Refresh Token File dialog box.
  • Save the SecureSmtpRefreshToken.xml file to your demo folder.

Step 4- Run the Demo Program

I strongly recommend running the demo program TestSecureSmtpClient.exe before starting programming. You want to be sure that the class library will work with your email service. The demo program will send an email consisting of two alternate views, plain text and HTML and two attachments. One attachment is a file for the recipient of the email and the other is inline image to be part of the HTML view. The two attachments are part of your demo folder. The email content can be viewed in the TestSecureSmtpClient.cs source. The text was taken out of one of the RFC documents associated with the MIME standard.

To run the demo program, start TestSecureSmtpClient.exe. Select the type of email server. Fill the relevant information. For Gmail, browse to the demo folder and select the SecureSmtpRefreshToken.xml file. And press Send Email. If the mail was sent, you will see "Email was successfully sent". Otherwise you will see an error message.

If there is a problem, load the source to Visual Studio and run it in debug mode. The process is being traced in the output view pane.

If you are successful, you are ready to integrate the class library to your code.

Step 5- Send Email From Your .NET Application

To use the library, you need to add a reference to the attached UziSecureSmtpClient.dll class library file. In each source file that references the library, you need to add a using UziSecureSmtpClient statement. The library UziSecureSmtpClient.dll must be included with your distribution. Alternatively, you can include the source code of the library with your application and avoid the need to distribute a separate data link library (dll) file. The software was developed with Microsoft Visual Studio Community 2013. The target .NET Framework was set to 4.5.

A typical email message has a subject line, from address and a list of to, cc or bcc addresses and a message body. Message body is made of parts. The parts are organized as a tree. Plain text content, HTML content and attachments are leaf nodes. If there is more than one part, the parts are divided by boundaries. This library supports three types of boundaries: mixed, alternate and related. The Wikipedia MIME entry describes these boundaries. Boundaries are parts. Boundaries can have children. Example three below shows how to create all of these parts and link them together to create a message tree.

The SecureSmtpClient class object is reusable. It is an advantage for an application sending multiple emails using GMail. The Gmail refresh token file never expires. When a SecureSmtpClient class object is being created, the software creates internally an authorization token that is valid for one hour. If the SecureSmtpClient object is reused for a long time, the software will request a new authorization token once an hour. All of this is transparent to your application. The advantage to you is a small gain in performance. If you create a new SecureSmtpClient for each mail, the software has to request a new authorization token for each mail message. If you reuse the SecureSmtpClient for sending multiple mail messages, there is only one request for authorization per hour.

Below, you will find three examples of sending email.

Example One: Unsecure Network Connection and Plain Text Password

C#
/////////////////////////////////////////////////////////////////////
// Example One: Unsecure network connection and plain text password.
// Message content is plain text.
// The message is a single part message with no boundaries.
/////////////////////////////////////////////////////////////////////
private void ExampleUnsecurePlainText
        (
        string Host,
        string UserName,
        string UserPassword,
        string FromName,
        string FromAddress,
        string ToName,
        string ToAddress,
        string MessageSubject,
        string MessageText
        )
    {
    try
        {
        // Create SMTP client.
        if(ConnectionUnsecurePlain == null) ConnectionUnsecurePlain = 
           new SecureSmtpClient(ConnectMethod.Secure, Host, UserName, UserPassword);

        // Create mail message object.
        SecureSmtpMessage Message = new SecureSmtpMessage();

        // Set subject.
        Message.Subject = MessageSubject;

        // Set mail from address and display name.
        Message.From = new MailAddress(FromAddress, FromName);

        // Add minimum one or more recipients.
        // in addition you can add CC or BCC recipients.
        Message.To.Add(new MailAddress(ToAddress, ToName));

        // Add mail body contents.
        // The plain text is the only content part.
        // Load it to the root part of the message.
        SecureSmtpContent PlainTextContent = 
                   new SecureSmtpContent(ContentType.Plain, MessageText);
        Message.RootPart = PlainTextContent;

        // Send mail.
        ConnectionUnsecurePlain.SendMail(Message);
        MessageBox.Show("Email was successfully sent");
        }

    // Catch exceptions.
    catch (Exception Exp)
        {
        MessageBox.Show(Exp.Message);
        }
    return;
    }

Example Two: Secure Network Connection and No Authentication

C#
/////////////////////////////////////////////////////////////////////
// Example Two: Secure network connection and no authentication.
// Message content is HTML.
// The HTML has an embedded image. The image is sent as an inline
// attachment. This message is a two parts message. It has two related 
// parts, the HTML part and the inline image attachment part.
// The two parts are separated by SecureSmtpMultipart boundary.
/////////////////////////////////////////////////////////////////////
private void ExampleSecureHtml
        (
        string Host,
        string UserName,
        string UserPassword,
        string FromName,
        string FromAddress,
        string ToName,
        string ToAddress,
        string MessageSubject,
        string MessageHtml
        )
    {
    try
        {
        // Create smtp client.
        if(ConnectionSecureHtml == null) ConnectionSecureHtml = 
         new SecureSmtpClient(ConnectMethod.Secure, Host, UserName, UserPassword);

        // Create mail message object.
        SecureSmtpMessage Message = new SecureSmtpMessage();

        // Set subject.
        Message.Subject = MessageSubject;

        // Set mail from address and display name.
        Message.From = new MailAddress(FromAddress, FromName);

        // Add minimum one or more recipients.
        // in addition you can add CC or BCC recipients.
        Message.To.Add(new MailAddress(ToAddress, ToName));

        // This message has two related parts, the html part and the inline image 
        // attachment part.
        // The two parts are separated by SecureSmtpMultipart boundary.
        // the multipart boundary is the root part.
        SecureSmtpMultipart Related = new SecureSmtpMultipart(MultipartType.Related);
        Message.RootPart = Related;

        // The first part is the HTML content.
        // It is added to array of part content children of the multipart parent.
        SecureSmtpContent HtmlContent = new SecureSmtpContent(ContentType.Html, MessageHtml);
        Related.AddPart(HtmlContent);

        // The second part is the inline image attachment.
        SecureSmtpAttachment ImageAttachment = 
          new SecureSmtpAttachment(AttachmentType.Inline, "EmailImage.png", "IMAGE001");
        ImageAttachment.MediaType = "image/png";
        Related.AddPart(ImageAttachment);

        // Send mail.
        ConnectionSecureHtml.SendMail(Message);
        MessageBox.Show("Email was successfully sent");
        }

    // Catch exceptions.
    catch (Exception Exp)
        {
        MessageBox.Show(Exp.Message);
        }
    return;
    }

Example Three GMail: Secure Network Connection and Oauth2 Authentication

C#
/////////////////////////////////////////////////////////////////////
// Example Three: Secure network connection and OAuth2 authentication.
// This example is specific to GMail.
// The message is a multi-part message. At the root level it is a
// mixed part message with two mixed parts: content and file 
// attachment.
// The content part is divided into two alternate parts: HTML content 
// and plain text content.
// The HTML part is divided into two related parts: the HTML content
// and an embedded image. The image is sent as an inline attachment.
/////////////////////////////////////////////////////////////////////
private void ExampleGMail
        (
        string Host,
        string UserName,
        string RefreshToken,
        string FromName,
        string FromAddress,
        string ToName,
        string ToAddress,
        string MessageSubject,
        string MessageHtml
        )
    {
    try
        {
        // Create smtp client.
        if(ConnectionGMail == null) ConnectionGMail = 
          new SecureSmtpClient(Host, UserName, new SecureSmtpOAuth2(RefreshToken));

        // Create mail message object.
        SecureSmtpMessage Message = new SecureSmtpMessage();

        // Set subject.
        Message.Subject = MessageSubject;

        // Set mail from address and display name.
        Message.From = new MailAddress(FromAddress, FromName);

        // Add minimum one or more recipients.
        // in addition you can add CC or BCC recipients.
        Message.To.Add(new MailAddress(ToAddress, ToName));

        // This message is made of two alternative methods for content plus 
        // an attachment file.
        // Create mixed multipart boundary.
        SecureSmtpMultipart Mixed = new SecureSmtpMultipart(MultipartType.Mixed);
        Message.RootPart = Mixed;

        // Create alternative boundary.
        // There are two alternatives to the content: plain text and HTML.
        // NOTE: The recipient of the message will display the last part it knows
        // how to display. For email program that can handle both HTML and text 
        // make sure the HTML part is last part.
        SecureSmtpMultipart Alternative = new SecureSmtpMultipart(MultipartType.Alternative);
        Mixed.AddPart(Alternative);

        // Add plain text mail body contents.
        SecureSmtpContent PlainTextContent = 
             new SecureSmtpContent(ContentType.Plain, PlainTextView);
        Alternative.AddPart(PlainTextContent);

        // The HTML alternative has two related parts. 
       // The HTML content and an inline image attachment
        // create related boundary
        SecureSmtpMultipart Related = new SecureSmtpMultipart(MultipartType.Related);
        Alternative.AddPart(Related);

        // Add html mail body content.
        SecureSmtpContent HtmlContent = new SecureSmtpContent(ContentType.Html, HtmlView);
        Related.AddPart(HtmlContent);

        // Add inline image attachment.
        // NOTE image id is set to IMAGE001 
        // this id must match the html image id in HtmlView text.
        SecureSmtpAttachment ImageAttachment = 
          new SecureSmtpAttachment(AttachmentType.Inline, "EmailImage.png", "IMAGE001");
        ImageAttachment.MediaType = "image/png";
        Related.AddPart(ImageAttachment);
        
        // Add file attachment to the email.
        // The recipient of the email will be able to save it as a file.
        SecureSmtpAttachment PdfAttachment = 
          new SecureSmtpAttachment(AttachmentType.Attachment, "rfc2045.pdf");
        Mixed.AddPart(PdfAttachment);

        // Send mail.
        ConnectionGMail.SendMail(Message);
        MessageBox.Show("Email was successfully sent");
        }

    // Catch exceptions.
    catch (Exception Exp)
        {
        MessageBox.Show(Exp.Message);
        }
    return;
    }

History

  • 2017/03/01: Version 1.0 Original version
  • 2019/06/20: Version 2.0 Support for subject line with non ASCII characters

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)