How to add Dynamic Contact Forms for S3 Static Websites Using AWS Lambda, API Gateway & Amazon SES – A step-by-step guide!

I have a static website thecloudadvisory. This website is designed in HTML, JavaScript & CSS, so it’s completely a static website. Due to its static nature, I have deployed this application in Amazon S3 and used the host static website feature, costing me nearly zero cents.

Off lately, I realized it’s good to have a contact page on the website to collect queries from customers/website visitors. 

A problem with adding server-side logic to static websites.

There are many ways to publish a static website for free. You can use free hosting like Github Pages, Firebase, Cloudflare etc. 

Do you know what static means?  

A static website only uses HTML, CSS and JavaScript. It doesn’t have server-side logic like PHP, Java etc. Static websites can’t generate dynamic content. So you can’t save information to a database or send an e-mail.

Now, the biggest problem with the static website to deploy on the server is that it does not make sense to have a server running all the time when you don’t know when a user will contact you.

As you understand serverless, these architectures are useful when you want to add server-side logic to static websites and allow you to run the server-side scripts only when you need them.

For example, AWS Lambda only charges you based on the number of requests for your function and the time your code executes. So you’re not charged while waiting for visitors to contact you.

So I have decided to develop this website further and add a contact form with AWS Lambda(Serverless Architecture).

Following is the architecture flow with detailed guidance.

In the above diagram, the visitor/customer submits an inquiry through a “contact us” form that is hosted in an Amazon Simple Storage (S3) Service bucket as a static website. Information will flow in three simple steps:

  1. The user will fill in and submit details in the “Contact us” form. Once the user submits the form, it will post the collected information to Amazon API Gateway Restful service.
  1. Then, the Amazon API Gateway service will pass collected user information to an AWS lambda function. You can use any supported programming language like Node.js, C#, Java and Python.
  1. AWS Lambda function will extract all information, auto-generate an email and forward it to your e-mail server using Amazon SES.

Your “Contact Us” Form

Let’s start with a simple “contact us” form html code snippet:

<!DOCTYPE html>



<title>Pravin Mishra</title>



<h1>Serverless Webinar: Pravin Mishra</h1>


<form action=”” method=”post”>

<div class=”section-title”>

<h2>Contact us <small>we love conversations. Let us talk!</small></h2>



<input type=”text” id=”name-input” placeholder=”Enter full name” name=”name” required=””>


<input type=”email” id=”email-input” placeholder=”Enter email address” name=”email” required=””>


<textarea id=”message-input” rows=”6″ placeholder=”Tell us about your message” name=”message” required=””></textarea>




<input type=”submit” onClick=”submitToAPI(event)” name=”send message” value=”Send Message”>






The above form will ask the user to enter their name, email-id and provide a message in the text box and a submit button.

Setup Amazon SES

As we know, Lambda functions can send emails, so we need to set up AWS SES. 

Amazon SES requires you to verify your identities (the domains or email addresses you use to send emails) to confirm that you own them and prevent unauthorized use. 

Follow the steps outlined in the Amazon SES user guide to verify your sender’s email.

Go to the Amazon SES dashboard and click on “Create Identity.” 

Make sure to select “Email” and enter your email-id from which you want to send the e-mail, and click on “Create Identity”.

Now, your screen will be redirected to the SES dashboard, and you need to open your e-mail and verify that it belongs to you. 

Once you verify. Refresh the Amazon SES dashboard and you will status will changed to “Verified” 

Create Lambda Execution Role.

Now, we need to create a Lambda execution role. That Lambda will get permission to access the Amazon SES service. 

  1. Let’s go to the IAM dashboard, select policy from the right panel and click “Create Policy.”
  1. Select JSON on the create policy page. Click next: Tag,  then next: Review


    “Version”: “2012-10-17”,

    “Statement”: [


            “Sid”: “PravinMishra”,

            “Effect”: “Allow”,

            “Action”: “ses:SendEmail”,

            “Resource”: “*”




  1. Enter the policy name and “Create Policy”.
  1. Now let’s create the role.  Select a role from the right panel and click on “create role.”
  1. On the Select trusted entity screen, select Lambda and click on “next.”
  1. Select the policy you created earlier and click Next. 
  1. Enter the role name and click on “create role”. Remember this role as we will use it in the next step while creating the Lambda function. 

Defining AWS Lambda Function

Now, we will create the lambda function. This lambda function will get all the user information through API Gateway. 

  1. Let’s go to the Lambda function dashboard and click on “Create Function.”
  1. Give a meaningful name to the lambda function. Then click on “Change default execution role”. Select “Use existing role” and from drop down select the role which we created in the last step. Then click “Create function”
  1. Now, paste the below code inside the lambda_function and click deploy

var aws = require(“aws-sdk”);

var ses = new aws.SES({ region: “us-east-1” });

var RECEIVER = “”;

var SENDER = “”;

var response = {

 “statusCode”: 200,

 “headers”: { 

 “Content-Type”: “application/json”,”Access-Control-Allow-Origin”: “*”


“isBase64Encoded”: false,

 “body”: “{ \”result\”: \”Success\”\n}”


exports.handler = async function (event, context) {

    console.log(‘Received event:’, event);

    console.log(‘In sendMail’);

    var params = {

        Destination: {

            ToAddresses: [




        Message: {

            Body: {

                Text: {

                    Data: ‘Full Name: ‘ + + ‘\nPhone: ‘ + + ‘\nEmail: ‘ + + ‘\nMessage: ‘ + event.message,

                    Charset: ‘UTF-8’



            Subject: {

                Data: ‘Website Query Form: ‘ +,

                Charset: ‘UTF-8’



        Source: SENDER,


   return ses.sendEmail(params).promise();


Creating the API Gateway

Now, let’s create an API endpoint that will be configured inside the HTML page. This API will also trigger the Lambda function that we will create next. 

  1. Log in to the AWS console and select the API Gateway service. Go to the REST API and click on build
  1. Select a new API, fill in your API name and click on “Create API.”
  1. Now the API is selected by default. Otherwise, you can also select this API from the dashboard. Now click on the “Actions” drop-down, and select “create resource.”
  1. Fill in the Resource Name. The path will be filled automatically for you, and click “Create Resource”. 
  1. Select your newly-created resource and choose “create method.” Choose a POST. 
  1. Here, you will choose our AWS Lambda Function. Search for the Lambda Function created earlier “contact” from the drop-down (Lambda Function) and save. 
  1. You will get the message “Add the permission”. Click OK.
  1. After saving the form above, Click on the “action” menu and choose “deploy API.” Give the stage name “prod”, description and click on “Deploy”. 
  1. Now get your Restful API URL from the “prod” tab, as shown in the screenshot below. We will use this URL on our “contact us” HTML page to send the request with all user information.
  1. Make sure to Enable CORS in the API Gateway, or you’ll get an error:”Cross-Origin Request Blocked: 
  2. Select the resources, go to Action and click on “Enable CORS
  1. Change the “Access-Control-Allow-Origin” to your website name. I will leave it to “*” as its’ demo.

Connecting it all Together

Since we created our AWS Lambda function and provided the API-endpoint access using the API gateway, it’s time to connect all the pieces together and test them. Put the following JQuery code in your ContactUs HTML page <head> section. Replace the URL variable with your API Gateway URL. You can change field validation as per your need.

<script language=”JavaScript” type=”text/javascript” src=”” ></script>


function submitToAPI(e) {


            var URL = “”;

            var name = $(“#name-input”).val();

            var email = $(“#email-input”).val();

            var message = $(“#message-input”).val();

            var data = {

               name : name,

               email : email,

               message : message



              type: “POST”,

              url : “”,

              dataType: “json”,

              crossDomain: “true”,

              contentType: “application/json; charset=utf-8”,

              data: JSON.stringify(data),

              success: function () {

                // clear form and show a success message

                alert(“Thanks for contacting us, we will get back to you soon”);




              error: function () {

                // show an error message





Now you should be able to submit your contact form and receive email notifications when a form is completed and submitted.


This article aims to address a common use case for any individual or small business that hosts its website on Amazon S3. You can make your static website more dynamic without spinning up any servers with the help of this post.

Stay tuned for more such AWS hands-on technical blogs!

2 thoughts on “How to add Dynamic Contact Forms for S3 Static Websites Using AWS Lambda, API Gateway & Amazon SES – A step-by-step guide!”

  1. Pingback: How to add AWS Dynamodb database to a static website hosted in Amazon S3? – A step-by-step guide! - Pravin Mishra - AWS Mentor & Trainer

  2. Pingback: Pravin Mishra - AWS Mentor & Trainer

Leave a Comment

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