Having a contact form is essential in making sure your potential new clients can get in contact with you fast and easy. Having a “Contact Us” form on your static S3 website is necessary; programming it on the frontend is easy, but for the backend? Now that’s a bit complicated. In this example, I will show you how to set up your S3 state website with a contact form.
With your S3 static website already up and running and your contact form already created, we first want to start with our Lambda function.
- Make sure your S3 bucket and Lambda function are in the same region.
- Click on Create function.
- Click on Use a blueprint.
- Type in hello in the search bar.
- Select the first option: hello-world using nodejs.
- Click on Configure on the bottom right.

Under Basic Information type in a function name you would like to use and select Create a new role with basic Lambda permissions, we’re going to modify that later. Click on Create function.

On the following screen, go ahead and copy and paste this function into your Function Code:
var AWS = require('aws-sdk'); var ses = new AWS.SES(); var RECEIVER = 'ADD YOUR EMAIL'; var SENDER = 'ADD YOUR EMAIL'; var response = { "isBase64Encoded": false, "headers": { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'}, "statusCode": 200, "body": "{\"result\": \"Success.\"}" }; exports.handler = function (event, context) { console.log('Received event:', event); sendEmail(event, function (err, data) { context.done(err, null); }); }; function sendEmail (event, done) { var params = { Destination: { ToAddresses: [ RECEIVER ] }, Message: { Body: { Text: { Data: 'name: ' + event.name + '\nphone: ' + event.phone + '\nemail: ' + event.email + '\ndesc: ' + event.desc, Charset: 'UTF-8' } }, Subject: { Data: 'ADD A SUBJECT NAME: ' + event.name, Charset: 'UTF-8' } }, Source: SENDER }; ses.sendEmail(params, done); }
When copying and pasting the format, it should automatically set itself up, but just in case this is how it should look like:

On lines 3 and 4, insert the email addresses you want to use for sending and receiving inquiries from your contact form, you can add the same email, it doesn’t matter. Also, on line 32, add a subject you would like to use when receiving emails. Save the function, but before testing it, we must do a couple of things beforehand:
Head to the SES Management Console:
- Click on Email Addresses.
- Click on Verify a New Email Address.
- Type in the email address you would like to use to receive the inquiries.
- You should receive an email from AWS asking you to verify the email; please do so.
- The status should say verified after a few minutes.

The emails come through, but all of the form data comes through as “undefined”. I can see the data is there when the form posts it via Chrome dev tools. Any ideas?
Hello Tom,
Thank you for reaching out. In my experience, when I do a test message via Lambda, I get the “undefined” that you mentioned. I honestly think that when you’re trying to do this on your website, it’s not going through, because you should be getting information like name, phone, etc. So, what I mean is that the message you’re getting with the “undefined” is from Lambda.
I’m not sure if you followed my blog, but if you did and when you submit the message, you should be getting a Thank you message IF it goes through. Please let me know if you did or not, and we can go from there.
Could you put up the complete html including header?
Hello Chris,
Thank you for the inquiry, but, no, there’s no reason for me to put up the entire HTML. All you need is the Header info, which I posted and the Contact Us info. If you follow the blog step by step ( I know it’s long), you will get it done. The rest of the body has absolutely nothing to do with the Contact Us form working. Please feel free to ask any other questions.
Nothing happens when I click on submit
Hello Ayush,
Please send me an email with your header and the contact form code to: steven.b.umana@gmail.com
That’s all I need I want to see what’s going on and try to help you out.
Thanks!
Steven
Can’t thank you enough. I spent almost 2 days to make this serverless contact us form by searching through 20-30 articles & videos & your this article helped me. Thank you so much. I’ll be adding this post link as a reference in my website. Please never remove this post.
Hello Aditya,
I’m so happy that my post helped you!
Yes, please add it and if you ever need anything else, please let me know and I’ll be more than happy to help.
I promise I won’t remove it!
Thanks again!
Hi, I tried to submit the form, but nothing happens. I followed your instructions throughout :/
Hello Rishi,
I apologize for the late response, I thought I had responded. Let me look into this and I’ll get back to you.
Hello everyone,
I just wanted to update everyone, newcomers, and old that I updated this blog, and I emailed everyone that has posted saying they still can’t get this to work. I found the fix, and here it is:
1) Recreate your API Gateway, make sure it’s a new one, and correct it without the S3 bucket endpoint, leave the Asterix in there. Then add that to your code, make sure to update it, and upload it to your S3 bucket.
I’m talking about this step:
Click on Actions.
Click on Enable CORS.
Leave the top 4 options as is, and for Access-Control-Allow-Origin*, leave it with the Astrix, leave it as is. IMPORTANT!
Click on Enable CORS and replace existing CORS headers.
Once that is done, click on Actions.
Click on Deploy API.
In the new window that appears under Deployment State, select [New Stage].
I usually use prod for Stage Name.
Then click on Deploy.
We will be sent to the Stages tab automatically.
Click on POST, and on the right side of your screen, you will see your Invoke URL. Please keep that in a secure place to get to; we’re going to need that soon.
2) Go to Route53 and create an A Record, pointing towards the S3 bucket where your website is located in:
image.png
If you’re working with Cloudfront, your website will no longer load, but if you go to http://yourwebsite.com, it will load. The reason why your website is not popping up is that you’re trying to reach https:// remove the s, and you should see your website.
3) To put your Cloudfront distribution back and make your website secure, go to Route53, and create an AAAA record with it.
4) Flush your cache from CloudFront; if you don’t know how to do that, let me know, and I can help you.
5) Refresh your page and try again; it should work.
If you followed my blog post step by step, it would work.
Hi Steven,
Thank you very much for your tutorial.
It works well but only if I remove the reCaptcha line in the HTML form. I have tried with both a ‘checkbox’ ReCaptcha key and an ‘invisible’ ReCaptcha key.
Any ideas?
Also the incoming messages in my gmail box are flagged with a spam warning.
Kind regards, Stephane
Hello Stephane,
Thank you for your kind comment!
I will respond to you here and to your email as well.
What version of reCAPTCHA do you have? I’m using the V2. I only use V2 “I’m not a robot” Checkbox. Both of my sites work perfectly fine with it. IF you are using that one, make sure it’s coded correctly:
div class=”g-recaptcha” data-sitekey=”xxxxxxxxxxxxxxxxxxxxxxxxxxxx” class=”form-control” style=”width:100%;”>