You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:简单字符串替换(快速上手)

如果你的邮件模板逻辑很简单,只是替换几个变量,直接用字符串替换就够了,不需要额外依赖:

  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>
  1. 在邮件服务中替换占位符:读取模板文件后,用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为例:

  1. 安装EJS:
npm install ejs
  1. 修改模板文件:把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>
  1. 用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:02:16