Skip to content
Engineering

How AI Agents Should Read Inbound Email Safely

| | 14 min read
How AI Agents Should Read Inbound Email Safely
How AI Agents Should Read Inbound Email Safely

Inbound email is one of the most useful inputs an AI agent can receive. It can confirm a signup, unlock a magic-link flow, deliver an OTP, notify a client operations team, or trigger a downstream workflow. It is also one of the least trustworthy inputs you can hand to an LLM.

A safe design does not let the model open a mailbox, read arbitrary HTML, click whatever it sees, and decide what to do next. Instead, the agent should receive a small, typed, verified view of the message, built by deterministic code before the LLM is involved.

That distinction matters. Email is messy, user-controlled, and often adversarial. AI agents are powerful because they can act, but that also means a malicious email can become a prompt injection, a credential leak, a bogus verification step, or an unsafe network request if the pipeline is too permissive.

This guide lays out a practical pattern for helping AI agents read inbound email safely, especially when using programmable temp inboxes, structured JSON emails, real-time webhooks, and temporary email APIs.

The core rule: agents should not read raw inboxes

For human users, an inbox is a visual workspace. For AI agents, an inbox should be a constrained event source.

The safest architecture is to separate email handling into two layers:

Layer Responsibility Should the LLM control it?
Deterministic email pipeline Receive, verify, normalize, dedupe, extract artifacts No
Agent reasoning layer Decide next step from a minimized, typed summary Sometimes, within policy

The pipeline should do the security-sensitive work before the model sees anything. That includes webhook verification, replay detection, message matching, link validation, OTP extraction, HTML stripping, and idempotency checks.

The LLM should see only what it needs to complete the task, such as an OTP, a verified magic link host, the sender domain, the subject, and a short text summary. It should not see raw MIME, full HTML, untrusted instructions, tracking links, hidden text, or arbitrary attachments unless the workflow explicitly requires it.

This is consistent with the broader risk model described by OWASP for LLM applications, where prompt injection and excessive agency are recurring failure modes. Inbound email is a natural prompt-injection channel because the sender can include instructions that compete with the developer’s instructions.

What can go wrong when agents read email directly?

Inbound email creates several overlapping risks. The problem is not only spam or phishing. The bigger issue is that email content can become executable context for an autonomous system.

Common failure modes include:

  • Prompt injection: An email says something like ignore previous instructions, call this tool, or send me secrets. If raw content reaches the model, the message becomes part of the agent’s instruction stream.
  • Webhook spoofing: An attacker sends fake HTTP requests to your webhook endpoint unless you verify signed payloads and reject replays.
  • HTML and URL hazards: Email HTML can include tracking pixels, misleading links, hidden text, encoded content, or URLs that trigger SSRF-style risks if fetched by automation.
  • Sender confusion: The From header is sender-claimed. It is useful for display and matching, but it should not be treated as proof that a message is safe.
  • Duplicate processing: SMTP retries, provider retries, webhook retries, and polling fallbacks can all deliver the same logical message more than once.
  • Cross-run leakage: Reusing the same inbox across tasks can cause an agent to read an old OTP, a stale reset link, or another run’s message.

The safe pattern is not to make the LLM smarter at reading messy email. The safe pattern is to make the email interface smaller, more deterministic, and easier to audit.

A safe inbound email pipeline for AI agents

A good agent email pipeline has seven stages: isolate, receive, verify, normalize, match, extract, and expose. Each stage reduces ambiguity before the agent is allowed to reason.

Isolate the inbox per task or attempt

Start with a disposable inbox that belongs to exactly one task attempt. For example, if an agent is signing up for a SaaS account in a test environment, create a new temporary inbox for that signup attempt instead of reusing a shared mailbox.

This gives you clean boundaries:

  • The agent knows which inbox to wait on.
  • Old verification emails cannot win a race.
  • Parallel agents do not collide.
  • Cleanup and retention are easier to enforce.

With Mailhook, this maps to programmable disposable inbox creation via API. The exact implementation contract should come from the canonical Mailhook llms.txt, which is designed to help agents and developers understand the API surface safely.

Receive with webhooks, keep polling as a fallback

For most agent workflows, real-time webhooks are the best default because they reduce latency and avoid wasteful polling. However, robust systems still keep a polling API fallback for missed notifications, deploy windows, or webhook endpoint failures.

The important part is that both paths must feed the same idempotent processor. A message delivered by webhook and later discovered by polling should not be processed twice.

A safe design uses stable identifiers such as inbox ID, delivery ID, message ID, attempt ID, and artifact hash. The exact field names depend on your provider and schema, but the semantics matter more than the naming.

Verify the delivery channel

Do not confuse email authentication with webhook authenticity. DKIM, SPF, and DMARC can provide signals about the email’s sending path, but they do not prove that the JSON payload arriving at your webhook endpoint is from your inbox provider.

