MailBee.NET Objects Developer's Guide

 

SMTP authentication in detail

 

  1. SMTP authentication explained
  2. POP-before-SMTP or ESMTP?
  3. Authenticate with POP-before-SMTP
  4. ESMTP authentication in more detail
  5. Secure authentication
  6. Use Integrated Windows Authentication (no username and password required)
  7. Use OAuth with Gmail (no password required)
  8. Fine-tune SMTP authentication process
  9. Create your own authentication method

 


 

SMTP authentication explained

 

SMTP authentication allows the client to show the server that this client has permission to relay e-mail through this server.

 

In most cases, you can send without authentication to local e-mail addresses of this domain (i.e. send from bob@domain.com to alice@domain.com) because the server does not need to relay your e-mail to external servers. Authentication is required whenever the recipient is not of a local domain (i.e. send from joe@company.com to tom@example.com, provided that company.com and example.com use different e-mail servers).

 

Every rule has its exceptions. Some servers require the client to authenticate itself even when sending to a local domain. But more popular case is opposite - some servers do not support authentication but allow the client to send with no limitations (so called open relays). To avoid exploiting such server by spammers, it usually restricts the IP address list of allowed sender. Typical case if when your application resides on such server and the server allows unauthenticated servers to relay e-mail only if they connect from the server computer itself.

 

When authentication is enabled, you usually need to supply your login name and password on this server (although variants with other parameters exist as well, such as OAuth tokens). The login name is the most tricky part: it can be your account name, account@domain, domain\account, domain\account\alias (in MS Exchange), and so on. For instance, if you're using account name in Outlook (which uses MAPI instead of SMTP), the SMTP name for the same could be domain\account.

 

There are two types of SMTP authentication, both supported by MailBee.NET:

  1. POP-before-SMTP authentication, now deprecated but still supported or even required by some very old servers.
  2. ESMTP authentication via so called SASL mechanism. All newer servers use this type.

 


 

POP-before-SMTP or ESMTP?

 

The only reason to use POP-before-SMTP authentication is the lack of support of ESMTP authentication by the server. However, if the server does not advertize ESMTP authentication support in response to EHLO command, it does not yet mean you have to use POP-before-SMTP.

 

Typical reasons why a newer server (which can support ESMTP authentication) might not advertize this capability to a client:

  1. STARTTLS first. The server wants the authentication process to take place under the SSL layer. MS Exchange 2010 is an example.
  2. The server may be configured to act as an open relay for the given IP address of the client. Typical case with intranet networks.
  3. The server does not relay e-mail to external domains at all but only accepts e-mail from other hosts. SMTP services of large e-mail providers often have different SMTP relay servers for outgoing e-mail and SMTP MX servers for incoming e-mail.

 

If any of the above is the case, it does not make sense to use POP-before-SMTP as it won't work anyway.

 


 

Authenticate with POP-before-SMTP

 

Generally speaking, POP-before-SMTP authentication is just an awkward way to overcome the limitation of the original SMTP protocol which did not support any authentication mechanism (ESMTP authentication has been invented years later). The idea is to connect to the POP3 service of the same e-mail server, authenticate there, and then immediately connect via SMTP to the same server. The server will remember your IP address for a few moments, and the SMTP part of the server will know that you recently passed POP3 authentication on this server.

 

Of course, this is not very secure (many different clients can have the same IP address due to NATs and proxies), and requires the server run both POP3 and SMTP services on the same system.

 

Anyway, if you have to use POP-before-SMTP, that's how you can do it:

 

C#

Smtp mailer = new Smtp();
 
// See in the log file what exactly happens during POP-before-SMTP.
mailer.Log.Enabled = true;
mailer.Log.Filename = "C:\\Temp\\log.txt";
mailer.Log.Clear();
 
// Add SMTP relay, no ESMTP authentication.
mailer.SmtpServers.Add("smtp.domain.com");
 
