283

I'm getting this error:

The remote certificate is invalid according to the validation procedure.

whenever I try to send e-mail using Gmail's SMTP server in my C# code. Can someone point me to the right direction for a solution to this problem?

The following is the stack trace...

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)
Himanshu
  • 31,810
  • 31
  • 111
  • 133
Josh
  • 13,530
  • 29
  • 114
  • 159
  • 1
    Can you tell us more about your config for using Gmail SMTP servers? My lucky guess: Can you tell us more about your security policies for SSL (like using a valid/invalid SSL certificate?). – Brian Clozel Apr 27 '09 at 12:15
  • Can you give us a code sample where you can reproduce the error? – zaTricky Dec 05 '17 at 20:23

25 Answers25

344

Warning: Do not use this in production code!

As a workaround, you can switch off certificate validation. Only ever do this to obtain confirmation that the error is being thrown because of a bad certificate.

Call this method before you call 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;
        };
}
Josh Correia
  • 3,807
  • 3
  • 33
  • 50
Yury Skaletskiy
  • 4,203
  • 1
  • 17
  • 4
  • 216
    This is a hack, not a fix? – LB. Apr 07 '10 at 19:28
  • 105
    Would love to see a fix, rather than turning off all security completely. – Roman Starkov Apr 14 '11 at 20:27
  • 85
    as a workaround to a security problem you can turn security off? WTF? – John Nicholas Jul 06 '12 at 17:03
  • 1
    For less typing (not having to put in the using statements) this is the same line of code: ServicePointManager.ServerCertificateValidationCallback = delegate( object s, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors ) { return true; }; – Clearly Jul 31 '12 at 18:47
  • Hey, i used this solution, and the callback is never triggered, any clue why? – guiomie Aug 13 '12 at 15:30
  • 2
    Explanation and fix is in another [answer](http://stackoverflow.com/a/13923610/553613). – Rick Sladkey Mar 28 '13 at 01:36
  • 1
    This was nice because it let me see what other things were wrong in my code apart from security; now that I know everything else is right, I can work on the security settings. Removing variables is helpful for debugging. – caleb Apr 09 '13 at 14:56
  • System.Net.ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, errors) => true; – shawndumas May 14 '13 at 17:05
  • 83
    Had to downvote this, as people still seem to think it's a solution. It's **JUST TURNING THE SECURITY OFF. DO NOT USE IN PRODUCTION**, people. He even says so. Sheesh. – MGOwen Jun 03 '13 at 06:32
  • 71
    Upvoted. I fully agree this should not be used in production **BUT**.. I'm making a prototype of something. The test server they happened to provide me with forces me to use SSL. Working with certificates is pretty new for me, so I just want a **QUICK WAY OUT**, which imho is fine since **I WILL NOT USE IT IN PRODUCTION** – TweeZz Mar 26 '14 at 10:46
  • Surely this workaround defeats the object of having a SSL certificate in the first place? – medina Apr 10 '14 at 09:45
  • 3
    I dislike the " i dont care" comments to SSL issues. So when does SSL get tested ? I have seen many issues related to SSL comms and enforce SSL everytime in DEV environments and make the DEVS get it working. Which can be a pain initially, but quickly admins get their certs and servers sorted out. Fix the cause not the symptom! I dont want system integration test testing untested code connections. Or poorly tested processes. Code like this can get forgotten and land in prod ... etc If i saw a dev do this he is in for an absolute ear bashing. – phil soady Aug 13 '14 at 01:08
  • 1
    For an actual fix, see T-Rex's answer below which involves manually trusting a certificate. – DeepSpace101 Sep 01 '14 at 19:26
  • 3
    What confuses me is that the default behavior with self-signed certificates is to abandon communication, while having no encryption at all (no SSL) shows no red flags to the user. – Zoey Dec 27 '14 at 21:20
  • Surely it's better to install the cert in your client code? – Dave Arkell Apr 24 '15 at 10:42
  • 1
    A bit shorter in C# 6: ServicePointManager.ServerCertificateValidationCallback = (s, certificate, chain, sslPolicyErrors) => true; – roeland Nov 23 '15 at 14:58
  • If you are in Prod you must have a valid certificate and you shouldn't face this issue. But I would recommend this fix for non-prod environments to use with an Appsetting like "IsTestMode= true". – Dhanuka777 Feb 11 '16 at 23:07
  • There's potentially nothing wrong with this. It could be an app sending an email through a TLS server on the LAN. The cert could be self-signed, meaning at least there is encryption, where there usually isn't. And even if used on the general internet, encryption-vs-no-encryption is still a valid argument even if there is no certificate validation. – Kind Contributor Sep 26 '16 at 01:29
  • 2
    @Todd If there is no certificate validation, the encryption is not secure. It's presence may require a potential intruder to take some extra steps, and may guard against accidental reveal of data to friendly administrators, but it can also give a false sense of security. If it's an internal application where you don't want to bother with an official certificate there are several other solutions, such as making the app trust THIS particular certificate instead of turning certificate validation off, or create a private CA that you install as trusted in the relevant computer. – Oskar Berggren Oct 12 '16 at 21:12
  • Perfect answer, for my test scenario! If you can't read warnings or don't are ignorant of what your code is doing, you're probably in the wrong profession... – tinonetic Apr 07 '17 at 06:37
  • Useful for unit testing, when you have to fake datetime, making certificate validity a problem. – kravits88 Apr 09 '17 at 09:42
  • 2
    “Do not use in production” as if dev machines are somehow immune to MITM, or GMail runs locally on your machine. – Sedat Kapanoglu Dec 05 '17 at 19:47
  • 2
    this handily contains four parameters, so you can use a nice four letter word to indicate that this is bad, for example: `ServicePointManager.ServerCertificateValidationCallback = (h,a,c,k) => true;` or `ServicePointManager.ServerCertificateValidationCallback = (f,u,c,k) => true;` – Marius Jun 26 '18 at 07:51
  • this should surely be a solution. Your app may use either a config setting to switch, or just check if the hostname contains localhost. – ZZZ Jul 12 '18 at 03:55
  • 2
    Agree this is a hack, but then so is using a self-signed cert. I plugged this code in (wrapped in `if (System.Diagnostics.Debugger.IsAttached)` to mitigate the effect of it getting into prod if I'm hit by a bus before removing it), and GLORY BE! it meant I was able to make the call and establish that everything else was working properly. So despite not having a solution that will safely run in dev and prod, I am still in a better position than before. – OutstandingBill Jul 23 '18 at 02:07
  • For those who came here running .NET Core instead of Framework, `ServicePointManager` is not used by Core's `HttpClient`, you've got to override `HttpClientHandler.ServerCertificateValidationCallback` as described in this ticket: https://github.com/dotnet/runtime/issues/26048 – Garrison Neely Sep 13 '21 at 16:16
82

The link here solved my problem.

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

I went to url of the web service (on the server that had the issue), clicked on the little security icon in IE, which brought up the certificate. I then clicked on the Details tab, clicked the Copy To File button, which allowed me to export the certifcate as a .cer file. Once I had the certificate locally, I was able to import it into the certificate store on the server using the below instructions.

Start a new MMC. File --> Add/Remove Snap-In... Click Add... Choose Certificates and click Add. Check the "Computer Account" radio button. Click Next.

Choose the client computer in the next screen. Click Finish. Click Close. Click OK. NOW install the certificate into the Trusted Root Certification Authorities certificate store. This will allow all users to trust the certificate.

T-Rex
  • 1,017
  • 7
  • 4
  • +1 when importing a certificate via the import tool on the cert and not through the snap in, it is only for your user account. Using the snap in allows you to choose who the import is for, user account, service account or everyone. Thanks for your pointer. I was scratching my head for a minute or two there! – medina Apr 10 '14 at 09:43
  • 2
    If you want to use the command line to automate over all dev/test workstations - `certutil -f -p test -importPFX Root devcert.pfx` and `certutil -f -p test -importPFX MY devcert.pfx`. Needs to be run in an admin command prompt (assuming the PFX password is `test`) – DeepSpace101 Sep 01 '14 at 19:23
  • This is the best way to fix it if you're using a self-signed certificate for testing, thanks T-Rex! – ToastyMallows Oct 30 '14 at 18:02
45

A little late to the party, but if you are looking for a solution like Yury's the following code will help you identify if the issue is related to a self-sign certificate and, if so ignore the self-sign error. You could obviously check for other SSL errors if you so desired.

The code we use (courtesy of Microsoft - http://msdn.microsoft.com/en-us/library/office/dd633677(v=exchg.80).aspx) is as follows:

  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;
  }
}
Hooligancat
  • 3,588
  • 1
  • 37
  • 55
  • 1
    For my case sslPolicyErrors was RemoteCertificateNameMismatch and I modified the certificate check because we didn't have the same Subject and Issuer values. – Ufuk Hacıoğulları Sep 27 '16 at 15:52
  • 2
    The X509Certificate the Exchange server used kept switching between a self-signed one and a Trusted one. Using this code helped my network admin and me not only figure out that this was the case, but also solved the problem altogether by only bypassing the self-signed certificates. This was perfect! – Bret Mar 24 '17 at 17:09
