Use SendGrid API & NodeJS with Dynamic Templates

Issue

I am unable to send a request from Express to SendGrid to send an email using a dynamic template.

Steps Taken

I have used Postman with a POST request to https://api.sendgrid.com/v3/mail/send with the following JSON:

{
    "personalizations": [{
        "to": [{
            "email": "dariusgoore@gmail.com",
            "name": "test"
        }],
        "dynamic_template_data":{
            "name":"John",
            "text": "Someone just added a new post!",
        }
    }],
    "from": {
        "email": "team@writerboards.com",
        "name": "test"
    },
    "reply_to": {
        "email": "dariusgoore@gmail.com",
        "name": "test"
    },
    "template_id": "d-c8f201dd360d40bc877da13a1a0b36b1"
}

which successfully sends an email using the template.

Here is the code from the Express route that calls SendGrid:

const express = require('express');
const User = require('../models/User');
const Act = require('../models/Act');
const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY);

let router = express.Router();

router.get('/', async (req, res) => { 
  // getdate 14 days ago
  var ago_date = new Date();
  ago_date.setDate(ago_date.getDate()-0)
  // loop through users
  console.log('crons: getting users');
  const users = await User.query();
  console.log('crons:  number of users: ', users.length);
  for (const user of users) {

console.log(user.username)
const lastAct = await Act
  .query()
  .where('users_id', user.id)
  .orderBy('created_at', 'desc')
  .limit(1);

  const msg = {
    to: 'dariusgoore@gmail.com',
    from: 'team@writerboards.com',
    templateId: 'd-c8f201dd360d40bc877da13a1a0b36b1',

    dynamic_template_data: {
      subject: 'Testing Templates',
      name: 'Some One',
      text: 'Denver',
    },
  };

  console.log('this is the msg 2b sent: ', msg)
  const {
    classes: {
      Mail,
    },
  } = require('@sendgrid/helpers');
  const mail = Mail.create(msg);
  const body = mail.toJSON();
  console.log('this is the body: ', body);
  await sgMail.send(msg); 
// };
  };

  res.json({
    success: true, message: 'ok' 
  }); 
});

Error Trace

The error trace shows an error of Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client. The full trace is below:

userone
sending email re on post
this is the msg 2b sent:  { to: 'dariusgoore@gmail.com',
  from: 'team@writerboards.com',
  templateId: 'd-c8f201dd360d40bc877da13a1a0b36b1',
  dynamic_template_data:
   { subject: 'Testing Templates',
     name: 'Some One',
     text: 'Denver' } }
this is the body:  { from: EmailAddress { email: 'team@writerboards.com', name: '' },
  subject: undefined,
  personalizations: [ { to: [Array], dynamic_template_data: [Object] } ],
  template_id: 'd-c8f201dd360d40bc877da13a1a0b36b1' }
usertwo
sending email re on post
this is the msg 2b sent:  { to: 'dariusgoore@gmail.com',
  from: 'team@writerboards.com',
  templateId: 'd-c8f201dd360d40bc877da13a1a0b36b1',
  dynamic_template_data:
   { subject: 'Testing Templates',
     name: 'Some One',
     text: 'Denver' } }
this is the body:  { from: EmailAddress { email: 'team@writerboards.com', name: '' },
  subject: undefined,
  personalizations: [ { to: [Array], dynamic_template_data: [Object] } ],
  template_id: 'd-c8f201dd360d40bc877da13a1a0b36b1' }
(node:19822) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:470:11)
    at ServerResponse.header (/Users/dariusgoore/development/writerboard/writerboard-express-api/node_modules/express/lib/response.js:771:10)
    at ServerResponse.send (/Users/dariusgoore/development/writerboard/writerboard-express-api/node_modules/express/lib/response.js:170:12)
    at ServerResponse.json (/Users/dariusgoore/development/writerboard/writerboard-express-api/node_modules/express/lib/response.js:267:15)
    at router.get (/Users/dariusgoore/development/writerboard/writerboard-express-api/src/routes/crons.js:54:11)
    at process._tickCallback (internal/process/next_tick.js:68:7)
(node:19822) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)

Issue

I am unable to send a request from Express to SendGrid to send an email using a dynamic template. The error trace shows an error of Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client.

The issue is that the Express route is trying to send a response to the client after the headers have already been sent. This is likely due to the fact that there is a loop in the code that sends multiple emails, and the response is being sent inside that loop. To fix this issue, move the response outside of the loop so that it is only sent after all the emails have been sent.