# 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 ", "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 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 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 |