37

You can improve the code by asking the user when the certificate is not valid whether he wants to continue or not. Do you want to continue? As below:

ServicePointManager.ServerCertificateValidationCallback = 
    new RemoteCertificateValidationCallback(ValidateServerCertificate);

And add a method like this:

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;
    }
}
OrionMD
  • 389
  • 1
  • 7
  • 13
LinuxLover
  • 475
  • 4
  • 2
25

I had the exact same problem and figured out that by default the Mail Shield from Avast antivirus had the "Scan SSL connection" activated. Make sure to turn that off.

From my knowledge, Avast will "open" the mail, scan it for any viruses and then sign it using it's own certificate so the mail won't be signed by the gmail's certificate anymore which produces that error.

Solution 1:

  • Turn off the SSL scans from your antivirus (or the entire mail shield).

Solution 2 (Should be the best security speaking):

  • Get somehow the certificate used by the antivirus (Avast has an option to export it)
  • Import it in your imap/pop/smtp client before connecting to gmail server.
tehCivilian
  • 460
  • 6
  • 8
24

I know I am pretty late in this game, but I haven't seen an answer here pointing to the system.diagnostics logs for the TLS Stream.

Before you do any changes to your code, make sure you understand what the problem is about. The AuthenticationException is one of that very generic exception which does not tell much. To learn what's going under the hood edit the app.config file for your application (or create a new one) and make sure you have System.Net trace source enabled in the system.diagnostics section, for example:

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

