2.8 ABP公共结构 - 邮件发送(MailKit集成)

2.8.1 简介

几乎所有的应用都有一个发送电子邮件的功能。ABP提供了一个基本的基础设施,它可以简单的发送邮件,并且将邮件服务的配置从发送邮件的功能中分离了出来。

2.8.2 IEmailSender

IEmailSender 是一个邮件发送服务接口,使用它你不需要知道详细信息就可以简单的发送邮件。如下所示:

public class TaskManager : IDomainService
{
    private readonly IEmailSender _emailSender;

    public TaskManager(IEmailSender emailSender)
    {
        _emailSender = emailSender;
    }

    public void Assign(Task task, Person person)
    {
        //分配任务给某个人
        task.AssignedTo = person;

        //发送一份邮件通知
        _emailSender.Send(
            to: person.EmailAddress,
            subject: "You have a new task!",
            body: $"A new task is assigned for you: <b>{task.Title}</b>",
            isBodyHtml: true
        );
    }
}

我们只是简单的注入 IEmailSender 接口以及使用了 Send 方法。Send方法有一些重载方法。它能够获取一个MailMessage对象(对于.net core它是无效的,因为.net core没有这些发送邮件的功能类:SmtpClient和MailMessage)。

注意:.net core 2.0及以后版本,已经提供System.Net.Mail.SmtpClient,经测试可以成功发送邮件,MailKit不再是必须。

ISmtpEmailSender

有一个 ISmtpEmailSender 的接口,该接口扩展自 IEmailSender,在该接口中有一个 BuildClient 方法,可以用直接使用该方法来创建一个 SmtpClient 对象(对于.net core它是无效的,因为.net core没有这些发送邮件的功能类:SmtpClient和MailMessage)。在大多数情况下使用 IEmailSender 发送邮件,这已经足够了。

NullEmailSender

NullEmailSender 是一个使用空对象模式来实现 IEmailSender 接口的类。你可以在单元测试中使用它或者使用属性注入的方式来注入 IEmailSender

2.8.3 配置

Email Sender使用设置管理系统来读取发送邮件的配置。所有的设置名称以常量字符串的方式定义在 Abp.Net.Mail.EmailSettingNames 类中。如下所示:

  • Abp.Net.Mail.DefaultFromAddress:在发送邮件时,如果没有指定邮件发送者,该值会自动作为邮件的发送者(如上例所示)

  • Abp.Net.Mail.DefaultFromDisplayName:在发送邮件时,如果没有指定邮件发送者,该值会自动作为邮件发送者的显示名(如上例所示)

  • Abp.Net.Mail.Smtp.Host:SMTP服务器的IP/域名(默认:127.0.0.1)

  • Abp.Net.Mail.Smtp.Port: SMTP服务器的端口(默认:25)

  • Abp.Net.Mail.Smtp.UserName: 用户名,如果SMTP需要身份认证

  • Abp.Net.Mail.Smtp.Password: 密码,如果SMTP需要身份认证

  • Abp.Net.Mail.Smtp.Domain: 域用户名,如果SMTP需要身份认证

  • Abp.Net.Mail.Smtp.EnableSsl: 用来配置SMTP是否使用SSL("true" or "false". 默认: "false")

  • Abp.Net.Mail.Smtp.UseDefaultCredentials: True,使用默认的凭证而不是使用用户名和密码认证的方式 ("true" or "false". 默认: "true").

2.8.4 MailKit 集成

由于.net core不支持标准的System.Net.Mail.SmtpClient,所以我们需要使用第三方插件来发送电子邮件。幸运的是,MailKit为默认的SmtpClient提供了一个很好的替代品。微软也建议使用该插件。

Abp使用 Abp.MailKit package 来集成邮件发送功能。所以,你可以一直使用 IEmailSender 接口通过MailKit来发送邮件(如上所述)。

安装

首先,安装 Abp.MailKit到你的项目:

Install-Package Abp.MailKit

集成

将AbpMailKitModule添加到模块的依赖项中:

[DependsOn(typeof(AbpMailKitModule))]
public class MyProjectModule : AbpModule
{
    //...
}

使用

你可以像之前所述的那样使用 IEmailSender,因为 Abp.MailKit package 中实现了该接口,并且注册了该接口的实现。也可以像之前所述那样来配置它。

自定制

当你创建MailKit的SmtpClient的时候,你可能需要做一些额外的配置或者定制。这样的话,你可以用你自己的实现来Replace(替换) IMailKitSmtpBuilder 接口。你可以继承DefaultMailKitSmtpBuilder 类来实现自定制,因为这样做更容易。例如:你想要接收所有的SSL证书,那么你可以重写 ConfigureClient 方法,如下所示:

public class MyMailKitSmtpBuilder : DefaultMailKitSmtpBuilder
{
    public MyMailKitSmtpBuilder(ISmtpEmailSenderConfiguration smtpEmailSenderConfiguration) 
        : base(smtpEmailSenderConfiguration)
    {
    }

    protected override void ConfigureClient(SmtpClient client)
    {
        client.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;

        base.ConfigureClient(client);
    }
}

然后你可以在模块的PreInitialize 方法中,用你自己的实现来替换 IMailKitSmtpBuilder 接口:

[DependsOn(typeof(AbpMailKitModule))]
public class MyProjectModule : AbpModule
{
    public override void PreInitialize()
    {
        Configuration.ReplaceService<IMailKitSmtpBuilder, MyMailKitSmtpBuilder>();
    }

    //...
}

记住要引用 :Abp.Configuration.Startup,因为ReplaceService的扩展方法定义在该名称空间中。