Skip to content

mucadoo/sns-email-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

9 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“¬ Contact Form Email Service

A serverless contact form backend built on AWS β€” Lambda, SNS, and API Gateway β€” provisioned with Terraform and deployed automatically via GitHub Actions.


Architecture Overview

Client (HTML Form)
      β”‚
      β–Ό POST /send-email
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   API Gateway (HTTP) β”‚  ← throttled: 10 req/s, burst 5
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚ AWS_PROXY
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Lambda Function    β”‚  ← Node.js 22.x
β”‚   (send-email)       β”‚  validates + sanitizes input
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚ sns:Publish
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     SNS Topic        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚ email subscription
          β–Ό
    πŸ“§ Your Inbox

Project Structure

.
β”œβ”€β”€ .github/
β”‚   └── workflows/
β”‚       └── deploy.yml          # CI/CD pipeline
β”œβ”€β”€ send-email/
β”‚   β”œβ”€β”€ index.js                # Lambda handler
β”‚   β”œβ”€β”€ package.json
β”‚   └── package-lock.json
└── terraform/
    β”œβ”€β”€ main.tf                 # All AWS resources
    β”œβ”€β”€ variables.tf
    └── outputs.tf

Features

  • Input validation β€” email format, name/subject (1–100 chars), message (1–1000 chars)
  • Input sanitization β€” all fields HTML-escaped before publishing
  • CORS configured β€” API Gateway accepts cross-origin requests
  • Rate limiting β€” 10 requests/second, burst of 5
  • CloudWatch logging β€” 14-day log retention for the Lambda
  • Automated deploys β€” push to main β†’ build β†’ plan β†’ apply

Prerequisites

  • AWS account with programmatic access
  • Terraform β‰₯ 1.5.0
  • Node.js 22.x
  • GitHub repository with Actions enabled

Setup

1. Configure GitHub Secrets

In your repository go to Settings β†’ Secrets and variables β†’ Actions and add:

Secret Description
AWS_ACCESS_KEY_ID IAM user access key
AWS_SECRET_ACCESS_KEY IAM user secret key

The IAM user needs permissions for Lambda, SNS, IAM, API Gateway, CloudWatch, and S3 (for Terraform state if remote).

2. Set the recipient email

The notification email defaults to samuelgiordano@live.com. To change it, edit terraform/variables.tf:

variable "email_endpoint" {
  default = "your@email.com"
}

Or pass it at apply time:

terraform apply -var="email_endpoint=your@email.com"

3. Confirm the SNS subscription

After the first deploy, AWS sends a confirmation email to the configured address. You must click the confirmation link before any notifications will be delivered.


Deployment

Automatic (recommended)

Push to main and the GitHub Actions workflow handles everything:

  1. Installs Lambda dependencies
  2. Zips the function code
  3. Configures AWS credentials
  4. Runs terraform init β†’ plan β†’ apply

Manual

# Install Lambda dependencies and zip
cd send-email
npm install
zip -r ../terraform/lambda_function_payload.zip .

# Provision infrastructure
cd ../terraform
terraform init
terraform plan
terraform apply

API Reference

POST /send-email

Endpoint: {api_endpoint}/prod/send-email

The API Gateway URL is printed as a Terraform output after deployment:

terraform output api_endpoint

Request body:

{
  "name":    "Jane Doe",
  "email":   "jane@example.com",
  "subject": "Hello there",
  "message": "Your message here."
}

Validation rules:

Field Rules
email Must be a valid email address
name 1–100 characters
subject 1–100 characters
message 1–1000 characters

Responses:

Status Body Meaning
200 "Email sent successfully!" Message published to SNS
500 "Internal server error" Validation failed or AWS error

Example request:

curl -X POST https://{api-id}.execute-api.us-east-1.amazonaws.com/prod/send-email \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Jane Doe",
    "email": "jane@example.com",
    "subject": "Hello",
    "message": "Reaching out from your site."
  }'

Infrastructure Details

All resources are defined in terraform/main.tf.

Resource Name Notes
SNS Topic email-notifications Fan-out to email
SNS Subscription β€” Email protocol
IAM Role email-lambda-role Least-privilege
Lambda send-email-function Node.js 22.x
CloudWatch Log Group /aws/lambda/send-email-function 14-day retention
API Gateway EmailAPI HTTP API (v2)
API Stage prod Auto-deploy enabled

Terraform outputs:

terraform output api_endpoint   # API Gateway base URL
terraform output sns_topic_arn  # SNS topic ARN

Local Development

cd send-email
npm install

# Test the handler locally with a mock event
node -e "
const handler = require('./index');
handler.handler({
  body: JSON.stringify({
    name: 'Test',
    email: 'test@example.com',
    subject: 'Hello',
    message: 'Testing locally'
  })
}).then(console.log);
"

Note: Local runs will fail at the SNS publish step unless SNS_TOPIC_ARN is set and valid AWS credentials are available in the environment.


Security Notes

  • All user input is validated with the validator library before processing
  • All fields are HTML-escaped via validator.escape() before being included in the SNS message
  • The Lambda IAM role follows least privilege β€” it can only publish to its own SNS topic and write CloudWatch logs
  • CORS is currently set to allow_origins = ["*"]; restrict this to your domain in production
  • Consider adding an API key or WAF in front of API Gateway for production workloads

Dependencies

Package Version Purpose
aws-sdk ^2.1692.0 AWS service client (SNS)
validator ^13.12.0 Input validation & sanitization

License

MIT

About

πŸ“¬ Serverless contact form backend using AWS Lambda, SNS, and API Gateway. Provisioned with Terraform and fully automated via GitHub Actions. Node.js 22.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors