1

I'm trying to change our code to send emails with MailKit since the old SMTPClient is obsolete.

We connect to our own server and don't need to authenticate. Here is the code:

Using client = New SmtpClient()
    Dim values = SQL.EMAIL_SQL.GetSMTPInfo("MailHostOutsideNetwork")
    client.Connect(values.Item1, values.Item2, Security.SecureSocketOptions.None)
    client.Send(Message)
    client.Disconnect(True)
End Using

I have it working and sending emails as long as I don't use TLS or SSL. When I try to use either of them, I get the exception:

An error occurred while attempting to establish an SSL or TLS connection. The server's SSL certificate could not be validated for the following reasons: - The server certificate has the following errors: - A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.

So, my first idea was to contact our IT department and ask about the certificates. They told me we've never had any certificates and most likely never will (some licensing bullshit). The problem is they still want us to use TLS when sending emails and my boss says that there must be a way to do that (which I basically answered with... well yeah if we had our system and certificates in order. She was not vey happy lol).

So, now I'm here asking you if there is any way of doing that. Sending emails using TLS with no certificates. Any ideas?

ElDourado
  • 13
  • 4
  • `ServicePointManager.ServerCertificateValidationCallback = Function(s, c, ca, pe) Return True End Function` (in 3 lines, before you create a connection) – Jimi May 12 '20 at 13:48
  • As @jstedfast noted, the use of a `ServerCertificateValidationCallback` must be limited to a well-known, reliable, source which, for understandable reasons, generates an exception because of a failed certificate validation. You can build a validation callback, as shown [here](https://stackoverflow.com/a/48675492/7444103) (see the `TlsValidationCallback` code), modify it (use the example in the answer here as a blueprint) to only handle a know issuer. After that, you can set the `ServerCertificateValidationCallback` to `Nothing` (so no other code can call it by mistake). – Jimi May 13 '20 at 08:12

1 Answers1

1

As Jimi noted, you can set a ServerCertificateValidationCallback method.

If you read the above docs, it may help you devise a better solution than just to return true, but in the simplest case, setting it to a function that always returns true will work for your needs.

Based on the error message, it sounds like there is a certificate chain, it's just that the SMTP server is probably using a self-signed SSL certificate and/or a root certificate that was generated by your company instead of by an official SSL Certificate Authority and therefore the root certificate used by your SMTP server is not trusted by the system sending the emails.

You can also check out MailKit's default behavior here: https://github.com/jstedfast/MailKit/blob/master/MailKit/MailService.cs#L356

Basically, if the problem is just an untrusted root (what it sounds like your issue is), then it falls back on a hard-coded list of trusted mail server certificate details that it checks against:

var cn = certificate.GetNameInfo (X509NameType.SimpleName, false);
var fingerprint = certificate.Thumbprint;
var serial = certificate.SerialNumber;
var issuer = certificate.Issuer;

Obviously you won't know these strings off the top of your head, but if you write a custom function that prints this information out, you could then hard-code those values into a future version of the validation callback function and feel a little safer than just returning true ;-)

jstedfast
  • 35,744
  • 5
  • 97
  • 110
  • Thank you very much for your answer. I'll take a look at that info and definitely use it in the callback function. I really didn't like it just returning true – ElDourado May 13 '20 at 08:07