Search code examples
asp.net-coreserilogappsettings

Serilog Email sink enableSSL false checks


I am trying to use EnableSsl = false in my EmailConnectionInfo but it seems like the smtp client being used for the smtp connection is trying to use SSL because the default SecureSocketOptions is set to Auto. When I created a client manually and used the overload with SecureSocketOptions = None it worked.

The error:

Failed to send email: MailKit.Security.SslHandshakeException: An error occurred while attempting to establish an SSL or TLS connection.

The SSL certificate presented by the server is not trusted by the system for one or more of the following reasons:
1. The server is using a self-signed certificate which cannot be verified.
2. The local system is missing a Root or Intermediate certificate needed to verify the server's certificate.
3. The certificate presented by the server is expired or invalid.

See https://github.com/jstedfast/MailKit/blob/master/FAQ.md#InvalidSslCertificate for possible solutions. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.

The workarround:

I am setting the ServerCertificateValidationCallback to true

When used in my Program.cs, it works:

.UseSerilog((hostingContext, loggerConfiguration) =>{
   Serilog.Debugging.SelfLog.Enable(Console.WriteLine);           
   loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration)
   .WriteTo.Email(
      new EmailConnectionInfo {
      FromEmail = "{email}",
      ToEmail = "{email}",
      MailServer = "{SMTP IP}",
      Port = {PORT},
      EnableSsl = false,
      EmailSubject = "Something to log",
      ServerCertificateValidationCallback = (senderX, certificate, chain, sslPolicyErrors) => true
   },
   outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
   batchPostingLimit: 1,
   restrictedToMinimumLevel: LogEventLevel.Warning);
});

But, when I try to include all my serilog settings for Email sink in appsettings.json the "ServerCertificateValidationCallback": "(senderX, certificate, chain, sslPolicyErrors) => true" cannot be read (my assumption)

my appsettings.json

"Serilog": {
    "Using": [ "Serilog.Sinks.File","Serilog.Sinks.Email" ],
    "MinimumLevel": "Information",
    "WriteTo": [
      ...
      {
        "Name": "Email",
        "Args": {
          "connectionInfo": {
            "MailServer": "{SMTP IP}",
            "Port": {PORT},
            "EnableSsl": false,
            "FromEmail": "{email}",
            "ToEmail": "{email}",
            "EmailSubject": "Something went wrong",
            "ServerCertificateValidationCallback": "(s, cert, chain, sslPolicyErrors) => true"
          },
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}",
          "restrictedToMinimumLevel": "Warning",
          "batchPostingLimit": 1
        }
      }
    ],
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
  }
...

Any ideas?

Edit: The githut issue I opened


Solution

  • I was able to get this working leveraging a few other questions and without the support for the callback being able to set this directly via configuration. This question's answer (https://stackoverflow.com/a/59914193/116208) was particularly helpful. If you follow his example there with a few modifications.

    You can add the ServerCertificateValidationCallback = (senderX, certificate, chain, sslPolicyErrors) => true to the EmailConnectionInfo in the SerilogEmailExtension extension class

    Adjust the Serilog configuration "Using" statement to include your compiled application's name so it can find the extension class instead of "MyApp":

    "Using": [ "Serilog", "Serilog.Sinks.Console", "Serilog.Sinks.File", "MyApp" ],
    

    This should let you achieve everything to be configuration driven, and still add in the callback to bypass the exception.