0
votes

I have a AWS Lambda that first gets data from an external API endpoint and then will loop the json data and will send email to each of the records. Here is the code:

var aws = require("aws-sdk");
var ses = new aws.SES({ region: "us-east-1" });
const https = require('https');

exports.handler = async function(event, context) {

    return httprequest().then((data) => {
        
        const response = {
            statusCode: 200,
            body: JSON.stringify(data),
        };

        data.forEach(function(item) {
           
            // send email
            sendEmailAsync(item);

        });

        return response;

    });

};


 function sendEmailAsync(item) {

    return new Promise((resolve, reject) => {

        console.log(`Sending email to: ${item.fullName} `);

        let emailFrom = process.env.emailFrom;


        const htmlBody = `
    <!DOCTYPE html>
    <html>
      <head>
      </head>
      <body>
        <p>Hi ${item.fullName},</p>
        <p>...</p>
      </body>
    </html>
  `;

        const textBody = `
    Hi ${item.fullName},
    ...
  `;

        var params = {
            Destination: {
                ToAddresses: [item.email],
            },
            Message: {
                Body: {
                    Html: {
                        Charset: "UTF-8",
                        Data: htmlBody
                    },
                    Text: {
                        Charset: "UTF-8",
                        Data: textBody
                    }
                },
                Subject: {
                    Charset: "UTF-8",
                    Data: "Test Email"
                }
            },
            Source: emailFrom,
        };

        const sendPromise = ses
            .sendEmail(params)
            .promise();

        sendPromise.then(data => {
                console.log(data.MessageId);
                context.done(null, "Success");
                resolve(data.MessageId);
            })
            .catch(err => {
                console.error(err, err.stack);
                context.done(null, "Failed");
                reject(err.message);
            });
    });
}


function httprequest() {

    let host = process.env.endPointHost;
    let path = process.env.endPointPath;
    let apiKey = process.env.apiKey;

    return new Promise((resolve, reject) => {
        const options = {
            host: host,
            path: path + '?APIKey=' + apiKey,
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
            }
        };
        const req = https.request(options, (res) => {
            if (res.statusCode < 200 || res.statusCode >= 300) {
                return reject(new Error('statusCode=' + res.statusCode));
            }
            var body = [];
            res.on('data', function(chunk) {
                body.push(chunk);
            });
            res.on('end', function() {
                try {
                    body = JSON.parse(Buffer.concat(body).toString());
                }
                catch (e) {
                    reject(e);
                }
                resolve(body);
            });
        });
        req.on('error', (e) => {
            reject(e.message);
        });
        // send the request
        req.end();
    });
}

Everything works fine except that when the sendEmailAsync(item); function is being called I get the console log but never get any result about the email being sent or not. Of course, I don't get any email but I'm pretty sure that the problem is that I have to await maybe the function inside the foreach statement but have tried some code and didn't work.

Any clue?

1
Use Promise.all if you want to go with forEach; or else you shall try other for looping mechanisms. Because using forEach with the Async/Await won't run as expected. - Muthu Thavamani
@MTM thanks a lot do you know where to look for an example? - VAAA

1 Answers

0
votes

As the forEach won't give the expected result with the await function, we shall use Promise.all or for..of way of looping.

Let me give you the example by taking only the loop from your snippet.

  1. Promise.all
await Promise.all(data.map(async (item) => {
    try {
      let res = await sendEmailAsync(item);
      console.log(res)
    } catch (error) {
      console.log('Error: '+ error);
    }
  }))
  1. for..of
for(let item of data) {
    try {
      let res = await sendEmailAsync(item);
      console.log(res);
    } catch (error) {
      console.log('Error: ' + error);
    }
  }