web-dev-qa-db-fra.com

"Le certificat distant est invalide selon la procédure de validation." utiliser un serveur Gmail SMTP

Je reçois cette erreur:

Le certificat distant n'est pas valide selon la procédure de validation.

chaque fois que j'essaie d'envoyer un courrier électronique en utilisant le serveur SMTP de Gmail dans mon code C #. Est-ce que quelqu'un peut m'indiquer la bonne direction pour une solution à ce problème?

Ce qui suit est la trace de la pile ...

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)
194
Josh

Attention: Ne l'utilisez pas dans le code de production!

Pour contourner le problème, vous pouvez désactiver la validation du certificat. Ne faites cela que pour obtenir la confirmation que l'erreur est générée à cause d'un mauvais certificat.

Appelez cette méthode avant d'appeler 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;
            };
    }
290
Yury Skaletskiy

Le lien ici a résolu mon problème.

http://brainof-dave.blogspot.com.au/2008/08/remote-certificate-is-invalid-according.html

Je suis allé à l'URL du service Web (sur le serveur qui a eu le problème), j'ai cliqué sur la petite icône de sécurité dans IE, qui a amené le certificat. J'ai ensuite cliqué sur l'onglet Détails, puis sur le bouton Copier dans un fichier, ce qui m'a permis d'exporter le certificat sous forme de fichier .cer. Une fois que j'ai eu le certificat localement, j'ai pu l'importer dans le magasin de certificats sur le serveur en suivant les instructions ci-dessous.

Démarrer une nouvelle MMC. Fichier -> Ajouter/Supprimer un composant logiciel enfichable ... Cliquez sur Ajouter ... Choisissez des certificats et cliquez sur Ajouter. Cochez la case d'option "Compte d'ordinateur". Cliquez sur Suivant.

Choisissez l'ordinateur client dans l'écran suivant. Cliquez sur Terminer. Cliquez sur Fermer. Cliquez sur OK. MAINTENANT, installez le certificat dans le magasin de certificats des autorités de certification racines de confiance. Cela permettra à tous les utilisateurs de faire confiance au certificat.

50
T-Rex

Vous pouvez améliorer le code en demandant à l'utilisateur si le certificat n'est pas valide s'il souhaite continuer ou non. Voulez-vous continuer? Comme ci-dessous:

ServicePointManager.ServerCertificateValidationCallback = 
    new RemoteCertificateValidationCallback(ValidateServerCertificate);

Et ajoutez une méthode comme celle-ci:

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;
    }
}
37
LinuxLover

Un peu tard pour le parti, mais si vous cherchez une solution comme celle de Yury, le code suivant vous aidera à déterminer si le problème est lié à un certificat d'auto-signature et, si tel est le cas, ignorez l'erreur d'auto-signature. Vous pouvez évidemment vérifier d’autres erreurs SSL si vous le souhaitez.

Le code que nous utilisons (avec la permission de Microsoft - http://msdn.Microsoft.com/en-us/library/office/dd633677 (v = exchg.80) .aspx ) est le suivant:

  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;
  }
}
28
Hooligancat

J'ai eu exactement le même problème et je me suis dit que par défaut, le Mail Shield de l'antivirus Avast avait le "Scan SSL connection" activé. Assurez-vous de éteignez ça.

De ma connaissance, Avast va "ouvrir" le courrier électronique, le scanner à la recherche de virus, puis le signer en utilisant son propre certificat afin que le courrier ne soit pas signé par le gmail certificat plus qui produit cette erreur.

Solution 1:

  • Désactivez les analyses SSL à partir de votre antivirus (ou de l’ensemble du bouclier de messagerie).

Solution 2 (devrait être la meilleure sécurité parlant):

  • Obtenez en quelque sorte le certificat utilisé par l'antivirus (Avast dispose d'une option pour l'exporter)
  • Importez-le dans votre client imap/pop/smtp avant de vous connecter au serveur gmail.
16
tehCivilian

Êtes-vous sûr que vous utilisez une adresse de serveur SMTP correcte?

Smtp.google.com et smtp.gmail.com fonctionnent tous les deux, mais un certificat SSL est émis pour le second.

8
Pawel Lesnikowski

Obtenez la même erreur lors de l'envoi à partir d'Outlook à cause de SSL. Le paramètre essayé EnableSSL = false a résolu le problème.

exemple:

var smtp = new SmtpClient
                {
                    Host = "smtp.gmail.com",                   
                    Port = 587,
                    EnableSsl = false,
                    DeliveryMethod = SmtpDeliveryMethod.Network,
                    UseDefaultCredentials = false,                   
                    Credentials = new NetworkCredential("[email protected]", "xxxxx")
                };
8

J'ai eu la même erreur quand j'ai essayé d'envoyer un email en utilisant SmtpClient via un serveur proxy (Usergate).

