Route Every Email to the Right Place, Automatically

Eliminate shared inbox chaos. AI agents classify, tag, and route incoming emails across departments without manual triage.


Why this matters

Shared inboxes don't scale. When billing inquiries, support tickets, sales leads, and partnership requests all land in one place, every team member sees everything and no one owns the response. Triage becomes a full-time job — and high-priority emails still get missed. The deeper problem is that routing logic lives in people's heads. It's inconsistent, it doesn't work nights and weekends, and it breaks whenever someone is on leave. Codifying that logic into a deterministic, auditable agent process is the only fix that holds.


How MultiMail solves this

MultiMail's multi-mailbox architecture lets AI agents implement consistent routing logic across your entire email operation. Agents call check_inbox on a shared mailbox, classify each message by department and priority using read_email content, stamp the original with tag_email, and forward to the correct destination via send_email — all in real time, with a complete audit trail. Routing rules live in code, not tribal knowledge. Monitored mode means your team sees every routing decision without approving each one, so the pipeline stays fast while staying observable. For VIP senders or escalations, switch to gated_send on those specific forwards to require human confirmation before the high-stakes message goes out.

1

Receive incoming email

The agent calls check_inbox on your shared mailbox to detect new arrivals, or you configure an inbound webhook to push new emails to your agent endpoint in real time. Webhook delivery eliminates polling latency for time-sensitive routing.

2

Read and classify content

read_email returns the full message: body, sender, headers, and attachments. The agent passes this content to your classification logic — keyword matching, an LLM classifier, or a rules engine — to determine destination department and priority level.

3

Tag the original message

tag_email stamps the message with routing metadata: department, priority, and routing status. Tags are queryable via the API, so you can audit routing decisions and build dashboards without a separate database.

4

Forward to the destination mailbox

send_email delivers the classified message to the target department mailbox — finance@, legal@, helpdesk@ — with the original content preserved. The agent prepends a routing summary so the receiving team has immediate context.

5

Notify the team

In monitored mode, your team has visibility into every routing decision without being required to approve each hop. For high-priority escalations or VIP senders, the agent routes those specific messages through gated_send, requiring explicit human confirmation before forwarding.


Implementation

Basic routing pipeline
python
from multimail import MultiMailClient

client = MultiMailClient(api_key="mm_live_...")

DEPARTMENT_MAILBOXES = {
    "billing": "[email protected]",
    "support": "[email protected]",
    "sales": "[email protected]",
    "legal": "[email protected]",
}

def classify_department(subject: str, body: str) -> str:
    text = f"{subject} {body}".lower()
    if any(w in text for w in ["invoice", "billing", "payment", "charge"]):
        return "billing"
    if any(w in text for w in ["contract", "agreement", "legal", "compliance"]):
        return "legal"
    if any(w in text for w in ["pricing", "demo", "trial", "upgrade"]):
        return "sales"
    return "support"

def route_emails():
    emails = client.check_inbox(
        mailbox="[email protected]",
        unread_only=True,
        limit=50,
    )

    for ref in emails:
        msg = client.read_email(email_id=ref.id)
        department = classify_department(msg.subject, msg.body_text)
        destination = DEPARTMENT_MAILBOXES[department]

        client.tag_email(
            email_id=msg.id,
            tags=[f"dept:{department}", "auto-routed"],
        )

        client.send_email(
            from_mailbox="[email protected]",
            to=[destination],
            subject=f"[{department.upper()}] {msg.subject}",
            body_text=(
                f"Routed from shared inbox.\n"
                f"Original sender: {msg.from_address}\n\n---\n\n"
                f"{msg.body_text}"
            ),
        )

route_emails()

Poll a shared inbox, classify each email by department, tag it, and forward to the correct destination mailbox.

Priority escalation routing
python
from multimail import MultiMailClient

client = MultiMailClient(api_key="mm_live_...")

DEPARTMENT_MAILBOXES = {
    "billing": "[email protected]",
    "support": "[email protected]",
    "sales": "[email protected]",
    "legal": "[email protected]",
}

VIP_DOMAINS = {"enterprise-client.com", "strategic-partner.io"}

