📨 Contact form on a static page with Amazon Lambda Function
If you are here, then I assume that you probably don’t know PHP nor Wordpress, and so you decided to build a static web page or use some static page generator like Jekyll, Grav or GatsbyJS. Right now your obvious option to provide ability to create a contact from is using a formspree.io or something similar. I’m going to show you how to write your own contact form ‘backend’ in very short time.
Please remember that this is not a step-by-step tutorial, I’m describing overall architecture with code (copy-paste ready certification). If you have any remarks, then let me know or create a Github issue. 😉
Requirements
- minimal knowledge about Amazon Web Services
- basic JavaScript skills
Used technologies
Build environment
If you are familiar with used technologies the diagram should be pretty straightforward for you.
Static web page should be gathering data from contact form, validate and send them using XHR Fetch, jQuery or in
other way to API Gateway by POST method. API Gateway will invoke Lambda function, and the Lambda function will invoke
our JavaScript code where we parse POST request, do some custom logic and call sendEmail(...)
on SES service.
0. Verify your e-mail address
SES e-mail address verification can be done here (eu-west-1)
1. Lambda Function
We will start with creating AWS Lambda function and choosing a NodeJS 8.1 environment.
The full code can be found on GitHub Gist
import aws-sdk
Once we have prepared environment, then we can start to implement the function. A first important thing is that we need to import aws-sdk
to use SES and other Amazon services.
AWS Lambda responses
Success and error responses. This part is more important than you think. If we return wrong JSON from lambda function to API Gateway, the client (contact form in this case) will get HTTP 500 status. Code will be invoked and email sent anyway, but it’s just a good practise to follow the documentation and just don’t return 500 status codes intentionally.
Check is domain allowed
By using this function we can easily turn on and off e-mail sending from certain domains.
E-mail message
This is a true strength of this solution. We are passing whole Javascript object from contact form to e-mail formatted
with <pre></pre>
tags and JSON.stringify
.
Send e-mail with SES service
The most important part of this function is of course sending email by SES. Let’s create a JSON params object with a message, subject and all other SES options which can be found here.
Now we can deploy our function and move to the API Gateway.
2. Set up API Gateway
Setting up API Gateway for Lambda functions, should be straightforward. There is no need to code anything, just click-and-play configuration.
In this case I set up my endpoint to receive any HTTP method. For working contact form you will need only http/post
method.
Things to remember
- Every time we change something on endpoint configuration we need deploy API again to see changes. Use:
Actions -> Deploy API
- Remember about setting up CORS while using API Gateway. Use:
Actions -> Enable CORS
3. Contact form example
HTML form
JavaScript to submit the form
Conclusion
We can scale this technique to multiple web pages with ease, but this solution in current form has few downsides. For now the only one protection against DDoS or some similar attack is rate limiter included in Lambda function. Right now there is no bot protection, no captcha or something like that. We can add Google re-captcha on the contact form and setup rate limiting on both API Gateway and Lambda function, to avoid unnecessary costs.
Update 2021-02-23
So far I didn’t have any issues with this solution. I’ve never received any SPAM or message from a bot. 😄