Build a Serverless Contact Form for your Stunning AWS S3 Static Website using Lambda, API Gateway, and SES in 2020.

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.
Contact Form Step 1

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.

Contact Form Step 2

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 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: [
        Message: {
            Body: {
                Text: {
                    Data: 'name: ' + + '\nphone: ' + + '\nemail: ' + + '\ndesc: ' + event.desc,
                    Charset: 'UTF-8'
            Subject: {
                Data: 'ADD A SUBJECT 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:

Contact Form Step 3

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.
Contact Form Step 4

19 thoughts on “Build a Serverless Contact Form for your Stunning AWS S3 Static Website using Lambda, API Gateway, and SES in 2020.”

  1. 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?

    1. 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.

    1. 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.

  2. 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.

    1. 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!

  3. 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:

    If you’re working with Cloudfront, your website will no longer load, but if you go to, 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.

  4. Stephane Bouclier

    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

    1. 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%;”>

  1. Hi Steven, thank you for your reply.

    I am using the V2 Checkbox reCAPTCHA.

    Does your JavaScript code verify the reCaptcha? I believe that I need to submit the response, along with my site key and secret key, to Google’s servers in order to determine if the Captcha was successfully answered.

    1. Hello Stephane,

      I apologize for not getting back to you faster.

      You know what! I think I know what it is. It just came to me. Add this code at the very top of your HTML code. I have it under the title and above the style portion of your code:
      script src=”” async defer>

  2. Hi Steven,

    Thank you for your reply.

    Not sure if you got my previous message.

    Yes I made sure my reCaptcha was coded properly in the HTML part.
    Does the code you submitted includes reCaptcha validation on the server side?

    Regards, Stephane

  • Leave a Comment

    Your email address will not be published. Required fields are marked *