def is_vip(sender: str) -> bool:
    domain = sender.split("@")[-1].lower()
    return domain in VIP_DOMAINS

def classify_department(subject: str, body: str) -> str:
    text = f"{subject} {body}".lower()
    if any(w in text for w in ["invoice", "billing", "payment"]):
        return "billing"
    if any(w in text for w in ["contract", "legal", "compliance"]):
        return "legal"
    if any(w in text for w in ["pricing", "demo", "upgrade"]):
        return "sales"
    return "support"

def route_with_escalation():
    emails = client.check_inbox(
        mailbox="[email protected]",
        unread_only=True,
    )

    for ref in emails:
        msg = client.read_email(email_id=ref.id)
        department = classify_department(msg.subject, msg.body_text)

        if is_vip(msg.from_address):
            client.tag_email(
                email_id=msg.id,
                tags=["vip", "escalation", f"dept:{department}"],
            )
            client.send_email(
                from_mailbox="[email protected]",
                to=["[email protected]"],
                subject=f"[VIP ESCALATION] {msg.subject}",
                body_text=(
                    f"VIP sender: {msg.from_address}\n"
                    f"Classified department: {department}\n\n"
                    f"{msg.body_text}"
                ),
            )
        else:
            client.tag_email(
                email_id=msg.id,
                tags=[f"dept:{department}", "auto-routed"],
            )
            destination = DEPARTMENT_MAILBOXES[department]
            client.send_email(
                from_mailbox="[email protected]",
                to=[destination],
                subject=f"[{department.upper()}] {msg.subject}",
                body_text=msg.body_text,
            )

route_with_escalation()

Detect VIP senders and high-priority signals. Route standard volume normally; escalate VIP messages to an exec mailbox with a routing summary.

Webhook-triggered routing
python
from fastapi import FastAPI, Request
import httpx

app = FastAPI()

API = "https://api.multimail.dev"
HEADERS = {"Authorization": "Bearer $MULTIMAIL_API_KEY...", "Content-Type": "application/json"}

DEPARTMENT_MAILBOXES = {
    "billing": "[email protected]",
    "support": "[email protected]",
    "sales": "[email protected]",
    "legal": "[email protected]",
}

def classify_department(subject: str, body: str) -> str:
    text = f"{subject} {body}".lower()
    if any(w in text for w in ["invoice", "billing", "payment"]):
        return "billing"
    if any(w in text for w in ["contract", "legal", "compliance"]):
        return "legal"
    if any(w in text for w in ["pricing", "demo", "upgrade"]):
        return "sales"
    return "support"

@app.post("/webhook/inbound")
async def handle_inbound(request: Request):
    payload = await request.json()

    if payload.get("event") != "email.received":
        return {"ok": True}

    email_id = payload["email_id"]
    subject = payload["subject"]
    sender = payload["from_address"]
    body = payload.get("body_text", "")

    department = classify_department(subject, body)
    destination = DEPARTMENT_MAILBOXES.get(department, "[email protected]")

    httpx.post(
        f"{API}/emails/{email_id}/tags",
        headers=HEADERS,
        json={"tags": [f"dept:{department}", "auto-routed"]},
    )

    httpx.post(
        f"{API}/send",
        headers=HEADERS,
        json={
            "from_mailbox": "[email protected]",
            "to": [destination],
            "subject": f"[{department.upper()}] {subject}",
            "body_text": f"From: {sender}\n\n{body}",
        },
    )

    return {"routed_to": destination, "department": department}

Handle inbound email webhook events and route in real time without polling.

MCP-based routing in Claude Desktop
text
# Example MCP tool sequence for routing a billing inquiry

# Step 1 — Check shared inbox for new emails
tool: check_inbox
args:
  mailbox: [email protected]
  unread_only: true

# Step 2 — Read the email flagged for routing
tool: read_email
args:
  email_id: <id from check_inbox result>

# Step 3 — Tag with classification result
tool: tag_email
args:
  email_id: <id>
  tags:
    - dept:billing
    - priority:high
    - auto-routed

