Skip to content

lpenap/aws-ses-lambda

Repository files navigation

AWS SES Email Forwarder

Forwards inbound emails received by any AWS SES verified domain to any destination address. It can also handle emails from multiple domains.

Architecture: SES → S3 (stores raw email) → Lambda → SES (forward)

First time? See SETUP.md for a complete step-by-step installation guide.


Repository structure

aws-ses-lambda/
├── src/
│   ├── lambda_function.py        # Lambda handler
│   └── requirements.txt          # empty — boto3 is pre-installed in Lambda
├── tests/
│   ├── conftest.py               # shared fixtures
│   └── test_lambda_function.py   # unit tests (mocked boto3, no real AWS calls)
├── template.yaml                 # AWS SAM template
├── samconfig.toml.example        # SAM deploy config template
├── .env.example                  # env var reference
├── .gitignore
├── requirements-dev.txt          # pytest, boto3 for local dev
├── SETUP.md                      # step-by-step installation guide
└── AGENTS.md                     # instructions for AI agents

Configuration

All configuration is via environment variables set as CloudFormation parameters in samconfig.toml.

Variable Required Default Description
EMAIL_BUCKET yes S3 bucket where SES stores raw inbound emails
EMAIL_KEY_PREFIX no "" S3 key prefix, e.g. email/ (include trailing slash)
FORWARD_MAPPING yes JSON: {"addr@domain.com": ["dest@gmail.com"]}
FROM_EMAIL no "" Verified SES sender address; falls back to original recipient if blank
SUBJECT_PREFIX no "" String prepended to the Subject header
ALLOW_PLUS_SIGN no false Strip +tag from recipient before mapping lookup

FORWARD_MAPPING lookup precedence

For each inbound recipient address, the mapping is checked in this order:

  1. Exact match"you@domain.com": [...]
  2. Domain match"@domain.com": [...]
  3. User match"you": [...] (matches you@ on any domain)
  4. Catch-all"@": [...]

Example:

{
  "you@example.com":   ["you@gmail.com"],
  "bob@example.com":   ["bob@gmail.com"],
  "@example.com":      ["fallback@gmail.com"],
  "@":                 ["admin@gmail.com"]
}

Local development

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txt
pytest tests/ -v

All 24 unit tests run with mocked boto3 — no AWS credentials required.


How it works

  1. SES receives an inbound email and stores the raw message to S3
  2. SES triggers the Lambda with an event containing the message ID and recipient list
  3. Lambda looks up each recipient in FORWARD_MAPPING
  4. If a match is found, Lambda downloads the raw email from S3 and rewrites the headers:
    • Adds Reply-To from From (if absent)
    • Replaces From with the verified sender, preserving the original display name
    • Optionally prepends SUBJECT_PREFIX to the subject
    • Removes Return-Path, Sender, Message-ID, and DKIM-Signature
  5. Lambda sends the rewritten email via SES SendRawEmail to the destination(s)

About

Lambda function to forwards inbound emails received by AWS SES to any destination address.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages