首次使用Nodemailer向Ethereal Mail发件报错:Cannot read properties of undefined (reading 'messageId')
Nodemailer发送Ethereal邮件报错排查:Cannot read properties of undefined (reading 'messageId')
首次使用Nodemailer发送邮件,尝试向Ethereal Mail发送时失败,报错信息:Cannot read properties of undefined (reading 'messageId')
控制台日志
[2022-10-18 14:08:55] DEBUG Creating transport: nodemailer (6.8.0; +https://nodemailer.com/; SMTP/6.8.0[client:6.8.0]) [2022-10-18 14:08:55] DEBUG Sending mail using SMTP/6.8.0[client:6.8.0] Error occurred. Cannot read properties of undefined (reading 'messageId') ::1 - - [18/Oct/2022:14:08:55 +0000] "POST /posts HTTP/1.1" 200 10 "http://localhost:5000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36" [2022-10-18 14:08:55] DEBUG [AO7ADWBuDE] Resolved smtp.ethereal.email as 54.36.85.113 [cache miss]
相关代码
utils/nodemailer.js
export async function sendMail(username, address, text) { // 创建SMTP传输器对象 let transporter = nodemailer.createTransport({ host: 'smtp.ethereal.email', port: 587, auth: { user: 'diego.marks28@ethereal.email', pass: 'YvQ1FS9g8Ut8qWE1Jz', }, debug: true, logger: true, }); // transporter.verify((err, success) => { // if (err) console.error(err); // console.log('配置正确'); // }); let message = { from: 'do_not_reply@northpole.com', to: 'santa@northpole.com', subject: 'New wish from a child has been requested!', html: `<p>Dear Santa Clause,<br> A child has sent his wish. Below are the details.<br> <ul>Username: ${username} </ul> <ul>Address: ${address}</ul> <ul>Wish: ${text}</ul> </p>`, }; return transporter.sendMail(message, (error) => { if (error) { return console.log(error); } console.log(info); }); // 仅通过Ethereal账户发送时可预览 }
server.js
app.post('/posts', async (request, response) => { const { username, address, text } = request.body; await addPost(username, address, text); try { const data = await sendMail(username, address, text); console.log('Message sent: %s', data.messageId); return response.json({ username: username, address: address, text: text, }); } catch (err) { console.log('Error occurred. ' + err.message); return response.send('error here'); } });
问题原因
- 返回值不匹配异步逻辑:
sendMail是async函数,但内部使用了transporter.sendMail的回调模式,该模式下不会返回Promise,导致await sendMail(...)得到的data是undefined,访问data.messageId触发报错。 - 错误未向上抛出:回调里的错误仅用
console.log打印,未抛出异常,导致server.js的try/catch无法捕获错误,无法正确处理失败场景。 - 未定义变量:回调中的
console.log(info)里info变量未声明,会引发额外错误。
修复方案
将sendMail改为Promise模式(Nodemailer原生支持Promise返回),修改后的代码如下:
修改后的utils/nodemailer.js
export async function sendMail(username, address, text) { // 创建SMTP传输器对象 let transporter = nodemailer.createTransport({ host: 'smtp.ethereal.email', port: 587, auth: { user: 'diego.marks28@ethereal.email', pass: 'YvQ1FS9g8Ut8qWE1Jz', }, debug: true, logger: true, }); // 可选:验证配置是否正确 // await transporter.verify(); // console.log('配置正确'); let message = { from: 'do_not_reply@northpole.com', to: 'santa@northpole.com', subject: 'New wish from a child has been requested!', html: `<p>Dear Santa Clause,<br> A child has sent his wish. Below are the details.<br> <ul>Username: ${username} </ul> <ul>Address: ${address}</ul> <ul>Wish: ${text}</ul> </p>`, }; // 直接返回sendMail的Promise结果 const info = await transporter.sendMail(message); console.log(info); return info; }
说明
- 移除回调函数,直接用
await获取transporter.sendMail的返回值,确保sendMail函数返回包含messageId的对象,server.js中的data能正确获取值。 - 发送过程中的错误会自动被Promise抛出,
server.js的try/catch可以捕获并处理。 - 修复了未定义的
info变量问题。
内容的提问来源于stack exchange,提问作者Johnspeed114
相关产品推荐
相关产品推荐

