.NET 6中如何发送带变量的自定义HTML邮件?
实现可复用的HTML邮件发送服务(带变量替换)
一、先重构EmailService,支持动态参数和HTML内容
首先把硬编码的内容改成可传入的参数,同时支持HTML邮件体和变量替换。修改后的代码示例:
public class EmailService : IEmailService { // 建议从配置文件读取SMTP参数,这里简化示例 private readonly string _smtpHost = "smtp.mailtrap.io"; private readonly int _smtpPort = 2525; private readonly string _smtpUsername = "your-mailtrap-username"; private readonly string _smtpPassword = "your-mailtrap-password"; private readonly string _senderName = "你的应用名称"; private readonly string _senderEmail = "no-reply@yourapp.com"; // 通用发送方法,支持HTML模板和变量替换 public void SendEmail(string toEmail, string subject, string htmlTemplate, Dictionary<string, string> variables = null) { var email = new MimeMessage(); email.From.Add(new MailboxAddress(_senderName, _senderEmail)); email.To.Add(MailboxAddress.Parse(toEmail)); email.Subject = subject; // 替换模板中的变量 var processedHtml = ReplaceTemplateVariables(htmlTemplate, variables); // 创建HTML邮件体,可选添加纯文本 fallback 兼容旧邮箱 email.Body = new TextPart("html") { Text = processedHtml }; using var smtp = new SmtpClient(); smtp.Connect(_smtpHost, _smtpPort, SecureSocketOptions.StartTls); smtp.Authenticate(_smtpUsername, _smtpPassword); smtp.Send(email); smtp.Disconnect(true); } // 基础变量替换方法(适合简单场景) private string ReplaceTemplateVariables(string template, Dictionary<string, string> variables) { if (variables == null || variables.Count == 0) return template; foreach (var kvp in variables) { template = template.Replace($"{{{{{kvp.Key}}}}}", kvp.Value); } return template; } }
二、模板与变量的处理方案
1. 数据库存储模板(对应你最初的想法)
把验证邮件、重置密码邮件等不同模板存在数据库中,模板里用{{变量名}}作为占位符,比如{{Username}}、{{VerificationLink}}。
示例数据库中存储的验证邮件模板:
<h1>欢迎加入{{AppName}}!</h1> <p>亲爱的{{Username}},请点击下方链接验证你的邮箱:</p> <a href="{{VerificationLink}}">验证邮箱</a> <p>如果这不是你操作的,请忽略此邮件。</p>
发送时从数据库取出模板,传入变量字典调用通用方法:
// 假设你有仓储类负责读取数据库模板 var verificationTemplate = _emailTemplateRepo.GetTemplate("EmailVerification"); var variables = new Dictionary<string, string> { {"Username", user.Username}, {"AppName", "你的应用"}, {"VerificationLink", $"https://yourapp.com/verify?token={user.VerificationToken}"} }; _emailService.SendEmail(user.Email, "请验证你的邮箱", verificationTemplate, variables);
2. 使用轻量级模板引擎(复杂场景推荐)
如果模板需要循环、条件判断等逻辑,基础字符串替换不够用,可以用Scriban或RazorLight这类模板引擎。
以Scriban为例:
- 先安装NuGet包:
Install-Package Scriban - 修改模板渲染方法:
private string RenderScribanTemplate(string templateContent, Dictionary<string, object> variables) { var template = Template.Parse(templateContent); return template.Render(variables, memberRenamer: null); }
- 支持逻辑的模板示例:
<h1>Hello {{username}}!</h1> {{if is_new_user}} <p>欢迎你成为我们的新用户!</p> {{end}} <p>你的重置密码链接:<a href="{{reset_link}}">点击重置</a></p>
- 调用时传入变量:
var variables = new Dictionary<string, object> { {"username", user.Username}, {"is_new_user", true}, {"reset_link", resetUrl} }; var processedHtml = RenderScribanTemplate(resetTemplate, variables); _emailService.SendEmail(user.Email, "重置你的密码", processedHtml);
3. 内嵌模板(简单场景快速实现)
如果邮件类型不多,也可以把模板作为静态字符串或资源文件存在代码里,比如创建一个静态类:
public static class EmailTemplates { public const string PasswordReset = @" <h2>重置你的密码</h2> <p>亲爱的{{Username}},请点击下方链接重置你的密码:</p> <a href=""{{ResetLink}}"">重置密码</a> <p>链接24小时内有效。</p> "; public const string EmailVerification = @" <h2>验证你的邮箱</h2> <p>亲爱的{{Username}},请点击下方链接完成邮箱验证:</p> <a href=""{{VerificationLink}}"">验证邮箱</a> "; }
发送时直接调用:
_emailService.SendEmail(user.Email, "重置密码", EmailTemplates.PasswordReset, new Dictionary<string, string> { {"Username", user.Username}, {"ResetLink", resetUrl} });
三、封装特定邮件类型的方法(提高复用性)
为了让业务代码调用更简洁,可以在EmailService里封装特定邮件的发送方法:
public void SendPasswordResetEmail(string toEmail, string username, string resetLink) { var template = _emailTemplateRepo.GetTemplate("PasswordReset"); var variables = new Dictionary<string, string> { {"Username", username}, {"ResetLink", resetLink} }; SendEmail(toEmail, "重置你的密码", template, variables); } public void SendVerificationEmail(string toEmail, string username, string verificationLink) { var template = _emailTemplateRepo.GetTemplate("EmailVerification"); var variables = new Dictionary<string, string> { {"Username", username}, {"VerificationLink", verificationLink} }; SendEmail(toEmail, "请验证你的邮箱", template, variables); }
业务代码里直接调用_emailService.SendPasswordResetEmail(...)即可,无需重复处理模板和变量。
四、额外建议
- 把SMTP配置(主机、端口、账号密码)放到
appsettings.json中,通过依赖注入读取,避免硬编码。 - 给邮件添加纯文本 fallback,用
MultipartAlternative组合HTML和纯文本部分,兼容不支持HTML的邮箱。 - 测试时用Mailtrap的预览功能,检查变量替换是否正确、HTML渲染是否符合预期。
内容的提问来源于stack exchange,提问作者Diego Velásquez
相关产品推荐
相关产品推荐

