在系统处理中,有时候需要发送邮件通知用户,如新增用户的邮件确认,密码找回,以及常规订阅消息、通知等内容处理,都可以通过邮件的方式进行处理。本篇随笔介绍结合VUE+Element 前端,实现系统的邮件参数配置管理,以及基于邮件模板的方式进行邮件的发送。
1、邮件参数的配置管理
邮件参数一般需要配置如用户名、密码、邮件地址,显示名称,以及其他邮件所需的必要配置,一般我们可以通过界面管理的方式进行常规的参数配置,如下界面所示。
其中的登录密码,现在一般是授权登录密码,而不是原始的账号密码了。以163为例,可以在设置中添加一个授权密码。
前端参数的配置管理,我们构建一个Api类,用于调用ABP后端的Api接口,如下所示。
查看窗体中显示邮件参数数据的代码如下所示。
showAbpEmail() { this.resetForm('emailForm') setting.GetEmailSettingsForApplication().then(data => { if (data.result) { Object.assign(this.abpEmailForm, data.result) } this.isAbpEmail = true // 编辑状态 }) },
2、ABP后端邮件的发送处理
系统参数配置完成后,我们需要根据这些邮件参数进行邮件的发送,ABP框架基于.net core 的实现,我们发送邮件,需要添加一个Abp.MailKit的依赖,如下所示。
然后在模块的依赖上,添加对应的AbpMailkitModule的依赖即可。
一般来说,我们发送邮件,还需要重写DefaultMailKitSmtpBuilder的配置处理项,以便自定义发送处理过程。
/// <summary> /// 重写默认的SmtpBuilder类 /// </summary> public class MyMailKitSmtpBuilder : DefaultMailKitSmtpBuilder { private readonly ISmtpEmailSenderConfiguration _smtpEmailSenderConfiguration; private readonly IAbpMailKitConfiguration _abpMailKitConfiguration; public MyMailKitSmtpBuilder(ISmtpEmailSenderConfiguration smtpEmailSenderConfiguration, IAbpMailKitConfiguration abpMailKitConfiguration) : base(smtpEmailSenderConfiguration, abpMailKitConfiguration) { _smtpEmailSenderConfiguration = smtpEmailSenderConfiguration; _abpMailKitConfiguration = abpMailKitConfiguration; } /// <summary> /// 配置发送处理 /// </summary> /// <param name="client"></param> protected override void ConfigureClient(SmtpClient client) { client.CheckCertificateRevocation = false; client.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true; client.Connect(_smtpEmailSenderConfiguration.Host, _smtpEmailSenderConfiguration.Port, GetSecureSocketOption()); if (_smtpEmailSenderConfiguration.UseDefaultCredentials) { return; } var username = _smtpEmailSenderConfiguration.UserName; var password = _smtpEmailSenderConfiguration.Password; //password = SimpleStringCipher.Instance.Decrypt(originalPass);//如果不重写自定义配置MySmtpEmailSenderConfiguration,那么密码需要解密 client.Authenticate(username, password); //base.ConfigureClient(client); } }
但是由于基类处理中,默认的邮件配置密码是直接从数据库读取信息的,没有进行加密,如基类SmtpEmailSenderConfiguration的实现如下。
但是我们应用程序的设置信息,密码是经过加密过的,因此需要重写这个配置项,进行对应的密码解密。
/// <summary> /// 邮件发送参数配置类 /// </summary> public class MySmtpEmailSenderConfiguration : SmtpEmailSenderConfiguration { public MySmtpEmailSenderConfiguration(ISettingManager settingManager) : base(settingManager) { } /// <summary> /// 重写密码处理,需要解密密码 /// </summary> public override string Password => SimpleStringCipher.Instance.Decrypt(GetNotEmptySettingValue(EmailSettingNames.Smtp.Password)); }
最后,在Module中初始化中处理下对应的自定义发送和自定义配置项的处理类。
这样默认注入的发送邮件的接口就正常了,我们接下来就是根据邮件的模板进行内容发送即可。
3、邮件模板的处理
一般的邮件模板,是一个独立的文件方式,文件中定义一些预设的内容,然后实际处理的时候,替换这些变量即可。
邮件模板的内容替换,我喜欢用基于模板引擎的方式处理变量的替换,一般我用NVelocity来进行处理。
我在早期介绍过一些关于NVelocity的知识,需要可以参考:
《使用NVelocity生成内容的几种方式》
《强大的模板引擎开源软件NVelocity》
《Database2Sharp版本更新之自定义模板生成 》
《使用NVelocity0.5实现服务器端页面自动生成 》
例如,我在文本中定义一个连接:http://www.iqidi.com/h5/EmailValidate?callback=${callback} 其中${callback} 就是变量定义,可以在运行中进行变量替换的。
我们在Host项目中定义一些邮件文件模板,如下所示。
然后在使用的应用服务类中注入对应的邮件发送接口以供使用。
具体的邮件发送,就是读取模板内容,进行替换变量,然后调用接口进行邮件的发送即可。
/// <summary> /// 发送校验的电子邮件 /// </summary> /// <returns></returns> public async Task SendEmailValidate(SendEmailActivationLinkDto input) { var user = await GetUserByChecking(input.EmailAddress); //user.SetNewEmailConfirmationCode(); #region 根据模板生成邮件正文 //使用相对路径进行构造处理 string template = string.Format("/UploadFiles/Email/EmailValidate.html"); var helper = new NVelocityHelper(template); //${标题} ${内容} ${称呼} ${日期} var tilte = "邮箱验证通知"; helper.AddKeyValue("title", tilte); helper.AddKeyValue("callname", ""); helper.AddKeyValue("date", DateTime.Now.ToLongDateString()); //邮箱校验码 var callback = Guid.NewGuid().ToString(); helper.AddKeyValue("callback", callback); var html = helper.ExecuteString(); #endregion #region 构建邮件内容对象 发送邮件 string toEmail = "wuhuacong@163.com"; await _emailSender.SendAsync(new System.Net.Mail.MailMessage { To = { toEmail }, Subject = tilte, Body = html, IsBodyHtml = true }); #endregion LogHelper.Logger.Info(string.Format("校验邮件发送给:{0}, {1}", toEmail, "发送邮件成功")); }
为了处理模板内容的方便,我们把规则放在辅助类 NVelocityHelper 中处理即可。
上面就是整个发送模板邮件的过程代码了。
发送邮件成功后,我们可以在邮箱中查看到对应的邮件,我们一般根据自己的业务需要定义不同的邮件模板即可。
邮件发送成功后,查看邮件效果如下所示。
为了方便读者理解,我列出一下前面几篇随笔的连接,供参考:
循序渐进VUE+Element 前端应用开发(1)--- 开发环境的准备工作
循序渐进VUE+Element 前端应用开发(2)--- Vuex中的API、Store和View的使用
循序渐进VUE+Element 前端应用开发(3)--- 动态菜单和路由的关联处理
循序渐进VUE+Element 前端应用开发(4)--- 获取后端数据及产品信息页面的处理
循序渐进VUE+Element 前端应用开发(5)--- 表格列表页面的查询,列表展示和字段转义处理
循序渐进VUE+Element 前端应用开发(6)--- 常规Element 界面组件的使用
循序渐进VUE+Element 前端应用开发(7)--- 介绍一些常规的JS处理函数
循序渐进VUE+Element 前端应用开发(8)--- 树列表组件的使用
循序渐进VUE+Element 前端应用开发(9)--- 界面语言国际化的处理
循序渐进VUE+Element 前端应用开发(10)--- 基于vue-echarts处理各种图表展示
循序渐进VUE+Element 前端应用开发(11)--- 图标的维护和使用
循序渐进VUE+Element 前端应用开发(12)--- 整合ABP框架的前端登录处理
循序渐进VUE+Element 前端应用开发(13)--- 前端API接口的封装处理
循序渐进VUE+Element 前端应用开发(14)--- 根据ABP后端接口实现前端界面展示
循序渐进VUE+Element 前端应用开发(15)--- 用户管理模块的处理
循序渐进VUE+Element 前端应用开发(16)--- 组织机构和角色管理模块的处理
循序渐进VUE+Element 前端应用开发(17)--- 菜单管理
循序渐进VUE+Element 前端应用开发(18)--- 功能点管理及权限控制
VUE+Element 前端应用开发框架功能介绍
循序渐进VUE+Element 前端应用开发(19)--- 后端查询接口和Vue前端的整合
使用代码生成工具快速生成基于ABP框架的Vue+Element的前端界面
循序渐进VUE+Element 前端应用开发(20)--- 使用组件封装简化界面代码
循序渐进VUE+Element 前端应用开发(21)--- 省市区县联动处理的组件使用
循序渐进VUE+Element 前端应用开发(22)--- 简化main.js处理代码,抽取过滤器、全局界面函数、组件注册等处理逻辑到不同的文件中
循序渐进VUE+Element 前端应用开发(23)--- 基于ABP实现前后端的附件上传,图片或者附件展示管理
循序渐进VUE+Element 前端应用开发(24)--- 修改密码的前端界面和ABP后端设置处理
循序渐进VUE+Element 前端应用开发(25)--- 各种界面组件的使用(1)
循序渐进VUE+Element 前端应用开发(26)--- 各种界面组件的使用(2)
电商商品数据库的设计和功能界面的处理
循序渐进VUE+Element 前端应用开发(27)--- 数据表的动态表单设计和数据存储
循序渐进VUE+Element 前端应用开发(28)--- 附件内容的管理
循序渐进VUE+Element 前端应用开发(29)--- 高级查询条件的界面设计
部署基于.netcore5.0的ABP框架后台Api服务端,以及使用Nginx部署Vue+Element前端应用
循序渐进VUE+Element 前端应用开发(30)--- ABP后端和Vue+Element前端结合的分页排序处理
循序渐进VUE+Element 前端应用开发(31)--- 系统的日志管理,包括登录日志、接口访问日志、实体变化历史日志
循序渐进VUE+Element 前端应用开发(32)--- 手机短信动态码登陆处理
循序渐进VUE+Element 前端应用开发(33)--- 邮件参数配置和模板邮件发送处理
使用代码生成工具快速开发ABP框架项目
使用Vue-TreeSelect组件实现公司-部门-人员级联下拉列表的处理
使用Vue-TreeSelect组件的时候,用watch变量方式解决弹出编辑对话框界面无法触发更新的问题