如何为SendGrid更好地配置C#和.NET应用程序(详细指南)

423 阅读19分钟

有一百种不同的方法来为你的应用程序提供配置。对于几乎所有的编程语言,你都可以使用环境变量和*.env*文件,但配置也可以存储在其他文件格式中,如JSON、YAML、TOML、XML、INI等,这个列表还在继续。然而,在某些情况下,配置不是从文件中提取,而是从Azure Key Vault、HashiCorp Vault或类似的保险库服务中提取。你的配置很少会来自单一来源。幸运的是,.NET中有一些API,可以帮助你从多个来源抓取配置,并将它们合并在一起。

在本教程中,你将从一个使用Twilio SendGrid发送电子邮件的应用程序开始,其中的配置是直接从环境变量中获取的。然后你将重构该应用,以便

  • 从多个来源获取配置,特别是JSON文件、用户秘密、环境变量和命令行参数
  • 将配置绑定到强类型的对象上
  • 按照选项模式,使用依赖性注入注入配置

配置你的SendGrid账户以发送邮件

在你发送电子邮件之前,你需要配置两件事。首先,你需要设置发送者认证。这将验证你拥有你将发送电子邮件的电子邮件地址或域名。第二,你需要创建一个具有发送电子邮件权限的SendGrid API密钥

发送者认证

为了快速上手,你将在本教程中使用单一发送者验证。这将验证你是否拥有应用程序将发送电子邮件的电子邮件地址。单一发件人验证对于测试来说是很好的,但不建议用于生产。

Twilio建议生产环境使用域名认证。一个经过认证的域名可以向电子邮件提供商证明你拥有该域名,并删除 "通过sendgrid.net "的文字,否则收件箱提供商会将其附加到你的发件地址上。

要设置单一发件人验证,请点击左侧菜单中的设置标签。打开设置选项卡后,点击发送者验证

Side-navigation with a Settings group and multiple links in the group. The link "Sender Authentication" is highlighted.

然后,在 "单一发件人验证"部分点击 "开始"。

A button saying "Get Started" to verify an individual email address.

这将在右侧面板上打开一个表格。在表格中填写你的信息和电子邮件地址。

A form to create a sender. The form asks for contact information including the email address that will be used to send emails from.

填写完表格后点击创建。右边会出现另一个面板,要求你在你的电子邮件收件箱中确认你的电子邮件地址。
进入你的个人电子邮件收件箱,打开来自SendGrid的电子邮件,并点击验证单一发件人

An email from SendGrid with a button saying "Verify Single Sender".

你的电子邮件地址已经被验证了。你现在可以用它来发送邮件了!

创建一个SendGrid API密钥来发送电子邮件

回到SendGrid网站,点击设置标签下的API密钥,然后点击右上角的创建API密钥。这将在右侧面板上打开另一个表格。

给你的API密钥一个有意义的名字。你可以给API密钥分配不同的权限。为了达到最佳的安全性,你应该只给你需要的最低限度的权限。

接下来,点击限制访问

A form to create an API Key. The form asks for a name for the key and what permissions to grant to the key.

向下滚动到 "邮件发送"手风琴项目,并点击它以显示下面的权限。将滑块拖到右边的 "邮件发送"权限。

A list of permissions that you can control using a slider bar next to each permission. The "Mail Send" accordion item is expanded to reveal the "Mail Send" permission underneath.

滚动到表格的底部,点击创建和查看。现在API密钥将显示在你的屏幕上。

一旦你离开这个屏幕,你将无法再次检索API密钥,所以请确保你将API密钥复制到安全的地方。

API key is displayed to copy and store elsewhere. Key will not be shown again.

在验证了发件人和创建了API密钥之后,你就可以写一些代码了

对于任何即将到来的命令和代码,像这样替换以下占位符:

  • 用你刚记下的API密钥替换[SENDGRID_API_KEY]
  • [FROM_EMAIL_ADDRESS][FROM_NAME] 替换为你之前验证的电子邮件地址和你希望收件人看到的名字。
  • [TO_EMAIL_ADDRESS][TO_NAME] 替换为所需的邮件收件人的电子邮件地址和姓名。

直接从环境变量中获取配置

为了让项目在你的机器上快速运行,打开你喜欢的shell,并使用下面的git命令来克隆源代码:

git clone https://github.com/Swimburger/SendGridOptionsPattern.git --branch Step1

