用途
该技能适用于以下场景:构建事务性邮件(注册、密码重置、发票、通知);创建跨邮件客户端可用的响应式邮件模板;在开发环境搭建邮件测试基础设施;实现邮件预览与审批工作流。
为什么使用 MJML
邮件 HTML 编写困难,各邮件客户端(Outlook、Gmail、Apple Mail)渲染方式不同,通常需要复杂的基于表格的布局和内联样式。MJML 是一种标记语言,可编译为响应式、跨客户端的 HTML。例如一段简单的 MJML 结构:
<mj-section>
<mj-column>
<mj-text>Hello {{UserName}}</mj-text>
<mj-button href="{{ActionUrl}}">Click Here</mj-button>
</mj-column>
</mj-section>
它会编译为约 200 行基于表格、带内联样式的 HTML,可在各处正常工作。
架构
邮件流程为:MJML 模板(嵌入资源)经 Mjml.Net 渲染器(编译期)生成 HTML 邮件,再进行变量替换(如 {{UserName}}、{{Link}}),最后通过 SMTP 网关发送(生产环境或开发用的 Mailpit)。
项目结构
示例结构如下:
src/
Infrastructure/
MyApp.Infrastructure.Mailing/
Templates/
_Layout.mjml # 共享布局(页眉、页脚)
UserInvitations/
UserSignupInvitation.mjml
InvitationExpired.mjml
PasswordReset/
PasswordReset.mjml
Billing/
PaymentReceipt.mjml
RenewalReminder.mjml
Mjml/
IMjmlTemplateRenderer.cs
MjmlTemplateRenderer.cs
MjmlEmailMessage.cs
Composers/
IUserEmailComposer.cs
UserEmailComposer.cs
MyApp.Infrastructure.Mailing.csproj
安装
添加 Mjml.Net 包:
dotnet add package Mjml.Net
在 .csproj 中将模板嵌入为资源:
<ItemGroup>
<EmbeddedResource Include="Templates\**\*.mjml" />
</ItemGroup>
模板结构
布局模板(_Layout.mjml)定义 mj-head(标题、预览文本、属性、内联样式)与 mj-body(页眉 logo、内容注入区、页脚版权)。内容模板(如 UserInvitations/UserSignupInvitation.mjml)会被自动包裹进 _Layout.mjml,其中使用 mj-text、mj-button 等组件并包含 {{OrganizationName}}、{{InviteeName}}、{{InviterName}}、{{InvitationLink}}、{{ExpirationDate}} 等变量。
模板渲染器
定义 IMjmlTemplateRenderer 接口,提供 RenderTemplateAsync 方法,接收模板名、变量字典与取消令牌。实现类 MjmlTemplateRenderer 使用 MjmlRenderer,从程序集加载内容模板与 _Layout,将内容注入布局的 {{Content}} 占位符,合并变量(含 SiteUrl),替换变量后编译为 HTML;若编译出错则抛出异常。变量替换使用正则 \{\{([^}]+)\}\}。
邮件组装器模式
将模板渲染与邮件组装分离。IUserEmailComposer 定义 ComposeSignupInvitationAsync 等方法,接收强类型参数(EmailAddress、PersonName、OrganizationName、AbsoluteUri、DateTimeOffset)。实现类构造变量字典(PreviewText、InviteeName、InviterName、OrganizationName、InvitationLink、ExpirationDate),调用渲染器生成 HTML,返回 EmailMessage(收件人、主题、HTML 正文)。
使用 Mailpit 进行开发测试
使用 Mailpit(或 Mailhog)在本地捕获邮件而不实际发送。Aspire 集成示例:在 AppHost/Program.cs 中添加容器 mailpit(axllent/mailpit),暴露 UI 端口 8025 与 SMTP 端口 1025,并让 API 项目引用其 SMTP 端点、设置 Smtp__Host 环境变量。SMTP 客户端配置中,开发环境使用 Mailpit,从配置读取 Smtp:Host(默认 localhost)与 Smtp:Port(默认 1025)。访问 http://localhost:8025 可查看捕获的邮件,包括完整 HTML 渲染、源码视图、头部检查与附件处理。
邮件快照测试
使用 Verify 捕获模板回归。测试方法渲染模板并调用 Verify(html, extension: "html"),生成 .verified.html 文件,可在浏览器或 diff 工具中审查。
邮件预览端点
添加管理端点用于开发期预览邮件:映射 GET /admin/emails/preview/{template},获取示例变量、渲染模板并返回 text/html 内容,要求 AdminOnly 授权。
最佳实践
模板设计:使用 MJML 组件(mj-section、mj-column、mj-text)而非原始 HTML 表格;图片使用生产环境 URL 而非相对路径。变量处理:使用强类型值对象而非原始字符串。测试:为每个模板变体编写测试,在集成测试中使用 Mailpit,对渲染后的 HTML 做快照测试;不要跳过邮件测试,不要只在生产环境测试。
MJML 组件参考
mj-section 为水平容器(类似行);mj-column 为 section 内的垂直容器;mj-text 为带样式的文本内容;mj-button 为行动号召按钮;mj-image 为响应式图片;mj-divider 为水平分隔线;mj-spacer 为垂直间距;mj-table 为数据表格;mj-social 为社交媒体图标。
资源
MJML 文档:https://documentation.mjml.io/ ;MJML Playground:https://mjml.io/try-it-live ;Mjml.Net:https://github.com/ArtZab/Mjml.Net ;Mailpit:https://github.com/axllent/mailpit ;Email on Acid(测试):https://www.emailonacid.com/ 。
限制
资料未提供该技能的具体收费、价格、平台支持范围或效果数据,这些信息暂未提供。