Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >结合ABP源码实现邮件发送功能

结合ABP源码实现邮件发送功能

作者头像
潘成涛
发布于 2018-01-18 03:55:33
发布于 2018-01-18 03:55:33
1.2K00
代码可运行
举报
文章被收录于专栏:程序员与猫程序员与猫
运行总次数:0
代码可运行

1. 前言

最近pm临时提出了多种邮件验证操作的需求,因为一时间也没有找到好的邮件收发组件,也抱着研究ABP的心态,就花了几小时时间探究了一下ABP中关于Email的处理和操作。其实邮件操作大多大同小异,这次只是希望介绍一下ABP中实现功能的代码结构而已,以下是具体过程

演示的ABP代码版本为0.9.0.0,不过后面版本对于这部分的修改较少,所以完全不影响之后版本的移植使用

2. 实现过程

ABP的Mail操作放在了Abp.Net.Mail和Abp.Net.Mail.Smtp中,第一步先让我们直接看看这个文件夹下类及接口的代码图(未经允许不可使用)

1. 代码图(重)

根据代码图可以发现ABP对于Mail处理主要由三部分组成

  • 第一部分是通过继承SettingProvider的EmailSettingProvider来对Mail相关参数进行设置(其中EmailSettingNames定义相关字符串)
  • 第二部分是以IEmailSenderConfiguration接口为基派生出的对SettingProvider设置的邮件参数进行读取和传输的相关操作类
  • 第三部分是以IEmailSender接口为基派生出的Mail发送操作相关类

至于Smtp开头的文件,则是以Smtp形式进行邮件发送的一种实现文件而已,后文也将直接使用该种方式进行处理

2.具体实现

在具体的实现上,我发现ABP本身的Mail相关类已经十分完整,只是在邮件参数的配置上需要采取自定义的实现,所以我直接抽取了ABP的源码来进行演示

2.1 定义AppSettingNames及AppSettingProvider

AppSettingNames中定义相关的唯一字符串,大家可以认为是Key,而AppSettingProvider中则是将Key对应的邮件参数赋值,供之后的Configuration读取

邮件功能推荐放在Core模块中,完成相关的provider后在CoreModule加入Configuration.Settings.Providers.Add<AppSettingProvider>();即可生效

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static class AppSettings
{
    /// <summary>
    /// SMTP related email settings.
    /// </summary>
    public static class Smtp
    {
        /// <summary>
        /// Abp.Net.Mail.DefaultFromAddress
        /// </summary>
        public const string DefaultAddress = "Trucking.Net.Mail.DefaultFromAddress";

        /// <summary>
        /// Abp.Net.Mail.DefaultFromDisplayName
        /// </summary>
        public const string DefaultDisplayName = "Trucking.Net.Mail.DefaultFromDisplayName";

        /// <summary>
        /// Abp.Net.Mail.Smtp.Host
        /// </summary>
        public const string Host = "Trucking.Net.Mail.Smtp.Host";

        /// <summary>
        /// Abp.Net.Mail.Smtp.Port
        /// </summary>
        public const string Port = "Trucking.Net.Mail.Smtp.Port";

        /// <summary>
        /// Abp.Net.Mail.Smtp.UserName
        /// </summary>
        public const string UserName = "Trucking.Net.Mail.Smtp.UserName";

        /// <summary>
        /// Abp.Net.Mail.Smtp.Password
        /// </summary>
        public const string Password = "Trucking.Net.Mail.Smtp.Password";

        /// <summary>
        /// Abp.Net.Mail.Smtp.Domain
        /// </summary>
        public const string Domain = "Trucking.Net.Mail.Smtp.Domain";

        /// <summary>
        /// Abp.Net.Mail.Smtp.EnableSsl
        /// </summary>
        public const string EnableSsl = "Trucking.Net.Mail.Smtp.EnableSsl";

        /// <summary>
        /// Abp.Net.Mail.Smtp.UseDefaultCredentials
        /// </summary>
        public const string UseDefaultCredentials = "Trucking.Net.Mail.Smtp.UseDefaultCredentials";
    }
}

