我收到这个错误:
根据验证程序,远程证书无效.
每当我尝试使用我的C#代码中的Gmail SMTP服务器发送电子邮件时.有人能指出我找到解决这个问题的正确方向吗?
以下是堆栈跟踪...
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.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, 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.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, 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.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, 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.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, 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.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, 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.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult) at System.Net.TlsStream.CallProcessAuthentication(Object state) 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.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size) at System.Net.Mail.SmtpConnection.Flush() at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port) at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port) at System.Net.Mail.SmtpClient.GetConnection() at System.Net.Mail.SmtpClient.Send(MailMessage message) at BulkEmail.frmemail.mailsending(String toaddress, String fromaddress, String fromname, String subject, String pwd, String attachements, String mailmessage, String htmlmessage, Int32 i, Int32 j, String replytoaddress)
小智.. 297
警告:不要在生产代码中使用它!
作为解决方法,您可以关闭证书验证.只有这样才能获得由于证书错误而导致错误丢失的确认.
在致电之前调用此方法smtpclient.Send()
:
[Obsolete("Do not use this in Production code!!!",true)] static void NEVER_EAT_POISON_Disable_CertificateValidation() { // Disabling certificate validation can expose you to a man-in-the-middle attack // which may allow your encrypted message to be read by an attacker // /sf/ask/17360801/ ServicePointManager.ServerCertificateValidationCallback = delegate ( object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors ) { return true; }; }
这是一个黑客,而不是修复? (170认同)
很想看到修复,而不是完全关闭所有安全性. (86认同)
作为安全问题的解决方法,您可以关闭安全性吗?WTF? (69认同)
不得不投票,因为人们似乎仍然认为这是一个解决方案.它只是**关闭安全.不要在生产中使用**,人.他甚至这么说.啧. (67认同)
Upvoted.我完全同意这不应该用于制作**但**..我正在做一些东西的原型.他们碰巧给我的测试服务器强迫我使用SSL.使用证书对我来说是一个很新的东西,所以我只想要一个**快速的方式**,这是非常好的,因为我不会在生产中使用它** (48认同)
**133赞成?震惊冲击......** (4认同)
Downvoted.完全没用的答案. (4认同)
我不喜欢SSL问题的"我不关心"评论.那么SSL什么时候开始测试?我已经看到许多与SSL通信相关的问题,并且每次在DEV环境中强制执行SSL,并使DEVS使其正常工作.这最初可能是一种痛苦,但很快管理员就会将他们的证书和服务器整理出来.修复原因不是症状!我不希望系统集成测试测试未经测试的代码连接.或者测试不良的流程.像这样的代码可能会被遗忘并落入产品......等等.如果我看到一个开发者这样做,他就是在进行绝对的抨击. (3认同)
让我感到困惑的是,自签名证书的默认行为是放弃通信,而根本没有加密(没有SSL)则表明用户没有红色标记. (3认同)
解释和修复在另一个[答案](http://stackoverflow.com/a/13923610/553613). (2认同)
@Todd如果没有证书验证,则加密不安全.它的存在可能需要潜在的入侵者采取一些额外的步骤,并可能防止向友好的管理员意外泄露数据,但它也可能给人一种虚假的安全感.如果它是一个您不想使用官方证书的内部应用程序,则还有其他几种解决方案,例如让应用程序信任此特定证书而不是关闭证书验证,或者创建您安装为受信任的私有CA.相关的电脑. (2认同)
这应该删除. (2认同)
"不要在生产中使用",好像开发机器在某种程度上对MITM免疫,或者GMail在你的机器上本地运行. (2认同)
小智.. 52
这里的链接解决了我的问题.
http://brainof-dave.blogspot.com.au/2008/08/remote-certificate-is-invalid-according.html
我去了网络服务的网址(在有问题的服务器上),点击了IE中的小安全图标,它提出了证书.然后我单击Details选项卡,单击Copy To File按钮,这允许我将certifcate导出为.cer文件.一旦我在本地获得了证书,我就可以使用以下说明将其导入服务器上的证书存储区.
启动一个新的MMC.文件 - >添加/删除管理单元...单击添加...选择证书,然后单击添加.选中"计算机帐户"单选按钮.点击下一步.
在下一个屏幕中选择客户端计算机.单击完成.单击关闭.单击确定.现在将证书安装到受信任的根证书颁发机构证书存储区.这将允许所有用户信任该证书.
警告:不要在生产代码中使用它!
作为解决方法,您可以关闭证书验证.只有这样才能获得由于证书错误而导致错误丢失的确认.
在致电之前调用此方法smtpclient.Send()
:
[Obsolete("Do not use this in Production code!!!",true)] static void NEVER_EAT_POISON_Disable_CertificateValidation() { // Disabling certificate validation can expose you to a man-in-the-middle attack // which may allow your encrypted message to be read by an attacker // /sf/ask/17360801/ ServicePointManager.ServerCertificateValidationCallback = delegate ( object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors ) { return true; }; }
这里的链接解决了我的问题.
http://brainof-dave.blogspot.com.au/2008/08/remote-certificate-is-invalid-according.html
我去了网络服务的网址(在有问题的服务器上),点击了IE中的小安全图标,它提出了证书.然后我单击Details选项卡,单击Copy To File按钮,这允许我将certifcate导出为.cer文件.一旦我在本地获得了证书,我就可以使用以下说明将其导入服务器上的证书存储区.
启动一个新的MMC.文件 - >添加/删除管理单元...单击添加...选择证书,然后单击添加.选中"计算机帐户"单选按钮.点击下一步.
在下一个屏幕中选择客户端计算机.单击完成.单击关闭.单击确定.现在将证书安装到受信任的根证书颁发机构证书存储区.这将允许所有用户信任该证书.
您可以改进代码以询问用户证书无效.你想继续吗?如下:
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
并添加如下方法:
public static bool ValidateServerCertificate(object sender,X509Certificate certificate,X509Chain chain,SslPolicyErrors sslPolicyErrors) { if (sslPolicyErrors == SslPolicyErrors.None) return true; else { if (System.Windows.Forms.MessageBox.Show("The server certificate is not valid.\nAccept?", "Certificate Validation", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes) return true; else return false; } }
派对有点晚,但如果您正在寻找像Yury这样的解决方案,以下代码将帮助您确定问题是否与自签名证书相关,如果是,则忽略自签名错误.如果您愿意,您显然可以检查其他SSL错误.
我们使用的代码(由Microsoft提供 - http://msdn.microsoft.com/en-us/library/office/dd633677(v=exchg.80).aspx)如下:
private static bool CertificateValidationCallBack( object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { // If the certificate is a valid, signed certificate, return true. if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None) { return true; } // If there are errors in the certificate chain, look at each error to determine the cause. if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) != 0) { if (chain != null && chain.ChainStatus != null) { foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in chain.ChainStatus) { if ((certificate.Subject == certificate.Issuer) && (status.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.UntrustedRoot)) { // Self-signed certificates with an untrusted root are valid. continue; } else { if (status.Status != System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NoError) { // If there are any other errors in the certificate chain, the certificate is invalid, // so the method returns false. return false; } } } } // When processing reaches this line, the only errors in the certificate chain are // untrusted root errors for self-signed certificates. These certificates are valid // for default Exchange server installations, so return true. return true; } else { // In all other cases, return false. return false; } }
我遇到了完全相同的问题,并且发现默认情况下,Avast防病毒软件的Mail Shield激活了"扫描SSL连接".一定要关闭它.
根据我的知识,Avast将"打开"邮件,扫描它以查找任何病毒,然后使用它自己的证书对其进行签名,这样邮件就不会再被gmail的证书签名而产生该错误.
解决方案1:
关闭防病毒软件(或整个邮件防护)的SSL扫描.
解决方案2(应该是最好的安全性说法):
以某种方式获取防病毒使用的证书(Avast有一个选项可以导出它)
在连接到gmail服务器之前,将其导入imap/pop/smtp客户端.
您确定使用的是正确的SMTP服务器地址吗?
smtp.google.com和smtp.gmail.com都可以使用,但SSL证书会发给第二个.
因为ssl而从outlook发送时收到相同的错误.尝试设置EnableSSL = false解决了问题.
例:
var smtp = new SmtpClient { Host = "smtp.gmail.com", Port = 587, EnableSsl = false, DeliveryMethod = SmtpDeliveryMethod.Network, UseDefaultCredentials = false, Credentials = new NetworkCredential("xxx@gmail.com", "xxxxx") };
当我尝试使用SmtpClient
通过代理服务器(Usergate)发送电子邮件时,我遇到了同样的错误.
验证证书包含服务器的地址,该地址不等于代理服务器的地址,因此错误.我的解决方案:检查证书时发生错误,接收证书,导出并检查.
public static bool RemoteServerCertificateValidationCallback(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { if (sslPolicyErrors == SslPolicyErrors.None) return true; // if got an cert auth error if (sslPolicyErrors != SslPolicyErrors.RemoteCertificateNameMismatch) return false; const string sertFileName = "smpthost.cer"; // check if cert file exists if (File.Exists(sertFileName)) { var actualCertificate = X509Certificate.CreateFromCertFile(sertFileName); return certificate.Equals(actualCertificate); } // export and check if cert not exists using (var file = File.Create(sertFileName)) { var cert = certificate.Export(X509ContentType.Cert); file.Write(cert, 0, cert.Length); } var createdCertificate = X509Certificate.CreateFromCertFile(sertFileName); return certificate.Equals(createdCertificate); }
我的电子邮件发件人类的完整代码:
public class EmailSender { private readonly SmtpClient _smtpServer; private readonly MailAddress _fromAddress; public EmailSender() { ServicePointManager.ServerCertificateValidationCallback = RemoteServerCertificateValidationCallback; _smtpServer = new SmtpClient(); } public EmailSender(string smtpHost, int smtpPort, bool enableSsl, string userName, string password, string fromEmail, string fromName) : this() { _smtpServer.Host = smtpHost; _smtpServer.Port = smtpPort; _smtpServer.UseDefaultCredentials = false; _smtpServer.EnableSsl = enableSsl; _smtpServer.Credentials = new NetworkCredential(userName, password); _fromAddress = new MailAddress(fromEmail, fromName); } public bool Send(string address, string mailSubject, string htmlMessageBody, string fileName = null) { return Send(new List{ new MailAddress(address) }, mailSubject, htmlMessageBody, fileName); } public bool Send(List addressList, string mailSubject, string htmlMessageBody, string fileName = null) { var mailMessage = new MailMessage(); try { if (_fromAddress != null) mailMessage.From = _fromAddress; foreach (var addr in addressList) mailMessage.To.Add(addr); mailMessage.SubjectEncoding = Encoding.UTF8; mailMessage.Subject = mailSubject; mailMessage.Body = htmlMessageBody; mailMessage.BodyEncoding = Encoding.UTF8; mailMessage.IsBodyHtml = true; if ((fileName != null) && (System.IO.File.Exists(fileName))) { var attach = new Attachment(fileName, MediaTypeNames.Application.Octet); attach.ContentDisposition.CreationDate = System.IO.File.GetCreationTime(fileName); attach.ContentDisposition.ModificationDate = System.IO.File.GetLastWriteTime(fileName); attach.ContentDisposition.ReadDate = System.IO.File.GetLastAccessTime(fileName); mailMessage.Attachments.Add(attach); } _smtpServer.Send(mailMessage); } catch (Exception e) { // TODO lor error return false; } return true; } public static bool RemoteServerCertificateValidationCallback(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { if (sslPolicyErrors == SslPolicyErrors.None) return true; // if got an cert auth error if (sslPolicyErrors != SslPolicyErrors.RemoteCertificateNameMismatch) return false; const string sertFileName = "smpthost.cer"; // check if cert file exists if (File.Exists(sertFileName)) { var actualCertificate = X509Certificate.CreateFromCertFile(sertFileName); return certificate.Equals(actualCertificate); } // export and check if cert not exists using (var file = File.Create(sertFileName)) { var cert = certificate.Export(X509ContentType.Cert); file.Write(cert, 0, cert.Length); } var createdCertificate = X509Certificate.CreateFromCertFile(sertFileName); return certificate.Equals(createdCertificate); }
}
我的问题是在Windows 2003 Server上调用AuthenticateAsClient时.上述解决方案(例如规避ServicePointManager.ServerCertificateValidationCallback
)不起作用.
原来这是Windows 2003中的一个错误,并且有一个修补程序:
"使用Cryptography API的应用程序无法验证Windows Server 2003中的X.509证书"
https://support.microsoft.com/en-us/kb/938397
安装此修补程序解决了我的问题.
我知道我在这场比赛中已经很晚了,但是我在这里没有看到指向TLS流的system.diagnostics日志的答案。
在对代码进行任何更改之前,请确保您了解问题所在。这AuthenticationException
是一个非常普通的异常之一,它并不能说明很多问题。要了解实际情况,请为您的应用程序编辑app.config文件(或创建一个新文件),并确保在该部分中启用了System.Net跟踪源system.diagnostics
,例如:
重新运行您的应用程序,然后检查c:\ network.log文件。您应该在此处看到有关TLS(SSL)连接的详细信息,例如:
System.Net Information: 0 : [12764] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = f44368:535f958, targetName = localhost, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation) System.Net Information: 0 : [12764] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=OK). System.Net Information: 0 : [12764] Remote certificate: [Version] V3 [Subject] CN=test Simple Name: test DNS Name: example.com [Issuer] CN=Root CA Simple Name: Root CA DNS Name: Root CA ... [Signature Algorithm] sha256RSA(1.2.840.113549.1.1.11) [Public Key] Algorithm: RSA Length: 2048 Key Blob: .... System.Net Information: 0 : [12764] SecureChannel#38496415 - Remote certificate has errors: System.Net Information: 0 : [12764] SecureChannel#38496415 - Certificate name mismatch. System.Net Information: 0 : [12764] SecureChannel#38496415 - Remote certificate was verified as invalid by the user. System.Net Error: 0 : [12764] Exception in AppDomain#10923418::UnhandledExceptionHandler - The remote certificate is invalid according to the validation procedure..
知道导致问题的原因后,您应该能够解决问题,或者至少缩小Google搜索范围。