// Authenticate with POP-before-SMTP.
mailer.AuthPopBeforeSmtp("pop.domain.com", 110, "jdoe""secret");
 
// Compose and send an e-mail.
mailer.From.Email = "jdoe@domain.com";
mailer.To.Add("jane@example.com");
mailer.Subject = "Test message";
mailer.Send();

VB

Dim mailer As New Smtp()
 
' See in the log file what exactly happens during POP-before-SMTP.
mailer.Log.Enabled = True
mailer.Log.Filename = "C:\Temp\log.txt"
mailer.Log.Clear()
 
' Add SMTP relay, no ESMTP authentication.
mailer.SmtpServers.Add("smtp.domain.com")
 
' Authenticate with POP-before-SMTP.
mailer.AuthPopBeforeSmtp("pop.domain.com", 110, "jdoe""secret")
 
' Compose and send an e-mail.
mailer.From.Email = "jdoe@domain.com"
mailer.To.Add("jane@example.com")
mailer.Subject = "Test message"
mailer.Send()

Here and below, we assume MailBee and MailBee.SmtpMail namespaces are imported and the license key is set. See Import namespaces and set license key topic for details.

 


 

ESMTP authentication in more detail

 

ESMTP authentication itself is not a particular method or algorithm. It's rather a protocol (SASL over SMTP). There are lots of particular authentication method implementations, and the most popular are: LOGIN, PLAIN, CRAM-MD5, DIGEST-MD5, NTLM, GSSAPI, XOAUTH. MailBee.NET supports them all and also provides the mechanism to implement your own methods.

 

The server lists the supported authentication methods in AUTH lines of the reply to EHLO command. All authentication data is base64-encoded to avoid issues with special symbols which may appear in username and password strings.

 

All methods except of LOGIN and PLAIN are secure and use hash-based algorithms. If LOGIN or PLAIN is being used, SSL connection is recommended if security considerations apply for your case (and many servers simply do not allow you to use these methods unless the connection is SSL-encrypted).

 

NTLM and GSSAPI methods are widely used by Microsoft products like MS Exchange or IIS SMTP Service.

 

SPA (Secure Password Authentication) is another name for NTLM.

 

NTLM and GSSAPI are often used in so-called Integrated Windows Authentication mode when the sender automatically uses the login and password of the Windows user under whose context the application runs. The application does not need to know the password of the user in order to operate their e-mail account. See Use Integrated Windows Authentication (no username and password required) topic for details.

 

Integrated Windows Authentication, however, won't work with a web application unless it's executed under the context of an interactive user. Most web apps are executed under a system user's account, not an interactive user's account.

 

The e-mail account password is also not required by the application in case of XOAUTH method. It implements OAuth technology which lets applications access restricted resources via authorization instead of authentication. See Use OAuth with Gmail (no password required) topic for details.

 

MailBee.NET can automatically select the best (the most secure) authentication method supported by the given server, and this is the default behaviour. However, some servers do not properly support secure authentication methods, and it may be required to fallback to simpler methods. By default, MailBee.NET then tries an insecure method if the secure method fails. If you can't afford using insecure methods for security reasons, you can set AuthenticationOptions.DisableSimpleMethodAfterSecure flag.

 

More specifically, the server may require you to pass different login name for different authentication methods. For instance, a simpler method may accept just an account name while a secure method may also require you to supply your domain name, workstation name, etc. See Fine-tune SMTP authentication process topic for more details on how to apply various AuthenticationOptions flags.

 


 

Secure authentication

 

By default, if the server supports secure authentication, MailBee.NET will use it automatically. No further action is required on your part.

 

However, if the server does not support any secure methods, MailBee.NET by default downgrades to insecure methods if supported by the server. If you cannot allow this for security reasons, you can explicitly specify which authentication methods to use. The sample below will connect to the e-mail server only if it supports secure authentication:

 

C#

Smtp mailer = new Smtp();
 
