Resend vs Mailgun for receiving email
Both are developer email APIs that can also receive mail on your domain, but they do it differently. This guide compares the inbound side only: DNS, routing, webhook payloads, retention, and cost. Sending deliverability is a separate topic.
TL;DR
- Resend: one MX record, domain-wide catch-all, metadata webhook plus a second API call for the body, 30-day retention, inbound included on all plans.
- Mailgun: MX records plus routes (per address or catch-all), the full parsed message is POSTed to your webhook, stored copies last 3 days, the free plan allows a single route.
- Neither gives a person an inbox. Both are built for code to consume the mail.
Comparison table
| Inbound feature | Resend | Mailgun |
|---|---|---|
| DNS needed | 1 MX record (domain-specific value) | 2 MX records (mxa / mxb.mailgun.org) |
| Address matching | Whole domain, automatic | Routes: match_recipient() per address or regex catch-all |
| Webhook event | email.received (JSON, metadata only) | Route forward() to URL (multipart, full body + attachments) |
| Fetching the body | Required: GET /emails/receiving/{id} | Already in the POST (or store() + retrieve URL) |
| Signature | Svix headers (svix-id / timestamp / signature) | HMAC of timestamp + token with the HTTP signing key |
| Retention of stored mail | 30 days (Free, Pro, Scale) | Up to 3 days (store() action) |
| Inbound on free tier | Yes, counts toward 3,000 / month | Yes, 1 route on Free; more routes on paid plans |
| Dashboard view of received mail | Read-only list with Preview / HTML / Raw | Logs only; no message view unless stored |
| Reply from dashboard | No (API with In-Reply-To) | No (API or SMTP) |
Setup, step by step
Resend
- Verify the domain for sending (SPF, DKIM).
- Domains → your domain → turn on Receiving.
- Add the MX record shown, lowest priority on the domain.
- Create a webhook for
email.received.
Detailed walkthrough: how to receive emails with Resend.
Mailgun
- Add Mailgun MX records (receiving DNS) and verify.
- Receiving → Routes → create a route: expression plus forward / store actions.
- Repeat per address, or use a catch-all expression for the domain.
- Verify the HTTP webhook signing key on every POST.
Detailed walkthrough: can Mailgun receive emails?
Webhook payloads: the practical difference
Mailgun hands you everything in one multipart POST: body-plain, body-html, message-headers, attachments as files. Your endpoint must answer within seconds, and large messages mean large requests.
Resend sends a small JSON event and expects you to call back for the content. That makes the webhook fast and retry-safe, but you need an API call per message and the signed attachment URLs expire, so download them promptly.
Threading works the same on both: keep the Message-ID and use In-Reply-To / References when you reply.
Retention and pricing
Resend lists 30 days of data retention on self-serve plans and includes inbound on every plan, with each received message counting toward the same quota as a send (3,000 per month and 100 per day on Free). Mailgun keeps stored copies for up to 3 days; the free plan includes one inbound route and paid plans add more, so check the current Mailgun pricing page for the route limit on your tier.
In both cases the provider is a buffer, not an archive. If a human needs to find last quarter's thread, the mail has to live somewhere else.
Getting an actual inbox on either provider
Inboxes connects to your Mailgun or Resend account with an API key, installs the webhooks (and Mailgun routes) for you, stores every message with threads and attachments, and lets you reply from your domain. If you are deciding between the two providers, you do not have to decide forever: connect both and move mailboxes when you are ready. Start with Mailgun webmail or Resend inbox.
Frequently asked questions
Resend. You turn on Receiving for the domain and add one MX record; every address is received. Mailgun needs its MX records plus a route per address or a catch-all route, created in the dashboard or via API.
Resend keeps email data for 30 days on Free, Pro, and Scale plans. Mailgun keeps messages stored with the store() route action for up to 3 days. Neither is an archive; keep your own copy if you need history.
Mailgun has no inbox at all. Resend shows received mail read-only in its dashboard and documents replying via the API. For a Gmail-like inbox on either provider, use a client such as Inboxes.
With Inboxes, yes. Connect both providers, add the Resend mailbox, and your existing Mailgun mail stays in the same app while new mail flows through Resend.