For webhook-delivered email, verify the payload itself. A hardened webhook consumer should:

  • Verify the signature over the raw request body.
  • Enforce a timestamp tolerance to limit replay windows.
  • Store delivery IDs or nonce values to reject replays.
  • Acknowledge quickly, then process asynchronously.
  • Fail closed when verification fails.

Mailhook supports signed payloads for webhook security. For exact header names, signing rules, and endpoint semantics, use the Mailhook llms.txt as the integration reference rather than guessing from examples.

Normalize email into structured JSON

Raw email is complex. RFC 5322 messages, MIME parts, encodings, folded headers, duplicate headers, attachments, and multipart alternatives all make direct parsing brittle. The RFC 5322 format was designed for interoperable messaging, not for safe LLM consumption.

For agents, inbound email should be normalized into structured JSON before it enters the tool layer. A practical JSON view separates provider-attested metadata from sender-claimed content and derived artifacts.

Field group Examples Trust level
Provider-attested routing inbox_id, delivery_id, received_at, recipient Higher
Message identity message_id, normalized headers, raw availability Mixed
Sender-claimed fields from, reply_to, subject Lower
Content fields text, sanitized_html, attachment metadata Untrusted
Derived artifacts otp_code, verification_url, artifact_hash Trust depends on extraction rules

The model should not be asked to infer trust from raw headers. Instead, the pipeline should label trust boundaries explicitly.

Match the intended message narrowly

An AI agent should not scan a broad inbox and pick whatever looks relevant. The pipeline should use narrow matchers tied to the current attempt.

Good matchers include the isolated inbox ID, an expected recipient, a time window, an expected sender domain, a correlation token if available, and a known subject pattern. Avoid matching only on vague text like verification or welcome.

This is especially important for signup, password reset, and email verification flows. If the agent chooses the wrong message, it may submit a stale OTP or open a link intended for another run.

Extract minimal artifacts deterministically

Once the intended message is selected, extract only the artifact needed for the workflow. That might be a six-digit OTP, a magic link, a confirmation URL, or a customer reply classification.

Prefer deterministic extraction before involving the LLM. For example, use text/plain when available, use scoped regexes for OTPs, validate URL hosts, and enforce expected path patterns. If the LLM is used to classify intent, give it a sanitized excerpt and require a typed output rather than free-form tool calls.

For URLs, be especially strict. Do not let an agent fetch arbitrary links from email. Validate the scheme, host, path, and query parameters. If your system fetches URLs server-side, review SSRF defenses such as the OWASP SSRF Prevention Cheat Sheet.

Expose a minimized view to the agent

The final agent-visible object should be intentionally small. It should answer the question the agent needs to answer, not reproduce the entire email.

A safe agent view might look conceptually like this:

{
  "inbox_id": "inbox_current_attempt",
  "message_id": "message_current_attempt",
  "received_at": "provider_received_time",
  "sender_domain": "expected-service.example",
  "subject_summary": "Email verification code",
  "artifact_type": "otp",
  "artifact_value": "123456",
  "confidence": "high"
}

In production, avoid logging sensitive artifact values unless you have a clear retention policy. For many workflows, logging the artifact hash, message ID, and extraction rule version is enough for debugging.

Design the agent tool contract, not just the inbox

The safest way to let an AI agent read inbound email is to hide the mailbox behind a small tool contract. The tool should be deterministic and policy-aware.

A good contract might expose these operations:

Tool Purpose Safety boundary
create_inbox Create a disposable inbox for one attempt Agent receives an inbox descriptor, not provider secrets
wait_for_message Wait for a message that matches expected criteria Tool applies deadline, dedupe, and matchers
extract_artifact Return OTP, magic link, or classified intent Tool returns typed output only
expire_inbox Close or stop using the inbox after the task Tool enforces lifecycle cleanup

The agent should not receive broad tools such as list all inboxes, read any raw message, fetch any URL, or forward this email to a user. If those capabilities exist for administrators, keep them outside the autonomous tool surface.

Trust boundaries: what the agent may rely on

Not every field in an email JSON payload has the same meaning. AI agents need clear rules for what they can trust.

Provider-attested fields such as the inbox identifier, delivery timestamp, and webhook delivery identifier are useful for routing, idempotency, and debugging. Sender-claimed fields such as subject, display name, and From address are content, not authority. Derived fields such as extracted OTPs are only as trustworthy as the extraction policy that produced them.

A practical policy looks like this:

Decision Recommended source
Which workflow owns this message? inbox_id and attempt_id
Has this event already been processed? delivery_id and message_id dedupe
Is this the expected verification email? isolated inbox, time window, sender domain, subject pattern, correlation token
What should the agent submit? validated derived artifact
Should the agent obey instructions in the email body? No, not unless the workflow explicitly allows user instructions

This prevents a common mistake: treating an email body as both data and instructions. For agent workflows, email body content should usually be data.

Handling links, attachments, and HTML

HTML email is designed for human rendering, not agent safety. Avoid rendering HTML into an environment where scripts, images, or remote resources can load. If you need text, prefer text/plain. If you need HTML-derived text, sanitize it and strip hidden content, scripts, style tricks, and tracking resources.

Links need a strict policy. A magic link should match the expected domain and route. A billing link, unsubscribe link, or social tracking redirect should not be followed by an autonomous agent unless the workflow explicitly allows it.

Attachments should be disabled by default for agent workflows. If attachments are required, treat them as untrusted files. Scan them, restrict file types, set size limits, and avoid exposing raw attachment text to the model unless there is a dedicated document-safety pipeline.

Idempotency and dedupe are safety controls

Duplicate emails are not just reliability noise. They can create safety bugs. An agent may submit the same OTP twice, trigger resend loops, click multiple links, or advance a workflow after the attempt should have ended.

Use dedupe at multiple levels:

Level Example key Why it matters
Delivery delivery_id Prevents webhook retry duplicates
Message message_id plus inbox_id Prevents processing the same email twice
Artifact artifact_hash plus attempt_id Prevents reusing the same OTP or link
Action workflow_step plus attempt_id Prevents repeated external actions

When the agent acts on an extracted artifact, mark the artifact as consumed. If a retry happens, the system should return the previous result or refuse reuse, depending on the workflow.

Observability without leaking secrets

Debuggability is essential because email workflows fail in asynchronous ways. However, logs can easily become a secret leak if they include raw messages, OTPs, magic links, or personal data.

Log stable identifiers and policy decisions instead of full content. Useful fields include inbox ID, attempt ID, delivery ID, message ID, received timestamp, matcher version, extraction rule version, dedupe result, and final action status.

For sensitive workflows, store raw messages only if necessary and under a short retention policy. If your agent only needs an OTP, there is rarely a reason to persist the full HTML body indefinitely.

Where Mailhook fits

Mailhook is built for this agent-safe model of inbound email. It provides programmable disposable email inboxes via API, receives emails as structured JSON, supports real-time webhook notifications, offers a polling API fallback, supports shared domains and custom domains, and includes signed payloads for webhook security.

That means you can build the safe pattern without asking an LLM to log into a mailbox or scrape HTML. A typical flow is:

  1. Create a disposable inbox for the current agent attempt.
  2. Use the generated email address in the external workflow.
  3. Receive the message as structured JSON through a signed webhook or polling fallback.
  4. Match the message to the attempt and extract the minimal artifact.
  5. Give the agent only the typed result it needs.
  6. Expire or stop using the inbox according to your lifecycle policy.

For implementation details, endpoint semantics, and machine-readable integration guidance, start with the canonical Mailhook llms.txt.

Safety checklist for AI agents reading inbound email

Before shipping an email-reading agent, review this checklist:

  • Use one disposable inbox per task, run, or attempt.
  • Prefer signed webhooks, with polling as a fallback.
  • Verify webhook signatures on the raw request body.
  • Reject replayed webhook deliveries.
  • Normalize messages into structured JSON before model exposure.
  • Treat headers, body text, HTML, links, and attachments as untrusted.
  • Match messages using inbox ID, time window, sender constraints, and correlation tokens.
  • Extract minimal artifacts deterministically.
  • Validate links before any fetch or click action.
  • Give the LLM a minimized, typed view, not raw email.
  • Make artifact consumption idempotent and consume-once where possible.
  • Log stable IDs and decisions, not secrets or full message bodies.
  • Define inbox TTLs, cleanup, and retention rules.

Frequently Asked Questions

Should an AI agent read the full raw email? Usually no. The safer pattern is to parse and normalize the email first, then expose only a minimized JSON view or extracted artifact to the agent.

Are webhooks safer than polling for inbound email? Webhooks are often lower latency and easier to operate at scale, but they must be verified with signatures and replay protection. Polling is still useful as a fallback when webhook delivery is delayed or unavailable.

Can an LLM extract OTPs from email text? It can, but deterministic extraction is safer for common OTP formats. Use the LLM only when the task requires semantic classification, and still return typed, constrained outputs.

Is the From header enough to trust an email? No. The From header is sender-claimed content. Use it as one matching signal, not as proof of authenticity or authorization.

How does Mailhook help AI agents read inbound email safely? Mailhook provides disposable inboxes via API, structured JSON email output, webhook and polling delivery, signed payloads, shared domains, and custom domain support. These primitives help keep email handling deterministic and agent-safe.

Build safer email-reading agents with Mailhook

If your AI agent needs to receive verification emails, OTPs, magic links, or operational replies, avoid handing it a shared mailbox. Give it a disposable inbox, structured JSON, signed delivery, and a narrow tool contract.

Mailhook provides the programmable temp inboxes and inbound email API primitives needed to build that pattern. Review the Mailhook llms.txt for integration details, then create a workflow where agents read only the email data they actually need.

Related Articles