Lambda

Lamda AWS icon Lambda is an AWS feature that allows you to run functions based on triggers such as API calls, SNS events or s3 file uploads. The advantage of Lambda is Amazon takes care of all the infrastructure for you so all you have to care about is the function. Amazon will elastically spin the infrastructure up and down to accommodate the load and even better will only charge you for the time your function is running. Nodejs, Python and Java are all supported, the below example is written in python but there are plenty of other language examples out there.

SES

SES AWS icon SES is Amazons email offering allowing you send or receive email in your AWS account. It can be used for marketing campaigns or adhoc emails and basically any email needs. As with Lambda you only pay for what you use. To send emails from a domain you have to verify your domain first by adding a TXT record on your DNS, this is all explained when setting up SES in your console.

Example

In this example we set up a lambda function to send an email to a predefined address using SES. We have already set up SES and verified our domain by adding the TXT record provided.

The example code below does minimum user input validation and is meant only as an example.

import boto3
        
def lamda_sendMessage(event, context):
    if not (('subject' in event) and ('message' in event) and ('from' in event) and ('name' in event)):
        return {"code": 1, "message": "Must preovide all values"}
    if event['subject'] != "" and event['message'] != "" and event['from'] != "" and event['name'] != "":
        toEmail = "email@domain.com"
        fromEmail = "email@domain.com"
        replyTo = event['from']
        name = event['name']
        subject = event['subject'] + " - " + name
        message = event['message']

        client = boto3.client('ses')
        response = client.send_email(
			Source=fromEmail,
			Destination={
				'ToAddresses': [
					toEmail,
				],
			},
			Message={
				'Subject': {
					'Data': subject,
					'Charset': 'utf8'
				},
				'Body': {
					'Text': {
						'Data': message,
						'Charset': 'utf8'
					}
				}
			},
			ReplyToAddresses=[
				replyTo
			]
		)
			
        print response['MessageId']
        return {'code': 0, 'message': 'success'}

The above code uses the boto client to send an email using the SES “send_email” function. More on the SES boto API can be found here:

http://boto.cloudhackers.com/en/latest/ref/ses.html

Now the function is setup we need to give the role the function runs under access to SES. To do this go to “Identity and Access Management” then Roles and click on the Role associated with the function. Click the Policy and put the below JSON into the Policy replacing the ID with your ARN ID.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:eu-west-1:ID:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:eu-west-1:ID:log-group:/aws/lambda/function:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:PutMetricData"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ses:SendEmail"
            ],
            "Resource": "*"
        }
    ]
}

Now we have a Lambda function we need to trigger it, in this example we will be triggering it through an API. To do this we need to implement Amazons API Gateway.

API Gateway

Create an API and then add a resource, in our case we will call the Resource “sendmessage”. Add a POST type method, select lambda function then set your Lambda region and then your lambda function

API Gateway POST method setup

This gives you the basic setup now you can deploy your API by clicking Actions->Deploy API. It will ask you which stage you want to deploy it to, just create a new one and deploy it. Go to Stages click on your stage you created previously and there will be a URL you can invoke the API with, it will look something like this:

https://{apikey}.execute-api.{location}.amazonaws.com/{stage}

This API can be called using a curl command similar to one below:

curl -i -XPOST 'https://{apikey}.execute-api.{location}.amazonaws.com/prod/sendmessage' -d '{"message": "sent from curl", "subject": "Sent from curl", "from": "email@domain.com", "name": "Test"}'

This should return some JSON with code 0 and a message of “success”.

CORS Consideration

Another consideration that needs to be made is how to call your API. In most cases you will want to call the API from some Javascript on your website.

This will not work by default due to “Access-Control-Allow-Origin” headers not being returned on the API call.

This can be enabled in the API gateway by going to Actions->Enable CORS by default this allows all Origins to query the API, you will want to change this to your own website.

Don’t forget once you have made a change to the API gateway you need to re-deploy the API for the changes to go live.

This example is a basic setup there are other considerations that need to be made such as API keys, rate limiting, input validation and response mappings.