2

I am having difficulty implementing multiple attachments to sendgrid. The issue I am facing is that fetchAttach function request, is not returning textBuffered before sendEmail object is created even though it is a async/await function. Below is my code for better understanding and also the result of the logs

let fileNames = [
  "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
  "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
];
let attachments = [];

async function fetchAttach(file) {
  let textBuffered;
  request(file, { encoding: null }, (err, res, body) => {
    if (err) {
      console.log("Error-->", err);
    }
    if (res) {
      console.log(res.statusCode);
    }
    if (body) {
      textBuffered = Buffer.from(body);
      console.log("textBuffered");
    }
  });
  return textBuffered;
}

app.post("/api/custom-email", async (req, res) => {
  const {
    firstName,
    lastName,
    email,
    message
  } = req.body;
   
  for (let file of fileNames) {
    await fetchAttach(file)
      .then((res) => {
        console.log("1st. then");
        const attachObj = {
          content: res.toString("base64"),
          filename: `${firstName}${lastName}.pdf`,
          type: "application/pdf",
          disposition: "attachment",
          content_id: "mytext",
        };
        attachments.push(attachObj);
      })

      .then(() => {
        console.log("attachments-->", attachments);
        console.log("2nd .then triggered");
        const sendEmail = {
          method: "POST",
          url: "https://api.sendgrid.com/v3/mail/send",
          headers: {
            "content-type": "application/json",
            Authorization: `Bearer SG.xxxxxxxxxxxxxxxxxxxxxxxxxxx`,
          },
          body: {
            personalizations: [
              {
                to: [
                  {
                    email,
                    name: `${firstName} ${lastName}`,
                  },
                ],
                dynamic_template_data: {
                   message,

                },
              },
            ],
            from: {
              email: "info@xxxxx.com",
              name: `(Do not reply) - ${businessName}`,
            },
            reply_to: {
              email: "info@xxxxx.com",
              name: "xxxxxxx",
            },
            template_id: "d-xxxxxxxxxxxxxxxxxx",
            attachments: attachments,
          },
          json: true,
        };

        console.log("sendEmail triggered");
      });
  }
 
  return res.send("OK");
});

Below are the logs in console:

1st. then
attachments--> [
  {
    content: undefined,
    filename: 'testEmaila.pdf',
    type: 'application/pdf',
    disposition: 'attachment',
    content_id: 'mytext'
  }
]
2nd .then triggered
sendEmail triggered
1st. then
attachments--> [
  {
    content: undefined,
    filename: 'testEmaila.pdf',
    type: 'application/pdf',
    disposition: 'attachment',
    content_id: 'mytext'
  },
  {
    content: undefined,
    filename: 'testEmaila.pdf',
    type: 'application/pdf',
    disposition: 'attachment',
    content_id: 'mytext'
  }
]
2nd .then triggered
sendEmail triggered
200
textBuffered
200
textBuffered

1 Answers1

1

I found a solution to my question above using this post.

request npm package does not support async/await instead I ended up using request-promise package and now my fetchAttach functions looks like below

async function fetchAttach(file) {
  let textBuffered;
  await request(file, { encoding: null }, (err, res, body) => {
    if (err) {
      console.log("Error-->", err);
    }
    if (res) {
      console.log(res.statusCode);
    }
    if (body) {
      textBuffered = Buffer.from(body);
      console.log("textBuffered");
    }
  });
  return textBuffered;
}

added await before the request(file, ...) which is supported by request-promise package.

  • 1
    Twilio SendGrid developer evangelist here. I'm glad you found this solution, I just wanted to point out that request and request-promise are both deprecated. I would recommend you use a different HTTP library, like [node-fetch](https://www.npmjs.com/package/node-fetch) or [got](https://www.npmjs.com/package/got) (which both support promises) to make your requests. – philnash Feb 11 '22 at 01:48