File: System\Net\Mail\SmtpConnection.Auth.cs
Web Access
Project: src\src\libraries\System.Net.Mail\src\System.Net.Mail.csproj (System.Net.Mail)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
namespace System.Net.Mail
{
    internal enum SupportedAuth
    {
        None = 0,
        Login = 1,
        NTLM = 2,
        GSSAPI = 4
    };
 
    internal sealed partial class SmtpConnection
    {
        private bool _serverSupportsEai;
        private bool _dsnEnabled;
#pragma warning disable CS0414      // Field is not used in test project
        private bool _serverSupportsStartTls;
#pragma warning restore CS0414
        private bool _sawNegotiate;
        private SupportedAuth _supportedAuth = SupportedAuth.None;
        private readonly ISmtpAuthenticationModule[] _authenticationModules;
 
        // accounts for the '=' or ' ' character after AUTH
        private const int SizeOfAuthExtension = 4;
 
        private static readonly char[] s_authExtensionSplitters = new char[] { ' ', '=' };
        private const string AuthExtension = "auth";
        private const string AuthLogin = "login";
        private const string AuthNtlm = "ntlm";
        private const string AuthGssapi = "gssapi";
 
        internal SmtpConnection(ISmtpAuthenticationModule[] authenticationModules)
        {
            _authenticationModules = authenticationModules;
        }
 
        internal bool DSNEnabled => _dsnEnabled;
 
        internal bool ServerSupportsEai => _serverSupportsEai;
 
        internal void ParseExtensions(string[] extensions)
        {
            _supportedAuth = SupportedAuth.None;
            foreach (string extension in extensions)
            {
                if (string.Compare(extension, 0, AuthExtension, 0,
                    SizeOfAuthExtension, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    // remove the AUTH text including the following character
                    // to ensure that split only gets the modules supported
                    string[] authTypes = extension.Remove(0, SizeOfAuthExtension).Split(s_authExtensionSplitters, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string authType in authTypes)
                    {
                        if (string.Equals(authType, AuthLogin, StringComparison.OrdinalIgnoreCase))
                        {
                            _supportedAuth |= SupportedAuth.Login;
                        }
                        else if (string.Equals(authType, AuthNtlm, StringComparison.OrdinalIgnoreCase))
                        {
                            _supportedAuth |= SupportedAuth.NTLM;
                        }
                        else if (string.Equals(authType, AuthGssapi, StringComparison.OrdinalIgnoreCase))
                        {
                            _supportedAuth |= SupportedAuth.GSSAPI;
                        }
                    }
                }
                else if (string.Compare(extension, 0, "dsn ", 0, 3, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    _dsnEnabled = true;
                }
                else if (string.Compare(extension, 0, "STARTTLS", 0, 8, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    _serverSupportsStartTls = true;
                }
                else if (string.Compare(extension, 0, "SMTPUTF8", 0, 8, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    _serverSupportsEai = true;
                }
            }
        }
 
        internal bool AuthSupported(ISmtpAuthenticationModule module)
        {
            if (module is SmtpLoginAuthenticationModule)
            {
                if ((_supportedAuth & SupportedAuth.Login) > 0)
                {
                    return true;
                }
            }
            else if (module is SmtpNegotiateAuthenticationModule)
            {
                if ((_supportedAuth & SupportedAuth.GSSAPI) > 0)
                {
                    _sawNegotiate = true;
                    return true;
                }
            }
            else if (module is SmtpNtlmAuthenticationModule)
            {
                // Don't try ntlm if negotiate has been tried
                if ((!_sawNegotiate && (_supportedAuth & SupportedAuth.NTLM) > 0))
                {
                    return true;
                }
            }
 
            return false;
        }
    }
}