Search code examples
amazon-web-servicesemail-verification

Implementing an email database from a website form


I want visitors of my website to be able to provide their email address in a form to get future company updates. Once they submit the form an email would be sent to their address with a link to click on, say www.mywebsite.com/<token>. Upon visiting that link their email would be validated and become part of the database I would use to send updates.

I have in mind deploying my website using AWS S3 together with AWS CloudFront and AWS Certificate Manager. For the implementation of the email verification process: a Lambda function would be triggered through API Gateway when a user submits the form, the token would be generated in that function, and an email would be sent to the visitor with a call to AWS SES.

I'm having issue understanding within that framework how I can create dynamically and serve URLs of the form www.mywebsite.com/<token>. I can see that with a server up and running in the backend, this could be achieved with something along the lines of

const express = require('express')
const app = express()

app.get('/verify-email/:token', async (req, res) => {
  const token = req.params.token;
  // check token
  // if match, validate email, add to database, and render page
  // if no match, redirect
});

How can I create and serve these URLs within the S3 framework I detailed above?

Do I need otherwise to change the implementation and run instead an EC2 server or use another AWS service?


Solution

  • You're on the right track. API Gateway/Lambda is perfect for this. It's not clear what you mean by "How can I create and serve these URLs within the S3 framework I detailed above?" since you mentioned creating these in the gateway but I assume you refer to what happens once the user clicks the link in their email.

    You can either create a GET route in the API gateway - this route will need to be publicly accessible (no auth). The Lambda can verify token (use JWT tokens for this as they are made for just this) and then send a redirect to say a thank you page on your S3 site.

    Alternatively you can have the S3 site handle that token route, then have it make a call to the server to process and return a success/fail. This would work well for example with a React site.

    In order to handle the <token> route on front end you would either use some of the built-in utilities your framework would have (for example if you used NextJS then useParams()) or use JS/JQuery to parse the path. You will only have a single page - i.e. index.html - that will handle all of this. This is defined in your S3 config. Meaning no matter what URL you type (domain.com, domain.com/sometoken , domain.com/contact, etc) the index.html will render and it's up to JS (native, JQuery, React) to parse the path and determine what to do next. If you intend to have other pages such as contact then Id recommend using something like /auth/<token> in order to help differentiate token URLS from the other pages.

    On a side note, you can have a single Lambda on API gateway run an Express app using some libs such as this for NodeJS.

    On an additional side note, Lambdas have Function URLs which can be useful - they do not provide auth/throttling etc that the gateway does nor can you change the domain/URL but would work well for the 2nd scenario.