.net Core 和 Serilog 电子邮件接收器 - json 配置

问题描述 投票:0回答:2

我正在使用 .net Core 2.0 和 Serilog 电子邮件接收器。我在使用

appsettings.json
配置电子邮件接收器时遇到问题。
program.cs
中的相同配置有效,而
appsetting.json
中的配置则无效。

Here is code from appsettings.json

Here is code from program.cs

json email asp.net-core .net-core serilog
2个回答
10
投票

设置系统(

ReadFrom.Configuration()
)实际上只尝试调用方法和扩展方法,它可以发现并传递从配置文件提供的参数

不幸的是,它暂时仅支持 basic 类型(可与

string
相互转换以及一些更具体的情况),因此无法提供
EmailConnectionInfo
类型的参数。

但是,作为一种解决方法,如果您只需要传递几个参数,您可以创建自己的扩展方法来接受您需要的参数并从配置系统调用它。

对于您的情况,您需要执行以下操作:

首先,定义一个扩展方法

EmailCustom(...)
,可以插入到
WriteTo
(类型为
Serilog.Configuration.LoggerSinkConfiguration
)并返回一个
LoggerConfiguration

这看起来像(未经测试,没有使用等:P):

namespace Serilog{
    public static class MyCustomExtensions
    {
        public static LoggerConfiguration EmailCustom(this LoggerSinkConfiguration sinkConfiguration, string param1, int param2, LogEventLevel restrictedToMinimumLevel){
            // the actual call to configure the Email sink, passing in complex parameters
            return sinkConfiguration.Email(... ... , restrictedToMinimumLevel , EmailConnectionInfo(){
            Foo = "bar",
            Baz = param1,
            Qux = param2,
            }
            );
        }
    }
}

从那时起,您应该能够编写如下 C# 代码:

new LoggerConfiguration()
    .WriteTo.EmailCustom(param1: "my param1", param2: 42)
   // ...
    .CreateLogger();

一旦完成该工作,您实际上可以在 json 中定义该方法调用,这要归功于 Serilog.Settings.Configuration 在这种情况下,看起来就像

{
"Serilog": {
    "Using" : ["TheNameOfTheAssemblyThatContainsEmailCustom"],
    "MinimumLevel": "Debug",
    "WriteTo": [
      {
        "Name": "EmailCustom",
        "Args": {
          "param1": "my param1",
          "param2": 42,
          "restrictedToMinimumLevel": "Verbose"
        }
      }]
    }
}

此策略也可以应用于 Serilog 的其他接收器和其他配置部分。


您可以在这里找到有关配置系统的更多信息:


8
投票

对于像我一样难以在字里行间拼凑事物的人,这里是使用 tsimbalar 提供的框架的完整答案,用于使用 SendGrid 发送电子邮件的解决方案。

我将以下类添加到我的项目的根目录(“MyApp”)。这会从 ReadFrom.Configuration(configuration).CreateLogger() 自动调用;由于应用程序设置中的 WriteTo EmailCustom。

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

namespace TrackumApi
{
    public static class SerilogEmailExtension
    {
        public static LoggerConfiguration EmailCustom(this LoggerSinkConfiguration sinkConfiguration,
            string fromEmail,
            string toEmail,
            string enableSsl,
            string mailSubject,
            string isBodyHtml,
            string mailServer,
            string networkCredentialuserName,
            string networkCredentialpassword,
            string smtpPort,
            string outputTemplate,
            string batchPostingLimit,
            string periodMinutes,
            string restrictedToMinimumLevel)
        {
            return sinkConfiguration.Email(new EmailConnectionInfo
            {
                FromEmail = fromEmail,
                ToEmail = toEmail,
                EnableSsl = GetBoolean(enableSsl),
                EmailSubject = mailSubject,
                IsBodyHtml = GetBoolean(isBodyHtml),
                MailServer = mailServer,
                NetworkCredentials = new NetworkCredential(networkCredentialuserName, networkCredentialpassword),
                Port = GetInt(smtpPort)
            }, outputTemplate, GetLevel(restrictedToMinimumLevel), 
                GetInt(batchPostingLimit), TimeSpan.FromMinutes(GetInt(periodMinutes))
            );
        }

      //The system hated converting the string inputs inline so I added the conversion methods:

        private static int GetInt(string instring)
        {
            return int.TryParse(instring, out var result) ? result : 0;
        }

        private static bool GetBoolean(string instring)
        {
            return bool.TryParse(instring, out var result) && result;
        }

        private static LogEventLevel GetLevel(string restrictedtominimumlevel)
        {
            return Enum.TryParse(restrictedtominimumlevel, true,
                out LogEventLevel level) ? level : LogEventLevel.Warning;
        }
    }
}