// See in the log file what exactly happens during authentication.
mailer.Log.Enabled = true;
mailer.Log.Filename = "C:\\Temp\\log.txt";
mailer.Log.Clear();
 
// Use SMTP relay with authentication (username in MS Exchange style).
SmtpServer relay = mailer.SmtpServers.Add(
    "smtp.here.com""jdoe\\here.com""secret");
 
// Allow secure authentication methods only.
relay.AuthMethods = AuthenticationMethods.SaslCramMD5 |
    AuthenticationMethods.SaslDigestMD5 |
    AuthenticationMethods.SaslGssApi |
    AuthenticationMethods.SaslNtlm;
 
// Compose and send an e-mail.
mailer.From.Email = "jdoe@here.com";
mailer.To.Add("jane@example.com");
mailer.Subject = "Test message";
mailer.Send();

VB

Dim mailer As New Smtp()
 
' See in the log file what exactly happens during authentication.
mailer.Log.Enabled = True
mailer.Log.Filename = "C:\Temp\log.txt"
mailer.Log.Clear()
 
' Use SMTP relay with authentication (username in MS Exchange style).
Dim relay As SmtpServer = mailer.SmtpServers.Add( _
    "smtp.here.com""jdoe\here.com""secret")
 
' Allow secure authentication methods only.
relay.AuthMethods = AuthenticationMethods.SaslCramMD5 Or _
    AuthenticationMethods.SaslDigestMD5 Or _
    AuthenticationMethods.SaslGssApi Or _
    AuthenticationMethods.SaslNtlm
 
' Compose and send an e-mail.
mailer.From.Email = "jdoe@here.com"
mailer.To.Add("jane@example.com")
mailer.Subject = "Test message"
mailer.Send()

If the server does not support any secure methods, MailBee.NET will throw MailBeeLoginNoSupportedMethodsException.

 

Note that we haven't included OAuth in the list of the allowed secure methods. OAuth, being the method of an authorization rather than authentication, is always used on its own because its parameters are not compatible with "real" authentication methods. MailBee.NET won't use OAuth unless it's the only method in the list of the allowed methods.

 


 

Use Integrated Windows Authentication (no username and password required)

 

NTLM and GSSAPI authentication methods can work in two modes:

  1. The user specifies their credentials explicitly (like other authentication methods work), and MailBee.NET creates the authentication token from them.
  2. Integrated Windows Authentication (IWA). The authentication token is created by Windows from the credentials of the currently logged Windows user. The application never deals with the account password. IWA mode provides increased security and spares the end user from entering their credentials.

 

IWA, however, cannot be used when the currently logged Windows user is not an interactive user. In web applications, you often deal with system users (like NETWORK SERVICE, ASPNET, etc). To be able to use IWA with MailBee.NET in an ASP.NET application, the application itself must run under the context of an interactive user (<authentication mode="Windows"/> in web.config).

 

Also, the user from whose context the authentication token is constructed, must have a valid mailbox on the e-mail server. This is an important note: even if the given user is registered in the Active Directory and can log in the domain, this does not necessarily mean that the system has already provisioned their mailbox.

 

Let's assume that the current user context denotes a user which has a mailbox on the e-mail server integrated with your Active Directory. The sample below authenticates using IWA and sends an e-mail:

 

C#

Smtp mailer = new Smtp();
 
// See in the log file what exactly happens during authentication.
mailer.Log.Enabled = true;
mailer.Log.Filename = "C:\\Temp\\log.txt";
mailer.Log.Clear();
 
// Use SMTP relay with authentication (take credentials from Windows).
SmtpServer relay = mailer.SmtpServers.Add(
    "mail.domain.com"nullnull);
 
// Allow methods which can do Integrated Windows Authentication.
relay.AuthMethods = AuthenticationMethods.SaslNtlm |
    AuthenticationMethods.SaslGssApi;
 