然后使用cd SendGridOptionsPattern ,导航到SendGridOptionsPattern文件夹。这个项目是一个控制台应用程序,只有一个C#文件,Program.cs,其中有以下代码:

using SendGrid;
using SendGrid.Helpers.Mail;

var apiKey = Environment.GetEnvironmentVariable("SendGridApiKey");
var fromEmailAddress = Environment.GetEnvironmentVariable("FromEmailAddress");
var fromName = Environment.GetEnvironmentVariable("FromName");
var toEmailAddress = Environment.GetEnvironmentVariable("ToEmailAddress");
var toName = Environment.GetEnvironmentVariable("ToName");

var client = new SendGridClient(apiKey);
var message = new SendGridMessage
{
    From = new EmailAddress(fromEmailAddress, fromName),
    Subject = "Sending with Twilio SendGrid is Fun",
    PlainTextContent = "and easy to do anywhere, especially with C#"
};
message.AddTo(new EmailAddress(toEmailAddress, toName));
var response = await client.SendEmailAsync(message);

// A success status code means SendGrid received the email request and will process it.
// Errors can still occur when SendGrid tries to send the email. 
// If email is not received, use this URL to debug: https://app.sendgrid.com/email_activity 
Console.WriteLine(response.IsSuccessStatusCode ? "Email queued successfully!" : "Something went wrong!");

该应用程序从环境变量中提取SendGrid API Key,以及发件人和收件人的电子邮件地址和姓名。然后,代码用API密钥创建一个新的SendGridClient ,使用SendGridMessage ,创建一个电子邮件,然后发送该电子邮件。

该应用程序使用适用于C#和.NET的SendGrid库,通过SendGrid API进行验证并发送电子邮件。SendGrid NuGet包已经作为你克隆的源代码的一部分被添加到项目中。你可以在csproj-file中找到这个依赖关系。

在你运行这个应用程序之前,你需要配置这个项目所依赖的环境变量。回到你的shell中,使用以下命令设置这些环境变量。

如果你使用的是Bash或类似的shell:

export SendGridApiKey=[SENDGRID_API_KEY]
export FromEmailAddress=[FROM_EMAIL_ADDRESS]
export FromName="[FROM_NAME]"
export ToEmailAddress=[TO_EMAIL_ADDRESS]
export ToName="[TO_NAME]"

如果你使用的是PowerShell

$Env:SendGridApiKey = "[SENDGRID_API_KEY]"
$Env:FromEmailAddress = "[FROM_EMAIL_ADDRESS]"
$Env:FromName = "[FROM_NAME]"
$Env:ToEmailAddress = "TO_EMAIL_ADDRESS]"
$Env:ToName = "[TO_NAME]"

如果你使用的是CMD

set "SendGridApiKey=[SENDGRID_API_KEY]"
set "FromEmailAddress=[FROM_EMAIL_ADDRESS]"
set "FromName=[FROM_NAME]"
set "ToEmailAddress=[TO_EMAIL_ADDRESS]"
set "ToName=[TO_NAME]"

一旦环境变量设置完毕,你就可以使用以下.NET CLI命令运行该项目:

dotnet run

该应用程序将从你经过验证的电子邮件地址向收件人发送一封电子邮件:

An email with title "Sending with Twilio SendGrid is Fun" and body "and easy to do anywhere, especially with C#

当SendGrid API响应一个成功的HTTP状态代码时,这并不一定意味着收件人成功地收到了该邮件。但是,它确实意味着SendGrid API已经接受了你的请求,并将发送电子邮件。如果收件人没有收到邮件,你可以使用邮件活动反馈来找出原因。

从环境变量中提取配置,效果很好,但与其使用环境变量,你还不如简单地硬编码所有配置,对吗?
许多这些配置元素,特别是API密钥,是敏感的秘密,你不想与他人分享。通过从环境变量这样的外部配置中提取它们,你可以确保你不会不小心把它们检查到你的公共源代码中,让大家看到。而每当别人想要运行同样的代码时,他们可以将自己的API Key配置到环境变量中并运行它。

这就是为什么在SendGrid样本中,我们总是会使用环境变量。尽管与硬编码配置相比,这是一个额外的步骤,但它是让你启动和运行SendGrid的最快方式,而不会意外地损害你的API Key。

然而,在.NET中,有一个更好的方法来检索外部配置,即使用ConfigurationBuilder.NET配置。

使用.NET配置生成器构建你的配置

有很多方法可以配置.NET应用程序,通常配置是由多个来源组成的。ASP.NET Core最初引入了一些API,可以使用配置提供者轻松地从一堆不同的来源加载配置,并通过ConfigurationBuilder 。这些API被移到Microsoft.Extensions.Hosting NuGet包中,这样它就可以在任何.NET应用程序中使用。

你不仅可以在.NET(核心)上使用新的配置API--你甚至可以在.NET框架上使用它们。.NET框架有它自己的配置API,但与新的配置API相比,它们不那么直观和过时。

回到你的外壳中,运行以下.NET CLI命令,为配置扩展和一些配置提供者添加NuGet包:

dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.CommandLine
dotnet add package Microsoft.Extensions.Configuration.EnvironmentVariables
dotnet add package Microsoft.Extensions.Configuration.UserSecrets

要开始使用配置API,用以下代码更新Program.cs文件:

using System.Reflection;
using Microsoft.Extensions.Configuration;
using SendGrid;
using SendGrid.Helpers.Mail;

IConfiguration config = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
    .AddUserSecrets(Assembly.GetExecutingAssembly(), optional: true, reloadOnChange: false)
    .AddEnvironmentVariables()
    .AddCommandLine(args)
    .Build();

var apiKey = config["SendGrid:ApiKey"];
var fromEmailAddress = config["Email:From:Email"];
var fromName = config["Email:From:Name"];
var toEmailAddress = config["Email:To:Email"];
var toName = config["Email:To:Name"];
var emailSubject = config["Email:Subject"];
var emailBody = config["Email:Body"];

var client = new SendGridClient(apiKey);
var message = new SendGridMessage
{
    From = new EmailAddress(fromEmailAddress, fromName),
    Subject = emailSubject,
    PlainTextContent = emailBody
};
message.AddTo(new EmailAddress(toEmailAddress, toName));
var response = await client.SendEmailAsync(message);

// A success status code means SendGrid received the email request and will process it.
// Errors can still occur when SendGrid tries to send the email. 
// If email is not received, use this URL to debug: https://app.sendgrid.com/email_activity 
Console.WriteLine(response.IsSuccessStatusCode ? "Email queued successfully!" : "Something went wrong!");

由此产生的应用程序与之前相同,但现在是从多个来源加载配置,而不是直接从环境变量加载。ConfigurationBuilder 是一个使用构建器模式的类,因此你可以使用Add... 扩展方法将多个配置提供者连锁起来。当来自不同提供者的配置元素具有相同的键时,在链中较晚加入的配置将覆盖在链中较早加入的配置。这意味着,你添加配置提供者的顺序很重要在这种情况下:

  • 用户秘密覆盖了来自JSON的配置

  • 环境变量覆盖了来自用户秘密和JSON的配置

  • 命令行参数覆盖了用户秘密、JSON和环境变量的配置。

optional 参数指定了如果底层源丢失,应用程序是否应该抛出一个异常。 参数指定了当底层源发生变化时是否要更新配置。例如,如果你的生产应用程序有一个问题,但由于性能原因,在reloadOnChange appsettings.json中,日志级别被设置为 ,你可以将日志级别改为 。一旦你保存了这个文件,应用程序就会开始从 级别开始写日志,而不需要重新启动你的应用程序!Warning Debug Debug

配置建立后,应用程序将从配置中抓取配置元素,但注意配置键现在使用两个不同的前缀:SendGrid:Email:

你可以通过添加冒号: 作为分隔符,将你的配置组织成分层次的部分。所以在这种情况下,ApiKeySendGrid 部分的一部分,而所有其他的配置是Email 部分的一部分。你也可以嵌套部分,如Email 部分所示。Email 部分包含子部分FromTo ,这些部分保留了发件人和收件人的电子邮件地址和名字。你可以用很多不同的方式来组织你的配置,但你如何组织你的配置完全取决于你的需求。

现在,应用程序从多个来源加载配置,你应该在哪个来源存储配置?这取决于配置、你的用例和个人偏好:

  • 对于不包含秘密或其他敏感信息的配置,使用JSON
  • 仅在本地开发中使用用户秘密来配置秘密和其他敏感信息。
  • 使用环境变量进行环境特定配置,包括秘密或其他敏感信息。然而,对于本地开发来说,用户秘密是首选。环境变量是一个强大的配置来源,因为所有操作系统、容器技术和云基础设施都支持它们。
  • 使用命令行参数来配置执行的具体设置。