在我原来的帖子中,我修改了我的 Program.cs,但事实证明这是不需要的。然而,在任何其他代码之前添加 Serilog.Debugging.SelfLog 仍然是无价的:

        Serilog.Debugging.SelfLog.Enable(Console.Out);
        var configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", true, true)
            .Build();

        Log.Logger = new LoggerConfiguration()
            .ReadFrom.Configuration(configuration)
            .CreateLogger();

最后我修改了appsettings.json如下(原谅额外的,但我认为这也可能对某人有帮助):

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",

  "Serilog": {
    "Using": [ "Serilog", "Serilog.Sinks.Console", "Serilog.Sinks.File", "MyApp" ],
    "MinimumLevel": {
      "Default": "Verbose",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning",
        "Microsoft.AspNetCore.Authentication": "Information"
      }
    },
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "[{Timestamp:HH:mm:ss.fff} [{Level}] {SourceContext} {Message}{NewLine}{Exception}",
          "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
        }
      },
      {
        "Name": "File",
        "Args": {
          "path": "C:\\Temp\\Logs\\MyApp.log",
          "fileSizeLimitBytes": 1000000,
          "rollOnFileSizeLimit": "true",
          "shared": "true",
          "flushToDiskInterval": 3,
          "outputTemplate": "[{Timestamp:MM/dd/yy HH:mm:ss} [{Level}] {SourceContext} {Message}{NewLine}{Exception}",
          "restrictedToMinimumLevel": "Verbose"
        }
      },
      {
        "Name": "EmailCustom",
        "Args": {
          "fromEmail": "[email protected]",
          "toEmail": "[email protected]",
          "enableSsl": false,
          "mailSubject": "MyApp Message",
          "isBodyHtml": true,
          "mailServer": "smtp.sendgrid.net",
          "networkCredentialuserName": "mysendgridusername",
          "networkCredentialpassword": "mysendgridpassword",
          "smtpPort": 587,
          "outputTemplate": "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}",
          "batchPostingLimit": 10,
          "periodMinutes": 5,
          "restrictedToMinimumLevel": "Verbose"
        }
      }
    ],
    "Enrich": [ "FromLogContext" ],
    "Properties": {
      "Application": "MyApp"
    }
  }

}

哈!

3.0 版本更新

using System.Net;

using MailKit.Security;

using Serilog;
using Serilog.Configuration;
using Serilog.Events;
using Serilog.Formatting.Display;
using Serilog.Sinks.Email;
using Serilog.Sinks.PeriodicBatching;

namespace SerilogMail3Test
{
    /*
     * Important! The assembly name must be in the Serilog Usings in the appsettings.json
     * such as
     *   "Serilog": {
     * "Using": [ "Serilog", "Serilog.Sinks.Console", "Serilog.Sinks.File", "SerilogMail3Test" ],
     *
     */

    public static class SerilogEmailExtension
    {
        public static LoggerConfiguration EmailCustom(this LoggerSinkConfiguration sinkConfiguration,
            string fromEmail,
            string toEmail,
            string mailSubject,
            string isBodyHtml,
            string mailServer,
            string networkCredentialUserName,
            string networkCredentialPassword,
            string smtpPort,
            string outputTemplate,
            string batchPostingLimit,
            string periodMinutes,
            string restrictedToMinimumLevel)
        {
            return sinkConfiguration.Email(new EmailSinkOptions
            {
                From = fromEmail,
                To = [toEmail],
                Host = mailServer,
                Port = GetInt(smtpPort),
                Credentials = new NetworkCredential(networkCredentialUserName, networkCredentialPassword),
                Subject = new MessageTemplateTextFormatter(mailSubject),
                Body = new MessageTemplateTextFormatter(outputTemplate),
                IsBodyHtml = GetBoolean(isBodyHtml),
                ConnectionSecurity = SecureSocketOptions.None,
                ServerCertificateValidationCallback = null
            },
                new PeriodicBatchingSinkOptions
                {
                    EagerlyEmitFirstEvent = false,
                    BatchSizeLimit = GetInt(batchPostingLimit),
                    Period = TimeSpan.FromMinutes(GetInt(periodMinutes)),
                    QueueLimit = null
                },
                GetLevel(restrictedToMinimumLevel)
            );
        }

        private static int GetInt(string inString)
        {
            return int.TryParse(inString, out var result) ? result : 0;
        }

        private static bool GetBoolean(string inString)
        {
            return bool.TryParse(inString, out var result) && result;
        }

        private static LogEventLevel GetLevel(string restrictedToMinimumLevel)
        {
            return Enum.TryParse(restrictedToMinimumLevel, true,
                out LogEventLevel level) ? level : LogEventLevel.Warning;
        }
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.