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