我想使用 html 模板通过 nodemailer 发送电子邮件。在该模板中,我需要动态注入一些变量,但我确实无法做到这一点。我的代码:
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
smtpTransport = nodemailer.createTransport(smtpTransport({
host: mailConfig.host,
secure: mailConfig.secure,
port: mailConfig.port,
auth: {
user: mailConfig.auth.user,
pass: mailConfig.auth.pass
}
}));
var mailOptions = {
from: 'my@email.com',
to : 'some@email.com',
subject : 'test subject',
html : { path: 'app/public/pages/emailWithPDF.html' }
};
smtpTransport.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
callback(error);
}
});
假设我想在 emailWithPDF.html 中添加如下内容:
Hello {{username}}!
我找到了一些例子,哪里是这样的:
...
html: '<p>Hello {{username}}</p>'
...
但我想要它在单独的 html 文件中。可以吗?
您可以做的是使用节点中的
fs
模块读取HTML文件,然后使用handlebars
替换html字符串中要更改的元素
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
var handlebars = require('handlebars');
var fs = require('fs');
var readHTMLFile = function(path, callback) {
fs.readFile(path, {encoding: 'utf-8'}, function (err, html) {
if (err) {
callback(err);
}
else {
callback(null, html);
}
});
};
smtpTransport = nodemailer.createTransport(smtpTransport({
host: mailConfig.host,
secure: mailConfig.secure,
port: mailConfig.port,
auth: {
user: mailConfig.auth.user,
pass: mailConfig.auth.pass
}
}));
readHTMLFile(__dirname + 'app/public/pages/emailWithPDF.html', function(err, html) {
if (err) {
console.log('error reading file', err);
return;
}
var template = handlebars.compile(html);
var replacements = {
username: "John Doe"
};
var htmlToSend = template(replacements);
var mailOptions = {
from: 'my@email.com',
to : 'some@email.com',
subject : 'test subject',
html : htmlToSend
};
smtpTransport.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
}
});
});
我在所有项目中都使用它。更加干净、最新且易于理解。回调地狱不存在。 sendMail.ts html文件用handlebar读取,将相关变量放入内容中,然后发送。
import * as nodemailer from 'nodemailer';
import * as handlebars from 'handlebars';
import * as fs from 'fs';
import * as path from 'path';
export async function sendEmail(email: string, subject: string, url: string) {
const __dirname = path.resolve();
const filePath = path.join(__dirname, '../emails/password-reset.html');
const source = fs.readFileSync(filePath, 'utf-8').toString();
const template = handlebars.compile(source);
const replacements = {
username: "Umut YEREBAKMAZ"
};
const htmlToSend = template(replacements);
const transporter = nodemailer.createTransport({
host: "smtp.mailtrap.io",
port: 2525, // 587
secure: false,
auth: {
user: "fg7f6g7g67",
pass: "asds7ds7d6"
}
});
const mailOptions = {
from: '"noreply@yourdomain.com" <noreply@yourdomain.com>',
to: email,
subject: subject,
text: url,
html: htmlToSend
};
const info = await transporter.sendMail(mailOptions);
console.log("Message sent: %s", info.messageId);
console.log("Preview URL: %s", "https://mailtrap.io/inboxes/test/messages/");
}
String replace 不是一个好主意,因为您必须恢复旧字符串或创建备份文件才能再次更改它们,而且它不会异步,并且会在各个方面导致问题! 你可以做到更容易并且更干净:
只需转到您的邮件选项并添加上下文与您的变量:
var mailOptions = {
from: 'nginx-iwnl@gmail.com',
to: 'username@gmail.com',
subject: 'Sending email',
template: 'yourTemplate',
context: { // <=
username: username,
whatever: variable
}
};
下一步要做的事情是打开 html 文件并调用变量,如下所示:
{{用户名}}
emailTemplates.js
您可以将每个模板存储为函数emailTemplates.js
const newsLetterEmail = (clientName) => `<p>Hi ${clientName}, here you have today news.</p>`
const welcomeEmail = (clientName, username) => `<p>Welcome ${clientName}, your username is ${username}.</p>`
export {newsLetterEmail, welcomeEmail}
然后在控制器中调用任何 templateFunction 并存储在输出变量中控制器.js
import {welcomeEmail} from './emailTeamplates.js'
const registerUser = async(req, res) => {
const {name, usename, email} = req.body
// User register code....
const output = welcomeEmail(name, username)
let mailOptions = {
from: '"Welcome" <welcome@welcome.com>',
to: 'client@gmail.com',
subject: 'Welcome email!',
text: 'Hello World',
html: output,
}
https://community.nodemailer.com/2-0-0-beta/template/ 他们解释了如何使用这样的模板进行外部渲染:
// external renderer
var EmailTemplate = require('email-templates').EmailTemplate;
var send = transporter.templateSender(new EmailTemplate('template/directory'));
他们还举了这个例子:
// create template based sender function
// assumes text.{ext} and html.{ext} in template/directory
var sendPwdReminder = transporter.templateSender(new EmailTemplate('template/directory'), {
from: 'sender@example.com',
});
您可以在其中看到如何传递变量。您将需要
email-templates
模块:https://github.com/crocodilejs/node-email-templates 和您选择的模板引擎。 此外,在
email-templates
的文档中,您还可以找到如何创建文件结构以便可以找到您的模板:
html.{{ext}} (必填) - 用于 html 格式的电子邮件text.{{ext}}(可选)- 用于电子邮件样式的文本格式。
{{ext}}(可选)- html 格式主题的样式。
{{ext}}(可选)- 用于电子邮件主题
请参阅支持的模板引擎,了解可能的模板引擎扩展(例如 .ejs、.jade、.nunjucks)以用于上面的 {{ext}} 值。
您可以在任何文件名前加上任何您喜欢的前缀,以帮助您在 IDE 中更轻松地识别文件。唯一的要求是文件名包含 html.、text.、style. 和 subject。分别。
对于那些使用 pug 作为模板引擎的人
使用 pug 的渲染函数在单独的文件中渲染模板的快速方法:
// function to send an e-mail. Assumes you've got nodemailer and pug templating engine installed.
// transporter object relates to nodemailer, see nodemailer docs for details
const nodemailer = require('nodemailer');
const pug = require('pug');
function send_some_mail(iterable){
var message = {
from: 'from@example.com',
to: 'to@example.com',
subject: 'Message title',
html: pug.renderFile(__dirname + 'path_to_template.pug', {iterable: iterable})
};
transporter.sendMail(message, function(err, info){...})
}
// template.pug
each item in iterable
li
p #{item.name}
请参阅
https://pugjs.org/api/getting-started.html 了解更多详细信息。请注意,这将导致每次发送消息时模板重新编译。这对于偶尔发送电子邮件来说是没问题的。如果您发送大量电子邮件,您可以缓存已编译的模板来解决这个问题。如果需要,请查看 pug 文档以了解该设置。
Web 请求 使用 handlebars
或任何其他引擎构建 html 模板。创建模板
hbs
文件。使用 html 进行设计并添加消息中需要的变量:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Welcome Email Template</title>
</head>
<body>
<p style="font-size: 14px; font-weight: normal;">Hi {{data.name}}</p>
</body>
</html>
创建模板请求
const web = express.Router()
web.post('/template/email/:template', function(req, res) {
res.render(`templates/email/${req.params.template}`, {
data: req.body
})
})
邮件功能
const nodemailer = require('nodemailer')
const request = require("request")
function sendEmail(toEmail, subject, templateFile) {
var options = {
uri: `http://localhost:3000/template/email/${templateFile}`,
method: 'POST',
json: { name: "Jon Snow" } // All the information that needs to be sent
};
request(options, function (error, response, body) {
if (error) console.log(error)
var transporter = nodemailer.createTransport({
host: mailConfig.host,
port: mailConfig.port,
secure: true,
auth: {
user: mailConfig.account,
pass: mailConfig.password
}
})
var mailOptions = {
from: mailConfig.account,
to: toEmail,
subject: subject,
html: body
}
transporter.sendMail(mailOptions, function(error, info) {
if (error) console.log(error)
})
})
}
尝试将其更改为:
`Hello ${username}!`
确保这些不是引号,而是反引号。
html:"<p>Your message "+variable1+".Message continueous "+variable 2+"</p>"
const fs = require("fs").promises;
const path = require("path");
const handlebars = require("handlebars");
const relativeTemplatePath = "../../html/reset-pw-email-template.html";
function sendEmail(){
const templatePath = path.join(__dirname, relativeTemplatePath);
const templateFile = await fs.readFile(templatePath, 'utf-8');
const template = handlebars.compile(templateFile);
const replacements = {
username:""
};
const finalHtml = template(replacements);
const mailOptions = {
from: "",
to: "",
subject: "",
html: finalHtml,
};
}
import fs from 'fs';
import Handlebars from 'handlebars';
import nodemailer from 'nodemailer';
const transporter = nodemailer.createTransport({
host: 'smtp.ethereal.email',
port: 587,
auth: {
user: 'anjali.pollich@ethereal.email',
pass: 'qZjeVE5F3WQWwdBmek',
},
});
const readFileSync = (path: string) => {
return fs.readFileSync(__dirname + path, { encoding: 'utf-8' });
};
export const registerMail = async (user) => {
const template = Handlebars.compile(readFileSync('/test.html'));
const mailOptions = {
from: '"Info" <info@marius.dev>',
to: 'm.mariakinas@gmail.com',
subject: 'Validate your email address',
html: template({ username: user.name }),
};
transporter.sendMail(mailOptions, (err, res) => {
if (err) console.log(err);
});
};