Skip to main content

Email Testing

Hooklistener gives you real email addresses at @hookinbox.com that capture every message sent to them, so you can check the emails your app sends without running a mail server. Each captured email comes back with its one-time code and its confirmation link already extracted, which keeps the two most common jobs short.

Test signup and login emails from CI​

Your end-to-end test signs up with a unique address, waits for the email through the REST API, and types the code or opens the link:

CODE=$(curl -sf -G "https://app.hooklistener.com/api/v1/inboxes/$INBOX_ID/emails/wait" \
-H "Authorization: Bearer $HOOKLISTENER_API_KEY" \
--data-urlencode "to=$ADDRESS" --data-urlencode "since=$SINCE" -d timeout=60 \
| jq -r '.data.code // empty')

Test emails in CI →

Test them from an AI agent​

Claude Code, Codex, Cursor and other agents connected to the MCP server create an inbox, sign up with it, wait for the email and finish the flow on their own:

"Sign up on http://localhost:3000 with a Hooklistener inbox, then confirm the account with the link from the email."

Test emails with AI agents →

No Hooklistener account yet? A script or an agent can create an inbox without an account with one request.

What you get for each email​

FieldContents
codeThe likely one-time code (the first entry of codes)
verification_linkThe link most likely to confirm the address, sign in, reset a password or accept an invite; null when no link looks like one
codes, linksEvery standalone 4 to 8 digit number and every http(s) link in the email
textThe text body, or the HTML body rendered as plain text
text_body, html_bodyThe bodies as sent
headers, header_listParsed headers (first value of each name), and every header in order
attachmentsAttachments and inline images, each with a download_url

The REST API, the MCP tools and webhook forwards all return these fields. See Get an email for how codes and links are picked.

Keep parallel runs apart​

Mail to <slug>[email protected] lands in the same inbox as <slug>@hookinbox.com. When you wait for an email:

  • Sign up with a unique plus-address for each run or test (<slug>[email protected]) and filter on it with to. Parallel runs never read each other's mail.
  • Record a since timestamp before you trigger the email. The wait then returns an email that arrived after that moment even if it came before the wait started, and ignores older mail to the same address.

More features​

  • Dashboard: new emails appear in real time, with bodies, headers and attachments. Create an inbox →
  • Clean up: delete one email, clear an inbox (which frees the Free plan's email allowance at once) or delete the inbox, from the dashboard, the API or an agent.
  • Forward email to webhooks: POST every received email as signed JSON to your app, for reply-by-email or ticket ingestion. Forward email to webhooks →

Limits and retention​

FreeProProductionScale
Inboxes15UnlimitedUnlimited
Emails per inbox10 per rolling 24 hoursUnlimitedUnlimitedUnlimited
Emails kept for1 day14 days30 days90 days
Webhook forwards per inbox—3UnlimitedUnlimited
  • Emails are kept as long as your plan keeps request history, then deleted automatically.
  • On Free, mail over the limit is rejected until older emails leave the 24-hour window, or until you clear the inbox.
  • Inboxes without an account have their own limits.

See Plans & Billing for everything else each plan includes.

Use cases​

  • Signup, magic-link, OTP and password-reset flows: check that the email arrives and that the code or link works, from a test or an agent
  • Transactional emails: check subjects, copy, links and headers in staging
  • Staging and CI mail: point your app's SMTP settings at an inbox, so every email it sends is captured and none reach real people
  • Attachments: check the invoices, receipts and exports your app sends
  • Inbound email features: forward captured email to your reply-by-email or ticketing handler

Getting started​

Create your first inbox →