SMTP authentication in detail
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:
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:
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:
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", null, null); // 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(Nothing, String), CType(Nothing, String)) ' 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:


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:
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).
Copyright © 2006-2012 AfterLogic Corporation. All rights reserved.