使用SSL发送邮件到Gmail时,身份验证或解密失败

10

我参考了这个C# SMTP邮件指南

这是我的代码:

MailMessage mail = new MailMessage();
SmtpClient SmtpServer = new SmtpClient("smtp.gmail.com");
mail.From = new MailAddress("dave.stockinger@gmail.com");
mail.To.Add("dave.stockinger@gmail.com");
mail.Subject = "Test Mail";
mail.Body = "This is for testing SMTP mail from GMAIL";
SmtpServer.Port = 587;
SmtpServer.Credentials = new System.Net.NetworkCredential("MyUserNameInGmail", "MyGmailPassWord");
SmtpServer.EnableSsl = true;

SmtpServer.Send(mail);

很不幸,关于SSL有一个例外情况,我无法解决:

未处理的异常:System.Net.Mail.SmtpException: 无法发送邮件。 ---> System.IO.IOException: 验证或解密失败。 ---> System.InvalidOperationException: SSL验证错误:RemoteCertificateNotAvailable,RemoteCertificateChainErrors at System.Net.Mail.SmtpClient.m__4 (System.Object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, SslPolicyErrors sslPolicyErrors) [0x00000] in :0 at System.Net.Security.SslStream+c__AnonStorey7.<>m__A (System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Int32[] certErrors) [0x00000] in :0
at Mono.Security.Protocol.Tls.SslClientStream.OnRemoteCertificateValidation (System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Int32[] errors) [0x00000] in :0
at Mono.Security.Protocol.Tls.SslStreamBase.RaiseRemoteCertificateValidation (System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Int32[] errors) [0x00000] in :0
at Mono.Security.Protocol.Tls.SslClientStream.RaiseServerCertificateValidation (System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Int32[] certificateErrors) [0x00000] in :0 at Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.validateCertificates (Mono.Security.X509.X509CertificateCollection certificates) [0x00000] in :0 at Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.ProcessAsTls1 () [0x00000] in :0
at Mono.Security.Protocol.Tls.Handshake.HandshakeMessage.Process () [0x00000] in :0
at (wrapper remoting-invoke-with-check) Mono.Security.Protocol.Tls.Handshake.HandshakeMessage:Process () at Mono.Security.Protocol.Tls.ClientRecordProtocol.ProcessHandshakeMessage (Mono.Security.Protocol.Tls.TlsStream handMsg) [0x00000] in :0 at Mono.Security.Protocol.Tls.RecordProtocol.InternalReceiveRecordCallback (IAsyncResult asyncResult) [0x00000] in :0 --- inner exception stack trace --- at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResult asyncResult) [0x00000] in :0 --- End of inner exception stack trace --- at System.Net.Mail.SmtpClient.Send (System.Net.Mail.MailMessage message) [0x00000] in :0 at csharpdungeon.MainClass.Main () [0x00000] in :0


1
有人已经实现了通过 Gmail 发送邮件(https://dev59.com/tXVD5IYBdhLWcg3wRpeX) - user57508
7个回答

23

请检查以下代码是否适用于您; 我已在我的Gmail帐户上测试过它,并且似乎在运行Ubuntu 10.04LTS的mono 2.0上运行良好。

using System;
using System.Net;
using System.Net.Mail;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

namespace mono_gmail
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            MailMessage mail = new MailMessage();

            mail.From = new MailAddress("my.name@gmail.com");
            mail.To.Add("my.name@hotmail.com");
            mail.Subject = "Test Mail";
            mail.Body = "This is for testing SMTP mail from GMAIL";

            SmtpClient smtpServer = new SmtpClient("smtp.gmail.com");
            smtpServer.Port = 587;
            smtpServer.Credentials = new System.Net.NetworkCredential("my.name", "my.password");
            smtpServer.EnableSsl = true;
            ServicePointManager.ServerCertificateValidationCallback = 
                delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) 
                    { return true; };
            smtpServer.Send(mail);
        }
    }
}

这个解决方案源自这里,希望对你有所帮助,问候。


11
代码实际上正在忽略证书错误,这对安全不利。 - Palani
6
这段代码有问题,因为它没有解决CA未被识别的问题。现在它们仍然无法被识别,并且你已经让你的应用程序面临了巨大的中间人攻击问题。 - Henrik

14

正确的解决方案不是移除SSL证书验证。GMail有一个有效的证书。问题在于Mono似乎无法找到该证书。

这种做法完全错误,因为它会移除非常重要的证书验证,原因有很多。

ServicePointManager.ServerCertificateValidationCallback = 
            delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) 
                { return true; };

正确的解决方案是在您的计算机中安装证书:

mozroots --import --ask-remove --machine
certmgr -ssl smtps://smtp.gmail.com:465

这将有效地下载gmail的证书,并使其可供mono使用。


有没有办法在进行时导入证书?我正在编写一个爬虫,需要在到达时将证书导入到单个存储中。 - Marcello Grechi Lins
certmgr -ssl smtps://smtp.gmail.com:465 会盲目地接受任何证书并将其暴露于中间人攻击问题吗? - Mads Y
@TonoNam 我知道已经晚了,但现在 - MechMK1

6

您缺少适当的证书颁发机构,这些机构需要安装在Mono可以访问到的地方。请查看Mono项目安全FAQ,了解解决此错误的步骤。


1

1

你尝试过更改端口吗?我知道SSL的默认SMTP端口是465。


1
是的,但它从“崩溃”变成了“冻结”。 - MechMK1

0

SmtpClient with Gmail 找到了另一个解决方案

certmgr -ssl smtps://smtp.gmail.com:465

如果您正在运行Mono Web服务器,请使用与Mono进程相同的用户名运行命令。


-1
你需要使用SSL安全发送吗?你可以移除这个语句SmtpServer.EnableSsl = true;,这样就不需要SSL证书了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接