Agent Workflow · Auth E2E

Giving the agent a real inbox it can read.

When the agent is wiring up auth on sitzio.de, it needs to actually complete the signup loop — receive the verification email, extract the magic link or code, click it, and assert the user lands logged in. Mailosaur gives every test run a disposable email address on a real domain, then lets the agent pull that inbox down as JSON via a single HTTP call.

Real MX records
Yes
Supabase, Clerk, Auth0 actually deliver
Addresses per server
Any local-part @<id>.mailosaur.net
Free tier
500/mo
1 server, plenty for CI auth runs
Arrival latency
~1–3s
Agent polls, rarely waits long
01 · THE SHAPE OF THE PROBLEM

Auth flows need a real email round-trip.

Mailpit can't help here — the site's auth provider sends from its SMTP, not ours. The agent is a consumer of mail, not a producer. What we need is a disposable inbox with a read API.

● Problem

Signup succeeds — then what?

Agent fills the signup form on sitzio.de with a guessed address. Supabase queues the verification email. The magic link goes… into the ether. No inbox, no verification, auth flow half-tested.

Using the developer's Gmail is slow, manual, and leaks between test runs.

● Solution

One domain, infinite fresh inboxes.

Mailosaur owns a domain like xyz123.mailosaur.net. Any address you invent at that domain is instantly a valid inbox: run-42@xyz123.mailosaur.net, abc@xyz123.mailosaur.net, whatever.

Agent generates a unique address per run, waits for mail, reads the body via API, extracts the link, completes the flow.

02 · ARCHITECTURE

How the round-trip closes.

The agent drives the browser (or HTTP client), Supabase/Clerk/Auth0 does its real thing, Mailosaur catches the outbound mail, and the agent reads it back. No local SMTP interception, no DNS tricks — auth provider config stays exactly as it runs in production.