创建一个名为appsettings.json的新文件并添加以下JSON:

{
  "Email": {
    "From": {
      "Email": "[FROM_EMAIL_ADDRESS]",
      "Name": "[FROM_NAME]"
    },
    "Subject": "Ahoy from JSON!",
    "Body": "Thank you for signing up to our website. See you around!"
  }
}

appsettings.json文件将提供FromEmailAddress,FromName,Subject, 和Body 的配置,尽管将这些配置作为命令行参数传入也是合理的。

默认情况下,在一个控制台应用程序中,appsettings.json文件将不会被复制到项目的输出中。因此,配置提供者将不会找到底层源,这意味着你的JSON中的配置将不会被加载。为了确保appsettings.json文件被复制到输出,请在csproj-file中添加一个Content ,如下:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>...</PropertyGroup>
  <ItemGroup>...</ItemGroup>

  <ItemGroup>
    <Content Include="appsettings.json" CopyToOutputDirectory="Always" />
  </ItemGroup>
</Project>

要开始使用秘密管理器,你首先需要使用以下命令为你的项目初始化它:

dotnet user-secrets init

现在你可以像这样设置SendGrid:ApiKey 的配置:

dotnet user-secrets set SendGrid:ApiKey [SENDGRID_API_KEY]

你很可能会在其他环境中把API Key配置为环境变量,但由于你是在本地运行,所以秘密管理器是首选。所以,在这种情况下,你不需要配置任何环境变量。

该应用程序现在已经配置了电子邮件将从谁那里发送,但没有配置电子邮件将发送给谁。与其使用之前的一个来源进行配置,不如使用.NET CLI运行该项目,并将其作为一个命令行参数传入:

dotnet run --Email:To:Email [TO_EMAIL_ADDRESS] --Email:To:Name "[TO_NAME]"

就像以前一样,收件人将收到一封邮件,但现在的主题将是 "Ahoy from JSON!"。

再次运行该命令,但使用命令行参数覆盖Email:Subject 的配置:

dotnet run --Email:To:Email [TO_EMAIL_ADDRESS] --Email:To:Name "[TO_NAME]" --Email:Subject "Ahoy from the CLI"

现在收件人将收到一封主题为 "Ahoy from the CLI "的邮件。

最终结果可能是一样的,但你的应用程序现在更灵活了,因为它可以用许多不同的方式进行配置。然而,这些并不是唯一的配置提供者。微软还有5个配置提供者,如果这些不能满足你的需要,你也可以开发你自己的提供者或使用别人的。

一些操作系统和外壳可能不允许你使用冒号。在这种情况下,你可以使用双下划线__ 作为分隔符,而.NET将为你用冒号来代替它。

将配置与强类型的对象绑定

你刚刚学会了如何使用配置生成器从多个来源获取配置,但配置的数量很快就会变得无法控制。一个更易于管理的解决方案是将你的配置绑定到强类型对象上:

为了开始绑定配置,用以下命令添加Microsoft.Extensions.Configuration.Binder NuGet包

dotnet add package Microsoft.Extensions.Configuration.Binder

用下面的代码更新Program.cs文件:

using System.Reflection;
using Microsoft.Extensions.Configuration;
using SendGrid;
using SendGrid.Helpers.Mail;

IConfiguration config = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
    .AddUserSecrets(Assembly.GetExecutingAssembly(), optional: true, reloadOnChange: false)
    .AddEnvironmentVariables()
    .AddCommandLine(args)
    .Build();

var apiKey = config["SendGrid:ApiKey"];

var emailOptions = config.GetSection("Email").Get<EmailOptions>();

var client = new SendGridClient(apiKey);
var message = new SendGridMessage
{
    From = emailOptions.From,
    Subject = emailOptions.Subject,
    PlainTextContent = emailOptions.Body
};
message.AddTo(emailOptions.To);
var response = await client.SendEmailAsync(message);

// A success status code means SendGrid received the email request and will process it.
// Errors can still occur when SendGrid tries to send the email. 
// If email is not received, use this URL to debug: https://app.sendgrid.com/email_activity 
Console.WriteLine(response.IsSuccessStatusCode ? "Email queued successfully!" : "Something went wrong!");

public class EmailOptions
{
    public EmailAddress From { get; set; }
    public EmailAddress To { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }
}