// Compose and send an e-mail.
mailer.From.Email = "jdoe@domain.com";
mailer.To.Add("jane@example.com");
mailer.Subject = "Test message";
mailer.Send();

VB

Dim mailer As New Smtp()
 
' See in the log file what exactly happens during authentication.
mailer.Log.Enabled = True
mailer.Log.Filename = "C:\Temp\log.txt"
mailer.Log.Clear()
 
' Use SMTP relay with authentication (take credentials from Windows).
Dim relay As SmtpServer = mailer.SmtpServers.Add( _
    "mail.domain.com"CType(NothingString), CType(NothingString))
 
' Allow methods which can do Integrated Windows Authentication.
relay.AuthMethods = AuthenticationMethods.SaslNtlm Or _
    AuthenticationMethods.SaslGssApi
 
' Compose and send an e-mail.
mailer.From.Email = "jdoe@domain.com"
mailer.To.Add("jane@example.com")
mailer.Subject = "Test message"
mailer.Send()

 

Use OAuth with Gmail (no password required)

 

OAuth addresses the common problem when the user does not want to give their password away to the external system which needs access to their data. The solution is to use authorization instead of authentication.

 

Let's imagine your application needs to send an e-mail from Gmail's account of a user. The user wants the e-mail to be sent but does not want your application to discover their password. In other words, the user wants to authorize your application to send an e-mail on their behalf but does not let your application to authenticate with their credentials on the e-mail server.

 

Here is the procedure:

  1. From the supplied URL of the Google's web site, MailBee.NET creates a URL with OAuth-specific query string parameters. This URL denotes "Request access" web page on Google site.
  2. Your application opens that page in the web browser:
  3. If the user is not already logged in a Google account on this computer, they confirm their identity to Google (remember, the page was opened on Google web site, your application just requested this but it has no access to the username and password the user may have entered at the Google site).
  4. The user grants access to your application by clicking Grant Access button.
  5. The Gmail web site responds with an authorization token:
  6. The user copies this token and provides it to your application.
  7. Your application uses the authorization token to get the access key from Google via HTTP request.
  8. Your application then connects to Gmail and logs in using OAuth as the authentication method and the access key as the password.

 

In most cases, if the user has "Remember me on this computer" option enabled in Gmail, they don't even need to confirm their identity to Google and re-enter their username and password at the step 3, so this step is usually skipped.

 

Note that by default Google warns you that the application which requests authorization is not trusted. To overcome this, you can register at Google's "Registration for Web Applications" page to receive your pair of unique keys instead of "anonymous".

 

In addition to OAuth, MailBee.NET also supports OpenID which makes it possible to determine the user's e-mail address automatically if this user has already logged in OpenID-compatible service on this computer (e.g. has "Remember me on this computer" option enabled in Gmail). See OpenID class reference for details.

 

This console sample sends an e-mail from your Gmail account, not knowing its password:

 

C#

using System;
using System.Collections.Specialized;
using MailBee;
using MailBee.SmtpMail;
 
