【问题标题】:GMAIL SMTP : A call to SSPI failed exception - The function requested is not supportedGMAIL SMTP:调用 SSPI 失败异常 - 不支持请求的函数
【发布时间】:2019-07-05 23:52:08
【问题描述】:

我正在使用 gmail smtp 发送邮件: 主机:smtp.gmail.com 端口:587

在 MVC 应用程序中使用 gmail smtp 发送邮件时出现异常。 以下代码用于发送邮件:

public static int SendMail(string StrFromAdd, string StrEmailTo, string StrSubject, string StrContents,
        string SMTPServer, int SMTPPort, string SMTPUserName, string SMTPPassword,
        string attachment = "", string CC = "", string BCC = "")
    {
        try
        {
            AlternateView AV = null;
            System.Net.Mail.SmtpClient smtpClient = new System.Net.Mail.SmtpClient();
            System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
            System.Net.Mail.MailAddress fromAddress = new System.Net.Mail.MailAddress(StrFromAdd, "Test");
            smtpClient.Host = SMTPServer;
            smtpClient.Port = SMTPPort;
            smtpClient.Credentials = new System.Net.NetworkCredential(SMTPUserName, SMTPPassword);

            smtpClient.EnableSsl = true;

            message.From = fromAddress;

            if (attachment != null)
            {
                string[] attachmentsarr = attachment.Split(';');
                foreach (string attach in attachmentsarr)
                {
                    if (attach != "")
                        message.Attachments.Add(new Attachment(attach));
                }
            }

            string pattern = @"^((([\w]+\.[\w]+)+)|([\w]+))@(([\w]+\.)+)([A-Za-z]{1,3})$";

            if (StrEmailTo != "")
            {
                if (StrEmailTo.IndexOf(',') > -1)
                {
                    string[] _strArrstrEmailTo = StrEmailTo.Split(',');
                    foreach (object objBCCEmailID in _strArrstrEmailTo)
                        if (Regex.IsMatch(objBCCEmailID.ToString().Trim(), pattern))
                            message.To.Add(new System.Net.Mail.MailAddress(objBCCEmailID.ToString().Trim()));

                }
                else
                    message.To.Add(new System.Net.Mail.MailAddress(StrEmailTo.ToString().Trim()));
            }

            if (CC != "")
            {
                if (CC.IndexOf(',') > -1)
                {
                    string[] _strArrstrEmailCC = CC.Split(',');
                    foreach (object objBCCEmailID in _strArrstrEmailCC)
                        if (Regex.IsMatch(objBCCEmailID.ToString().Trim(), pattern))
                            message.CC.Add(new System.Net.Mail.MailAddress(objBCCEmailID.ToString().Trim()));

                }
                else
                    message.CC.Add(new System.Net.Mail.MailAddress(CC.ToString().Trim()));
            }

            if (BCC != "")
            {
                if (BCC.IndexOf(',') > -1)
                {
                    string[] _strArrstrEmailBCC = BCC.Split(',');
                    foreach (object objBCCEmailID in _strArrstrEmailBCC)
                        if (Regex.IsMatch(objBCCEmailID.ToString().Trim(), pattern))
                            message.Bcc.Add(new System.Net.Mail.MailAddress(objBCCEmailID.ToString().Trim()));

                }
                else
                    message.Bcc.Add(new System.Net.Mail.MailAddress(BCC.ToString().Trim()));
            }
            // This is added for custom form & email template image
            List<string> ImageFiles = Common.GetImagesInHTMLString(StrContents);
            if (ImageFiles != null && ImageFiles.Count > 0)
            {
                string addStrContents = string.Empty;

                for (int i = 0; i < ImageFiles.Count; i++)
                {
                    // this is for custom form
                    if (ImageFiles[i].Contains("CustomFormImage"))
                    {
                        string Path = Regex.Match(ImageFiles[i], "<img.+?src=[\"'](.+?)[\"'].+?>", RegexOptions.IgnoreCase).Groups[1].Value;
                        int pos = Path.LastIndexOf("\\") + 1;
                        string FullPath = HttpContext.Current.Server.MapPath("~/img/CustomFormImage/" + Path.Substring(pos, Path.Length - pos));
                        if (System.IO.File.Exists(FullPath))
                        {
                            //addStrContents = addStrContents + "<img style='width:100px;height:100px;' src=\"cid:" + Path.Substring(pos, Path.Length - pos).Split('.')[0] + "\">" + Environment.NewLine;
                            StrContents = StrContents.Replace(Path, "cid:" + Path.Substring(pos, Path.Length - pos).Split('.')[0]);
                        }
                    }
                    // this is for email template image
                    else if (ImageFiles[i].Contains("EmailHeaderFooterImgs"))
                    {
                        string Path = Regex.Match(ImageFiles[i], "<img.+?src =[\"'](.+?)[\"'].+?>", RegexOptions.IgnoreCase).Groups[1].Value;
                        int pos = Path.LastIndexOf("\\") + 1;
                        if (System.IO.File.Exists(Path))
                        {
                            //addStrContents = addStrContents + "<img style='width:100px;height:100px;' src=\"cid:" + Path.Substring(pos, Path.Length - pos).Split('.')[0] + "\">" + Environment.NewLine;
                            StrContents = StrContents.Replace(Path, "cid:" + Path.Substring(pos, Path.Length - pos).Split('.')[0]);
                        }
                    }
                }
                AV = AlternateView.CreateAlternateViewFromString(StrContents, null, MediaTypeNames.Text.Html);
                for (int i = 0; i < ImageFiles.Count; i++)
                {
                    // this is for custom form
                    if (ImageFiles[i].Contains("CustomFormImage"))
                    {
                        string Path = Regex.Match(ImageFiles[i], "<img.+?src=[\"'](.+?)[\"'].+?>", RegexOptions.IgnoreCase).Groups[1].Value;
                        int pos = Path.LastIndexOf("\\") + 1;
                        string FullPath = HttpContext.Current.Server.MapPath("~/img/CustomFormImage/" + Path.Substring(pos, Path.Length - pos));
                        if (System.IO.File.Exists(FullPath))
                        {
                            //FileStream fs = new FileStream(FullPath, FileMode.Open, FileAccess.Read);
                            //Attachment a = new Attachment(fs, Path.Substring(pos, Path.Length - pos), MediaTypeNames.Application.Octet);
                            //message.Attachments.Add(a);
                            //addStrContents = addStrContents + "<img src=\"cid:" + Path.Substring(pos, Path.Length - pos).Split('.')[0] + "\">" + Environment.NewLine;
                            LinkedResource Img = new LinkedResource(FullPath, MediaTypeNames.Image.Jpeg);
                            Img.ContentId = Path.Substring(pos, Path.Length - pos).Split('.')[0];
                            AV.LinkedResources.Add(Img);
                        }
                    }
                    // this is for email template image
                    else if (ImageFiles[i].Contains("EmailHeaderFooterImgs"))
                    {
                        string Path = Regex.Match(ImageFiles[i], "<img.+?src =[\"'](.+?)[\"'].+?>", RegexOptions.IgnoreCase).Groups[1].Value;
                        int pos = Path.LastIndexOf("\\") + 1;
                        if (HttpContext.Current != null)
                        {
                            string FullPath = HttpContext.Current.Server.MapPath("~/EmailHeaderFooterImgs/" + Path.Substring(pos, Path.Length - pos));
                            if (System.IO.File.Exists(Path))
                            {
                                LinkedResource Img = new LinkedResource(Path, MediaTypeNames.Image.Jpeg);
                                Img.ContentId = Path.Substring(pos, Path.Length - pos).Split('.')[0];
                                AV.LinkedResources.Add(Img);
                            }
                        }
                    }
                }
            }

            message.Subject = StrSubject;
            message.IsBodyHtml = true;
            if (AV != null)
                message.AlternateViews.Add(AV);
            else
                message.Body = StrContents;

            smtpClient.Send(message);
            message.Dispose();
            return 1;
        }
        catch (Exception ex)
        {

        }
    }

