elmeg-demo/docs/AWS_SES_SETUP.md
fullsizemalt 9af0bc4b96 refactor: Switch from SendGrid to AWS SES for email
- Replace httpx/SendGrid with boto3/SES
- Add boto3 to requirements.txt
- Create AWS_SES_SETUP.md documentation
- Remove SendGrid setup doc
2025-12-21 13:42:07 -08:00

3.3 KiB

AWS SES Email Setup

Overview

The Elmeg platform uses AWS SES (Simple Email Service) for sending transactional emails (verification, password reset). Cost: ~$0.10 per 1,000 emails.


Prerequisites

  • AWS Account
  • Domain: elmeg.xyz (for verified sender)
  • Production server: tangible-aacorn / nexus-vector

Setup Steps

1. Verify Email Domain in SES

  1. Go to AWS Console → SES → Verified Identities
  2. Click "Create identity" → Choose "Domain"
  3. Enter: elmeg.xyz
  4. Enable "Use a custom MAIL FROM domain" (optional)
  5. Add the provided DNS records to your domain

Required DNS Records (example):

Type: TXT
Name: _amazonses.elmeg.xyz
Value: [provided by AWS]

Type: CNAME  
Name: [dkim1]._domainkey.elmeg.xyz
Value: [provided by AWS]

2. Move Out of SES Sandbox

By default, SES is in sandbox mode (can only send to verified emails).

  1. Go to SES → Account dashboard
  2. Click "Request production access"
  3. Fill out:
    • Mail type: Transactional
    • Website URL: https://elmeg.runfoo.run
    • Use case: User registration verification, password reset
  4. Wait for approval (usually 24hrs)

3. Create IAM User for SES

  1. Go to IAM → Users → Create user
  2. Name: elmeg-ses-sender
  3. Attach policy: AmazonSESFullAccess (or create custom with ses:SendEmail only)
  4. Create access key for "Application running outside AWS"
  5. Save:
    • Access Key ID
    • Secret Access Key

4. Configure Production Server

SSH into server and update environment:

ssh root@tangible-aacorn
cd /srv/containers/elmeg-demo

Edit docker-compose.yml, add to backend service:

backend:
  environment:
    - DATABASE_URL=postgresql://elmeg:elmeg@db:5432/elmeg
    - AWS_ACCESS_KEY_ID=AKIA...
    - AWS_SECRET_ACCESS_KEY=...
    - AWS_SES_REGION=us-east-1
    - EMAIL_FROM=noreply@elmeg.xyz
    - FRONTEND_URL=https://elmeg.runfoo.run

Or create .env file:

AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_SES_REGION=us-east-1
EMAIL_FROM=noreply@elmeg.xyz
FRONTEND_URL=https://elmeg.runfoo.run

5. Add boto3 to Requirements

# Add to backend/requirements.txt
boto3>=1.28.0

6. Run Migration & Restart

docker compose build backend
docker compose exec backend python migrations/add_email_verification.py
docker compose restart backend

7. Test

  1. Register at https://elmeg.runfoo.run/register
  2. Check for verification email
  3. Test forgot password at https://elmeg.runfoo.run/forgot-password

Environment Variables

Variable Description Example
AWS_ACCESS_KEY_ID IAM user access key AKIA...
AWS_SECRET_ACCESS_KEY IAM user secret wJalr...
AWS_SES_REGION SES region us-east-1
EMAIL_FROM Verified sender address noreply@elmeg.xyz
FRONTEND_URL Base URL for links https://elmeg.runfoo.run

Cost

  • $0.10 per 1,000 emails
  • No monthly minimum
  • First 62,000 emails/month free if sending from EC2

Troubleshooting

Issue Solution
"Email address is not verified" Domain not verified in SES, or still in sandbox
"Access Denied" Check IAM permissions for ses:SendEmail
Emails not sending Check docker compose logs backend
Emails in spam Complete DKIM setup, verify domain