1
votes

I have Twilio Studio calling a Twilio Function and need it to send email to a variable list (small list) of emails. This question is mostly around looping through them as I can pass variables just fine. I have an array of emails to send a text to and am in a Twilio Function. But all examples I find online are about sending to just ONE. Part of me thinks this needs to be a Twilio Function calling another Twilio function (one loops, the other sends Emails)... but I can't figure out a way to do that. If I could contain it to one Twilio function, that would be great.

I have Twilio Studio calling a Twilio function. I need to keep this all on Twilio... so looping through via PHP and running functions one at a time through there doesn't work. I need this to run on Twilio's serverless setup.

Here's an example of what I have that works:

exports.handler = function(context, event, callback) {
    // using SendGrid's v3 Node.js Library
    // https://github.com/sendgrid/sendgrid-nodejs
    const sgMail = require('@sendgrid/mail');
    sgMail.setApiKey(context.SENDGRID_API_KEY);
    const msg = {
      to: '[email protected]',
      from: '[email protected]',
      templateId: 'my-id-goes-here',
      dynamic_template_data: {
        recipient_name: 'John Smith'
      }
    };
    sgMail.send(msg).then(response => {
      let twiml = new Twilio.twiml.MessagingResponse();
      callback(null, twiml);
    })
    .catch(err => {
      callback(err);
    });
};

Here's me trying to loop through in similar fashion and failing

exports.handler = function(context, event, callback) {
    const sgMail = require('@sendgrid/mail');

    sgMail.setApiKey(context.SENDGRID_API_KEY);

    var responder_emails = '[email protected],[email protected]';
    var emails_a = responder_emails.split(',');

    emails_a.forEach(function(responder_email) {
        const msg = {
          to: responder_email,
          from: '[email protected]',
          templateId: 'my-id-goes-here',
          dynamic_template_data: {
            recipient_name: 'John Smith'
          }
        };
        sgMail.send(msg);
    });

    callback();
};

I can pass in multiple emails into a Twilio function... I'm just not sure how to loop through correctly.

1

1 Answers

2
votes

Heyo. Twilio Evangelist here. 👋

In your first example, you rightfully waited for the send call to be done by using then. In your second example, you missed that. You run several send calls but immediately call callback without waiting.

A fixed (roughly prototyped version) could look as follows.

exports.handler = function(context, event, callback) {
  const sgMail = require('@sendgrid/mail');

  sgMail.setApiKey(context.SENDGRID_API_KEY);

  var responder_emails = '[email protected],[email protected]';
  var emails_a = responder_emails.split(',');

  Promise.all(emails_a.map(function(responder_email) {
    const msg = {
      to: responder_email,
      from: '[email protected]',
      templateId: 'my-id-goes-here',
      dynamic_template_data: {
        recipient_name: 'John Smith'
      }
    };
    return sgMail.send(msg);
  })).then(function() {
    callback();
  }).catch(function(e) {
    callback(e);
  })
});

You have already an array of emails because you called split. You can use this array in combination with Array.map and Promise.all.

Map basically iterates over your array and lets you create a new array with whatever you return from the function inside of map. What the code above does is that it transforms [email, email] to [Promise, Promise]. The promises are the return value of sgMail.send.

Now, that you have an array holding promises that will resolve when sendgrid accepted your call, you can use Promise.all. This method waits for all the promises to be resolved (or rejected) and returns itself a new promise which you can use then with. When all sendgrid calls are done it's time to finish the function by calling the function callback.

Side note: this "map/Promise.all" trick performs all send grid calls in parallel. There might be situations where you want to call them one after another (saying you are doing a lot of calls and run into rate limiting).

Hope that helps and let me know how it goes. :)