skip to Main Content

I have a server (Centos 7) setup to be used as mail server. Using postfix/dovecot/opendkim/opendmarc..
It works as it should, users are able to connect their emails using gmail for example. Able to send and receive mail.

Also when I use MailKit and test my .NET Core application from my home pc MailKit connects fine and the emails are send.

However, when I deploy the application to my server MailKit fails to connect.

If I look in the logs I see the following

postfix/submission/smtpd[4486]: match_hostname: unknown ~? 127.0.0.1/32
postfix/submission/smtpd[4486]: match_hostaddr: MY_SERVER_IP ~? 127.0.0.1/32
postfix/submission/smtpd[4486]: match_hostname: unknown ~? MY_SERVER_IP/32
postfix/submission/smtpd[4486]: match_hostaddr: MY_SERVER_IP  ~? MY_SERVER_IP/32
postfix/submission/smtpd[4486]: lost connection after STARTTLS from unknown[MY_SERVER_IP]

But if I look a bit higher in the logs I see

Anonymous TLS connection established from unknown[MY_SERVER_IP]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)

My MailKit (which works fine from outside of the server):

using (SmtpClient emailClient = new SmtpClient())
{
    await emailClient.ConnectAsync(emailConfiguration.SmtpServer, emailConfiguration.SmtpPort, SecureSocketOptions.StartTls);
    emailClient.AuthenticationMechanisms.Remove("XOAUTH2");  

    await emailClient.AuthenticateAsync(emailConfiguration.SmtpUsername, emailConfiguration.SmtpPassword);
    await emailClient.SendAsync(message);

    await emailClient.DisconnectAsync(true);
}

edit:
The exception from MailKit (certificate is proper and not self-signed):

MailKit.Security.SslHandshakeException: An error occurred while attempting to establish an SSL or TLS connection.
May 19 16:07:37 domain.com NETCoreApp[4452]: The server's SSL certificate could not be validated for the following reasons:
May 19 16:07:37 domain.com NETCoreApp[4452]: • The server certificate has the following errors:
May 19 16:07:37 domain.com NETCoreApp[4452]: • unable to get certificate CRL
May 19 16:07:37 domain.com NETCoreApp[4452]: • The root certificate has the following errors:
May 19 16:07:37 domain.com NETCoreApp[4452]: • unable to get certificate CRL
May 19 16:07:37 domain.com NETCoreApp[4452]: • unable to get local issuer certificate
May 19 16:07:37 domain.com NETCoreApp[4452]: ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.

3

Answers


  1. Chosen as BEST ANSWER

    I found an answer which works but isn't my preferred method since I wanted to be able to use MailKit for more that just my own server (make it configurable from within the app itself)

    I came to the solution because I thought it had to do with some internal traffic going wrong..

    By using the old SmtpClient from System.Net.Mail I was able to use the DefaultCredentials.

    using (SmtpClient client = new SmtpClient("127.0.0.1"))
    {
        client.UseDefaultCredentials = true;
    
        MailAddress from = new MailAddress(emailMessage.FromAddress.Address, emailMessage.FromAddress.Name);
    
        foreach (IEmailAddress emailAddress in emailMessage.ToAddresses)
        {
            MailAddress to = new MailAddress(emailAddress.Address, emailAddress.Name);
    
            MailMessage email = new MailMessage(from, to)
            {
                Subject = emailMessage.Subject,
                Body = emailMessage.Content
            };
    
            await client.SendMailAsync(email);
        }
    }
    

  2. The unable to get certificate CRL error sounds like SslStream was unable to get the CRL, perhaps because the CRL server is unreachable for some reason.

    You could try adding emailClient.CheckCertificateRevocation = false; before the ConnectAsync to check if that’s the issue.

    The other error, unable to get local issuer certificate, might be because the server that MailKit is running on doesn’t have the Root CA certificate in its X509Store but your home PC does.

    Update:

    The problem is that LetsEncrypt SSL certificates do not include a CRL location which means that certificate revocation checks will fail.

    To bypass this, you need to set client.CheckCertificateRevocation = false; before connecting.

    Login or Signup to reply.
  3. I have the same problem on ubuntu 20.04 with .NET core 3.1

    and after 3 hours of trial and error, I finally found the solution.
    I’ve just ignored the Certificate Validation CallBack.

    using var client = new SmtpClient(new ProtocolLogger("smtp.log"));
    client.CheckCertificateRevocation = false;
    client.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
    client.Connect("your.smtp.host", 587, SecureSocketOptions.StartTls);
    

    I hope this would be helpful 🙂

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search