Node.js中使用Nodemailer如何向独立HTML模板传递token参数
如何将token参数传递到Nodemailer的独立HTML模板中?
问题描述
我正在用Node.js开发一项服务,使用Nodemailer向用户发送带有验证链接的邮件。之前直接在代码里写HTML内容时,能正常访问token变量,但现在把HTML部分移到独立的templates/mail.html文件后,没办法访问这个token参数了,请问该怎么把token传递到这个HTML模板里?
相关代码
modules/users.js
let sendNotification = await mailer.sendMail(userDetail.email, token);
mailer/applicationMailer.js
async function sendMail(userMail, token) { // let htmlTemplate = fs.readFileSync(__dirname + '/templates/mail.html'); let transporter = nodemailer.createTransport(smtpTransport({ host: 'smtp.gmail.com', port: 587, secure: false, auth: { user: 'xxx@gmail.com', pass: '********' } })); let mailOptions = { from: 'xxx@gmail.com', to: userMail, cc: '', subject: 'Account verification', // html: htmlTemplate html: `<p>To verify your account click <a href="https://employee-attendance-service.herokuapp.com/users/verify?token=${token}">LINK</a></p>` + `<p>This link will be expired in two days.</p>` + `<p><strong>Note:</strong> Contact your ADMIN, if the link is expired</p>` }; transporter.sendMail(mailOptions, async function (error, info) { if (error) { console.log(error); } else { console.log('Email sent: ' + info.response); } }); };
解决方案
这问题我做邮件服务时也碰到过,给你两种实用的方案,你可以根据模板复杂度选:
方案1:简单字符串替换(快速上手)
如果你的邮件模板逻辑很简单,只是替换几个变量,直接用字符串替换就够了,不需要额外依赖:
- 修改HTML模板:在
templates/mail.html里用自定义占位符标记需要替换的token,比如{{token}}:
<p>To verify your account click <a href="https://employee-attendance-service.herokuapp.com/users/verify?token={{token}}">LINK</a></p> <p>This link will be expired in two days.</p> <p><strong>Note:</strong> Contact your ADMIN, if the link is expired</p>
- 在邮件服务中替换占位符:读取模板文件后,用
replace()把占位符换成实际的token值(建议用path模块拼接路径,避免跨平台路径问题):
const fs = require('fs'); const path = require('path'); async function sendMail(userMail, token) { // 读取模板文件,注意指定编码为utf8,否则会返回Buffer let htmlTemplate = fs.readFileSync(path.join(__dirname, 'templates/mail.html'), 'utf8'); // 替换占位符 let htmlContent = htmlTemplate.replace('{{token}}', token); let transporter = nodemailer.createTransport(smtpTransport({ host: 'smtp.gmail.com', port: 587, secure: false, auth: { user: 'xxx@gmail.com', pass: '********' } })); let mailOptions = { from: 'xxx@gmail.com', to: userMail, cc: '', subject: 'Account verification', html: htmlContent // 使用替换后的内容 }; transporter.sendMail(mailOptions, async function (error, info) { if (error) { console.log(error); } else { console.log('Email sent: ' + info.response); } }); };
方案2:使用模板引擎(推荐复杂场景)
如果之后你的邮件模板需要更复杂的逻辑(比如根据用户角色显示不同内容、循环展示列表等),用专业的模板引擎会更灵活,这里以EJS为例:
- 安装EJS:
npm install ejs
- 修改模板文件:把
templates/mail.html改成templates/mail.ejs(或者保持.html后缀,只要配置EJS解析即可),直接在模板里用<%= token %>引用变量:
<p>To verify your account click <a href="https://employee-attendance-service.herokuapp.com/users/verify?token=<%= token %>">LINK</a></p> <p>This link will be expired in two days.</p> <p><strong>Note:</strong> Contact your ADMIN, if the link is expired</p>
- 用EJS渲染模板:在邮件服务中读取模板,传入变量渲染出最终HTML:
const fs = require('fs'); const path = require('path'); const ejs = require('ejs'); async function sendMail(userMail, token) { let templatePath = path.join(__dirname, 'templates/mail.ejs'); // 读取模板内容 let htmlTemplate = fs.readFileSync(templatePath, 'utf8'); // 渲染模板,传入token变量 let htmlContent = ejs.render(htmlTemplate, { token }); let transporter = nodemailer.createTransport(smtpTransport({ host: 'smtp.gmail.com', port: 587, secure: false, auth: { user: 'xxx@gmail.com', pass: '********' } })); let mailOptions = { from: 'xxx@gmail.com', to: userMail, cc: '', subject: 'Account verification', html: htmlContent }; transporter.sendMail(mailOptions, async function (error, info) { if (error) { console.log(error); } else { console.log('Email sent: ' + info.response); } }); };
小提示:如果你的服务对性能要求很高,可以把fs.readFileSync换成异步的fs.readFile配合Promise,不过邮件模板一般都是小文件,同步读取完全没问题,代码还更简洁。
内容的提问来源于stack exchange,提问作者Prabha
相关产品推荐
相关产品推荐

