简体   繁体   English

SendGrid + Nodejs - 发送批量电子邮件时处理错误

[英]SendGrid + Nodejs - Handling errors when sending bulk emails

I'm building a command line app that will query a DynamoDB table, collect email addresses for each item on the table that has not already had an email sent to it, map over that array of items to create a customized message object for each one, pass that array into SendGrid's sgMail.send() method to send an email for each message inside, and then create a Communication object for each one on a second DynamoDB table.我正在构建一个命令行应用程序,该应用程序将查询 DynamoDB 表,为表中尚未向其发送电子邮件的每个项目收集电子邮件地址,映射该项目数组以为每个项目创建自定义消息对象,将该数组传递给 SendGrid 的sgMail.send()方法,以便为里面的每条消息发送一封电子邮件,然后在第二个 DynamoDB 表上为每个消息创建一个 Communication 对象。 I followed the steps outlined in option three of this Twilio blog , and the code is working.我按照此 Twilio 博客的选项三中概述的步骤操作,代码正在运行。

However, this method does not seem to allow error handling on a message by message basis when you pass in an array to .send() .但是,当您将数组传递给.send()时,此方法似乎不允许.send()消息处理错误。 Right now I first run sgMail.send(messages) in a try/catch block, and then create all of my Communication objects separately for each item only if the .send() call is completely successful.现在,我首先在 try/catch 块中运行sgMail.send(messages) ,然后仅当.send()调用完全成功时才为每个项目单独创建所有通信对象。 I'd prefer to be able to create an individual Communication object each time an email is successfully sent, rather than hoping that the try/catch block hits no errors and then wholesale creating the Communication objects after the fact.我希望能够在每次成功发送电子邮件时创建一个单独的 Communication 对象,而不是希望 try/catch 块没有出错,然后在事后批量创建 Communication 对象。

My first thought was to iterate through the array returned from the DynamoDB query, and for each one first send an email, then once successful, create a Communication object.我的第一个想法是遍历从 DynamoDB 查询返回的数组,并为每个人先发送一封电子邮件,然后在成功后创建一个 Communication 对象。 That method didn't work (the Communication was being created but the email was never sent, even though I was using await on all async calls).该方法不起作用(正在创建通信,但从未发送电子邮件,即使我在所有异步调用上都使用了await )。 Once that didn't work, I found the blog linked above and used that method.一旦那不起作用,我找到了上面链接的博客并使用了该方法。

My worry is that if a random batch of the messages in the array fails and triggers the exception, but another chunk of emails was successfully sent before the error was caught, then I'll have a portion of emails sent out without corresponding Communication objects for them since the creation of those objects happens entirely independently from the email being sent.我担心的是,如果数组中的随机一批消息失败并触发异常,但在捕获错误之前成功发送了另一组电子邮件,那么我将发送一部分没有相应通信对象的电子邮件因为这些对象的创建完全独立于发送的电子邮件。

I've combed through SendGrid's documentation as well as numerous Google searches, but haven't been able to find a helpful answer.我已经梳理了 SendGrid 的文档以及大量的 Google 搜索,但没有找到有用的答案。 Here's the current working code:这是当前的工作代码:

// First wait to send emails
console.log("Sending emails...")
try {
    const messages = items.map((item) => {
        return {
            to: item.details.email,
            from: SendGrid domain here,
            subject: Email subject here,
            html: Email content here
    })

    // Send email to each address passed in.
    await sgMail.send(messages).then(() => {
        console.log('emails sent successfully!');
      }).catch(error => {
        console.log(error);
      });          
} catch (error) {
    throw error
}

// Then create communications
console.log("Creating communication objects...")
try {
    for (let i = 0; i < items.length; i++) {
        const params = {
            TableName: process.env.COMMUNICATION_TABLE,
            Item: {
                communication_id: uuidv1(),
                item_id: items[i].item_id,
                date: new Date().toLocaleDateString()
            }
        };

        try {
            await docClient.put(params).promise();
        } catch (error) {
            throw error
        }
    }
} catch (error) {
    throw error
}

// On success
console.log("Process complete!")

Twilio SendGrid developer evangelist here. Twilio SendGrid 开发人员布道者在这里。

When you send an array of mail objects to sgMail.send , the @sendgrid/mail package actually loops through the array and makes an API call for each message .当您将一组邮件对象发送到sgMail.send@sendgrid/mail包实际上会遍历该数组并对每条消息进行 API 调用 You are right though, that one may fail to send and you will be left in the state where some emails have sent and others failed or were cancelled.不过,您是对的,那个可能无法发送,您将处于某些电子邮件已发送而其他电子邮件已发送失败或被取消的状态。

So, you can loop through the array yourself and handle the successes/failures yourself too.因此,您可以自己遍历数组并自己处理成功/失败。

Try something like this:尝试这样的事情:

console.log("Sending emails...");
items.forEach(async (item) => {
  const mail = {
    to: item.details.email,
    from: "SendGrid domain here",
    subject: "Email subject here",
    html: "Email content here",
  };
  try {
    await sgMail.send(mail);
    console.log(`Sent mail for ${item.item_id} successfully, now saving Communication object`);
    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();
      console.log(`Communications object saved successfully for ${item.item_id}.`);
    } catch (error) {
      console.log(
        "There was a problem saving the Communications object: ",
        error
      );
    }
  } catch (error) {
    console.error("Email could not be sent: ", error);
  }
});

// On success
console.log("Process complete!");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM