Mailgun is a sending platform that also receives. If receiving is the part you actually need, you are paying for and configuring a lot of machinery aimed at the other direction.
| Capability | MXcatch | Mailgun Routes |
|---|---|---|
| Built for | Inbound mail only | Outbound sending, with inbound as a feature |
| Webhook payload | JSON, HMAC-SHA256 signed | Multipart form fields, signed |
| Attachments | Signed URLs with SHA-256 and size | Inlined in the multipart body, or stored |
| Configuration | Aliases and actions in a UI | Filter expressions and action strings |
| Webmail inbox | Yes, on every plan | No |
| Routing rules | Sender, recipient, subject, body, regex | Recipient and header expressions |
| Archive to storage | Built-in action, date-partitioned | store(), retrieved over the API |
| Slack / Discord | Built-in action | Build it yourself |
| Outbound sending | No | Yes — the main product |
| Pricing model | Fixed monthly, daily ceiling | Volume-based, tied to sending plans |
| Hosting | EU — Germany and Amsterdam | US and EU regions available |
Compiled from publicly documented behaviour. Check Mailgun's current plans and docs before deciding.
Mailgun Routes are filter expressions attached to a domain. You write a match — match_recipient(".*@your-domain.com") — and a list of actions such as forward(), store() or stop(), ordered by priority. It is powerful and it is expressed as strings in a form field.
MXcatch models the same job as aliases with actions. The address is a first-class object with a list of things that happen to its mail, and rules handle the cases where the address alone is not enough.
Neither is wrong. Which fits depends on whether you think in expressions or in addresses — and on what else you need from the provider.
This is the most practical distinction. A Mailgun Route that forwards to a URL delivers the message as multipart form fields, with attachments inlined in the same request. Your handler parses a multipart body, and a message with a 20 MB attachment is a 20 MB request.
MXcatch POSTs JSON. Attachments are not inlined — each arrives as a pre-signed URL valid for 60 minutes, with its filename, MIME type, byte size and SHA-256:
"attachments": [{
"name": "receipt.pdf",
"mime": "application/pdf",
"size": 49152,
"sha256": "9f8e7d6c...",
"url": "https://ams3.digitaloceanspaces.com/..."
}]
The payload stays small and predictable, you fetch only the files you actually want, and the digest lets you verify what you downloaded. Full schema in the webhook reference.
Mailgun's plans are built around messages sent. Inbound routing comes along with them, which is efficient if you send a lot and incidental if you send nothing — a team that only wants to receive ends up on a sending plan for the inbound feature.
MXcatch charges a fixed monthly price with a daily ceiling. Free covers one domain and 50 messages a day; the other tiers are on the pricing page. There is no per-message component, so a burst of traffic does not produce an invoice.
Mailgun's store() keeps a message for later retrieval over the API — it is storage, not a mailbox. MXcatch includes a webmail inbox on every plan, which changes debugging: when a webhook does not fire you can open the message, see its parsed body and attachments, and read the per-action status rather than reconstructing it from logs.
Running both is normal: Mailgun for outbound, MXcatch for inbound. They use different DNS records and do not conflict.
match_recipient(".*@domain") route becomes a catch-all; a specific recipient becomes a named alias.X-MXcatch-Signature.ImprovMX for straightforward forwarding, and Cloudflare Email Routing if your DNS is already at Cloudflare.
Free for one domain. Test it on a subdomain before you move anything.
Create your free account