A Clojure Lambda designed to receive a JSON message from the Contact Us form on the site and send an email through SES.
Requirements for deployment:
- AWS Account
- At least 1 email address
- Java
- Leiningen
- AWS Command Line tools
High level steps to deploy a fully working serverless Contact Us form:
- Set up code
- Create IAM roles and policies for Lambda function
- Create new Lambda function
- Set up SES
- Set up API Gateway
- Set up and deploy frontend
- Test!
Pull down the repository, pull in the dependencies, and modify the from and to addresses for SES.
git clone git@github.com:epxlabs/contact-us-lambda-demo.git
cd contact-us-lambda-demo
lein deps
In src/contact_us_lambda_demo/core.clj
modify the from-address
and to-addresses
.
In resources/aws/contact-us-lambda-policy.json
change the "ses:FromAddress"
.
Create a new IAM policy named contact-us-lambda-demo
. For the policy body use the policy in resources/aws/contact-us-lambda-policy.json
.
Create a new IAM role named contact-us-lambda-demo
. Add the contact-us-lambda-demo
policy and the AWSLambdaBasicExecutionRole
to the IAM role.
To create the JAR
lein uberjar
Verify that contact-us-lambda-demo-0.1.0-SNAPSHOT-standalone.jar exists in target/
To create the lambda run (REMEMBER TO REPLACE {AWS ACCOUNT ID}):
aws lambda create-function \
--function-name contact-us-lambda-demo \
--handler 'contact_us_lambda_demo.core' \
--runtime java8 \
--memory 1024 \
--timeout 20 \
--role 'arn:aws:iam::{AWS ACCOUNT ID}:role/contact-us-lambda-demo' \
--zip-file 'fileb://./target/contact-us-lambda-demo-0.1.0-SNAPSHOT-standalone.jar'
This will return something like:
{
"CodeSha256": "aUDD2xOT2VvCE4/y49ntBK7uNIi9gP5HZzB87ZA0jko=",
"FunctionName": "contact-us-lambda-demo",
"CodeSize": 8414199,
"MemorySize": 1024,
"FunctionArn": "arn:aws:lambda:us-east-1:{AWS ACCOUNT ID}:function:contact-us-lambda-demo",
"Version": "$LATEST",
"Role": "arn:aws:iam::{AWS ACCOUNT ID}:role/contact-us-lambda-demo",
"Timeout": 10,
"LastModified": "2016-05-15T00:22:05.873+0000",
"Handler": "contact_us_lambda_demo.core",
"Runtime": "java8",
"Description": ""
}
Verify your email addresses in the SES console so mail can be sent and received by your account.
API Gateway is very picky about what you send it. It seems to strongly prefer application/json. So in order to get it to accept form data we must use a mapping.
The Velocity mapping template we use is heavily influenced by: https://forums.aws.amazon.com/thread.jspa?messageID=673012&tstart=0#673012
- Create a new API
- Add a resource named Contact Us with url
/contact-us
- Create POST Method
- Connect POST Method to
contact-us-lambda-demo
Lambda function - In
Integration Request
-> 200 Response ->Body Mapping Templates
->application/x-www-form-urlencoded
paste in the mapping template fromresources/aws/api_gateway_mapping_template
- Enable CORS
- Deploy the API as
prod
- Note the Invoke URL, you will need it for the frontend
Update the API Gateway Invoke URL in resources/public/js/view.contact.js
.
Should be like https://t0nlhdyll3.execute-api.us-east-1.amazonaws.com/prod/contact-us
.
- Create a new S3 bucket named
www.contactuslambda.com
(or other URL if taken). - Update the bucket name in
resources/aws/public-s3-bucket-policy.json
with your bucket name. - Add the Bucket Policy to your S3 bucket.
- Enable website hosting and make the Index Document index.html.
In the root of the repo upload resources/public/*
into www.contactuslambda.com
with:
aws s3 sync ./resources/public/ s3://www.contactuslambda.com --acl=public-read
To test the contact us email sending we must use the test data in resources/test/input/sample_contact_data.json
.
To invoke the function we run:
aws lambda invoke \
--invocation-type RequestResponse \
--function-name contact-us-lambda-demo \
--payload 'file://./resources/test/input/sample_contact_data.json' \
resources/test/output/contact_output.json
On your local machine execute:
curl -X POST -v -d 'name=EPX+Labs&email=hello%40epxlabs.com&phone=1234567890&message=Look+Ma%21+No+servers%21' https://{API GATEWAY DOMAIN}/prod/contact-us --header "Content-Type:application/x-www-form-urlencoded; charset=UTF-8"
Visit https://{S3 Bucket URL}
to see the Contact Us form. Fill out and send!
Don't forget to run lein uberjar
before deploying!
To deploy new code run:
aws lambda update-function-code \
--function-name contact-us-lambda-demo \
--zip-file 'fileb://./target/contact-us-lambda-demo-0.1.0-SNAPSHOT-standalone.jar'
To update configuration as opposed to code run:
aws lambda update-function-configuration \
--function-name contact-us-lambda-demo \
--memory 1024 \
--timeout 20