Scheduled PostgreSQL backups using AWS Lambda, S3 and EventBridge
AWS Lambda at its core, is a serverless compute platform where developers can write small, independent and often single-purpose applications without …
Implementing contact forms in popular Content Management Systems (CMS) like Wordpress is a breeze, you download a form plugin, setup your SMTP and you’re done. Wordpress and Wix are nice and gets the job done, but I’m not really a fan of server-based CMSes or anything that requires you to natively run it in a VPS/VM. It’s expensive and it’s slow (fight me!).
There are tons of headless form API services out there like formspree.io and cognito forms, but that’s 8 and 15 dollars a month respectively, to provide a contact form for a landing page that nobody’s ever going to read anyway (hopefully somebody does but well..). I’m cheap and a basic plan for Netflix in the Philippines is a little short of 5 dollars, so Netflix wins over formspree.
This leads me to creating my own contact form with my favorite AWS service - AWS Lambda. We will be implementing the architecture below:
Note
Prerequisites:
Now, before everything else, we have to remember that we are exposing an auth-less public service that is not in anyway excused from spam and abuse. Spam requests to our Lambda function may potentially cost us money from useless/fraudulent invocations, furthermore we will be utilizing another service - Amazon SES which is a separate cost concern.
We can protect our form by utilizing CAPTCHAs - which act as cushion from service abuse by providing challenges to differentiate bots/automated scripts from legitimate humans (or aliens) trying to make first contact.
To do this, We’ll head over to Google reCAPTCHA (note that this is a free service - i like free stuff) and register our site. I used reCAPTCHAv2 which uses challenge-based validation, rather than the score-based v3. For comparison check out this link.
Then we need to grab our site key and secret key and note it somewhere, as we will use this for our static html form and Lambda function later on.
Previously, you would only be able to execute AWS Lambda through event sources like SNS and EventBridge. Exposing Lambda as an HTTP/S endpoint typically would require you to set it up behind an Application Load Balancer (which slaps you with a 20 USD/month minimum) or API Gateway which tops you with unnecessary additional complexity. However, in early 2022 last year, AWS released Function URLs - which allow you to expose HTTPS endpoints for Lambda functions.
We’ll create a Lambda function from the prepared code above, but we need to specify in the Advanced Settings section that we want to use function URLs.
This will give us an AWS-generated public endpoint by which we can invoke our function.
Before we deploy our Lambda application, we need to populate some required values in here first. You may ought to use environment variables if you want, but for simplicity I put the values directly inside my application:
6 const toAddress = '<--recipient-address-->';
7 const fromAddress = '<--sender-address-->';
8 const secret_key = '<--reCAPTCHAv2 secret key-->';
9 const region = '<--region-->';
toAddress
- where we want to send notifications to, can be your verified identity / personal gmail accountfromAddress
- what identity will SES use to send the email in behalf ofsecret_key
- the reCAPTCHAv2 secret keyregion
- AWS region where Lambda and SES residesInfo
Note that we cannot just simply send an email via SES to anyone while in sandbox mode. We are only allowed to send mails to verified identities that we own. To send outgoing mails for production, AWS requires you to move out and get production access .
We’ll do npm install
and zip up our lambda application, or simply run sh build.sh
to automatically package the whole thing.
After uploading our code and creating a deployment, we’ll then need to configure a few things in the function URL settings:
Allow origin
- we need to set this to our domain or ‘*’ if we want to test it anywhereAllow headers
- not really required, but I allowed content-type here so I can choose to use application/json content type when passing the payloadAllowed methods
- we set this simply to POSTNow we just need to note the actual function URL, as we will put this later as an action in the static form.
I prepared a sample contact form below. By default, the form accepts a name, email address and a message, you can customize it and modify the Lambda function to accept more fields. I plugged TailwindCSS as well to give it a look.
We need to replace a few values in the form.
<--action--url-->
- the generated lambda function URL<--reCAPTCHA v2 site key-->
- registered google reCAPTCHAv2 site key we noted earlierAfter that we just need to deploy our contact form somewhere in our static site and voila! We’ve successfully implemented a serverless contact form.
So I tried sending myself an email from Ellie in the Last of Us (great series btw.).
I used a verified identity domain type (reiland.dev) and one of my Protonmail aliases as a recipient.
- Created a reCAPTCHA enabled static contact form
- Deployed a Lambda function to verify the reCAPTCHA and handle form data
- Automated email notifications through Amazon SES invoked from Lambda
- It’s serverless again, no bill, no idle charges
AWS Lambda at its core, is a serverless compute platform where developers can write small, independent and often single-purpose applications without …
Here is a stock photo of Octocat and Groot I found, cause GitHub and S3 (S-Tree, get it? no? okay). S3 stands for Simple Storage Service, as its name …