'Sendgrid API: How to send bulk emails with individual template data?

Requested behaviour:

I would like to send out bulk emails using Sendgrid and Firestore Cloud functions together. The email should display some individual user data depending on the recipient (e.g. user id and user name).

Current State

I created a working cloud function. It gets the user data from firestore and sends out emails by using the sendgrid API to the given email addresses.

Issue

However, it sends the ids of all users to every email address, instead of only sending the id belonging to a certain subscriber. Example:

There are 3 subscribers with 3 ids in my firestore collection: "abc", "pqr", "xyz"

The function should deliver three emails including the id belonging to the email adress. Instead, the function sends "abcpqrxyz" to every address right now.

My cloud function:

export const sendAllEmails = functions.https.onCall(async (event) => {

  const subscriberSnapshots = await admin.firestore().collection('subscribers').get();

  const emails = subscriberSnapshots.docs.map(snap => snap.data().email);
  const ids = subscriberSnapshots.docs.map(snap => snap.id);

  const individualMail = {
    to: emails,
    from: senderEmail,
    templateId: TEMPLATE_ID,
    dynamic_template_data: {
        subject: event.subject,
        text: event.text,
        id: ids // sends all ids to everyone instead of a single id in every mail
  }

  await sendGridMail.send(individualMail);
  return {success: true};
});

Do I need to loop over emails and IDs or does the SendGrid API have a smarter implementation for this behaviour?



Solution 1:[1]

You have to read over each one of these elements to get the value and construct the object.

Maybe the parameters are not being included correctly in the body of the request. Please note that the personalizations object contains the data provided for each one of these mails.

https://sendgrid.com/docs/ui/sending-email/how-to-send-an-email-with-dynamic-transactional-templates/#send-a-transactional-email

var data = JSON.stringify({
  "personalizations": [
    {
      "to": [
        {
          "email": "[email protected]",
          "name": "John Doe"
        }
      ],
      "dynamic_template_data": {
        "verb": "",
        "adjective": "",
        "noun": "",
        "currentDayofWeek": ""
      },
      "subject": "Hello, World!"
    }
  ],
  "from": {
    "email": "[email protected]",
    "name": "John Doe"
  },
  "reply_to": {
    "email": "[email protected]",
    "name": "John Doe"
  },
  "template_id": "<<YOUR_TEMPLATE_ID>>"
});

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.sendgrid.com/v3/mail/send");
xhr.setRequestHeader("authorization", "Bearer <<YOUR_API_KEY_HERE>>");
xhr.setRequestHeader("content-type", "application/json");

xhr.send(data);

Solution 2:[2]

You need to make multiple "personalizations" objects within the data. I'm not sure what the limitations are with the maximum amount of emails in one request. You might need to research that and check. However I tested with the following json data, and it worked for me:

let data = JSON.stringify({
  "from": {
    "email": senderEmail
  },
  "personalizations": [
    { //first individual starts here
      "to": [
        {
          "email": "[email protected]"
        }
      ],
      "dynamic_template_data": {
        "subject": "The subject",
        "text": "Event Text goes here",
        "id": "abc" // the individual id you need goes here
      }
    },
    { //next individual starts here
      "to": [
        {
          "email": "[email protected]"
        }
      ],
      "dynamic_template_data": {
        "subject": "The subject",
        "text": "Event Text goes here",
        "id": "pqr" // the individual id you need goes here
      }
    } //end - but one can add more indivuals
  ],
  "template_id": "[your_template_id]" //add your template id here
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Lyle Bennett