简体   繁体   中英

AWS: Sending email through SES from Lambda

Whenever I try to send email with SES from Lambda (using Java), it fails - the connection times out.

I've tested the exact same code from an EC2 instance in the same VPC as the Lambda function and it works from there (they have the same role assigned). I've also tried running the Lambda function without it being in a VPC (though it would need to be in one anyway) and that also doesn't work.

Here's the relevant bit of code

    SendEmailRequest request = new SendEmailRequest().withSource(from)
                                                     .withDestination(destination)
                                                     .withMessage(message);

    try {
        System.out.println("Attempting to send an email through Amazon SES by using the AWS SDK for Java...");

        if (client == null) {
            client = new AmazonSimpleEmailServiceClient();
            client.setRegion(Region.getRegion(Regions.EU_WEST_1));
        }

        client.sendEmail(request); // this is where the exception is thrown
        System.out.println("Email sent!");
    } catch (Exception ex) {
        ex.printStackTrace();
        System.err.println(ex.getMessage());
    }
}

The error message states that it failed to connect (to email.eu-west-1...) due to a timeout.

Any ideas why it's not working from Lambda?

I ended up getting help from someone in this area - there was information missing from my question that would be necessary to figure out the issue, so here's the guide on how you need to set things up to get it working. Also to note is that I actually couldn't run the Lambda function outside the VPC - it's just assigned a default one when you remove your own, which I didn't realise.

First off, here's the minimal policy to attach to your Lambda function's role that's needed just to send the email (you could remove one of the Send options depending on what you're actually using, and of course you could also limit the resource).

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ses:SendEmail",
                "ses:SendRawEmail",
                "ec2:CreateNetworkInterface"
            ],
            "Resource": "*"
        }
    ]
}

I'll try guide you through the resources you need to create in order now. First, you'll need a subnet which you'll use for your NAT gateway.

Open up the VPC dashboard and create a subnet, give it a useful label so you know it's your NAT's subnet. Put it in the same VPC as your Lambda function.

Next, you'll need to set up the route table so it has the (already existing) local route, which depends on your VPC, and also the default route 0.0.0.0/0 which targets an Internet Gateway. If you don't have one, just go to the Internet Gateways section and create one.

Now, you need to create a NAT Gateway. You can set this up on EC2, but I used the NAT Gateways section of the VPC Dashboard instead to avoid managing another EC2 instance. Put it in the subnet you just created and allocate it a public IP (you can just create a new EIP).

Set up two more subnets for the Lambda function (one is enough, but AWS recommends two for availability). These two will share a route table with the local route (of course) and the default route targetting the NAT Gateway you just created.

You should now be able to send email from your Lambda function! The above steps are needed as Lambda functions only have private IPs - to get access to SES you need a public one, which the NAT Gateway provides to your Lambda functions.

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