如何在NestJS Mailer的EJS模板中定义邮件主题?
实现方案
完全可以实现,NestJS Mailer本身没有原生提供从模板提取主题的能力,但通过简单的自定义封装就能适配EJS、Handlebars等所有模板引擎,满足你把主题和正文都写在模板文件里的需求。
核心思路
先读取模板文件,分步骤完成渲染:
- 解析渲染模板中的主题部分,得到最终的邮件主题
- 解析渲染剩余的正文内容,得到HTML邮件正文
- 把解析出来的主题和正文传给
MailerService.sendMail方法即可
具体实现(以EJS为例)
步骤1:按约定格式写EJS模板
你可以直接用你期望的开头声明Subject的格式,也可以用EJS变量存主题方便处理动态内容:
Subject: '你好 <%= username %>,这是你的验证邮件' <!DOCTYPE html> <html> <body> <p>尊敬的 <%= username %>:</p> <p>你的账号验证码是:<strong><%= code %></strong></p> <p>验证码15分钟内有效,请尽快完成验证</p> </body> </html>
步骤2:封装模板解析工具方法
import * as ejs from 'ejs'; import * as fs from 'fs'; import { join } from 'path'; interface ParsedEmailTemplate { // 解析得到的邮件主题 subject: string; // 解析得到的HTML正文 html: string; } /** * 解析邮件模板,提取主题和正文 * @param templateName 模板文件名(不需要后缀) * @param context 模板渲染需要的变量上下文 */ async function parseEmailTemplate( templateName: string, context: Record<string, any> ): Promise<ParsedEmailTemplate> { // 替换为你实际存放模板文件的目录路径 const templatePath = join(__dirname, './email-templates', `${templateName}.ejs`); const templateContent = fs.readFileSync(templatePath, 'utf-8'); // 1. 提取模板中声明的Subject const subjectReg = /^Subject: '([^']+)'/; const subjectMatch = templateContent.match(subjectReg); if (!subjectMatch) { // 模板没声明主题的话返回默认值,也可以直接抛错误 return { subject: '默认邮件主题', html: await ejs.render(templateContent, context) } } const rawSubject = subjectMatch[1]; // 2. 渲染主题中的动态变量 const subject = await ejs.render(rawSubject, context); // 3. 去掉模板中的Subject声明行,渲染剩余的正文内容 const htmlContent = templateContent.replace(subjectReg, '').trim(); const html = await ejs.render(htmlContent, context); return { subject, html }; }
步骤3:业务代码中调用
import { Injectable } from '@nestjs/common'; import { MailerService } from '@nestjs-modules/mailer'; @Injectable() export class EmailService { constructor(private readonly mailerService: MailerService) {} async sendVerifyEmail(receiverEmail: string, username: string, verifyCode: string) { // 解析模板得到主题和正文 const { subject, html } = await parseEmailTemplate('verify-email', { username, code: verifyCode }); // 调用NestJS Mailer发送邮件 await this.mailerService.sendMail({ to: receiverEmail, subject, html }); } }
其他模板引擎适配
如果用Handlebars等其他模板引擎,只需要把上面工具方法中的ejs.render替换为对应模板引擎的渲染方法即可,逻辑完全一致。
可选优化
如果你不想改动现有调用逻辑,也可以自定义NestJS Mailer的模板适配器,重写render方法自动提取主题,直接在适配器内部完成主题的注入,上层业务不用做任何修改。
内容的提问来源于stack exchange,提问作者Nikolaj Dam Larsen
相关产品推荐
相关产品推荐