Program.cs的底部,有一个新的类,它的属性名称与你的配置相符。通过匹配属性的名称和配置的键,你将能够把配置与所述类的实例绑定。你可以使用config.GetSection("YourSectionName") 从配置中抓取部分,然后使用.Get<YourClass>() 将该部分绑定到强类型对象上。这样,Email 部分被绑定到EmailOptions 的实例上,然后像以前一样用于发送电子邮件。

对于EmailOptions 类,FromTo 属性是使用 SendGrid 库提供的EmailAddress 类定义的。EmailAddress 类包含两个属性:EmailName 。因为这些属性名称与你的配置名称相匹配,即使这些嵌套对象也会被绑定。

如果你现在运行该项目,你将继续得到同样的结果:

dotnet run --Email:To:Email [TO_EMAIL_ADDRESS] --Email:To:Name "[TO_NAME]" --Email:Subject "Ahoy from the CLI"

如果在配置提供者上启用了reloadOnChange ,而配置源中的配置发生了变化,配置对象将被更新,但任何已经被绑定的强类型对象将不会被相应地更新。

将配置生成器与默认的主机生成器互换

如果你使用了ASP.NET模板,你可能会注意到,配置已经被设置好了,没有任何ConfigurationBuilder 代码。这是因为ASP.NET模板使用了默认的网络主机,它设置了默认的配置、日志、依赖注入、网络相关功能等。

如果你想从Web主机生成器中获得相同的配置、日志和依赖注入,但不需要Web相关的功能,你可以使用通用主机而不是Web主机:

使用.NET CLI添加Microsoft.Extensions.Hosting NuGet包

dotnet add package Microsoft.Extensions.Hosting

Program.cs中,用以下代码替换using 语句和ConfigurationBuilder 的代码:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SendGrid;
using SendGrid.Helpers.Mail;

using IHost host = Host.CreateDefaultBuilder(args).Build();
var config = host.Services.GetRequiredService<IConfiguration>();

该项目现在不需要自己构建配置,而是使用通用主机附带的默认值。然后代码从依赖注入容器中检索配置(host.Services),并像以前一样继续使用配置对象。

默认的Generic Host将构建配置,类似于你自己做的方式,但也有一些区别。你可以在微软文档中找到Generic Host默认的概述

默认的通用主机构建配置的方式略有不同。更具体地说,只有当Environment 被配置为Development ,你的用户秘密才会被加载。有多种方法来配置环境,但在本教程中,当你运行你的项目时传入Environment 参数,像这样:

dotnet run --Environment Development  --Email:To:Email [TO_EMAIL_ADDRESS] --Email:To:Name "[TO_NAME]" --Email:Subject "Ahoy from the CLI"

使用选项模式从依赖注入中获取配置

现在你已经使用了通用主机,你可以开始使用它附带的依赖注入(DI),就像你在ASP.NET应用程序上一样。

用下面的代码替换你在Program.cs中的现有代码:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using SendGrid;
using SendGrid.Helpers.Mail;

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((context, services) =>
    {
        services.Configure<EmailOptions>(context.Configuration.GetSection("Email"));
        services.AddTransient<EmailSender>();
    })
    .Build();

var config = host.Services.GetRequiredService<IConfiguration>();

var apiKey = config["SendGrid:ApiKey"];
var client = new SendGridClient(apiKey);

var emailSender = host.Services.GetRequiredService<EmailSender>();
await emailSender.SendEmail(client);

public class EmailSender
{
    private readonly EmailOptions emailOptions;

    public EmailSender(IOptions<EmailOptions> emailOptions)
    {
        this.emailOptions = emailOptions.Value;
    }

    public async Task SendEmail(ISendGridClient client)
    {
        var message = new SendGridMessage
        {
            From = emailOptions.From,
            Subject = emailOptions.Subject,
            PlainTextContent = emailOptions.Body
        };
        message.AddTo(emailOptions.To);
        var response = await client.SendEmailAsync(message);

        // A success status code means SendGrid received the email request and will process it.
        // Errors can still occur when SendGrid tries to send the email. 
        // If email is not received, use this URL to debug: https://app.sendgrid.com/email_activity 
        Console.WriteLine(response.IsSuccessStatusCode ? "Email queued successfully!" : "Something went wrong!");
    }
}

public class EmailOptions
{
    public EmailAddress From { get; set; }
    public EmailAddress To { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }
}

