Ghost + Mailgun Configuration Guide: The Two Email Systems You Need to Know About
If you're setting up Ghost with Mailgun for email, you might run into some confusion. That's because Ghost actually uses two completely separate email systems — and they need different credentials configured in different places.
Here's everything I learned getting this working.
The Two Email Systems
| Type | Purpose | Protocol | Where to Configure |
|---|---|---|---|
| Transactional | Password resets, staff invites, login links | SMTP | Environment variables or config.production.json |
| Bulk/Newsletter | Sending posts to subscribers, analytics | Mailgun API | Ghost Admin UI |
This distinction tripped me up at first. You can have SMTP working perfectly for password resets, but newsletters won't send because that's a completely different system using the Mailgun API directly.
1. Transactional Email (SMTP)
What it's for
- Staff invitation emails
- Password reset emails
- Login magic links
- Member signup confirmations
Credentials needed
From Mailgun → Domain → SMTP credentials tab:
- Username:
postmaster@your-domain.comor a custom SMTP user - Password: The SMTP password (looks like a long hex string)
Configuration via environment variables
mail__transport=SMTP
mail__options__service=Mailgun
mail__options__host=smtp.mailgun.org # US region
# mail__options__host=smtp.eu.mailgun.org # EU region
mail__options__port=587 # or 465 for SSL, 2525 as fallback
mail__options__secure=false # true if using port 465
mail__options__auth__user=<YOUR_SMTP_USERNAME>
mail__options__auth__pass=<YOUR_SMTP_PASSWORD>
Or in config.production.json
{
"mail": {
"transport": "SMTP",
"options": {
"service": "Mailgun",
"host": "smtp.mailgun.org",
"port": 587,
"secure": false,
"auth": {
"user": "<YOUR_SMTP_USERNAME>",
"pass": "<YOUR_SMTP_PASSWORD>"
}
}
}
}
2. Bulk Email / Newsletters (Mailgun API)
What it's for
- Sending newsletter posts to all subscribers
- Email open/click analytics
- Delivery tracking
Credentials needed
From Mailgun → API Security (Account Settings) or Domain → Sending Keys:
Two types of API keys exist:
| Key Type | Can Send | Can Read Analytics | Scope |
|---|---|---|---|
| Primary Account API Key | ✅ | ✅ | All domains |
| Domain Sending Key | ✅ | ❌ | Single domain only |
Recommendation: Use the Primary Account API Key for Ghost so analytics work too.
Where to configure: Ghost Admin UI
⚠️ This is NOT in environment variables or config files — it's in Ghost's web interface!
- Go to
https://yoursite.com/ghost/ - Click Settings (gear icon, bottom left)
- Click Email newsletter
- Scroll to Mailgun section
- Enter:
- Mailgun region: United States (or EU if your domain is in EU)
- Mailgun domain:
your-sending-domain.com← YOUR SENDING DOMAIN, not the API URL! - Mailgun private API key: Your API key from Mailgun
Common mistake ❌
WRONG: Mailgun domain = api.mailgun.net
RIGHT: Mailgun domain = your-sending-domain.com
The domain field is your sending domain, not the Mailgun API endpoint!
Environment variables (optional, but Admin UI takes precedence)
bulk_email__mailgun__apiKey=<YOUR_API_KEY>
bulk_email__mailgun__domain=your-sending-domain.com
bulk_email__mailgun__baseUrl=https://api.mailgun.net/v3 # US region
# bulk_email__mailgun__baseUrl=https://api.eu.mailgun.net/v3 # EU region
3. Region Matters!
Your Mailgun domain is created in either US or EU region. You must use the matching endpoints:
| Region | SMTP Host | API Base URL |
|---|---|---|
| US | smtp.mailgun.org |
https://api.mailgun.net/v3 |
| EU | smtp.eu.mailgun.org |
https://api.eu.mailgun.net/v3 |
How to check your region: Look at the URL when logged into Mailgun:
app.mailgun.com= USapp.eu.mailgun.com= EU
4. Where to Find Credentials in Mailgun
SMTP Password
- Mailgun Dashboard → Sending → Domains
- Click your domain
- SMTP credentials tab
- Click Reset Password next to your user (password is only shown once!)
Domain Sending API Key
- Mailgun Dashboard → Sending → Domains
- Click your domain
- Sending keys tab
- Click Add sending key (key is only shown once!)
Primary Account API Key
- Mailgun Dashboard → Settings (top right) → API Keys
- Click eye icon next to your key to reveal it
5. Testing
Test SMTP (transactional)
If Ghost can send password reset emails, SMTP is working.
Test API (bulk)
curl -s --user "api:<YOUR_API_KEY>" \
"https://api.mailgun.net/v3/<YOUR_DOMAIN>/messages" \
-F from="test@<YOUR_DOMAIN>" \
-F to="your@email.com" \
-F subject="Test" \
-F text="Test message"
Should return: {"id":"<...>","message":"Queued. Thank you."}
6. Troubleshooting
| Error | Cause | Fix |
|---|---|---|
Mailgun Error 401: Forbidden |
Wrong API key or region mismatch | Check key and region match |
404 page not found |
Wrong domain or using Domain Sending Key for non-send operations | Use Primary Account API Key |
| Analytics errors on boot | Using Domain Sending Key (can't fetch events) | Use Primary Account API Key |
| Emails send via curl but not Ghost | Ghost Admin has wrong settings | Check Ghost Admin → Settings → Email newsletter → Mailgun |
Summary
┌─────────────────────────────────────────────────────────────┐
│ MAILGUN │
├─────────────────────────────────────────────────────────────┤
│ │
│ SMTP Credentials API Keys │
│ (for transactional) (for bulk/newsletters) │
│ │
│ ┌─────────────────┐ ┌─────────────────────────────┐ │
│ │ Username │ │ Primary Account Key │ │
│ │ SMTP Password │ │ (full access) │ │
│ └────────┬────────┘ │ OR │ │
│ │ │ Domain Sending Key │ │
│ │ │ (send only, no analytics) │ │
│ │ └──────────────┬──────────────┘ │
│ │ │ │
└───────────┼───────────────────────────────┼──────────────────┘
│ │
▼ ▼
┌───────────────────────┐ ┌───────────────────────────────┐
│ Environment vars / │ │ Ghost Admin UI │
│ config.production.json│ │ Settings → Email newsletter │
│ │ │ → Mailgun section │
│ mail__options__* │ │ │
└───────────────────────┘ └───────────────────────────────┘
│ │
▼ ▼
Password resets Newsletter sending
Staff invites Open/click analytics
Login links Delivery tracking
The key insight: two systems, two sets of credentials, two different configuration locations. Once you understand that, the setup becomes much clearer.