How AI Agents Handle Email Verification Codes (OTP) Automatically
Ask an agent to sign up for a service and the flow runs smoothly — until the service says "we sent a 6-digit code to your email." If the agent has no inbox, the task ends there, waiting for a human. This article explains how agents handle email verification codes properly: their own inbox, automatic code extraction, and the safety checks around it.
The pattern that works
- The agent owns an inbox before it needs one (create it at agent setup time, not mid-task).
- It uses that address at sign-up.
- It watches its inbox — by webhook, or by polling the messages endpoint for a few minutes.
- It reads the code from the message's
extracted_codefield — no HTML parsing, no guessing which number in the email is the code. - It completes the verification and continues the task.
Automatic extraction, concretely
On BotsInbox, every incoming message is processed on arrival. When the subject or body contains a verification code, it is extracted and stored on the message:
GET /v0/inboxes/{id}/messages
{ "from_addr": "noreply@service.example",
"subject": "Your verification code",
"extracted_code": "482916", ... }
The same field is returned by the MCP get_message and list_messages tools, and included in message.received webhook payloads — so whichever way your agent consumes email, the code is one field away.
Why not just parse the email yourself?
You can, and for one service it works. Across many services it gets brittle: codes appear in subject lines, in HTML buttons, split by spaces, next to other numbers (dates, prices, order IDs). Centralising extraction where the email is received means every agent benefits from the same hardened parsing — and the full body remains available as a fallback.
The security details that matter
- Prompt injection: an inbox is an attack surface — anyone can email your agent instructions. BotsInbox flags suspicious messages with
prompt_injection_suspectedso the agent (and its framework) can treat email content as data, never as commands. - Expected sender: when waiting for a code, match on the sender and recency, not just "any code in the inbox".
- Expiry: codes usually live for minutes. Poll briefly and give up cleanly rather than reusing a stale code.
- Secrets hygiene: the API key that reads the inbox is a credential — keep it in your secret store, not in prompts or code.
A note on acceptance
Some services filter sign-ups from very new domains or shared domains, and a few block non-human sign-ups in their terms. An agent-owned inbox removes the technical blocker; respecting each service's terms remains the operator's job — the same judgement call as any other automation.