Vérifie que le certificat contient l'adresse du serveur, qui n'est pas égale à l'adresse du serveur proxy, d'où l'erreur. Ma solution: lorsqu'une erreur survient lors de la vérification du certificat, recevez-le, exportez-le et vérifiez.

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);
    }

Code complet de ma classe d'expéditeur de courrier électronique:

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);
}

}

7
Evgeny Ivanov

Mon problème était sur Windows 2003 Server, lors de l'appel de AuthenticateAsClient. Les solutions ci-dessus (par exemple, contourner ServicePointManager.ServerCertificateValidationCallback) ne fonctionnaient pas.

Il s’avère qu’il s’agit d’un bogue dans Windows 2003 et qu’il existe un correctif logiciel:

"Les applications utilisant l'API Cryptography ne peuvent pas valider un certificat X.509 dans Windows Server 2003"

https://support.Microsoft.com/en-us/kb/938397

L'installation de ce correctif a résolu mon problème.

6
user326608

Vérifiez la date et l'heure de votre ordinateur. Si ce n'est pas le cas, mettez-le à l'heure actuelle ou réglez-le automatiquement pour obtenir l'heure sur Internet.

Comme les certificats sont liés à une période de temps fixe, si votre horloge est incorrecte, vous risquez de recevoir des erreurs de ce type. Dans ce scénario, en fixant l'heure, le problème sera résolu.

4
AliSafari186

Le dossier de votre site Web a besoin de la sécurité du service réseau. Surtout le web.config. Il utilise ce compte pour accéder à votre registre pour les certificats. Cela mettra fin à la nécessité d'ajouter un piratage à votre code.

4
Frans

Je sais que je suis assez en retard dans ce jeu, mais je n'ai pas vu de réponse indiquer les journaux system.diagnostics du flux TLS.

Avant de modifier votre code, assurez-vous de bien comprendre en quoi consiste le problème. La AuthenticationException fait partie de cette exception très générique qui ne dit pas grand chose. Pour savoir ce qui se passe sous le capot, éditez le fichier app.config de votre application (ou créez-en un nouveau) et assurez-vous que la source de trace System.Net est activée dans la section system.diagnostics, par exemple:

<?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>

Relancez votre application et consultez le fichier c:\network.log. Vous devriez y voir des informations détaillées sur votre connexion TLS (SSL), par exemple:

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..

En connaissant la cause du problème, vous devriez pouvoir le résoudre ou au moins limiter vos recherches sur Google.

4
lowleveldesign

Mon problème n'était pas que je faisais référence au serveur par l'adresse IP au lieu de l'URL. J'avais acheté un certificat signé auprès d'une autorité de certification pour l'utiliser dans un réseau privé. L'URL spécifiée sur le certificat est importante pour référencer le serveur. Une fois que j'ai référencé le serveur par l'URL du certificat, tout a commencé à fonctionner.

3
Josh

Il existe un article de blog MSDN sur l’enquête sur ce type de problème:

Dépannage de ASP.NET - Le certificat distant n'est pas valide conformément à la procédure de validation:
http://blogs.msdn.com/b/jpsanders/archive/2009/09/16/troubleshooting-asp-net-the-remote-certificate-is-invalid-according-to -the-validation-procedure.aspx

2
David Burg

Dans notre cas, le problème était causé par IIS certificat de serveur. Le sujet du certificat était défini sur Nom DNS et les utilisateurs essayaient d'accéder au site Web par adresse IP. La validation de la certification .NET a donc échoué. Le problème a disparu lorsque les utilisateurs ont commencé à utiliser le nom DNS.

Vous devez donc modifier l'URL de votre fournisseur en https: //CertificateSubject/xxx/xxx.application

2
Ludwo

Pour les personnes rencontrant cette même erreur lors de la connexion à un site local avec un certificat auto-signé, l'article suivant du blog m'a aidé.

http://brainof-dave.blogspot.com.au/2008/08/remote-certificate-is-invalid-according.html

2
NullPointer

L'ajout de cette ligne a fonctionné pour moi. Cela fait en fait confiance à tous les certificats comme mentionné ici . Cependant, ceci peut être utilisé principalement pour le dépannage. Si cela fonctionne pour vous, cela signifie que le certificat du serveur distant n'est pas ajouté en tant que certificat approuvé sur votre ordinateur.

System.Net.ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(RemoteServerCertificateValidationCallback);

Le code complet est

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;
}
1
Erdnase

Ça a résolu mon problème

smtpClient.Credentials = new NetworkCredential(sendMail.UserName, sendMail.Password);
smtpClient.EnableSsl = false;//sendMail.EnableSSL;

// Avec référence à // Le problème vient uniquement Utilisez la ligne ci-dessus pour définir false SSl pour résoudre l'erreur lorsque le nom d'utilisateur et le mot de passe sont entrés dans les paramètres SMTP.

0
user3584038

voici la solution que j'ai décidé d'utiliser.

        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;
        };
0
The Lazy Coder