下面是堆栈跟踪:

    System.Security.Authentication.AuthenticationException: A call to SSPI failed, see inner exception. System.ComponentModel.Win32Exception: The function requested is not supported
   at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, Exception exception)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
   at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.Mail.SmtpConnection.Flush()
   at System.Net.Mail.ReadLinesCommand.Send(SmtpConnection conn)
   at System.Net.Mail.EHelloCommand.Send(SmtpConnection conn, String domain)
   at System.Net.Mail.SmtpConnection.GetConnection(ServicePoint servicePoint)
   at System.Net.Mail.SmtpClient.GetConnection()
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   at MVC.Common.SendMails.SendMail(String StrFromAdd, String StrEmailTo, String StrSubject, String StrContents, String SMTPServer, Int32 SMTPPort, String SMTPUserName, String SMTPPassword, String attachment, String CC, String BCC) in SendMails.cs:line 296

注意:相同的代码正在另一个应用程序中运行,该应用程序托管在同一台服务器上,并且也使用相同的 gmail 配置来发送邮件。

【问题讨论】:

    标签: c# email smtp gmail smtpclient


    【解决方案1】:

    假设您的代码是为(例如).NET Framework 4.7.2 编译的,那么请确保您的 Web.config 包括:

    <httpRuntime targetFramework="4.7.2" />
    

    如果您的targetFramework 设置过低或缺失,则编译后的代码将自动尝试请求 TLS 1.2(从 .NET Framework 4.7 开始发生)但目标运行时不支持它,因此会出现错误。

    (感谢this SO answer,这让我意识到这里出了什么问题——尽管那个问题和这个问题不是重复的。)

    【讨论】:

    • 我最初把这个答案放在这里stackoverflow.com/q/38527662,但我把它移到了这里,因为我认为它在这里更明确相关。我刚刚在另一个问题上留下了带有链接的评论。
    【解决方案2】:

    我在发送前更改了安全协议解决了这个问题

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
    

    【讨论】:

      猜你喜欢
      • 2012-10-18
      • 2016-04-10
      • 2021-06-25
      • 1970-01-01
      • 2022-12-18
      • 1970-01-01
      • 2019-01-20
      • 2020-09-24
      • 1970-01-01
      相关资源
      最近更新 更多