Rerun your application and check the c:\network.log file. You should see there detailed information about your TLS (SSL) connection, for example:

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

Knowing what causes the problem, you should be able to resolve it or at least narrow your Google searches.

Sebastian
  • 3,764
  • 21
  • 28
16

Get the same error while sending from outlook because of ssl. Tried setting EnableSSL = false resolved the issue.

example:

var smtp = new SmtpClient
                {
                    Host = "smtp.gmail.com",                   
                    Port = 587,
                    EnableSsl = false,
                    DeliveryMethod = SmtpDeliveryMethod.Network,
                    UseDefaultCredentials = false,                   
                    Credentials = new NetworkCredential("xxx@gmail.com", "xxxxx")
                };
11

I had the same error when i tried to send email using SmtpClient via proxy server (Usergate).

Verifies the certificate contained the address of the server, which is not equal to the address of the proxy server, hence the error. My solution: when an error occurs while checking the certificate, receive the certificate, export it and check.

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

Full code of my email sender class:

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

}

Evgeny Ivanov
  • 504
  • 6
  • 14
9

Are you sure you are using correct SMTP server address?

Both smtp.google.com and smtp.gmail.com work, but SSL certificate is issued to the second one.

Pawel Lesnikowski
  • 6,264
  • 4
  • 38
  • 42
6

My issue was not that I was referencing the server by the IP address instead of the URL. I had purchased a signed certificate from a CA for use inside a private network. The URL specified on the certificate does matter when referencing the server. Once I referenced the server by the URL in the certificate everything started to work.

Josh
  • 2,422
  • 2
  • 27
  • 18
  • This answer deserves to be upper, because it points out a common mistake; people (including myself) think that the purpose of Host is only for finding the server. – Mojtaba Feb 21 '18 at 14:58
6

My issue was on Windows 2003 Server, when calling AuthenticateAsClient. The solutions above (e.g. circumventing ServicePointManager.ServerCertificateValidationCallback) did not work.

Turns out this is a bug in Windows 2003, and there is a hotfix:

"Applications that use the Cryptography API cannot validate an X.509 certificate in Windows Server 2003"

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

Installing this hotfix resolved my issue.

user326608
  • 2,210
  • 1
  • 26
  • 33
5

Adding this line worked for me. This in fact trusts all the certificates as mentioned here. However, this can be used primarily for troubleshooting. If this works for you, then it means that the certificate of the remote server is not added as a trusted certificate in your machine.

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

Full code is

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("from@mydomain.com");
            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("sender@sample.com", "");
            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;
}
Erdnase
  • 750
  • 3
  • 12
  • 25
4

Your website folder needs network service security. Especially the web.config. It uses this account to access your registry for the certificates. This will stop the need to add a hack to your code.

Frans
  • 47
  • 1
4

Check your computer's Date and Time. If it is wrong, update it to the current time or set it automatically to get the time from the Internet.

Because certificates are tied to a fixed time period, if your clock is wrong, you are likely to get errors like this. In that scenario, by fixing the time, the problem will be fixed.

zaTricky
  • 1,838
  • 17
  • 22
AliSafari186
  • 113
  • 9
  • 1
    If you system date is "too far" from current time, the validity of the certificate received from google causes an issue. It sees issued on and valid to info that dont much current time. This isnt only thing that cant cause this issue. But it certainly one that can. – phil soady Aug 13 '14 at 01:01
  • 1
    A hugely useful reminder to double check this in my case! Occam's Razor and all that... :) Now about that CMOS battery... – Mike G Oct 03 '17 at 04:44
