Search code examples
aws-lambdaamazon-sesaws-sdk-js

Sometimes my email is sent but sometimes it isn't?


I'm using a lambda function to send email with SES, but it doesn't work every time. This morning I sent 3 emails to my email accounts, but now I can't send emails anymore. My SES is in sandbox mode and I verified two email accounts.

I looked at Cloud Watch, and it doesn't show any errors.

'use strict';

let AWS = require('aws-sdk');

AWS.config.update({
    accessKeyId: 'xxxx',
    secretAccessKey: 'xxxx',
    region: 'us-east-1'
});

let SES = new AWS.SES();

function criarResposta( statusCode, message ) {
    return {
        statusCode: statusCode,
        body: `{
            "message": "${message}"
        }`
    };
}

module.exports.enviar = async (event) => {
    const dados = JSON.parse( event.body );

    let params = {
        Destination: {
            ToAddresses: [
                dados.para
            ]
        },
        Message: {
            Body: {
                Html: {
                    Charset: "UTF-8",
                    Data: dados.body
                }
            },
            Subject: {
                Charset: 'UTF-8',
                Data: dados.assunto
            }
        },
        Source: dados.from,
        ReplyToAddresses: [
            dados.from
        ]
    };

    if( dados.hasOwnProperty( 'cc' ) ) {
        params.Destination.CcAddresses.push( dados.cc );
    }

    let sendPromise = new AWS.SES({apiVersion: '2010-12-01'}).sendEmail(params).promise();

    sendPromise.then(function(data) {
        console.log(data.MessageId);
    }).catch(function(err) {
        console.error(err, err.stack);
    });

    return criarResposta( 200, 'OK' );
};

Solution

  • You need to make sure that the promise returned by the sendEmail() function is resolved (or rejected). Currently, you get a reference to the sendPromise, but then you immediately execute return criarResposta( 200, 'OK' ); without waiting for the promise resolution. Try change the following lines:

    sendPromise.then(function(data) {
        console.log(data.MessageId);
    }).catch(function(err) {
        console.error(err, err.stack);
    });
    
    return criarResposta( 200, 'OK' );
    

    with

    try {
        const data = await sendPromise;
        console.log(data.MessageId);
        return criarResposta( 200, 'OK' );
    } catch (err) {
        console.error(err, err.stack);
        return criarResposta( 500, 'Internal Server Error' );
    }
    

    More information about promises and async / await in Node.js Lambda runtimes can be found in this blog post on the AWS blog.


    Side note, you should never store your AWS credentials (accessKeyId and secretAccessKey) as part of your source code. In case of Lambda, the Lambda function gets its permission with from its associated Lambda Execution Role, which should be tailored for the specific needs of the Lambda such as ses:SendEmail and AWSLambdaBasicExecutionRole in this example.