- A+
个人博客-发送邮件优化?
前言
之前的发送邮件就弄了个方法,比如回复评论会给评论的人发送邮件,留言回复也是,而且2者的代码有很多一样的地方,比较冗余。然后也是抽空优化一下,思路也是比较常用的工厂+策略模式,然后评论回复和留言回复的模板是不一样的,所以需要创建模板类和方法。。。
内容比较多,可以自己创建个小项目试试~
模板创建
⌨先把模板给定义好
定义EmailContent
类
主要是用传入发送邮件的内容,Content参数为必须,其他的可以根据自己的需求进行更改。
public class EmailContent { public string Content { get; set; } public string? Link { get; set; } } public class EmailContent<T> { public string Content { get; set; } public string Link { get; set; } public T Data { get; set; } }
首先创建一个基类定义邮件内容生成的方法:
EmailTemplate
:基本模板类SEmailTemplate
:泛型模板类
public abstract class EmailTemplateBase { protected abstract string GetStyle(); } public abstract class EmailTemplate:EmailTemplateBase { public string GenerateContent(EmailContent emailContent) { return $"<html>n<head>n<style>{GetStyle()}</style>n</head>n<body>n{GetBodyContent(emailContent)}n</body>n</html>"; } protected abstract string GetBodyContent(EmailContent emailContent); } public abstract class SEmailTemplate<T>:EmailTemplateBase { public string GenerateContent(EmailContent<T> emailContent) { return $"<html>n<head>n{GetStyle()}n</head>n<body>n{GetBodyContent(emailContent)}n</body>n</html>"; } protected abstract string GetBodyContent(EmailContent<T> emailContent); }
然后为每一种邮件内容创建一个子类:
情况一:简单情况
只发送简单的邮件内容,不包含对象等复杂内容。
GetStyle
里面写样式就行GetBodyContent
里面写内容
public class MessageBoardNotificationEmailTemplate:EmailTemplate { protected override string GetStyle() { return @" /* 添加样式 */ body { font-family: Arial, sans-serif; font-size: 14px; line-height: 1.5; color: #333; } .box { background-color:#90F8FF ; border-radius: 5px; padding: 20px; } h1 { font-size: 24px; font-weight: bold; margin-bottom: 20px; color: #333; } p { margin-bottom: 10px; color: #333; } a { color: #333; }"; } protected override string GetBodyContent(EmailContent emailContent) { return $@" <div class='box'> <h1>ZY知识库</h1> <h3>留言板通知</h3> <p>内容如下:{emailContent.Content}</p> <p>点击跳转:<a href='https://pljzy.top/MsgBoard?page=1'>留言板地址</a></p> </div>"; } }
情况二:复杂情况
GetStyle
同上GetBodyContent
里面参数为泛型参数EmailContent<LinkExchange>
,这样在发送邮件时就能发送对象信息
public class LinksNotificationEmailTemplate:SEmailTemplate<LinkExchange> { protected override string GetStyle() { return ""; } protected override string GetBodyContent(EmailContent<LinkExchange> emailContent) { const string blogLink = "<a href="https://pljzy.top">ZY知识库</a>"; var sb = new StringBuilder(); sb.AppendLine($"<p>{emailContent.Content}</p>"); sb.AppendLine($"<br>"); sb.AppendLine($"<p>以下是您申请的友链信息:</p>"); sb.AppendLine($"<p>网站名称:{emailContent.Data.Name}</p>"); sb.AppendLine($"<p>介绍:{emailContent.Data.Description}</p>"); sb.AppendLine($"<p>网址:{emailContent.Data.Url}</p>"); sb.AppendLine($"<p>站长:{emailContent.Data.WebMaster}</p>"); sb.AppendLine($"<p>补充信息:{emailContent.Data.Reason}</p>"); sb.AppendLine($"<br>"); sb.AppendLine($"<br>"); sb.AppendLine($"<br>"); sb.AppendLine($"<p>本消息由 {blogLink} 自动发送,无需回复。</p>"); return sb.ToString(); } }
发送邮件服务
首先,创建一个接口定义邮件发送服务
public interface IEmailService { Task SendEmail(string recipient, EmailTemplate template, EmailContent emailContent); Task SendEmail<T>(string recipient, SEmailTemplate<T> template, EmailContent<T> emailContent); }
然后创建实现类MimeKitEmailService
,这里用的是MimeKit
库发送邮件
public class MimeKitEmailService : IEmailService { private readonly SmtpClient client; public MimeKitEmailService(SmtpClient client) { this.client = client; } public async Task SendEmail(string recipient, EmailTemplate template, EmailContent emailContent) { var message = CreateEmailMessage(recipient, template.GenerateContent(emailContent)); await SendAsync(message); } public async Task SendEmail<T>(string recipient, SEmailTemplate<T> template, EmailContent<T> emailContent) { var message = CreateEmailMessage(recipient, template.GenerateContent(emailContent)); await SendAsync(message); } private MimeMessage CreateEmailMessage(string recipient, string content) { var message = new MimeMessage(); message.From.Add(new MailboxAddress("ZY", "zy1767992919@163.com")); message.To.Add(new MailboxAddress("", recipient)); message.Subject = "来自ZY知识库通知~"; message.Body = new TextPart("html") { Text = content }; return message; } private async Task SendAsync(MimeMessage message) { await client.SendAsync(message); await client.DisconnectAsync(true); } }
创建工厂类
配置
将邮箱信息存放在appsettings.json
文件中方便统一管理
{ "Email": { "Address": "你的邮箱", "Password": "授权码" } }
然后创建一个类对应上述参数
public class EmailConfig { public string Address { get; set; } public string Password { get; set; } }
在Program.cs
文件中绑定EmailConfig
类,添加到容器中
builder.Services.Configure<EmailConfig>(builder.Configuration.GetSection("Email"));
工厂类
创建EmailServiceFactory
工厂类用于实例化EmailService
- 网易:smtp.163.com
- QQ:smtp.qq.com
在EmailServiceFactory
类中注入IOptions<EmailConfig>
来邮箱信息配置
public class EmailServiceFactory { private readonly EmailConfig emailConfig; public EmailServiceFactory(IOptions<EmailConfig> emailConfigOptions) { emailConfig = emailConfigOptions.Value; } public async Task<IEmailService> CreateEmailService() { var client = new SmtpClient(); // configure the client await client.ConnectAsync("smtp.163.com", 465, true); await client.AuthenticateAsync(emailConfig.Address, emailConfig.Password); return new MimeKitEmailService(client); } }
注册EmailServiceFactory
服务
builder.Services.AddTransient<EmailServiceFactory>();
发送邮件
声明
IEmailService
和EmailServiceFactory
变量,然后使用emailServiceFactory
的CreateEmailService
方法异步创建一个IEmailService
对象用于创建邮箱通信,并将其赋给emailService
变量,然后new一个模板对象,最后调用emailService
的SendEmail
方法发送邮件
private IEmailService emailService; private readonly EmailServiceFactory _emailServiceFactory; public LinkExchangeService(MyDbContext myDbContext, EmailServiceFactory emailServiceFactory) { _myDbContext = myDbContext; _emailServiceFactory = emailServiceFactory; } public async Task SendEmailOnAdd(LinkExchange item) { //创建邮箱连接 emailService = await _emailServiceFactory.CreateEmailService(); //内容模板 var template = new LinksNotificationEmailTemplate(); //发送邮件 await emailService.SendEmail(item.Email, template, new EmailContent<LinkExchange>() { Content = "您好,友链申请已通过!感谢支持,欢迎互访哦~", Data = item }); }