class Sample
{
    static void Main(string[] args)
    {
        Console.Write("Please enter your email: ");
        string userEmail = Console.ReadLine().Trim();
 
        OAuth myOAuth = new OAuth("anonymous""anonymous");
 
        StringDictionary parameters = new StringDictionary();
        parameters.Add("scope""https://mail.google.com/");
        parameters.Add(OAuth.OAuthCallbackKey, "oob");
 
        // First: Fetch Request Token.
        myOAuth.RequestToken(
            "https://www.google.com/accounts/OAuthGetRequestToken", parameters);
 
        // Second: Redirect to Authorization and Fire up the browser.
        System.Diagnostics.Process.Start(myOAuth.AuthorizeToken(
            "https://www.google.com/accounts/OAuthAuthorizeToken"));
 
        Console.Write("Please enter the key: ");
        string key = Console.ReadLine().Trim();
 
        try
        {
            // Third: Fetch Access Token.
            myOAuth.AccessToken(
                "https://www.google.com/accounts/OAuthGetAccessToken", key);
        }
        catch (MailBeeWebException e)
        {
            Console.WriteLine("If Bad request (400), the key is incorrect.");
            Console.WriteLine("Be sure to copy/paste it correctly next time.");
            Console.WriteLine();
            Console.WriteLine(e.Message);
            return;
        }
 
        // Get XOAuth key for SMTP.
        string smtpXOAuthKey = myOAuth.GetXOAuthKey(
            string.Format("https://mail.google.com/mail/b/{0}/smtp/", userEmail));
 
        Smtp mailer = new Smtp();
 
        // Use SMTP relay of Gmail with OAuth.
        SmtpServer relay = mailer.SmtpServers.Add(
            "smtp.gmail.com"null, smtpXOAuthKey);
 
        // OAuth must be specified explicitly.
        relay.AuthMethods = AuthenticationMethods.SaslOAuth;
 
        // Compose and send an e-mail.
        mailer.From.Email = userEmail;
        mailer.To.Add("jane@example.com");
        mailer.Subject = "Test message";
        mailer.Send();
    }
}

VB

Imports System
Imports System.Collections.Specialized
Imports MailBee
Imports MailBee.SmtpMail
 
Module Module1
    Sub Main(ByVal args() As String)
        Console.Write("Please enter your email: ")
        Dim userEmail As String = Console.ReadLine().Trim()
 
        Dim myOAuth As New OAuth("anonymous""anonymous")
 
        Dim parameters As New StringDictionary()
        parameters.Add("scope""https://mail.google.com/")
        parameters.Add(OAuth.OAuthCallbackKey, "oob")
 
        ' First: Fetch Request Token.
        myOAuth.RequestToken( _
            "https://www.google.com/accounts/OAuthGetRequestToken", parameters)
 
        ' Second: Redirect to Authorization and Fire up the browser.
        System.Diagnostics.Process.Start(myOAuth.AuthorizeToken( _
            "https://www.google.com/accounts/OAuthAuthorizeToken"))
 
        Console.Write("Please enter the key: ")
        Dim key As String = Console.ReadLine().Trim()
 
        Try
            ' Third: Fetch Access Token.
            myOAuth.AccessToken( _
                "https://www.google.com/accounts/OAuthGetAccessToken", key)
        Catch e As MailBeeWebException
            Console.WriteLine("If Bad request (400), the key is incorrect.")
            Console.WriteLine("Be sure to copy/paste it correctly next time.")
            Console.WriteLine()
            Console.WriteLine(e.Message)
            Return
        End Try
 
        ' Get XOAuth key for SMTP.
        Dim smtpXOAuthKey As String = myOAuth.GetXOAuthKey( _
            String.Format("https://mail.google.com/mail/b/{0}/smtp/", userEmail))
 
        Dim mailer As New Smtp()
 
        ' Use SMTP relay of Gmail with OAuth.
        Dim relay As SmtpServer = mailer.SmtpServers.Add( _
            "smtp.gmail.com"Nothing, smtpXOAuthKey)
 
        ' OAuth must be specified explicitly.
        relay.AuthMethods = AuthenticationMethods.SaslOAuth
 
        ' Compose and send an e-mail.
        mailer.From.Email = userEmail
        mailer.To.Add("jane@example.com")
        mailer.Subject = "Test message"
        mailer.Send()
    End Sub
End Module

Note: to run this sample, use "Start without Debugging" command instead of "Debug". In some versions of Windows, paste operations are not working in Debug mode of Visual Studio. Or, convert it in a WinForms or web application.

 

This sample uses 3-legged OAuth. There is also a simpler 2-legged OAuth available but it's not as secure and Gmail supports it only for some accounts. Refer to OAuth topic in MailBee.NET Objects reference to learn more and find the sample code.

 


 

Fine-tune SMTP authentication process

 

