私はこのエラーを得ています:
検証手順に従って、リモート証明書が無効です。
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)
警告:本番コードでは使用しないでください。
回避策として、証明書の検証を無効にすることができます。証明書が正しくないためにエラーがスローされていることを確認するためにこれを行うだけです。
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
// https://stackoverflow.com/a/14907718/740639
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
私は(問題を抱えていたサーバー上の)WebサービスのURLに行き、証明書を表示したIEの小さなセキュリティアイコンをクリックしました。次に、[詳細]タブをクリックし、[ファイルにコピー]ボタンをクリックして、証明書を.cerファイルとしてエクスポートしました。証明書をローカルで取得したら、以下の手順に従って、証明書をサーバーの証明書ストアにインポートできました。
新しいMMCを起動します。ファイル - >スナップインの追加と削除...追加...をクリックします。証明書を選択して追加をクリックします。 [コンピュータアカウント]ラジオボタンを確認してください。 Nextをクリックしてください。
次の画面でクライアントコンピュータを選択してください。完了をクリックします。閉じるをクリックしてください。 OKをクリックしてください。今すぐ証明書を信頼されたルート証明機関の証明書ストアにインストールします。これにより、すべてのユーザーが証明書を信頼できるようになります。
証明書が有効でないときにユーザーに続行したいかどうかを尋ねることで、コードを改善できます。 続けますか?下記のように:
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エラーをチェックすることができます。
私たちが使用するコード(マイクロソフトの好意による--- 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が"Scan SSL connection"を有効にしていることを考え出しました。 それをオフにするを確認してください。
私の知る限りでは、Avastはメールを"open"し、ウィルスをスキャンしてから自分の証明書を使って署名しますだからgmailの署名はしません。証明書はもうそのエラーを引き起こします。
解決策1:
解決策2(最もセキュリティが高いと言えます):
正しいSMTPサーバーアドレスを使用していますか?
Smtp.google.comとsmtp.gmail.comの両方が機能しますが、2番目の証明書には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("[email protected]", "xxxxx")
};
私はプロキシサーバー(ユーザーゲート)を経由してSmtpClient
を使用して電子メールを送信しようとしたときに私は同じエラーがあった。
証明書にサーバーのアドレスが含まれていることを確認します。これは、プロキシサーバーのアドレスと等しくないため、エラーになります。私の解決策:証明書のチェック中にエラーが発生したら、証明書を受け取り、それをエクスポートしてチェックします。
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);
}
私のEメール送信者クラスのフルコード:
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<MailAddress> { new MailAddress(address) }, mailSubject, htmlMessageBody, fileName);
}
public bool Send(List<MailAddress> 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);
}
}
AuthenticateAsClientを呼び出すときの私の問題は、Windows 2003 Serverにありました。上記の解決策(ServicePointManager.ServerCertificateValidationCallback
を回避するなど)は機能しませんでした。
これはWindows 2003のバグであり、修正プログラムがあります。
「暗号化APIを使用するアプリケーションは、Windows Server 2003でX.509証明書を検証できません」
https://support.Microsoft.com/en-us/kb/938397
この修正プログラムをインストールすると私の問題は解決しました。
コンピュータの日付と時刻を確認してください。間違っている場合は、現在時刻に更新するか、インターネットから時刻を取得するように自動的に設定してください。
証明書は固定期間に関連付けられているため、時計が間違っていると、このようなエラーが発生する可能性があります。そのシナリオでは、時間を修正することによって、問題は修正されます。
あなたのウェブサイトフォルダはネットワークサービスセキュリティを必要とします。特にweb.config。証明書を入手するために、このアカウントを使用してレジストリにアクセスします。これにより、コードにハッキングを加える必要がなくなります。
私はこのゲームがかなり遅れていることは知っていますが、ここではTLS Streamのsystem.diagnosticsログを指す答えを見たことがありません。
コードを変更する前に、問題が何であるかを理解しておいてください。 AuthenticationException
は、あまり一般的ではない例外の1つです。何が起こっているのかを知るには、アプリケーションのapp.configファイルを編集して(または新しいファイルを作成して)、system.diagnostics
セクションでSystem.Net trace sourceが有効になっていることを確認します。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.diagnostics>
<trace autoflush="true" />
<sharedListeners>
<add name="file" initializeData="c:\network.log" type="System.Diagnostics.TextWriterTraceListener" />
</sharedListeners>
<sources>
<source name="System.Net" switchValue="Verbose">
<listeners>
<add name="file" />
</listeners>
</source>
</sources>
</system.diagnostics>
</configuration>
アプリケーションを再実行して、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検索を絞り込むことができるはずです。
私の問題は、URLではなくIPアドレスでサーバーを参照していることではありませんでした。私は、プライベートネットワーク内で使用するためにCAから署名付き証明書を購入しました。証明書に指定されているURLは、サーバーを参照するときに重要です。証明書内のURLでサーバーを参照すると、すべてが機能し始めました。
この種の問題の調査に関するMSDNのブログ記事があります。
ASP.NETのトラブルシューティング - 検証手順に従って、リモート証明書が無効です。
http://blogs.msdn.com/b/jpsanders/archive/2009/09/16/troubleshooting-asp-net-the-remote-certificate-is-invalid-according-to -the-validation-procedure.aspx
私たちの場合、問題はIISサーバー証明書によって引き起こされました。証明書の件名がDNS名に設定され、ユーザーがIPアドレスでWebサイトにアクセスしようとしていたため、.NET証明の検証に失敗しました。ユーザーがDNS名を使用し始めたときに問題は消えました。
したがって、プロバイダURLを https://CertificateSubject/xxx/xxx.application に変更する必要があります。
自己署名証明書を使ってローカルサイトに接続したときに同じエラーが発生する人のために、次のブログ投稿が役立ちました。
http://brainof-dave.blogspot.com.au/2008/08/remote-certificate-is-invalid-according.html
この行を追加するとうまくいきました。これは実際に言及されているようにすべての証明書を信頼します ここ 。ただし、これは主にトラブルシューティングに使用できます。これがうまくいくなら、リモートサーバーの証明書があなたのマシンに信頼できる証明書として追加されていないことを意味します。
System.Net.ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(RemoteServerCertificateValidationCallback);
フルコードは
private void sendAMail(String toAddress, String messageBody)
{
String msg = "Sending mail to : " + toAddress;
MailMessage mail = new MailMessage();
mail.To.Add(toAddress);
mail.From = new MailAddress("[email protected]");
mail.Subject = "Subject: Test Mail";
mail.Body = messageBody;
mail.IsBodyHtml = true;
//Added this line here
System.Net.ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(RemoteServerCertificateValidationCallback);
SmtpClient smtp = new SmtpClient();
smtp.Host = "myhostname.com";
smtp.Credentials = new System.Net.NetworkCredential("[email protected]", "");
smtp.EnableSsl = true;
smtp.Port = 587;
smtp.Send(mail);
}
private bool RemoteServerCertificateValidationCallback(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
//Console.WriteLine(certificate);
return true;
}
それは私の問題を解決しました
smtpClient.Credentials = new NetworkCredential(sendMail.UserName, sendMail.Password);
smtpClient.EnableSsl = false;//sendMail.EnableSSL;
//を参照して//問題が発生した場合SMTP設定でユーザー名とパスワードを入力したときのエラーを解決するために上記の行を使用してfalse SSlを設定する.
これが私が使うことにした解決策です。
ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
string name = certificate.Subject;
DateTime expirationDate = DateTime.Parse(certificate.GetExpirationDateString());
if (sslPolicyErrors == SslPolicyErrors.None || (sslPolicyErrors == SslPolicyErrors.RemoteCertificateNameMismatch && name.EndsWith(".acceptabledomain.com") && expirationDate > DateTime.Now))
{
return true;
}
return false;
};