# AWS SES Email Setup ## Environment Configuration ### Production (`elmeg.xyz`) ```bash AWS_ACCESS_KEY_ID=AKIA... # IAM user with SES send-only perms AWS_SECRET_ACCESS_KEY=... AWS_SES_REGION=us-east-1 # Must match region where domain is verified EMAIL_FROM=noreply@elmeg.xyz # Must be on SES-verified domain FRONTEND_URL=https://elmeg.xyz NODE_ENV=production APP_ENV=production ``` ### Development (`elmeg.runfoo.run`) ```bash FRONTEND_URL=https://elmeg.runfoo.run APP_ENV=development # AWS keys optional in dev - emails log to console instead ``` --- ## SES Setup Checklist ### 1. Verify Domain in SES 1. AWS Console → SES → Verified Identities → Create identity 2. Select "Domain" → enter `elmeg.xyz` 3. Add DNS records AWS provides: - **TXT record** for domain verification - **3 CNAME records** for DKIM signing > [!IMPORTANT] > Add DKIM records or mail will get flagged as spam ### 2. Move Out of Sandbox By default SES is sandboxed (can only send to verified emails). 1. SES → Account dashboard → Request production access 2. Fill out: - Mail type: **Transactional** - Website URL: `https://elmeg.xyz` - Use case: "User registration verification, password reset for live music rating platform" 3. Wait for approval (~24hrs) ### 3. Create IAM User 1. IAM → Users → Create user: `elmeg-ses-sender` 2. Attach inline policy (SES send only): ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ses:SendEmail", "ses:SendRawEmail" ], "Resource": "*" } ] } ``` 3. Security credentials → Create access key 4. Save credentials securely > [!CAUTION] > **Never commit AWS keys.** Use environment variables only. Never use root AWS credentials - always create a scoped IAM user. --- ## DNS Records Required Add these to `elmeg.xyz` DNS (exact values from SES console): | Type | Name | Value | |------|------|-------| | TXT | `_amazonses.elmeg.xyz` | (provided by SES) | | CNAME | `xxxx._domainkey.elmeg.xyz` | (DKIM 1) | | CNAME | `xxxx._domainkey.elmeg.xyz` | (DKIM 2) | | CNAME | `xxxx._domainkey.elmeg.xyz` | (DKIM 3) | --- ## Deployment ### Add to production server ```bash ssh root@tangible-aacorn cd /srv/containers/elmeg-demo ``` Edit `docker-compose.yml` backend environment: ```yaml 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.xyz - APP_ENV=production ``` Rebuild and restart: ```bash docker compose build backend docker compose restart backend ``` --- ## 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, or still in sandbox | | "Access Denied" | Check IAM policy has `ses:SendEmail` | | Emails not sending | Check `docker compose logs backend` | | Emails in spam | Verify DKIM records are set correctly | | Wrong links in emails | Check `FRONTEND_URL` matches prod domain |