4

In our case problem was caused by IIS server certificate. The certificate's subject was set to DNS name and users were trying to access web site by IP adress, so .NET certification validation failed. Problem disappeared when users started to use DNS name.

So you have to change your Provider URL to https://CertificateSubject/xxx/xxx.application

Ludwo
  • 6,043
  • 4
  • 32
  • 48
  • Can you elaborate this? In my case app works on one server and does not work on the other. I'm clueless... I'm not an expert, but domain is still connected to the working one, and server certificate is already installed on both machines. Still don't get why could that be anyhow relevant since it says "remote certificate". – Michael Brennt Sep 01 '16 at 09:38
4

Below code worked for me in dotnetcore to bypass the ssl certificate

using (var httpClientHandler = new HttpClientHandler())
{                  
 httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
  using (var client = new HttpClient(httpClientHandler))
  {
  }
}
Hisham Shahid
  • 225
  • 3
  • 7
3

For those encountering this same error when connecting to a local site with a self-signed certificate, the following blog post helped me out.

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

NullPointer
  • 545
  • 1
  • 6
  • 17
2

There is an MSDN blog article on investigating this type of issues:

Troubleshooting ASP.NET – The remote certificate is invalid according to the validation procedure:
http://blogs.msdn.com/b/jpsanders/archive/2009/09/16/troubleshooting-asp-net-the-remote-certificate-is-invalid-according-to-the-validation-procedure.aspx

David Burg
  • 1,064
  • 12
  • 14
2

Haven't seen anyone point out the obvious, that if you want to debug SSL issues safely then always use this approach:

#if DEBUG
    ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
#endif

Even if you do accidentally commit your code, you'll still be OK it won't be compiled in Release mode.

keithl8041
  • 2,383
  • 20
  • 27
  • Sometime when deploying debug version(for my case, in AWS dev dedicated environnement) DEBUG symbol will be set. So better for that to check if debugger is attached with if (Debugger.IsAttached) { ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; } – Jérémie Leclercq Oct 19 '21 at 12:31
  • That's a slightly different use case, I think, but good point nonetheless. – keithl8041 Oct 19 '21 at 22:14
1

If you are getting this error while upload files to S3 using AWS SDK. Make sure that you have selected the correct region for S3.

enter image description here

If you have used the incorrect region. That will return such an error which is not meant for this error btw.

dush88c
  • 1,918
  • 1
  • 27
  • 34
0

It solved my issue

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

// With Reference to // Problem comes only Use above line to set false SSl to solve error when username and password is entered in SMTP settings.

Reza
  • 18,865
  • 13
  • 88
  • 163
0

here is the solution that I decided to use.

        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;
        };
The Lazy Coder
  • 11,560
  • 4
  • 51
  • 69
0

The code from the accepted answer helped me to debug the issue. I then realized that the SN field of the certificate argument wasn't the same as what I thought was my SMTP server. By setting the Host property of the SmtpClient instance to the SN value of the certificate I was able to fix the issue.

ulu
  • 5,872
  • 4
  • 42
  • 51
  • 1
    Can you elaborate more? Were I see SN field of certificate? – MarchalPT Apr 22 '21 at 15:26
  • @MarchaIPT I think the SN field is the Subject Name field in certificate properties. For this type of certificates it contains usually server's DNS name or something similar like *.stackexchange.com describing whole domain. That's why he needed to correctly set the Host property of SMTPClient. – SalgoMato Jul 06 '23 at 11:09
0

use my function as diagnostic certificates issues - see screen

            System.Net.ServicePointManager.ServerCertificateValidationCallback = Function(s As Object,
                                                                                          cert As System.Security.Cryptography.X509Certificates.X509Certificate,
                                                                                          chain As System.Security.Cryptography.X509Certificates.X509Chain,
                                                                                          err As System.Net.Security.SslPolicyErrors)
                                                                                     Return True
                                                                                 End Function

enter image description here

Viacheslav
  • 1,054
  • 12
  • 16
0

Ran into this error running a dotnet core web application on an Amazon Linux EC2 virtual machine. Turns out we hadn't run sudo yum update to patch this server in a while, and the root/intermediate certificates installed on the machine were out of date. (Specifically, the issue started for us on 2021-09-30.)

We ran this command to update the certs and then restarted our dotnet process:

sudo yum update ca-certificates

AWS support further pointed us to this support article for similar issues: Why am I receiving a certificate expiration error for the Let's Encrypt certificate on my EC2 instance?

Mason G. Zhwiti
  • 6,444
  • 11
  • 61
  • 97