serilog / serilog-sinks-email

A Serilog sink that writes events to SMTP email
Apache License 2.0
70 stars 68 forks source link

Error during reading sink configuration from JSON file #90

Open adriangutowski opened 3 years ago

adriangutowski commented 3 years ago

Hi, I encountered error during reading sink configuration from JSON file.

System.InvalidOperationException HResult=0x80131509 Message=Cannot create instance of type 'System.Net.ICredentialsByHost' because it is either abstract or an interface. Source=Microsoft.Extensions.Configuration.Binder

{
  "Serilog": {
    "Using": [ "Serilog.Sinks.Email" ],
    "MinimumLevel": "Debug",
    "WriteTo": [
      {
        "Name": "Email",
        "Args": {
          "ConnectionInfo": {
            "NetworkCredentials": {
              "UserName": "username",
              "Password": "password"
            }
          }
        }
      }
    ]
  }
}

I wanted to use extension method with parameter connectionInfo. https://github.com/serilog/serilog-sinks-email/blob/5fb82c6be87f40fb69e74fe301e57dac55cc6993/src/Serilog.Sinks.Email/LoggerConfigurationEmailExtensions.cs#L206-L214 It wont work, because constructor for EmailConnectionInfo class doesn't initialize new object for NetworkCredentials property. https://github.com/serilog/serilog-sinks-email/blob/5fb82c6be87f40fb69e74fe301e57dac55cc6993/src/Serilog.Sinks.Email/Sinks/Email/EmailConnectionInfo.cs#L38-L48 I ended up writing custom extension method, but this issue looks like easy to fix.

adriangutowski commented 3 years ago

This is my workaround:

using Serilog;
using Serilog.Configuration;
using Serilog.Events;
using Serilog.Sinks.Email;
using System.Net;

namespace MyConsoleApp
{
    public static class SerilogCustomEmailExtension
    {
        const string DefaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}";

        public static LoggerConfiguration CustomEmail(
            this LoggerSinkConfiguration loggerConfiguration,
            CustomEmailConnectionInfo connectionInfo,
            string outputTemplate = DefaultOutputTemplate,
            LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum
        )
        {
            return loggerConfiguration.Email(
                connectionInfo,
                outputTemplate,
                restrictedToMinimumLevel
            );
        }

        public class CustomEmailConnectionInfo : EmailConnectionInfo
        {
            public CustomEmailConnectionInfo()
            {
                NetworkCredentials = new NetworkCredential();
            }
        }
    }
}

appsettings.json

{
  "Serilog": {
    "Using": [ "Serilog.Sinks.Email", "MyConsoleApp" ],
    "MinimumLevel": "Information",
    "WriteTo": [
      {
        "Name": "CustomEmail",
        "Args": {
          "ConnectionInfo": {
            "NetworkCredentials": {
              "UserName": "example@email.com",
              "Password": "password"
            },
            "FromEmail": "EXAMPLE <example@email.com>",
            "MailServer": "smtp.email.com",
            "EmailSubject": "[{Level}] <{MachineName}> Log Email",
            "Port": "587",
            "IsBodyHtml": false,
            "EnableSsl": false,
            "ToEmail": "admin@email.com"
          },
          "RestrictedToMinimumLevel": "Error",
          "OutputTemplate": "{Timestamp:yyyy-MM-dd HH:mm} [{Level}] <{MachineName}> {Message}{NewLine}{Exception}"
        }
      }
    ],
    "Enrich": [ "WithMachineName" ]
  }
}