Skip to content
Blog / Engineering

Mailgun Review for Agent Builders: Inbound Parsing, Retention and Pricing (2026)

Binoy Perera

A Mailgun review for developers whose AI agent must receive and answer email: how Routes deliver replies, what store() keeps, retries, plans and the MCP server.

  • engineering
  • mailgun
  • inbound-email
  • reviews
  • ai-agents

TL;DR

This review looks at Mailgun from the point of view of a developer whose AI agent has to read and answer email, not only send it. It covers how inbound mail reaches your code, what Mailgun keeps for you afterward, what happens when your server is down, and what each plan allows. By the end you will know when Mailgun is the right pick for an agent and when it is not.

Most teams pick an email provider for the outbound half. Password resets, receipts, alerts. The provider sends them, tracks bounces, and nobody thinks about it again. Then an agent goes into production, and people start writing back.

Replies change the job. Your agent now has to receive a message, work out which conversation it belongs to, read what came before, and answer in the same thread. That is an inbox problem, and a sending service was not designed around one. Some sending services handle it better than their reputation suggests. Others do not handle it at all.

The questions below are the ones a developer asks before betting an agent on a provider they already use for sending. Each answer comes from the provider's own documentation and pricing page. The last two sections say where a dedicated agent inbox fits instead, and what we do not do.

What is Mailgun built for?

Mailgun is a sending service with a flexible inbound router attached. You send through a REST API or SMTP relay, from a US or EU region, with templates, tracking, suppression lists and dedicated IPs on the larger plans. Address validation is sold alongside. That is application email, the kind a product sends to its users.

Inbound is a second system bolted to the side. It receives mail for your domain, runs it through rules you write, and hands the result to your code. It does not give an agent a mailbox. Nothing on the receiving side is an object your agent owns and can list later.

The verdict up front: Mailgun suits an agent that mostly sends and needs replies routed to the right handler by rule. It is a poor fit when each agent needs its own inbox with history it can read back days later.

How does Mailgun inbound email work?

Inbound runs on Routes, which pair a filter with an action. Every incoming message is tested against each route in priority order, lower numbers first. By default all matching routes run, even after one has fired, unless an action calls stop(). The filter or action field on a route cannot exceed 4k characters, so a long rule set spreads across several routes.

There are three filters. match_recipient tests the SMTP recipient against a Python-style regular expression. match_header tests any MIME header, such as the subject or a spam flag. catch_all matches whatever no earlier route took, so it belongs at the lowest priority.

The detail most reviews skip is regex captures. A filter like match_recipient("(.*)@bar.com") captures the local part, and the action can pass it on as forward("http://myhost.com/post/?mailbox=\1"). Named groups work too. For an agent product that is the routing key. Give each agent an address on one domain, capture the local part, and your webhook receives the agent id in the URL without parsing anything.

The URL also picks the payload format. A forward URL ending in json receives one JSON document with attachments base64-encoded inside it. A URL ending in mime or raw-mime receives the raw MIME in body-mime, with the parsed text and HTML bodies left out. Any other URL gets a form post, multipart when there are attachments.

Mailgun also documents a newer Forwards API for the simple case. It matches the recipient with * wildcards rather than regex, forwards to URLs, addresses or storage, and is built to scale with large rule sets. Routes stay the tool when you need captures, header matching or several actions per message.

How do replies tie back to a conversation?

They do not, unless your code ties them. Mailgun has no thread object on the receiving side. Each forwarded message arrives on its own, and the message-headers field carries the full ordered header list, including Message-Id, In-Reply-To and References. Matching a reply to the conversation it answers is your job.

Mailgun does help with the text. Each payload carries body-plain, which is always present, plus stripped-text, stripped-signature and stripped-html, which drop quoted history and the signature block. Those stripped fields are best effort. If parsing fails they are absent from the payload, so an agent that reads only stripped-text will sometimes get nothing and must fall back to the full body.

In practice developers combine both tricks. A regex capture or plus addressing, such as ^chris\+(.*)@example.com$, identifies the agent or the ticket. The headers identify the parent message. Your database holds the thread.

What can an agent get back later?

Not much, and not for long. The store() action keeps a message on Mailgun's servers so you can fetch it later through a message-url. The route documentation describes that storage as temporary, for up to 3 days. The pricing page scopes it by plan: 1 day of message retention on Foundation, up to 7 days on Scale. Free and Basic list none.

There is no mailbox to list or search. Stored messages are found through the logs and fetched one at a time, and after the retention window they are gone. An agent that needs to reread last month's thread before replying needs its own store, written at the moment each message arrives.

What happens when the agent's endpoint is down?

Mailgun retries for 8 hours, then stops. A 200 from your server marks the post delivered. A 406 tells Mailgun to drop it with no retry. Any other response, or no response, triggers retries that back off from minutes to hours. After 8 hours in total the message is not posted again.

So an agent that is down overnight can lose mail. Eight hours is the window. Return 200 fast, put the work on a queue, and use store() as a backstop if your plan includes message retention.

Verify every post before acting on it. Form posts carry signature, timestamp and token fields for an HMAC check. JSON posts move them into X-Mailgun-Signature and X-Mailgun-Timestamp headers, and the HMAC is computed over the entire request body.

Spam filtering is off by default. A domain can delete spam or mark it with headers: X-Mailgun-Sflag, a numeric X-Mailgun-Sscore, and the DKIM and SPF check results. Turn marking on before an agent reads anything. Email from strangers is untrusted input, and an agent that acts on mail is a target.