graph LR
  A["AI Agent
(CLI + browser)"] -->|"1. signup form
email = run-42@xyz.mailosaur.net"| B["sitzio.de
auth UI"] B -->|"2. create user"| C["Auth Provider
(Supabase / Clerk / Auth0)"] C -->|"3. SMTP send
magic link"| D[("Mailosaur
MX records")] D -->|stores| E[["Inbox
@xyz.mailosaur.net"]] A -->|"4. GET /messages
?server=xyz&sentTo=..."| F{{"Mailosaur API
api.mailosaur.com"}} F -->|reads from| E F -.->|"5. JSON: body + links"| A A -->|"6. follow magic link"| B B -->|"7. user verified"| G(["✓ Auth flow passed"]) classDef agent fill:#7c3aed,stroke:#a78bfa,color:#fff,stroke-width:2px classDef site fill:#1e293b,stroke:#22d3ee,color:#e2e8f0,stroke-width:2px classDef provider fill:#334155,stroke:#64748b,color:#e2e8f0,stroke-width:1.5px classDef mailosaur fill:#164e63,stroke:#22d3ee,color:#cffafe,stroke-width:2px classDef success fill:#365314,stroke:#a3e635,color:#ecfccb,stroke-width:2px class A agent class B site class C provider class D,E,F mailosaur class G success
Why this pattern is clean. The auth provider runs its real SMTP config — same production code path, same DKIM, same templates. The only thing that changes is the recipient domain, which the agent controls at signup time. Zero production drift.
03 · THE LOOP

Six steps the agent runs on every auth test.

Every step is a single CLI call or browser action. The unique-per-run address in step 1 is what keeps parallel test runs from stepping on each other.

01 · MINT
Generate address
run-$(uuid)@<id>.mailosaur.net
02 · SIGNUP
Submit form
POST to sitzio.de signup with the minted address.
03 · TRIGGER
Provider sends
Supabase/Clerk queues the verification email.
04 · POLL
Read inbox via API
Poll /messages?sentTo=... until found.
05 · EXTRACT
Pull the link
Mailosaur parses links & codes out of the body for you.
06 · ASSERT
Follow & verify
Agent hits the link, confirms user is authenticated.
04 · API COMMANDS

What the agent actually calls.

Auth header on every request: Authorization: Basic $(echo -n api:$MAILOSAUR_API_KEY | base64). Replace $SERVER with your Mailosaur server ID.

Purpose Call What comes back
Wait for mail GET /api/messages/await?server=$SERVER&sentTo=run-42@$SERVER.mailosaur.net Blocks until a message arrives or times out. The agent's go-to.
List messages GET /api/messages?server=$SERVER All recent messages on the server with metadata.
Search by recipient POST /api/messages/search {"sentTo": "run-42@..."} Filter by to / from / subject / body text.
Read full message GET /api/messages/<id> HTML + text body, headers, attachments, parsed links and codes.
Clear server DELETE /api/messages?server=$SERVER Wipe everything between suites. Good hygiene.
Delete one DELETE /api/messages/<id> Per-message cleanup when running suites in parallel.
Killer feature. message.html.links[] and message.html.codes[] come pre-extracted in the response. The agent doesn't need to regex magic links out of HTML — Mailosaur already did it. Pull the first link, navigate, done.
05 · THE CONTRACT

Drop this into CLAUDE.md.

Once the agent has these three env vars and the protocol below, auth testing becomes a deterministic loop. No more "I assume the email was sent" hand-waving.

# Auth Testing — Mailosaur

# Mailosaur credentials — get from app.mailosaur.com
MAILOSAUR_API_KEY="<your api key>"
MAILOSAUR_SERVER_ID="<8-char id>"
MAILOSAUR_DOMAIN="${MAILOSAUR_SERVER_ID}.mailosaur.net"

# API base
MAILOSAUR_API=https://mailosaur.com/api

## Protocol for ANY auth-flow change on sitzio.de

  1. Mint a per-run address:
       EMAIL="run-$(date +%s)-$(openssl rand -hex 3)@$MAILOSAUR_DOMAIN"

  2. Submit signup / login form with $EMAIL

  3. Await the verification mail (blocks up to 10s):
       curl -s -u "api:$MAILOSAUR_API_KEY" \
         "$MAILOSAUR_API/messages/await?server=$MAILOSAUR_SERVER_ID&sentTo=$EMAIL"

  4. Parse the response — use message.html.links[0].href
     (or message.html.codes[0].value for OTPs)

  5. Follow the link / submit the code, then assert the
     authenticated session exists (cookie, /me returns 200, etc.)

  6. Clean up:
       curl -X DELETE -u "api:$MAILOSAUR_API_KEY" \
         "$MAILOSAUR_API/messages?server=$MAILOSAUR_SERVER_ID"

  RULES:
  - NEVER use a hardcoded email for auth tests — always mint a fresh one.
  - NEVER skip step 5; SMTP acceptance != user verified.
  - If await times out, the auth provider's SMTP config is broken — report, don't retry blindly.
06 · WHAT IT COSTS

Free tier covers our use case.

One server, 500 emails/month. An auth test burns ~1–3 emails (signup + maybe password reset). That's ~150–500 test runs a month on zero dollars.

Free
$0 / mo
Start here. Upgrade when we outgrow it.
  • 1 virtual server
  • 500 emails / month
  • Email + SMS inboxes
  • Full REST API access
  • Link & code extraction
Starter
$9 / mo
If CI runs a lot of parallel tests.
  • 3 servers
  • 5 000 emails / month
  • 30-day message retention
  • Spam analysis
Team
$49 / mo
Own your inbox domain for real prod-shaped tests.
  • 10 servers, unlimited addresses
  • 50 000 emails / month
  • Custom domain (inbox.sitzio.de)
  • Webhooks on receive
Path forward. Start on Free. When we're running sitzio.de auth tests several times a day across branches, the Starter tier pays for itself in engineer minutes saved. The Team tier is only relevant if we want auth emails going to a subdomain we actually own — matters for e.g. DMARC-strict providers, not for day-to-day testing.