Mailgun
Mailgun is a developer-oriented transactional email service. It is a solid default for Frontmail: a simple API, US and EU regions, detailed event data and webhooks for delivery, bounces, complaints, opens and clicks.
Choose Mailgun when you send transactional mail (sign-ups, receipts, notifications, form submissions) from your own domain, want bounce and complaint tracking, and prefer to keep data in the EU (Mailgun EU region). For a handful of emails from a personal mailbox, SMTP or Gmail is simpler. See the services overview for a comparison.
Prerequisites
Section titled “Prerequisites”- A Mailgun account. New accounts start with a sandbox domain that can only send to authorized recipients (see Sandbox & limits).
- A sending domain added and verified in Mailgun – we recommend a subdomain such as
mg.example.com, so your root domain’s reputation and DNS stay separate. - An API key. Create a dedicated key for Frontmail in Account settings → API security → Add new key (older UI: Account → API keys).
- Use a key with the most restrictive role that can still send and read domain info (e.g. Developer rather than Admin).
- A domain sending key (Sending → Domain settings → Sending API keys) can send, but cannot read the domain, so Test connection and the daily health check will report it as broken. Use a private account key.
- Optional: the HTTP webhook signing key from Sending → Webhooks for delivery events.
Connect in Frontmail
Section titled “Connect in Frontmail”- Open Email services → Add service → Mailgun.
- Fill in the fields:
| Field | Where to find it | Example |
|---|---|---|
| Region | The region shown next to the domain in Mailgun (Sending → Domains) | EU (api.eu.mailgun.net) |
| Sending domain | Sending → Domains, exactly as listed | mg.example.com |
| API key | Account settings → API security (shown only once when created) | key-3ax6… / a1b2c3…-us |
| Webhook signing key | Sending → Webhooks → HTTP webhook signing key | 8c1f… |
| Max emails per second | Optional; default 10/s | 5 |
- Click Verify & save – Frontmail calls the Mailgun API for the domain and checks that the key, region and domain match.
- The service is saved once the check passes. Credentials are encrypted with AWS KMS envelope encryption; only the sender process decrypts them at send time.
The template’s From address must be on the sending domain (e.g. hello@mg.example.com) – or on the root domain if you verified that one.
DNS: SPF, DKIM and DMARC
Section titled “DNS: SPF, DKIM and DMARC”Mailgun shows the exact records for your domain under Sending → Domains → DNS records. They look like this for mg.example.com:
; SPFmg.example.com. TXT "v=spf1 include:mailgun.org ~all"
; DKIM – selector is generated per domain (e.g. pic, k1, smtp, mx)pic._domainkey.mg.example.com. TXT "k=rsa; p=MIGfMA0GCSqGSIb3DQEB…"
; Receiving / bounce handling (recommended)mg.example.com. MX 10 mxa.mailgun.org.mg.example.com. MX 10 mxb.mailgun.org. ; EU: mxa.eu.mailgun.org / mxb.eu.mailgun.org
; Open & click trackingemail.mg.example.com. CNAME mailgun.org. ; EU: eu.mailgun.org
; DMARC – on the organizational domain, start with monitoring_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com"- Copy the DKIM selector from Mailgun, not from this example – it differs per domain (
pic._domainkey,k1._domainkey, …). Newer domains can also use delegated DKIM via CNAME with automatic key rotation. - If the root domain already has SPF for your mailbox, that is fine – the subdomain has its own SPF record.
- Click Verify DNS settings in Mailgun; propagation can take minutes to hours.
- Once DMARC reports look clean, tighten to
p=quarantineand laterp=reject.
Regions
Section titled “Regions”Mailgun runs two fully separate regions:
| Region | API host | Use when |
|---|---|---|
| US | api.mailgun.net |
the domain was created in the US region (default) |
| EU | api.eu.mailgun.net |
the domain was created in the EU region (data stays in the EU) |
A domain exists in exactly one region, so pick the region the domain was created in. A mismatch returns 404 Domain not found, which Frontmail treats as an auth error. The region cannot be changed later – to move, add the domain again in the other region.
Sandbox & limits
Section titled “Sandbox & limits”- Sandbox domain (
sandbox123….mailgun.org): sends only to authorized recipients (up to 5) that confirmed an invitation email. Anything else fails with “Free accounts are for test purposes only”. Good for a first test, not for production. - Free plan: around 100 emails per day.
- New accounts / domains may be rate-limited by Mailgun until you build sending history or complete business verification.
- Frontmail’s default rate for Mailgun is 10 messages per second per service; lower it in Max emails per second if Mailgun throttles you.
Webhooks (delivery tracking)
Section titled “Webhooks (delivery tracking)”Mailgun can report what happened after it accepted a message.
-
Copy the webhook URL from the service page in Frontmail (copy button next to Webhook URL). It looks like:
https://api.frontmail.dev/webhooks/providers/mailgun/<token><token>is unique to this service – don’t share it between services. -
In Mailgun open Sending → Webhooks, choose the right domain (and region), and add the URL for these events:
| Mailgun event | Frontmail event |
|---|---|
| Delivered | delivered |
| Permanent failure | bounced – the address is added to the suppression list |
| Temporary failure | recorded on the message; Mailgun keeps retrying |
| Spam complaints | complained – added to the suppression list |
| Opens | opened (requires open tracking on the domain) |
| Clicks | clicked (requires click tracking on the domain) |
- Copy the HTTP webhook signing key from the same page into the service’s Webhook signing key field in Frontmail.
Signature verification: every Mailgun webhook carries timestamp, token and signature. Frontmail computes HMAC-SHA256 of timestamp + token with your signing key and rejects requests whose signature does not match. Without the signing key, events cannot be verified and are ignored.
Frontmail tags every message with v:frontmail_message_id, so events are matched to the right message even when you send the same template many times.
Common errors
Section titled “Common errors”Frontmail sorts provider errors into three classes:
- auth – the service is broken (invalid API key, 401/403, wrong domain or region, sandbox restrictions). The service is marked
unhealthyand the owner gets an email plus a dashboard banner. If the template has a fallback service, the message is sent through it; otherwise the credit is refunded and the message waits in the hold queue asheld_service_error, to be sent automatically after you fix the service (re-checked on save and by the daily health check). - permanent – this message cannot be sent (invalid recipient, 4xx validation error). The fallback service is tried if configured; otherwise the status is
failedand the credit is refunded. - transient – timeouts, 5xx, 429 throttling. Retried with exponential backoff; after the retries are exhausted the message is
failedand the credit is refunded.
| Mailgun response | Class | What to do |
|---|---|---|
401 Forbidden |
auth | The API key is wrong, deleted or belongs to another account. Create a new key and update the service. |
404 Domain not found: mg.example.com |
auth | Check the domain spelling and the Region (EU domains need api.eu.mailgun.net). |
400 Domain mg.example.com is not allowed to send: Free accounts are for test purposes only… |
auth | Sandbox domain or unverified account – add an authorized recipient, verify your own domain or upgrade. |
403 “account disabled / domain disabled” |
auth | Mailgun suspended sending; check the Mailgun dashboard and contact their support. |
400 'to' parameter is not a valid address |
permanent | The recipient address is malformed – see invalid recipient. |
413 Request Entity Too Large |
permanent | The message with attachments exceeds Mailgun’s size limit (25 MB). |
429 Too Many Requests |
transient | Throttled; Frontmail honours Retry-After. Lower Max emails per second if it happens often. |
500 / 502 / 503, timeout |
transient | Mailgun outage – nothing to do, Frontmail retries. |
Checklist
Section titled “Checklist”- Own sending domain (e.g.
mg.example.com) added and verified in Mailgun - SPF, DKIM, MX and tracking CNAME published; DMARC at least
p=none - Region in Frontmail matches the domain’s region
- Private API key with a restricted role, not a domain sending key
- Test connection passes
- Webhook URL added for delivered, permanent failure, complaints (+ opens/clicks if needed)
- Webhook signing key copied into Frontmail
- From address in the template is on the verified domain