public class AppSettingProvider : SettingProvider
{
    public override IEnumerable<SettingDefinition> GetSettingDefinitions(SettingDefinitionProviderContext context)
    {
        return new[]
        {
            new SettingDefinition(AppSettings.Smtp.Host, "smtp.gmail.com", L("SmtpHost"),
                scopes: SettingScopes.Application | SettingScopes.Tenant),
            new SettingDefinition(AppSettings.Smtp.Port, "587", L("SmtpPort"),
                scopes: SettingScopes.Application | SettingScopes.Tenant),
            new SettingDefinition(AppSettings.Smtp.UserName, "myemail@gmail.com", L("Username"),
                scopes: SettingScopes.Application | SettingScopes.Tenant),
            new SettingDefinition(AppSettings.Smtp.Password, "mypassword", L("Password"),
                scopes: SettingScopes.Application | SettingScopes.Tenant),
            new SettingDefinition(AppSettings.Smtp.Domain, "", L("DomainName"),
                scopes: SettingScopes.Application | SettingScopes.Tenant),
            new SettingDefinition(AppSettings.Smtp.EnableSsl, "true", L("UseSSL"),
                scopes: SettingScopes.Application | SettingScopes.Tenant),
            new SettingDefinition(AppSettings.Smtp.UseDefaultCredentials, "false", L("UseDefaultCredentials"),
                scopes: SettingScopes.Application | SettingScopes.Tenant),
            new SettingDefinition(AppSettings.Smtp.DefaultAddress, "myemail@gmail.com",
                L("DefaultEmailAddress"), scopes: SettingScopes.Application | SettingScopes.Tenant),
            new SettingDefinition(AppSettings.Smtp.DefaultDisplayName, "CompanyName",
                L("DefaultDisplayName"), scopes: SettingScopes.Application | SettingScopes.Tenant)
        };
    }

    private static LocalizableString L(string name)
    {
        return new LocalizableString(name, AbpConsts.LocalizationSourceName);
    }
}

2.2 EmailSenderConfiguration配置

这个类的作用如上面提到的那样,主要是读取自定义的AppSettingProvider中设置的邮件参数值

IUserEmailSenderConfiguration接口略

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class UserEmailSenderConfiguration : TruckingServiceBase, IUserEmailSenderConfiguration, ITransientDependency
{
    /// <summary>
    /// Gets a setting value by checking. Throws <see cref="AbpException"/> if it's null or empty.
    /// </summary>
    /// <param name="name">Name of the setting</param>
    /// <returns>Value of the setting</returns>
    protected string GetNotEmptySettingValue(string name)
    {
        var value = SettingManager.GetSettingValue(name);
        if (value.IsNullOrEmpty())
        {
            throw new AbpException(String.Format("Setting value for '{0}' is null or empty!", name));
        }

        return value;
    }

    /// <summary>
    /// SMTP Host name/IP.
    /// </summary>
    public string Host
    {
        get { return GetNotEmptySettingValue(AppSettings.Smtp.Host); }
    }

    /// <summary>
    /// SMTP Port.
    /// </summary>
    public int Port
    {
        get { return SettingManager.GetSettingValue<int>(AppSettings.Smtp.Port); }
    }

    /// <summary>
    /// User name to login to SMTP server.
    /// </summary>
    public string UserName
    {
        get { return GetNotEmptySettingValue(AppSettings.Smtp.UserName); }
    }

    /// <summary>
    /// Password to login to SMTP server.
    /// </summary>
    public string Password
    {
        get { return GetNotEmptySettingValue(AppSettings.Smtp.Password); }
    }

    /// <summary>
    /// Domain name to login to SMTP server.
    /// </summary>
    public string Domain
    {
        get { return SettingManager.GetSettingValue(AppSettings.Smtp.Domain); }
    }

    /// <summary>
    /// Is SSL enabled?
    /// </summary>
    public bool EnableSsl
    {
        get { return SettingManager.GetSettingValue<bool>(AppSettings.Smtp.EnableSsl); }
    }

    /// <summary>
    /// Use default credentials?
    /// </summary>
    public bool UseDefaultCredentials
    {
        get { return SettingManager.GetSettingValue<bool>(AppSettings.Smtp.UseDefaultCredentials); }
    }

    public string DefaultAddress
    {
        get { return GetNotEmptySettingValue(AppSettings.Smtp.DefaultAddress); }
    }

    public string DefaultDisplayName
    {
        get { return SettingManager.GetSettingValue(AppSettings.Smtp.DefaultDisplayName); }
    }
}

