- Fork elmeg-demo codebase for multi-band support - Add data importer infrastructure with base class - Create band-specific importers: - phish.py: Phish.net API v5 - grateful_dead.py: Grateful Stats API - setlistfm.py: Dead & Company, Billy Strings (Setlist.fm) - Add spec-kit configuration for Gemini - Update README with supported bands and architecture
233 lines
5.5 KiB
Markdown
233 lines
5.5 KiB
Markdown
# Mailgun Integration Spec
|
|
|
|
**Date:** 2023-12-23
|
|
**Domain:** elmeg.xyz
|
|
**Purpose:** Transactional email (signup, login, password reset, notifications)
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
Elmeg will use **Mailgun** as the transactional email provider instead of AWS SES. Traffic is low-volume and strictly transactional; no marketing or bulk sending.
|
|
|
|
---
|
|
|
|
## Account & Domain Setup
|
|
|
|
### 1. Mailgun Account
|
|
|
|
- Create/use shared Mailgun org account owned by Antigravity (not personal)
|
|
- Add maintainers with least-privilege roles
|
|
|
|
### 2. Domain Configuration
|
|
|
|
- **Sending Domain:** `mail.elmeg.xyz` (subdomain recommended)
|
|
- Select appropriate region (US or EU)
|
|
|
|
### 3. DNS Records (Cloudflare)
|
|
|
|
Add the following records as provided by Mailgun:
|
|
|
|
```
|
|
# SPF
|
|
TXT mail.elmeg.xyz "v=spf1 include:mailgun.org ~all"
|
|
|
|
# DKIM (2 records typically)
|
|
TXT smtp._domainkey.mail.elmeg.xyz "k=rsa; p=..."
|
|
TXT mailo._domainkey.mail.elmeg.xyz "k=rsa; p=..."
|
|
|
|
# DMARC
|
|
TXT _dmarc.mail.elmeg.xyz "v=DMARC1; p=none; rua=mailto:dmarc@elmeg.xyz"
|
|
|
|
# MX (for receiving bounces)
|
|
MX mail.elmeg.xyz mxa.mailgun.org 10
|
|
MX mail.elmeg.xyz mxb.mailgun.org 20
|
|
|
|
# Tracking (optional)
|
|
CNAME email.mail.elmeg.xyz mailgun.org
|
|
```
|
|
|
|
Wait for Mailgun to show domain as **"Verified"** before switching production.
|
|
|
|
---
|
|
|
|
## Sending Model & Limits
|
|
|
|
| Aspect | Configuration |
|
|
|--------|---------------|
|
|
| Plan | Free tier (~100 emails/day), scales to pay-per-use |
|
|
| Budget | Well under $10/month for current volume |
|
|
| Sending Identity | `no-reply@mail.elmeg.xyz` for notifications |
|
|
| Reply Address | `support@elmeg.xyz` for human replies |
|
|
| Email Types | Account creation, login/OTP, password reset, security alerts |
|
|
| **Not Allowed** | Newsletters, promos, bulk imports |
|
|
|
|
---
|
|
|
|
## Application Integration
|
|
|
|
### Environment Variables
|
|
|
|
```env
|
|
# Mailgun API Credentials
|
|
MAILGUN_API_KEY=key-xxxxxxxxxxxxxxxxxxxxxxxx
|
|
MAILGUN_DOMAIN=mail.elmeg.xyz
|
|
MAILGUN_API_BASE=https://api.mailgun.net/v3 # or eu.api.mailgun.net for EU
|
|
|
|
# Legacy (keep for transition)
|
|
EMAIL_FROM=no-reply@mail.elmeg.xyz
|
|
|
|
# Optional SMTP (if not using API)
|
|
MAILGUN_SMTP_HOST=smtp.mailgun.org
|
|
MAILGUN_SMTP_PORT=587
|
|
MAILGUN_SMTP_LOGIN=postmaster@mail.elmeg.xyz
|
|
MAILGUN_SMTP_PASSWORD=xxxxxxxx
|
|
```
|
|
|
|
### Recommended: Use HTTP API
|
|
|
|
Prefer Mailgun's HTTP API over SMTP for:
|
|
|
|
- Better error reporting
|
|
- Delivery metrics
|
|
- Simpler debugging
|
|
|
|
### Code Changes Required
|
|
|
|
Update `backend/services/email.py` (or equivalent) to:
|
|
|
|
```python
|
|
import httpx
|
|
|
|
MAILGUN_API_KEY = os.getenv("MAILGUN_API_KEY")
|
|
MAILGUN_DOMAIN = os.getenv("MAILGUN_DOMAIN")
|
|
MAILGUN_API_BASE = os.getenv("MAILGUN_API_BASE", "https://api.mailgun.net/v3")
|
|
|
|
async def send_email(to: str, subject: str, text: str, html: str = None):
|
|
"""Send email via Mailgun API"""
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.post(
|
|
f"{MAILGUN_API_BASE}/{MAILGUN_DOMAIN}/messages",
|
|
auth=("api", MAILGUN_API_KEY),
|
|
data={
|
|
"from": f"Elmeg <no-reply@{MAILGUN_DOMAIN}>",
|
|
"to": to,
|
|
"subject": subject,
|
|
"text": text,
|
|
"html": html,
|
|
}
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
```
|
|
|
|
---
|
|
|
|
## Email Templates
|
|
|
|
### Registration/Verification
|
|
|
|
```
|
|
Subject: Verify your Elmeg account
|
|
From: Elmeg <no-reply@mail.elmeg.xyz>
|
|
|
|
Hi {username},
|
|
|
|
Welcome to Elmeg! Please verify your email address:
|
|
|
|
{verification_link}
|
|
|
|
This link expires in 24 hours.
|
|
|
|
If you didn't create this account, please ignore this email.
|
|
|
|
— The Elmeg Team
|
|
```
|
|
|
|
### Password Reset
|
|
|
|
```
|
|
Subject: Reset your Elmeg password
|
|
From: Elmeg <no-reply@mail.elmeg.xyz>
|
|
|
|
Hi {username},
|
|
|
|
You requested a password reset. Click below to set a new password:
|
|
|
|
{reset_link}
|
|
|
|
This link expires in 1 hour.
|
|
|
|
If you didn't request this, you can safely ignore this email.
|
|
|
|
— The Elmeg Team
|
|
```
|
|
|
|
---
|
|
|
|
## Deliverability & Monitoring
|
|
|
|
| Setting | Value |
|
|
|---------|-------|
|
|
| Open/Click Tracking | Off (for transactional, reduces complexity) |
|
|
| Bounce Handling | Monitor in Mailgun dashboard |
|
|
| Target Metrics | <1% bounce rate, <0.1% complaints |
|
|
|
|
### Monitoring Checklist
|
|
|
|
- [ ] Check Mailgun dashboard weekly for delivery rates
|
|
- [ ] Review any bounces/complaints immediately
|
|
- [ ] Ramp up gradually if sending volume increases
|
|
|
|
---
|
|
|
|
## Migration Steps
|
|
|
|
### Phase 1: Setup (Today)
|
|
|
|
1. [ ] Create/access Mailgun account
|
|
2. [ ] Add `mail.elmeg.xyz` domain
|
|
3. [ ] Configure DNS in Cloudflare
|
|
4. [ ] Wait for domain verification
|
|
|
|
### Phase 2: Integration
|
|
|
|
5. [ ] Add `httpx` to requirements.txt
|
|
2. [ ] Update email service to use Mailgun API
|
|
3. [ ] Add environment variables to production `.env`
|
|
4. [ ] Test with a single email before full migration
|
|
|
|
### Phase 3: Switchover
|
|
|
|
9. [ ] Remove AWS SES credentials from production
|
|
2. [ ] Update documentation
|
|
3. [ ] Monitor deliverability for first week
|
|
|
|
---
|
|
|
|
## Security & Access
|
|
|
|
| Role | Access |
|
|
|------|--------|
|
|
| Org Owner | Full Mailgun access (Antigravity) |
|
|
| Maintainers | Send access, dashboard view |
|
|
| DNS | Cloudflare managed by Antigravity |
|
|
| Credentials | Environment variables only, never in Git |
|
|
|
|
---
|
|
|
|
## Future Considerations
|
|
|
|
- **Marketing Email:** If needed, use separate provider (Sendgrid, Postmark) to keep Mailgun clean
|
|
- **High Volume:** If >100/day, upgrade to paid tier
|
|
- **Webhooks:** Mailgun can send delivery/bounce webhooks for advanced tracking
|
|
|
|
---
|
|
|
|
## Cost Estimate
|
|
|
|
| Tier | Volume | Cost |
|
|
|------|--------|------|
|
|
| Free | ~100/day | $0 |
|
|
| Flex | Pay per 1,000 | ~$0.80/1,000 |
|
|
| Estimated Monthly | ~500 emails | <$1 |
|