0
votes

I am using mail-confirm to validate an email address and the Lambda function is returning rather than waiting for the promise result on

email.check().then(results=>{

And jumps straight to

console.log('callback issue');

and returns. I would expect the email check to finish and return the results object inside of the callback. Instead the function is returned before the promise can resolve. Any pointers will be appreciated.

Function example:

const MailConfirm = require('mail-confirm');
const isemail = require('isemail');

module.exports.app = async (event, context) => {
  let request = JSON.parse(event.body)


  if(request.email){
    var emailToValidate = request.email
    if(isemail.validate(emailToValidate)){
      console.log(`${emailToValidate} - stage 1 pass`);

      const email = new MailConfirm({
        emailAddress: emailToValidate,
        timeout: 2000,
        invalidMailboxKeywords: ['noreply', 'noemail']
      });

      //Promise issue
      email.check().then(results=>{
        console.log(results); 
        return {
          statusCode: 200,
          body: JSON.stringify({
            validatedEmail: emailToValidate,
            isValid: true,
          }),
        };     
      }).catch(err=>{
        console.log(`${emailToValidate} stage 2/3 failed`)
        return {
          statusCode: 200,
          body: JSON.stringify({
            validatedEmail: emailToValidate,
            isValid: false,
            message: err,
          }),
        };         
      });
      //Returns here
      console.log('callback issue');
    }else{
      return {
        statusCode: 200,
        body: JSON.stringify({
          validatedEmail: emailToValidate,
          isValid: false,
          message: 'Failed stage 1 validation',
        }),
      }; 
    }
  }

  // return {
  //   statusCode: 500,
  //   body: JSON.stringify({
  //     message: 'Something went wrong.',
  //   }),
  // };
};

EDIT:

Thanks everyone for your responses. I have implemented the await and it is working nicely when testing

[email protected]

. However if i validate

[email protected]

the email.check() function doesn't return and my lambda function returns with a blank response (502 to API gateway). I am no sure what happens after let results = await email.check(); when validating [email protected]. My Lambada function is not timing out.

 try{
    let results = await email.check();
    console.log(results); 
    //Returns ok on [email protected]
    return {
      statusCode: 200,
      body: JSON.stringify({
        validatedEmail: emailToValidate,
        isValid: true,
      }),
    };
  } catch(err){
    console.log(`${emailToValidate} stage 2/3 failed`)
    return {
      statusCode: 200,
      body: JSON.stringify({
        validatedEmail: emailToValidate,
        isValid: false,
        message: err,
      }),
    };    
  }

Lambda logs START Version: $LATEST [email protected] - stage 1 pass END REPORT Duration: 647.88 ms Billed Duration: 700 ms Memory Size: 128 MB Max Memory Used: 21 MB

API Gateway 502 Bad Gateway (Due to the Lambda function response being null) { "message": "Internal server error" } EDIT 2:

It turns out i am getting a 554 error in mail-confirm when validating [email protected].

3
not found result on console.log(results); and console.log(${emailToValidate} stage 2/3 failed)? - PPShein

3 Answers

1
votes

You need to do some reading but basically anything in a async function that returns a promise you can await like so

module.exports.app = async (event, context, callback) => {
    try {
    const results = await SomeClass.somePromise()

    const anotherResult = await SomeOtherClass.somePromise()

// do some stuff

    callback(null, some_valid_http_response)


    } catch (e) [

        callback(e, null) // or handle another way
    }
}

In short you dont await somePromise.then you just await the promise.

If you want to save yourself a whole world of hurt switch to Node 8.10 you can use most of the latest ES6 features, just make sure you use:

const someLib = require('whatever)

rather than import!

0
votes

Your function is async, email.check().then(...) returns a promise which is never awaited on your side. Remove async at your lambda handler or await await email.check().then(...) the returned promise. If you remove async you have to use the callback property of lambda.

0
votes

Any method that is "thenable" is considered a Promise and will execute asynchronously. Therefore, email.check() is being invoked as a Promise and will not block code execution, which results in console.log() being invoked before you get a response. Since you're already using async/await in your lambda handler, you can just await for the response from email.check() before continuing.

let resp = await email.check().then(results=>{
    console.log(results); 
    return {
        statusCode: 200,
        body: JSON.stringify({
            validatedEmail: emailToValidate,
            isValid: true,
        }),
    };
})

console.log( resp ); // outputs object returned from email.check()