# Step 4 — Forward to finance mailbox with routing context
tool: send_email
args:
  from_mailbox: [email protected]
  to:
    - [email protected]
  subject: "[BILLING] Fwd: Invoice inquiry from VIP customer"
  body_text: |
    Routed by classification agent. Billing keywords detected.
    Original sender: [email protected]

    --- Original message ---
    <body from read_email result>

# The agent decides routing by analyzing email content with its LLM,
# then executes send_email. In monitored mode, all actions are visible
# to your team in real time without blocking the workflow.

Use MultiMail MCP tools to route emails interactively inside any MCP-compatible client without writing a custom pipeline.


What you get

Routing logic as code

Rules live in your codebase, not in people's heads. Version-controlled, testable, and consistent — the same logic runs at 3 AM on a Sunday as it does during business hours. Roll back a bad rule the same way you roll back any code change.

Complete audit trail via tags

Every routing decision is recorded: which email was classified as what department, by which rule, forwarded where, and when. Tags set via tag_email are returned on every subsequent read_email call, so the full routing history follows the message.

Graduated oversight per message type

Standard volume runs in monitored mode — zero approval friction, full team visibility. High-value senders and escalations use gated_send on those specific forwards. Oversight granularity is per-send, not a single account-wide toggle.

Multi-mailbox architecture built in

MultiMail accounts support multiple mailboxes under one API key. Create department-specific inboxes for finance, legal, sales, and support — each with its own access controls, storage quotas, and webhook endpoints.

No duplicate responses or missed emails

Emails arrive once, get routed once, and land in exactly one place. The routing agent tags processed messages before forwarding, so re-runs are idempotent and team members only see emails that belong to them.


Recommended oversight mode

Recommended
monitored
Email routing is high-volume and time-sensitive — approval gates on every forward would recreate the exact bottleneck you're trying to eliminate. Monitored mode lets the agent route continuously while your team retains full visibility into every decision. Reserve gated_send for specific high-stakes categories: VIP senders, legal correspondence, or any message type where a misroute has material consequences. That way, 95% of volume flows unblocked while the 5% that matters gets human eyes before it moves.

Common questions

Can I route to external email addresses, not just MultiMail mailboxes?
Yes. The send_email endpoint accepts any valid RFC-5321 address as a recipient. You can route to external department aliases, third-party ticketing systems that ingest via email (Zendesk, Linear, Jira), or any destination that accepts SMTP delivery.
How do I prevent routing loops if a destination mailbox is also monitored by the agent?
Tag routed messages with 'auto-routed' before forwarding, then filter check_inbox calls to exclude that tag. Alternatively, set destination mailboxes to read_only oversight mode so the agent can observe them but cannot act on messages it placed there.
Can routing rules be updated without redeploying the agent?
If routing rules are stored in a config file, database, or KV store rather than hardcoded, yes — updates take effect on the next polling cycle with no redeployment. Separating rule storage from agent logic is the recommended pattern for production routing systems.
What happens when the classifier has low confidence?
That is an application-layer decision. A common pattern: if the classifier returns a confidence score below a defined threshold, tag the email 'needs-triage' and route it to a human-reviewed queue rather than auto-forwarding. The decide_email endpoint is designed for exactly this gating pattern.
Can I trace the full routing history for a specific email?
Yes. Tags set via tag_email are returned on every read_email call. Combine that with get_thread to trace the full path: original receipt timestamp, classification tags, every downstream send, and any reply activity. No separate logging infrastructure required.
How do I test routing rules without delivering real emails?
Use test API keys (mm_test_...) against the staging environment. Sends are processed and all API behavior is identical to production, but emails are not delivered externally. This lets you validate routing logic against realistic message content with no side effects.
Is there a rate limit on check_inbox polling?
Yes — polling at sub-second intervals will hit rate limits. The recommended pattern for latency-sensitive routing is inbound webhooks: configure a webhook on your shared mailbox and MultiMail will push new messages to your endpoint immediately on receipt, eliminating the need to poll at all.

Explore more use cases

The only agent email with a verifiable sender

Email infrastructure built for AI agents. Verifiable identity, graduated oversight, and a 50-tool MCP server. Formally verified in Lean 4.