2.3 SmtpEmailSender实现(Smtp实现邮件发送)

UserSmtpEmailSender类才是真正的对Mail操作类,它通过注入IUserEmailSenderConfiguration接口,读取相关的Mail参数,如Host,UserName,Password等,然后再调用.NET的Mail发送邮件。

IUserSmtpEmailSender接口略

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class UserSmtpEmailSender : IUserSmtpEmailSender, ITransientDependency
{
    private readonly IUserEmailSenderConfiguration _configuration;

    public UserSmtpEmailSender(IUserEmailSenderConfiguration configuration)
    {
        _configuration = configuration;
    }
    
    public async Task SendAsync(string to, string subject, string body, bool isBodyHtml = true)
    {
        await SendAsync(_configuration.DefaultAddress, to, subject, body, isBodyHtml);
    }

    public void Send(string to, string subject, string body, bool isBodyHtml = true)
    {
        Send(_configuration.DefaultAddress, to, subject, body, isBodyHtml);
    }

    public async Task SendAsync(string from, string to, string subject, string body, bool isBodyHtml = true)
    {
        await SendAsync(new MailMessage(from, to, subject, body) {IsBodyHtml = isBodyHtml});
    }

    public void Send(string from, string to, string subject, string body, bool isBodyHtml = true)
    {
        Send(new MailMessage(from, to, subject, body) {IsBodyHtml = isBodyHtml});
    }

    public async Task SendAsync(MailMessage mail, bool normalize = true)
    {
        if (normalize)
            NormalizeMail(mail);

        await SendEmailAsync(mail);
    }

    public void Send(MailMessage mail, bool normalize = true)
    {
        if (normalize)
            NormalizeMail(mail);

        SendEmail(mail);
    }

    public SmtpClient BuildClient()
    {
        var host = _configuration.Host;
        var port = _configuration.Port;

        var smtpClient = new SmtpClient(host, port);
        try
        {
            if (_configuration.EnableSsl)
                smtpClient.EnableSsl = true;

            if (_configuration.UseDefaultCredentials)
            {
                smtpClient.UseDefaultCredentials = true;
            }
            else
            {
                smtpClient.UseDefaultCredentials = false;

                var userName = _configuration.UserName;
                if (!userName.IsNullOrEmpty())
                {
                    var password = _configuration.Password;
                    var domain = _configuration.Domain;
                    smtpClient.Credentials = !domain.IsNullOrEmpty()
                        ? new NetworkCredential(userName, password, domain)
                        : new NetworkCredential(userName, password);
            }
        }
        
        return smtpClient;
    }
    catch
    {
            smtpClient.Dispose();
            throw;
        }
    }

    /// <summary>
    ///     Normalizes given email.
    ///     Fills <see cref="MailMessage.From" /> if it's not filled before.
    ///     Sets encodings to UTF8 if they are not set before.
    /// </summary>
    /// <param name="mail">Mail to be normalized</param>
    protected virtual void NormalizeMail(MailMessage mail)
    {
        if ((mail.From == null) || mail.From.Address.IsNullOrEmpty())
            mail.From = new MailAddress(
                _configuration.DefaultAddress,
                _configuration.DefaultDisplayName,
                Encoding.UTF8
            );

        if (mail.HeadersEncoding == null)
            mail.HeadersEncoding = Encoding.UTF8;

        if (mail.SubjectEncoding == null)
            mail.SubjectEncoding = Encoding.UTF8;

        if (mail.BodyEncoding == null)
            mail.BodyEncoding = Encoding.UTF8;
    }

    protected async Task SendEmailAsync(MailMessage mail)
    {
        using (var smtpClient = BuildClient())
        {
            await smtpClient.SendMailAsync(mail);
        }
    }

    protected void SendEmail(MailMessage mail)
    {
        using (var smtpClient = BuildClient())
        {
            smtpClient.Send(mail);
        }
    }
}

