You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 21:06:03