What does Mailgun cost for an agent product?

Inbound routing is where the plans differ most for agents. Sending volume decides the price, but the route count and retention decide whether the inbound loop works at all.

PlanPriceIncluded sendingInbound routingMessage retentionBest for
Free$0100 emails a day1 routeNone listedTesting one inbound address
BasicFrom $15 a month10,000 a month, extra from $1.80 per 1,0005 routesNone listedA few fixed reply addresses
Foundation$35 a month after a free month50,000 a month, extra from $1.30 per 1,000Full access1 dayRegex routing across many agents
Scale$90 a month after a free month100,000 a month, extra from $1.10 per 1,000Full accessUp to 7 daysHigh volume with dedicated IP pools and SSO

Foundation is the realistic floor for an agent product. Basic caps you at 5 routes, and a regex route can cover many agents, but you lose room for header rules and a catch-all fast. Log retention runs from 1 day on Free and Basic to 30 on Scale. Extra dedicated IPs cost $59 per IP per month. The pricing page does not say whether received mail counts toward the monthly volume, so check with Mailgun before you model costs on inbound.

Does Mailgun have an MCP server?

Yes, and it runs on your machine. MCP, the Model Context Protocol, lets an AI assistant call outside tools. Mailgun's server installs through npx from the @mailgun/mcp-server package, needs Node.js 18 or later and an API key, and exposes more than 50 operations, including managing Routes. Mailgun says it does not currently offer a hosted version.

That fits a developer asking an assistant to check delivery stats or edit a route. It is an admin tool for the account. It does not give the assistant an inbox to read, because Mailgun has none to expose.

When should you choose Mailgun, and when not?

Choose by what the agent does with replies. The agent sends application email at volume and replies only need to reach the right handler: Mailgun. The agent needs EU data residency for sending, or dedicated IP pools: Mailgun. Your team already runs Mailgun and has a database that can hold threads: Mailgun, on Foundation or above.

Look elsewhere when the agent has to reread a conversation from last week before it answers. Do the same when you create agents at runtime and each one needs its own address and history, or when you cannot afford to lose mail because your endpoint was down for a night. Those are mailbox jobs, and on Mailgun you would build the mailbox yourself.

If each agent needs its own inbox

That is the job we built AgentMail for. The inbox is the API object. Each agent gets its own address, a message store it can list and search, threads assembled for it, and replies sent into the right thread by message id. Messages stay in the inbox after the webhook fires, so a missed event costs nothing more than a later read. Creating an agent's inbox and subscribing to its mail is two calls in Python.

Python

# create an inbox for one agent, then get a webhook when mail arrivesimport osfrom agentmail import AgentMailfrom agentmail.inboxes.types import CreateInboxRequestclient = AgentMail(api_key=os.environ["AGENTMAIL_API_KEY"])inbox = client.inboxes.create(    request=CreateInboxRequest(username="billing-agent-42", client_id="billing-agent-42"))client.webhooks.create(    url="https://example.com/hooks/email",    event_types=["message.received"],    client_id="billing-agent-42-hook",)print(inbox.inbox_id)  # billing-agent-42@agentmail.to

The client_id makes both calls safe to retry, so a crash halfway through does not leave a second inbox behind. Sender reputation attaches to the domain, not the inbox. Agents that need separate reputations each need their own domain. Custom domains start on the Developer plan, and the Free plan has none, so every Free inbox shares the agentmail.to domain.

The full comparison is in AgentMail vs Mailgun, and our roundup of email APIs for AI agents covers the rest of the field. For the receiving side in depth, see why inbound is the hard part.

What AgentMail does not do

We do not offer regex routing rules on arbitrary headers the way Mailgun Routes do. We do not run email address validation or sell dedicated IP pools. A team that mainly needs high-volume sending, with rule-based parsing of replies to a handful of addresses, is better served by Mailgun.

FAQ

Questions, answered.

Yes. Mailgun receives mail for your domain, and a Route forwards each matching message to your webhook as a parsed post. It does not keep a mailbox the agent can browse later.

The Free plan includes a single inbound route and Basic includes five. Full inbound routing starts on Foundation, which is free for the first month and then paid monthly. Check the Mailgun pricing page for the current figures before you budget.

Put all agents on one receiving domain and write a single Route whose regex captures the part of the address before the @ sign. Pass that capture into the webhook URL, and your handler knows which agent the message is for. Storing each agent's history is still up to your application.

No. Each inbound message arrives on its own with its full header list, so your code links a reply to its parent using the In-Reply-To and References headers. Mailgun does strip quoted text and signatures when it can, which saves a parsing step.

Blog

Suggested reading

View all posts

Developer Resources · August 21, 2026

AgentMail vs Mailgun

Mailgun is a transactional email API with a catch-all route and short-window MIME retention. AgentMail is built around the inbox as the primitive for AI agents, with framework connectors, prompt-injection defenses, and BYOC deployment. Here is what each one is built for, the agent loop in code, and how the routing, retention, threading, security, and pricing compare.

Engineering · October 10, 2026

Inbound is the hard part

Sending email from an AI agent is solved. Receiving it is not: duplicate deliveries, broken threading, spoofed senders and no memory. Why a mailbox fixes all four.

Prompt

Give yourself access to AgentMail by following the guide at:

https://agentmail.to/docs/get-started/agent-signup

and refer to:

https://agentmail.to/llms.txt

for the documentation index.

Start integrating AgentMail into your AI agents today.