Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
335 views
in Technique[技术] by (71.8m points)

node.js - AWS NodeJS Lambda email function not working correctly

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?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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);
    }
  }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...