Mailgun handles email delivery. MultiMail adds the agent identity layer, graduated oversight controls, and compliance tooling that AI agents require in production.
Mailgun is a well-engineered transactional email API built for human-authored messages. When an AI agent sends email through Mailgun, there is no mechanism to declare the sending identity as an AI system, no way to require human approval before high-stakes messages are delivered, and no built-in path to EU AI Act compliance. Developers building agent systems on Mailgun end up bolting on approval queues, audit logs, and disclosure headers manually — and those homegrown solutions rarely hold up under compliance review. The missing layer is not deliverability; it is agent-aware infrastructure.
MultiMail provides the same high-volume email delivery developers expect from Mailgun, with an additional layer designed specifically for AI agents: cryptographically signed identity headers that prove which agent sent a message, graduated oversight modes that let you gate sends on human approval without rebuilding your webhook stack, pre-send domain intelligence to catch reputation problems before delivery, and EU AI Act disclosure compliance out of the box. Migrating from Mailgun is a single endpoint swap — the send_email API accepts the same fields. What you gain is the agent trust and compliance infrastructure that Mailgun does not provide.
Replace your Mailgun API calls with POST https://api.multimail.dev/v1/send_email. The request shape maps directly: from, to, subject, and body fields are identical. Your existing message construction logic does not change.
Add an agent_id field to your send payload. MultiMail signs outbound messages with an X-MultiMail-Agent header backed by your account's Ed25519 key. Recipients and compliance auditors can verify which agent sent the message without trusting the From address alone.
Set oversight_mode: gated_send on your mailbox to hold all outbound sends in a pending queue until a human approves them. Use list_pending to surface queued messages and decide_email to approve or reject. Reads and replies to inbound mail proceed autonomously.
Point your inbound MX or forwarding rules at MultiMail. Inbound messages fire a webhook to your endpoint with parsed headers, body, and attachments. Use check_inbox and read_email to pull messages programmatically from your agent loop.
MultiMail evaluates recipient domain reputation, DMARC alignment, and EU AI Act disclosure requirements before each send. Messages that would damage deliverability or violate disclosure rules are flagged before they leave the queue, not after a bounce.
import httpx
client = httpx.Client(
base_url="https://api.multimail.dev/v1",
headers={"Authorization": "Bearer $MULTIMAIL_API_KEY"}
)
response = client.post("/send_email", json={
"from": "[email protected]",
"to": ["[email protected]"],
"subject": "Follow-up from your support request",
"body_text": "Hi — I reviewed your ticket and have a fix ready. See details below.",
"body_html": "<p>Hi — I reviewed your ticket and have a fix ready.</p>",
"agent_id": "support-agent-v2",
"oversight_mode": "gated_send"
})
result = response.json()
print(result["message_id"], result["status"]) "cm"># pending | queued | sentThe MultiMail send_email endpoint accepts the same fields as Mailgun's messages API. The agent_id field attaches cryptographic identity to the outbound message.
import httpx
client = httpx.Client(
base_url="https://api.multimail.dev/v1",
headers={"Authorization": "Bearer $MULTIMAIL_API_KEY"}
)
"cm"># Pull all messages waiting for approval
pending = client.get("/list_pending").json()
for msg in pending["messages"]:
print(f"[{msg[&"cm">#039;message_id']}] To: {msg['to']} | Subject: {msg['subject']}")
# Human reviews here — approve or reject
decision = "approved" # or "rejected"
reason = "Reviewed and accurate"
client.post("/decide_email", json={
"message_id": msg["message_id"],
"decision": decision,
"reason": reason
})
print(f"Processed {len(pending[&"cm">#039;messages'])} pending messages")With gated_send, outbound messages wait for human approval. Use list_pending to surface the queue and decide_email to approve or reject each message.
import httpx
client = httpx.Client(
base_url="https://api.multimail.dev/v1",
headers={"Authorization": "Bearer $MULTIMAIL_API_KEY"}
)
"cm"># Check for unread messages in the mailbox
inbox = client.post("/check_inbox", json={
"mailbox": "[email protected]",
"filter": "unread",
"limit": 10
}).json()
for item in inbox["messages"]:
email = client.post("/read_email", json={
"message_id": item["message_id"]
}).json()
"cm"># Agent processes the message...
draft_reply = generate_reply(email["body_text"]) "cm"># your agent logic
"cm"># Reply preserves threading
client.post("/reply_email", json={
"message_id": email["message_id"],
"body_text": draft_reply,
"agent_id": "support-agent-v2",
"oversight_mode": "gated_send"
})Agents poll check_inbox and read_email to process inbound messages. The reply_email endpoint preserves threading, so responses stay in the same conversation.
# Claude Desktop / Cursor / Windsurf — MultiMail MCP tools
# Send a message (held for approval in gated_send mode)
send_email(
from="[email protected]",
to="[email protected]",
subject="Your order has shipped",
body_text="Your order #4821 shipped today via FedEx. Tracking: 123456789.",
agent_id="fulfillment-agent"
)
# Review pending outbound messages
list_pending(mailbox="[email protected]")
# Approve a specific message
decide_email(message_id="msg_01HX...", decision="approved")
# Check inbound and read a message
check_inbox(mailbox="[email protected]", filter="unread")
read_email(message_id="msg_01HX...")If your agent runs in a Model Context Protocol client, MultiMail's 43 MCP tools replace direct API calls. No HTTP client code required.
Every message sent through MultiMail carries an X-MultiMail-Agent header signed with your account's Ed25519 key. Unlike a custom From address, this header is verifiable by recipients and auditors even after the message passes through forwarding rules or mailing list processors.
Mailgun delivers messages immediately. MultiMail's gated_send mode holds outbound sends in a queue that a human reviews via the decide_email endpoint or the MCP tool — no approval webhook infrastructure to build and maintain. Switch modes per mailbox as your deployment matures.
EU AI Act Article 50 requires that AI-generated communications be disclosed to recipients. MultiMail prepends a machine-readable disclosure header and optionally a human-readable footer to messages sent by agents, keyed to your agent_id. Mailgun has no equivalent.
Before a message leaves the queue, MultiMail checks recipient domain reputation, DMARC alignment, and known spam-trap patterns. Problems surface as warnings on the pending record before delivery, giving the oversight reviewer or the agent itself a chance to cancel rather than absorb a bounce.
The send_email request body is a superset of the fields Mailgun's messages API accepts. From, to, subject, body_text, and body_html map directly. Migration is an endpoint swap plus adding agent_id — existing message construction code does not change.
Email infrastructure built for AI agents. Verifiable identity, graduated oversight, and a 50-tool MCP server. Formally verified in Lean 4.