Search code examples
node.jsaws-lambdaserverless-frameworkmandrill

Getting timeout from Mailchimp Transactional when running from Lambda function


I'm trying to send emails through Mailchimp Transactional/Mandrill using Node and Serverless Framework.

I'm able to send emails fine locally (using serverless-offline), however when I deploy the function to our staging environment, it is giving a timeout error when trying to connect to the API.

My code is:

const mailchimp = require('@mailchimp/mailchimp_transactional')(MAILCHIMP_TRANSACTIONAL_KEY);

async function sendEmail(addressee, subject, body) {
    const message = {
      from_email: '[email protected]',
      subject,
      text: body,
      to: [
        {
          email: addressee,
          type: 'to',
        },
      ],
    };
    const response = await mailchimp.messages.send({ message });
    return response;
}

My Lambda is set at a 60 second timeout, and the error I'm getting back from Mailchimp is:

Response from Mailchimp:  Error: timeout of 30000ms exceeded

It seems to me that either Mailchimp is somehow blocking traffic from the Lambda IP, or AWS is not letting traffic out to connect to the mail API.

I've tried switching to use fetch calls to the API directly instead of using the npm module, and still get back a similar error (although weirdly in html format):

Mailchimp send email failed:  "<html><body><h1>408 Request Time-out</h1>\nYour browser didn't send a complete request in time.\n</body></html>\n\n"

Are there any AWS permissions I've missed, or Mailchimp Transactional/Mandrill configs I've overlooked?


Solution

  • I was having the identical issue using Mailchimp's Marketing API and solved it by routing traffic through an NAT Gateway. Doing this allows your lambda functions that are within a VPC to reach external services.

    The short version of how I was able to do this:

    • Create a new subnet within your VPC
    • Create a new route table for the new subnet you just created and make sure that the new subnet is utilizing this new route table
    • Create a new NAT Gateway
    • Have the new route table point all outbound traffic (0.0.0.0/0) to that NAT Gateway
    • Have the subnet associated with the NAT Gateway point all outbound traffic to an Internet Gateway (this is generally already created when AWS populates the default VPC)

    You can find out more at this link: https://aws.amazon.com/premiumsupport/knowledge-center/internet-access-lambda-function/