使用Nodemailer连接池批量发送个性化邮件的正确方式
批量发送专属邮件的正确实现及连接管理
核心问题分析
你当前的代码存在两个关键问题:
sendMail使用回调异步执行,map遍历完成时邮件可能还在发送中,无法准确判断所有邮件是否发送完毕- 开启了连接池(
pool: true),若不手动关闭连接池,脚本会因连接保持而无法自动退出
正确实现步骤
- 改用Promise风格处理异步发送:Nodemailer的
sendMail在不传入回调时会返回Promise,方便统一管理所有异步任务 - 收集所有发送任务的Promise:遍历数组生成每个邮件的发送Promise
- 等待所有任务完成后关闭连接池:用
Promise.all等待全部发送任务结束,再调用transporter.close()关闭连接池,最后返回响应
修改后的完整代码
const nodemailer = require('nodemailer'); // 假设这是你的Express/axios路由处理函数 async function sendBulkEmails(req, res) { const arr = [ { email: "something@something.com", content: "Hello user 1!" }, { email: "something1@something.com", content: "Hello user 2!" } ]; const transport = { // 你的邮件服务器认证信息 pool: true, maxConnections: 20, maxMessages: Infinity }; const transporter = nodemailer.createTransport(transport); try { // 生成所有邮件发送的Promise数组 const mailPromises = arr.map(one => { const mailOptions = { from: "someone@mail.com", to: one.email, subject: "Test mail", text: one.content // 把专属内容加到邮件正文里 }; // 发送邮件并处理单个任务的结果 return transporter.sendMail(mailOptions) .then(() => console.log(`Message sent to: ${one.email}`)) .catch(err => { console.error(`Failed to send to ${one.email}:`, err); throw err; // 若需要让整体任务失败则抛出错误,否则可忽略继续 }); }); // 等待所有邮件发送完成 await Promise.all(mailPromises); console.log("All emails sent successfully"); // 关闭连接池,释放资源 await transporter.close(); // 返回成功响应 res.status(200).json({ message: "所有邮件已成功发送" }); } catch (err) { console.error("邮件发送过程出错:", err); // 即使出错也要关闭连接池 await transporter.close(); // 返回错误响应 res.status(500).json({ error: "部分邮件发送失败", details: err.message }); } }
关键细节说明
- 连接池关闭时机:必须在所有邮件发送任务完成后(包括失败的情况)调用
transporter.close(),否则会中断正在进行的邮件发送 - 错误处理:
Promise.all会在任何一个Promise失败时立即抛出错误,若希望即使部分邮件失败仍继续发送其他邮件,可以在单个Promise的catch中不抛出错误,而是收集错误信息最后统一返回 - 邮件内容:不要忘记将
content字段加入mailOptions的text或html属性,否则收件人看不到专属内容
内容的提问来源于stack exchange,提问作者Cookie
相关产品推荐
相关产品推荐

