简体   繁体   中英

NodeMailer inside of Axios request on a AWS Lambda function

I must admit I'm pretty new to Javascript and async functions, my main expertise is Python but the client I'm working for now requested me to develop some features using Node.js.

The problem I'm encountering is with sending an email using NodeMailer after a chain of Axios requests are completed. This inside of a Lambda function on AWS. On my local machine if I extract the code from the handler and execute it, it works like a charm. On AWS, however, it looks like the piece of code for sending the email is never reached.

exports.handler = async (event) => {
    email_address = event.queryStringParameters.email_address;

    // initialize nodemailer transport
    let transporter = nodemailer.createTransport({
        service: 'gmail',
        port: 8000,
        secure: false,
        auth: {
            user: 'username@gmail.com',
            pass: 'PASS',
        },
    });

    await axios({
        method: 'GET',
        url: 'https://api.a-service.com/accounts?email=' + email_address,
        auth: {
            username: username,
            password: password
        }
    })
    .then(response => {

        // MY PIECE OF CODE

        return some_values;
    })
    .then(some_values => {

        axios({
            method: 'GET',
            url: 'https://api.a-service.com/orders/' + some_values,
            auth: {
                username: username,
                password: password
            }
        })
        .then(response => {
            // MY PIECE OF CODE

            return some_other_values;
        })
        .then(some_other_values => {
            try{
                transporter.sendMail({
                    from: "User",
                    to: email_address, // list of receivers
                    subject: "Hello " // Subject line
                    text: JSON.stringify(some_other_values), // plain text body
                    html: JSON.stringify(some_other_values), // html body
                });
            } catch (e) {
                console.log(e);
            }
        });
    })
    .catch(error => {
        errors = error;
    })

    if (errors){
        return makeResponse(400, errors);
    } else {
        return makeResponse(200, 'Successful');
    }
};

The flow is as follow:

  1. Call the /accounts API endpoint and get some data out of it
  2. Use the data from the previous call to call the /orders API endpoint
  3. Use the data from the second API call to send an email using NodeMailer

I'm pretty sure I'm making some mistakes with promises, as I found them quite different from the way I usually work with sync code.

Thanks anyone for any tips!

The second call to axios() is running asynchronously, but you do not await it, or return it in the promise chain.

Changing the call to:

   .then(some_values => {

      return axios({...})
             .then(...)
    })

should do the trick.

Alternatively, you can simply remove the curly brackets in the arrow function to ensure that the promise resulting from the axios call and then chain is the return value of the function. That would look like:

    .then(some_values => axios({...})
                         .then(...))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM