node.js - Nodemailer:如何正确发送“存储”在文件中的 html 消息?
问题描述
我想通过使用存储为 html 文件而不是“硬编码”消息字符串的消息来简化使用 Nodemailer 发送 html 消息。但是,由于某种原因,Nodemailer 不能像我期望的那样工作。
以下代码运行良好(带有“硬编码”消息字符串的版本):
const nodemailer = require('nodemailer');
const fs = require('fs');
let htmlMessage = "";
// Retrieve message from file
fs.readFile("./Message.html", 'utf8', (err, data) => {
if (err) throw err;
console.log(data)
htmlMessage = data;
});
console.log(htmlMessage);
// 1.) Define "transporter"
const transporter = nodemailer.createTransport({
service: ...,
auth: {
user: ...,
pass: ...
}
})
// 2.) Configure email
const email = {
from: ...,
text: 'This is a test! (Plain Text)',
// html: htmlMessage
html: '<div style="margin: 1em; padding: 0.5em; background-color: rgb(90, 168, 90); font-size: 1.5em; '
+ 'border-radius: 0.5em; font-family: Arial, Helvetica, sans-serif;"> '
+ 'This is a test!'
+ '</div>'
};
// 3.) Send email
transporter.sendMail(email, (error, info) => { if (error) {
console.error(error); } else {
console.log('Message sent: %s', info.messageId); }
});
但是,如果我像这样更改消息...
// 2.) Configure email
const email = {
from: ...,
text: 'This is a test! (Plain Text)',
html: htmlMessage
/*
html: '<div style="margin: 1em; padding: 0.5em; background-color: rgb(90, 168, 90); font-size: 1.5em; '
+ 'border-radius: 0.5em; font-family: Arial, Helvetica, sans-serif;"> '
+ 'This is a test!'
+ '</div>'
*/
};
...并用此文件替换“硬编码”字符串...
消息.html
<div style="margin: 1em;
padding: 0.5em;
background-color: rgb(90, 168, 90);
font-size: 1.5em;
border-radius: 0.5em;
font-family: Arial, Helvetica, sans-serif;">
This is a test!
</div>
...发送 html 内容不再起作用。我只收到“纯文本版本”。由于某种原因,Nodemailer 失败了。我究竟做错了什么?
解决方案
您的问题是初学者对异步代码的常见误解之一。
在您的代码中,您这样做了:
let htmlMessage = "";
// 1.) Retrieve message from file
fs.readFile("./Message.html", 'utf8', (err, data) => {
// 3.) Callback completes
if (err) throw err;
console.log(data)
htmlMessage = data;
});
// ....
console.log(htmlMessage); // SHOULD show empty string
// 2.) Configure email
const email = {
from: ...,
text: 'This is a test! (Plain Text)',
html: htmlMessage
};
如您所见,代码在您发送电子邮件1.)
后的2.)
几毫秒内执行。在阅读 HTML 文件之前,您基本上已经发送了电子邮件。3.)
你需要做的是:
let htmlMessage = "";
// 1.) Retrieve message from file
fs.readFile("./Message.html", 'utf8', (err, data) => {
// 2.) Callback completes
if (err) throw err;
console.log(data)
htmlMessage = data;
// ...
// 3.) Configure email
const email = {
from: ...,
text: 'This is a test! (Plain Text)',
html: htmlMessage
};
});
或者,如果您更喜欢阅读原始代码的流程,您可以承诺fs.readFile()
并使用async/await
:
const util = require('util');
const readFile = util.promisify(fs.readFile);
async function foo () {
// 1.) Retrieve message from file
let htmlMessage = await readFile("./Message.html", 'utf8');
// ....
// 2.) Configure email
const email = {
from: ...,
text: 'This is a test! (Plain Text)',
html: htmlMessage
};
}
foo();