MailBee.NET supports lots of parameters and options that affect the authentication process. The most important are:

  1. AuthenticationOptions.PreferSimpleMethods - try insecure methods first instead of secure methods. Fixes problems with servers which declare support of secure methods but implement them incorrectly. By default, MailBee.NET then tries an insecure method but this may not work if the server aborts the connection instead of returning a negative reply in case of authentication error. This flag allows even not to try secure methods if less secure are available.
  2. AuthenticationOptions.DisableSimpleMethodAfterSecure - set it if you don't want MailBee.NET to fall-back to an insecure method if the secure method failed.
  3. SmtpServer.AccountDomain and SmtpServer.TargetName - used with NTLM and GSSAPI. You may need to set SmtpServer.AccountDomain and, sometimes, SmtpServer.TargetName when using MS Exchange (especially newer versions).
  4. SmtpServer.IgnoreLoginFailure - try to send even if ESMTP or POP-before-SMTP authentication failed. There is still a chance the server will accept the message (for instance, if it's addressed to local recipients only) so that this setting makes some sense.

 

The code snippet below makes MailBee.NET to use an insecure method even if a secure method seems to be supported. MailBee.NET will still use a secure method when no insecure methods are supported by the server:

 

C#

SmtpServer relay = mailer.SmtpServers.Add(
    "smtp.here.com""joe""secret");
 
relay.AuthOptions = AuthenticationOptions.PreferSimpleMethods;

VB

Dim relay As SmtpServer = mailer.SmtpServers.Add( _
    "smtp.here.com""joe""secret")
 
relay.AuthOptions = AuthenticationOptions.PreferSimpleMethods

We assume mailer is an Smtp instance.

 

The next code snippet configures MailBee.NET to use GSSAPI/Kerberos authentication when using SMTP Service of Microsoft IIS 7 or above:

 

C#

SmtpServer relay = mailer.SmtpServers.Add(
    "mail.company.com""joe""secret");
 
relay.AccountDomain = "company.com";
relay.TargetName = "SmtpSvc/mail.company.com";
relay.AuthMethods = AuthenticationMethods.SaslGssApi;

VB

Dim relay As SmtpServer = mailer.SmtpServers.Add( _
    "mail.company.com""joe""secret")
 
relay.AccountDomain = "company.com"
relay.TargetName = "SmtpSvc/mail.company.com"
relay.AuthMethods = AuthenticationMethods.SaslGssApi

You can explore AuthenticationOptions enumeration to learn which other options are available.

 


 

Create your own authentication method

 

To learn how create your own SASL method, refer to SaslMethod class documentation. It demonstrates creating a SASL method which is then used with Pop3 class but SASL methods are protocol-independent, so that you can use the same class you developed, with all protocols including SMTP.

 

The code snippet below indicates how to configure SmtpServer object so that MailBee.NET could use your custom method during the authentication process:

 

C#

SmtpServer relay = mailer.SmtpServers.Add(
    "mail.company.com""joe@domain.com""secret");
 
relay.AuthMethods = AuthenticationMethods.SaslUserDefined;
relay.AuthUserDefined = new SaslLoginMethod();

VB

Dim relay As SmtpServer = mailer.SmtpServers.Add( _
    "mail.company.com""joe@domain.com""secret")
 
relay.AuthMethods = AuthenticationMethods.SaslUserDefined
relay.AuthUserDefined = New SaslLoginMethod()

We assume mailer is an Smtp instance and SaslLoginMethod represents your custom authentication method as defined in SaslMethod class documentation.

 

You can also use your custom method together with the standard methods. For instance, you can leave relay.AuthMethods in its default AuthenticationMethods.Auto state. MailBee.NET will treat your custom method accordingly the same rules applied to other methods (i.e. try it first if it's secure, do not try if the server does not advertize this method as supported, etc).

 


Send feedback to AfterLogic

Copyright © 2006-2012 AfterLogic Corporation. All rights reserved.