How to force System.Net.Mail to use AUTH LOGIN instead of AUTH gssapi


When we send a mail out using System.Net.mail, It sends out a EHLO command, It then parses out the response to create a list of the Authentication mechanism that are supported by the SMTP Server.
It then loops through the internal Authentication mechanisms which are listed below:
-SmtpNegotiateAuthenticationModule
-SmtpNTLMAuthenticationModule
-SmtpDigestAuthenticationModule
-SmtpLoginAuthenticationModule

Then it compared each one against the list to check if it is supported by the SMTP server. If it is supported by the SMTP Server that Authentication mechanism is selected and it proceeds further. 

System.Net.Mail code below(Visual Studio 2008 allows us to step through the source code):

for (int i = 0; i < authenticationModules.Length; i++) 
 {
   //only authenticate if the auth protocol is supported  - [....]
   if (!AuthSupported(authenticationModules[i])) { 
      continue;
      } 
   NetworkCredential cred;
   cred=credentials.GetCredential(host,port,authenticationModules[i].AuthenticationType); 

   if (cred == null) 
            continue;
   Authorization auth;
   auth = SetContextAndTryAuthenticate(authenticationModules[i],cred, null);
   .............
 } 

Assuming the SMTP Server supports SmtpNegotiateAuthenticationModule(gssapi) and SmtpLoginAuthenticationModule(Login) but we would want System.Net.Mail to use Login, How do we do it?

We will have to build a class that implements ICredentialByHost, and then intercept calls checking for the methods we wish to block, and just return null for those.

In the above code block when the call to "cred = credentials.GetCredential(host, port, authenticationModules[i].AuthenticationType);" is made, the code in our custom class is executed with the AuthenticationType sent as a parameter. If we return null, we hit the continue statement, System.Net.Mail switches to a different AuthenticationModule.

Below is the class that we need to create and implement in our code:

private class BlockGSSAPINTLMCredential : ICredentialsByHost
{
  private NetworkCredential WrappedNetworkCredential;
  public BlockGSSAPINTLMCredential(string username, string password)
  {
      WrappedNetworkCredential = new NetworkCredential(username, password);            
  }
  #region ICredentialsByHost Members
  public NetworkCredential GetCredential(string host, int port, string authenticationType)
  {
    if (authenticationType.ToLower() == "gssapi" || authenticationType.ToLower() == "ntlm")
        {
            return null;
        }
    return WrappedNetworkCredential.GetCredential(host, port, authenticationType);
  }
  #endregion
}

In the code above we are returning null if the AuthentationType is “gssapi” or “ntlm” thus forcing System.Net.Mail to use “Login”.

When sending out the mail, set the credentials in the code as below:

client.Credentials = new BlockGSSAPINTLMCredential("user@domain.com", "Password"); 
Comments (2)

  1. Raul says:

    Could you provide all code for SendMail,Thanks a lo

  2. Rahul Vaidya says:

    Fantastic!  Our app’s mails were failing due to bad GSSAPI authentication (bad implementation in .NET?).  This little hack does the trick!

Skip to main content