SendGrid+Node.js批量发送邮件时逐消息错误处理与状态同步问题
方案1:批量发送后匹配状态,再创建对应记录
SendGrid的sgMail.send()方法传入消息数组时,就算出现部分邮件发送失败,返回的错误对象会携带每个请求的状态信息,和你传入的消息数组下标一一对应,你可以通过下标匹配到哪些邮件发送成功,只为这部分条目创建Communication记录,兼顾批量发送的效率和状态准确性。
示例代码:
console.log("Sending emails...") // 提前绑定item和对应邮件消息,方便后续匹配 const messageItemMap = items.map((item) => { return { item, message: { to: item.details.email, from: '你的SendGrid发件域名', subject: '邮件主题', html: '邮件内容' } } }) const messages = messageItemMap.map(i => i.message) const sendSuccessIndexes = [] try { await sgMail.send(messages) // 走到此处说明所有邮件全部发送成功 sendSuccessIndexes.push(...Array.from({length: messages.length}, (_, i) => i)) console.log('所有邮件发送成功') } catch (error) { // 部分发送失败场景,从错误响应中提取成功的下标 if (error.response && error.response.body) { error.response.body.forEach((res, index) => { if (res.statusCode === 202) { sendSuccessIndexes.push(index) } }) } console.log(`共${sendSuccessIndexes.length}封邮件发送成功,${messages.length - sendSuccessIndexes.length}封发送失败`, error) } // 只为发送成功的条目入库 console.log("Creating communication objects...") for (const index of sendSuccessIndexes) { const item = messageItemMap[index].item const params = { TableName: process.env.COMMUNICATION_TABLE, Item: { communication_id: uuidv1(), item_id: item.item_id, date: new Date().toLocaleDateString() } } try { await docClient.put(params).promise() } catch (dbError) { // 此处可记录入库失败日志,不要直接抛错中断其他正常条目入库 console.error(`条目${item.item_id}入库失败`, dbError) } } console.log("Process complete!")
方案2:修复逐封发送的异步逻辑
你之前逐封发送时出现先入库再发邮件的问题,大概率是异步遍历写法错误,不要用forEach处理异步任务,改用普通for循环加await就能严格保证「发送成功再入库」的顺序:
console.log("Starting processing...") for (const item of items) { try { // 先等待邮件发送结果返回 await sgMail.send({ to: item.details.email, from: '你的SendGrid发件域名', subject: '邮件主题', html: '邮件内容' }) // 发送成功后再执行入库操作 const params = { TableName: process.env.COMMUNICATION_TABLE, Item: { communication_id: uuidv1(), item_id: item.item_id, date: new Date().toLocaleDateString() } } await docClient.put(params).promise() console.log(`条目${item.item_id}处理成功`) } catch (error) { console.error(`条目${item.item_id}处理失败`, error) } } console.log("Process complete!")
如果担心逐封发送效率太低,可以引入p-limit这类工具库控制并发数,既能提升处理速度也不会触发SendGrid的频率限制。
内容的提问来源于stack exchange,提问作者user16248109
相关产品推荐
相关产品推荐