你可以使用host builder上的ConfigureServices 方法,并传入一个lambda来为DI容器添加更多的服务。在这个lambda中,Email 配置部分被添加为使用services.Configure<YourOptions> 的配置。结果,你的配置将被注入到任何支持DI的地方,只要在你的构造函数或方法签名中添加一个IOptions<YourOptions> 类型的参数。微软将此称为选项模式

除了IOptions<T> ,还有IOptionsSnapshot<T>IOptionsMonitor<T>IOptionsFactory<TOptions> ,它们都有不同的行为和用例。在微软的文档中了解更多关于这些选项接口之间的区别

在配置完选项后,程序将把EmailSender 类添加到CI容器中。EmailSender 是一个新的类,将负责发送Emails。现在DI容器已经建立,你可以从它那里获取服务。所以现在你已经把你的EmailOptions 注入到支持DI的任何地方。

现在,代码将从DI容器中检索到一个EmailSender 的实例,它被用来使用​​SendEmail 方法来发送电子邮件。

EmailSender 被DI容器创建时,容器将IOptions<EmailOptions> 的实例注入到EmailSender 的构造函数中。EmailSender 使用.Value 属性抓取消息选项并在SendEmail 方法中使用它来发送电子邮件。

将SendGridClient添加到依赖注入容器中

你已经使你的应用程序更加灵活和可配置,但你还可以进一步将SendGrid集成到你的应用程序中。SendGrid SDK for .NET有一个额外的NuGet包,它将把SendGrid客户端添加到依赖注入容器中。

运行以下命令来添加SendGrid DI包:

dotnet add package SendGrid.Extensions.DependencyInjection

然后像这样更新Program.cs文件:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using SendGrid;
using SendGrid.Extensions.DependencyInjection;
using SendGrid.Helpers.Mail;

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((context, services) =>
    {
        services.AddSendGrid(options =>
            options.ApiKey = context.Configuration["SendGrid:ApiKey"]
        );
        services.Configure<EmailOptions>(context.Configuration.GetSection("Email"));
        services.AddTransient<EmailSender>();
    })
    .Build();

var emailSender = host.Services.GetRequiredService<EmailSender>();
await emailSender.SendEmail();

public class EmailSender
{
    private readonly ISendGridClient sendGridClient;
    private readonly EmailOptions emailOptions;

    public EmailSender(IOptions<EmailOptions> emailOptions, ISendGridClient sendGridClient)
    {
        this.sendGridClient = sendGridClient;
        this.emailOptions = emailOptions.Value;
    }

    public async Task SendEmail()
    {
        var message = new SendGridMessage
        {
            From = emailOptions.From,
            Subject = emailOptions.Subject,
            PlainTextContent = emailOptions.Body
        };
        message.AddTo(emailOptions.To);
        var response = await sendGridClient.SendEmailAsync(message);

        // A success status code means SendGrid received the email request and will process it.
        // Errors can still occur when SendGrid tries to send the email. 
        // If email is not received, use this URL to debug: https://app.sendgrid.com/email_activity 
        Console.WriteLine(response.IsSuccessStatusCode ? "Email queued successfully!" : "Something went wrong!");
    }
}

public class EmailOptions
{
    public EmailAddress From { get; set; }
    public EmailAddress To { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }
}

该应用程序使用services.AddSendGrid 方法将SendGrid客户端添加到DI容器中。
为了配置SendGrid的选项,另一个lambda被使用并传入AddSendGrid 。lambda-inception可能很棘手,所以要确保验证你所有的括号与上面的代码一致。

现在,ISendGridClient 将被注入到EmailSender 类的构造函数中,而不是像之前那样构造SendGridClient ,然后像之前那样用于发送电子邮件。

为什么这么复杂?

你从大约12行简单的代码,变成了大约26行带有类、接口、lambda表达式、泛型等等的代码。
为什么要把代码弄得这么复杂?

对于一个你想尽快从A点到B点的小样本来说,你可以使用环境变量就可以了,但对于现实世界的应用来说,虽然需要在前期进行额外的设置,但本教程中的技术将减少你需要编写的代码量,提高解决方案的灵活性和可维护性。

更好的.NET配置

学习完本教程后,你已经学会了如何使用.NET的配置API来:

  • 安全地配置秘密和敏感信息
  • 从多个来源检索配置
  • 用一个来源的配置覆盖另一个来源的配置
  • 将配置添加到依赖性注入容器中
  • 将配置注入你的类中