.NET 个人博客-发送邮件优化🧐

  • .NET 个人博客-发送邮件优化🧐已关闭评论
  • 106 次浏览
  • A+
所属分类:.NET技术
摘要

之前的发送邮件就弄了个方法,比如回复评论会给评论的人发送邮件,留言回复也是,而且2者的代码有很多一样的地方,比较冗余。然后也是抽空优化一下,思路也是比较常用的工厂+策略模式,然后评论回复和留言回复的模板是不一样的,所以需要创建模板类和方法。。。


个人博客-发送邮件优化?

前言

之前的发送邮件就弄了个方法,比如回复评论会给评论的人发送邮件,留言回复也是,而且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

  1. 网易:smtp.163.com
  2. 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>(); 

发送邮件

声明 IEmailServiceEmailServiceFactory变量,然后使用 emailServiceFactoryCreateEmailService 方法异步创建一个 IEmailService 对象用于创建邮箱通信,并将其赋给 emailService 变量,然后new一个模板对象,最后调用emailServiceSendEmail方法发送邮件

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                                  }); } 

参考资料