如何在Nodemailer中通过messageId获取已发送邮件的状态或详情?
通过Message ID获取已发送邮件详情(检查退信状态)
你当前用Nodemailer发送邮件后得到的messageId,仅代表邮件已被Gmail的SMTP服务器接收,但Nodemailer本身没有能力通过这个ID查询后续的送达状态或退信信息。要实现这个需求,得借助Gmail官方API来获取邮件详情并判断是否退信。
实现步骤
启用Gmail API并获取OAuth2凭据
前往Google Cloud控制台,启用Gmail API,创建OAuth2客户端ID(类型选桌面应用即可),下载包含client_id、client_secret的JSON配置文件。安装依赖
安装Google API的Node.js客户端:npm install googleapis扩展原有邮件类,添加查询方法
对现有的SendMailWithAppPass类进行扩展,新增查询邮件状态的方法,注意要先把messageId的尖括号去除(Gmail API使用的ID不带尖括号):const { google } = require('googleapis'); const fs = require('fs'); class SendMailWithAppPass{ #user #appPassword #transporter #oauthClient constructor(userEmail, appPassword, oauthConfigPath){ this.#user = userEmail; this.#appPassword = appPassword; // 初始化SMTP transporter(保留原代码逻辑) this.#transporter = nodemailer.createTransport({ host: 'smtp.gmail.com', port: 465, secure: true, auth: { user: this.#user, pass: this.#appPassword, }, tls: { rejectUnauthorized: false }, }); // 初始化OAuth2客户端用于Gmail API调用 const oauthConfig = JSON.parse(fs.readFileSync(oauthConfigPath)); this.#oauthClient = new google.auth.OAuth2( oauthConfig.web.client_id, oauthConfig.web.client_secret, 'http://localhost:3000/oauth2callback' // 需和控制台配置的回调地址一致 ); // 需提前完成授权获取刷新令牌,首次运行可通过Google官方授权流程获取 this.#oauthClient.setCredentials({ refresh_token: '你的刷新令牌' }); } // 保留原有的send方法 async send(from, to, sub, text, html=null){ let info = await this.#transporter.sendMail({ from: `"Automata" <${from}>`, to: to, subject: sub, text: text, html: html, }); if(info){ console.log(info); return info; } } // 新增:通过messageId查询邮件详情及退信状态 async getEmailStatus(messageId){ // 去除messageId中的尖括号 const cleanMessageId = messageId.replace(/[<>]/g, ''); const gmail = google.gmail({ version: 'v1', auth: this.#oauthClient }); try { // 获取完整邮件信息,包含headers和内容 const res = await gmail.users.messages.get({ userId: 'me', id: cleanMessageId, format: 'full' }); const message = res.data; let isBounced = false; let bounceReason = ''; // 检查邮件头中的退信标识 const headers = message.payload.headers; headers.forEach(header => { if(header.name === 'X-Failed-Recipients'){ isBounced = true; bounceReason = `收件人地址无效:${header.value}`; } else if(header.name === 'Diagnostic-Code'){ bounceReason = `退信原因:${header.value}`; } }); // 辅助检查主题是否包含退信关键词 const subjectHeader = headers.find(h => h.name === 'Subject'); if(subjectHeader?.value.includes('Delivery Status Notification')){ isBounced = true; if(!bounceReason) bounceReason = '邮件送达失败'; } return { messageId: message.id, isBounced, bounceReason, fullMessage: message }; } catch (err) { console.error('查询邮件状态失败:', err); throw err; } } }
使用说明
- 首次使用需完成OAuth2授权流程获取刷新令牌,可参考Google官方文档的授权示例。
- 调用
getEmailStatus方法时,直接传入发送邮件后得到的messageId(如<1b796af0-d69b-f497-a91c-84d7970cd8b1@gmail.com>),方法会自动处理格式并返回退信状态。
注意事项
- 若使用其他邮箱服务商(如Outlook、网易邮箱),需对应使用其官方API查询邮件状态,逻辑思路一致。
- 退信存在延迟,建议在发送邮件后间隔一段时间再执行查询。
内容的提问来源于stack exchange,提问作者Abhisek Upadhaya
相关产品推荐
相关产品推荐