之后我们只需要再调用该EmailSender的SendAsync,填入对应的参数,亲测有效。如果之后要更换邮件组件,则只需要实现对应的UserLibraryEmailSerder即可。

至此,我们便将ABP中单独的一个邮件功能抽离了出来并做了相关解释,其实只要花点功夫,自己手动剥离代码图也可以理解了。至于一个简单的邮件功能为什么在ABP中要实现得如此复杂,每个程序员有每个程序员的答案,还是继续学习吧

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-09-29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
java开发_STMP邮箱客户端_发送邮件
http://zhiwenweb.cn/jszx/czxt/201009/20179.html
Hongten
2018/09/13
2.5K0
ABP入门系列(17)——使用ABP集成的邮件系统发送邮件
ABP中对邮件的封装主要集成在Abp.Net.Mail和Abp.Net.Mail.Smtp命名空间下,相应源码在此。 #一、Abp集成的邮件模块是如何实现的 分析可以看出主要由以下几个核心类组成: E
圣杰
2018/01/11
2.9K0
ABP入门系列(17)——使用ABP集成的邮件系统发送邮件
ASP.NET(C#) 发送邮件帮助类Mailhelper
using System; using System.Data; using System.Configuration; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; u
KenTalk
2018/09/11
1.4K0
.Net魔法堂:发个带附件的邮件
一、前言                             由于工作需要最近把邮件发送封装成WebService,现在把代码记录在此,以便日后查阅。 二、二话不说写代码                     private void _SendMail(string form, string pw, string subject, string[] to, string[] cc, string body, string attachmentName, byte[] attachment)
^_^肥仔John
2018/01/18
6820
【.NET】几行代码实现自动发送邮件功能
前言:邮件自动发送功能应该场景比较多,例如遇到程序bug、或者运行报告等,补获到就发送邮件提醒。或者其他用途。
Wesky
2024/08/13
2000
【.NET】几行代码实现自动发送邮件功能
使用.Net发电子邮件小结
电子邮件是通过互联网发出去的,互联网中传输层协议有TCP/IP协议,邮件服务在基于TCP/IP底层协议之上的应用层实现SMTP、POP3、IMAP4等协议,通过这些协议实现了邮件的收发服务。
小蜜蜂
2019/08/06
1.7K0
使用.Net发电子邮件小结
Unity 如何在程序中发送Email邮件
发送邮件需要用到System.Net.Mail命名空间下的MailMessage和SmtpClient类,smtp是一种提供可靠且有效的电子邮件传输协议,是建立在FTP文件传输服务上的一种邮件服务。下面封装一个Email类,声明MailMessage和SmtpClient字段:
CoderZ
2022/08/29
9950
Unity 如何在程序中发送Email邮件
MYSQL自动备份并发送邮件工具
最近在开发小程序,由于服务器只有一台,所以不能数据库异机备份,出于数据安全的考虑,就做了一个数据库定时备份并发送邮件到自己的邮箱的小工具,先看下工具界面
code2roc
2023/07/19
3310
MYSQL自动备份并发送邮件工具
邮件发送功能开发
作为一名.Net开发,"邮件发送"功能的开发和使用是必须要掌握的,因为这个功能作为“消息推送”的一种手段经常出现在各种.Net系统中,所以本文将对.Net平台下的“邮件发送”,做一个细致的分析! 一、who需要邮件功能 1、服务提供方:需提供邮件收发客户端或Web服务。如:QQ邮箱、GMail邮箱、126、163等知名邮件服务提供商。注:如果你使用的第三方不知名邮件服务商提供的邮件收发服务,通过其发出的邮件,可能会被其他知名邮件服务提供商的STMP服务器视为是"恶意邮件或垃圾邮件"! 2、消息推送:消息推送
郑小超.
2018/01/26
4.1K0
.net下发送Email的Helper类一、适用场景二、代码三、调用方法四、结束
前段时间因为业务需要自动给客户发送支持HTML格式的而且带附件的Email,而且使用的还是Office365邮箱,就抽时间看了一下这方面的内容,并写了这个帮助类。 该类是使用的SMTP服务发送Email,可以支持OFFICE365等邮箱,支持SSL、HTML邮件、附件等。目前未启用加密的常规发送和使用Office365邮箱发送都已经测试通过。 该代码目前是使用在.net 4.0环境下,理论上.net 4.0~.net 4.7都可以使用,.net core下没有测试。
徐大嘴
2019/03/21
7330
使用 MimeKit 和 MailKit 发送邮件
MimeKit 给.NET 社区带来了一流的 MIME 解析器,它能处理复杂的各种Mime, 性能好。而且开箱即用支持 S/MIME 和 PGP。MimeKit 和 MailKit 支持最新的国际化的电子邮件标准,是.NET 中为一个支持完整支持这些标准电子邮件库,最近正式发布了1.0版本。如果你想做所有与的电子邮件相关的事情,看看 MimeKit 和 MailKit。我保证你不会失望,它支持.NET/Mono的所有平台,包括移动电话、平板等。 使用方法很简单和.NET的SmtpClient 差不多,不过比
张善友
2018/01/29
2.2K0
c# 发送Email的2中方式
我相信大多数人发送邮件使用第二种,但是有时候第二种方式是发不出去的,那么什么情况发布出去呢???
冰封一夏
2019/09/11
5400
ASP和ASP.NET发送邮件笔记
    这两天因公司网站邮件发不出去,然后研究了在asp网站发送邮件和在asp.net网站发送邮件的代码,把碰到的问题这里记录一下。
tandaxia
2018/09/27
7.7K0
ASP和ASP.NET发送邮件笔记
VB.NET 发送QQ邮件,可用于发送验证码和批量文件,通知信息
首先打开邮箱的POP3/IMAP/SMTP,获取邮箱授权码,具体操作如下:
办公魔盒
2019/08/28
1.7K0
VB.NET 发送QQ邮件,可用于发送验证码和批量文件,通知信息
System.Net.Mail.SmtpClient通过SSL/TLS协议发送邮件失败问题解决
通过System.Net.Mail使用SSL协议发送邮件失败并报错 System.Net.Mail.SmtpException: Failure sending mail
KenTalk
2020/03/05
1.7K0
Abp通用配置模块的设计
下面我将尝试用最简单易懂的方式,对Abp源码中通用配置模块的实现方式加以提炼和精简,尽量继承原作者的设计思想,给大家呈现通用配置模块的“最佳实践”。
圣杰
2018/09/20
1.4K0
Abp通用配置模块的设计
C#邮件发送类 简单实用 可自定义发件人名称
上图看效果 MailHelper: public class MailHelper { public bool SendMail(MailSender sender,out s
晓晨
2018/06/22
1.2K0
c#发送邮件含附件
在网上巴拉巴拉找个的,然后修改了下,测试可用 using System; using System.Collections.Generic; using System.Text; using System.Net.Mail; using System.Net.Mime; using System.Net; namespace CustomerDetails { public class SendEmail { private MailMessage mailMessage;
冰封一夏
2019/09/10
1.2K0
C#进阶-实现邮箱收发功能
在C#中,发送邮件是一项常见的任务,通常用于实现自动化通知、报警和与用户进行交互等场景。C#提供了多种发送邮件的方式,主要方式包括SMTP协议、POP3协议、IMAP协议、Exchange服务器等。使用这些方式,开发人员可以灵活地发送和接收邮件,满足各种应用场景的需求。
Damon小智
2024/03/20
4340
C#进阶-实现邮箱收发功能
.NET实现注册发送邮件激活账户
要实现注册的时候同时发送一个邮件到注册人的邮箱,通过发送的邮箱链接来激活帐号,发送邮件实现如下:
用户1503405
2021/09/23
6210
相关推荐
java开发_STMP邮箱客户端_发送邮件
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验