SslHandshakeException: An error occurred while attempting to establish an SSL or TLS connection

Yohan Blake picture Yohan Blake · Nov 25, 2019 · Viewed 11.4k times · Source

I'm trying to access gmail emails using imap and the code is failing at the ssl handshake without showing me any errors. Really appreciate if anyone could please help with this. I've built this using xunit, .NET Core 2.1. I'm using MailKit Nuget

   public GMailHandler(string mailServer, int port, bool ssl, string login, string password)

          //mailServer = imap.gmail.com
          //port = 993
          //ssl = true

          {

                  if (ssl)

                         Client.Connect(mailServer, port);

                  else

                         Client.Connect(mailServer, port);

                  Client.Authenticate(login, password);

                  Client.Inbox.Open(FolderAccess.ReadOnly);

          }

Answer

jstedfast picture jstedfast · Nov 25, 2019

Here's a copy & paste from the MailKit FAQ:

Q: Why do I get "MailKit.Security.SslHandshakeException: An error occurred while attempting to establish an SSL or TLS connection." when I try to Connect?

When you get an exception with that error message, it usually means that you are encountering one of the following scenarios:

1. The mail server does not support SSL on the specified port.

There are 2 different ways to use SSL/TLS encryption with mail servers.

The first way is to enable SSL/TLS encryption immediately upon connecting to the SMTP, POP3 or IMAP server. This method requires an "SSL port" because the standard port defined for the protocol is meant for plain-text communication.

The second way is via a STARTTLS command (aka STLS for POP3) that is optionally supported by the server.

Below is a table of the protocols supported by MailKit and the standard plain-text ports (which either do not support any SSL/TLS encryption at all or only via the STARTTLS command extension) and the SSL ports which require SSL/TLS encryption immediately upon a successful connection to the remote host.

|Protocol|Standard Port|SSL Port|
|:------:|:-----------:|:------:|
| SMTP   | 25 or 587   | 465    |
| POP3   | 110         | 995    |
| IMAP   | 143         | 993    |

It is important to use the correct SecureSocketOptions for the port that you are connecting to.

If you are connecting to one of the standard ports above, you will need to use SecureSocketOptions.None, SecureSocketOptions.StartTls or SecureSocketOptions.StartTlsWhenAvailable.

If you are connecting to one of the SSL ports, you will need to use SecureSocketOptions.SslOnConnect.

You could also try using SecureSocketOptions.Auto which works by choosing the appropriate option to use by comparing the specified port to the ports in the above table.

2. The mail server that you are connecting to is using an expired (or otherwise untrusted) SSL certificate.

Often times, mail servers will use self-signed certificates instead of using a certificate that has been signed by a trusted Certificate Authority. Another potential pitfall is when locally installed anti-virus software replaces the certificate in order to scan web traffic for viruses.

When your system is unable to validate the mail server's certificate because it is not signed by a known and trusted Certificate Authority, the above error will occur.

You can work around this problem by supplying a custom RemoteCertificateValidationCallback and setting it on the client's ServerCertificateValidationCallback property.

In the simplest example, you could do something like this (although I would strongly recommend against it in production use):

using (var client = new SmtpClient ()) {
    client.ServerCertificateValidationCallback = (s,c,h,e) => true;

    client.Connect (hostName, port, SecureSocketOptions.Auto);

    // ...
}

Most likely you'll want to instead compare the certificate's Thumbprint property to a known value that you have verified at a prior date.

You could also use this callback to prompt the user (much like you have probably seen web browsers do) as to whether or not the certificate should be trusted.

3. A Certificate Authority CRL server for one or more of the certificates in the chain is temporarily unavailable.

Most Certificate Authorities are probably pretty good at keeping their CRL and/or OCSP servers up 24/7, but occasionally they do go down or are otherwise unreachable due to other network problems between you and the server. When this happens, it becomes impossible to check the revocation status of one or more of the certificates in the chain.

To ignore revocation checks, you can set the CheckCertificateRevocation property of the IMAP, POP3 or SMTP client to false before you connect:

using (var client = new SmtpClient ()) {
    client.CheckCertificateRevocation = false;

    client.Connect (hostName, port, SecureSocketOptions.Auto);

    // ...
}

4. The server does not support the same set of SSL/TLS protocols that the client is configured to use.

MailKit attempts to keep up with the latest security recommendations and so is continuously removing older SSL and TLS protocols that are no longer considered secure from the default configuration. This often means that MailKit's SMTP, POP3 and IMAP clients will fail to connect to servers that are still using older SSL and TLS protocols. Currently, the SSL and TLS protocols that are not supported by default are: SSL v2.0, SSL v3.0, and TLS v1.0.

You can override MailKit's default set of supported SSL and TLS protocols by setting the value of the SslProtocols property on your SMTP, POP3 or IMAP client.

For example:

using (var client = new SmtpClient ()) {
    // Allow SSLv3.0 and all versions of TLS
    client.SslProtocols = SslProtocols.Ssl3 | SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13;

    client.Connect ("smtp.gmail.com", 465, true);

    // ...
}