docs/guide
Guide
Everything the four-command quickstart left out: how providers and state work, every flag that matters, what each exit code means, and what to do when something misbehaves. Flag-by-flag syntax lives on the CLI reference.
Concepts you need first
Three facts explain almost all of TossInbox's behavior.
- Providers are free public mail APIs.
mailtmis the default;guerrillamailis the fallback. No accounts, no API keys — the CLI creates the mailbox itself and keeps its credentials in local state. Runtossinbox providersto see them. - State is one local file:
~/.tossinbox/state.json, written with0600and saved atomically (v0.1.2+) — a crash mid-write can no longer truncate it. It holds the addresses + tokens of your live inboxes. Override its location withTOSSINBOX_STATE— useful for CI parallelism and tests. - TossInbox receives; it never sends. It exists to collect signup/verification mail. There is no send path, which is exactly why providers tolerate it.
Creating inboxes
spawn creates the mailbox, saves it to state, and prints
the address. Plain text for humans, --json for programs.
tossinbox spawn # default provider, plain output tossinbox spawn --json # machine-readable (ok, inbox{address,…}) tossinbox spawn -p guerrillamail # pick a provider explicitly tossinbox spawn -p mailgw --no-failover # strict: mailgw or nothing tossinbox spawn -l github-test # label it — labels show in `inboxes` tossinbox inboxes # every inbox saved in local state
If the provider you asked for is down (network error, 5xx, 429),
spawn fails over: it retries the create against the remaining providers
and reports the switch (provider : mailtm (failover from mailgw), or a
failover object in JSON).
Inboxes on the provider expire on their own schedule; the local record is
what TossInbox cleans when you toss. Neither expires just because your terminal closed.
Receiving mail and codes
Three commands: list peeks at what arrived,
read opens one message, and wait blocks until the message you
care about lands — then prints its extracted code.
| flag | meaning | default |
|---|---|---|
--code | require an extractable verification code; keep polling until one arrives | off (first message wins) |
--from, -f | only messages from this sender | any |
--subject, -s | only messages whose subject matches | any |
--timeout, -t | give up after N seconds (exit code 2) | 60 |
--interval, -i | seconds between polls | 3 |
tossinbox list # messages in the newest inbox tossinbox list -a qwd6996p1lbc@uberip.com # messages for a specific address tossinbox read 42 # full body + headers of message 42 tossinbox read 42 --save # attachments + bodies → ./tossinbox-attachments/42/ tossinbox read 42 --html # raw HTML body instead of the plain text tossinbox wait --code --from noreply@example-app.dev --timeout 120
Messages can carry attachments: read prints an
attachments block (name, size, type), and read --save [dir]
downloads every attachment plus the HTML/plain-text bodies into
<dir>/<message-id>/ (default dir: ./tossinbox-attachments).
With --json a saved array lists the exact file paths.
--html prints the raw HTML body and warns when the message has none.
Attachment downloads are full on mailtm, mailgw and
tempmailplus, partial on tempmailio (only when its upstream
exposes a URL), and absent on tempmaillol, guerrillamail and
maildrop — their upstreams never expose attachments.
Code extraction handles digits-only and letter+digit OTPs (letters come back uppercased) and understands prompts in twelve languages — English and Arabic (رمز / كود / تفعيل / تحقق), plus French, Spanish, German, Portuguese, Italian, Russian, Turkish, Chinese, Japanese, and Korean.
Cleanup: toss vs clear
Two cleanup verbs with one important difference.
tossinbox tossdeletes the inbox on the provider (where supported) and wipes its local record.toss --alldoes every saved inbox.tossinbox clearwipes local records only — no server-side deletion. Use it when the mailbox already expired upstream and you just want clean state.
tossinbox toss # delete current inbox on server + locally tossinbox toss --all # same, for every saved inbox tossinbox clear # local records only, server untouched
Exit codes (the whole contract)
Scripts should never parse human text when an exit code will do.
| code | meaning | typical cause |
|---|---|---|
0 | success | — |
1 | error | provider API failure, network error |
2 | timeout | no matching message before --timeout |
3 | not found | unknown address, no saved inbox, nothing to toss |
4 | usage error | bad flags, unknown provider, garbage values |
With --json, failures additionally print
{"ok":false,"error":"…"} on stdout before exiting non-zero.
Troubleshooting
The failures that actually happen, in the order you'll meet them.
wait exits with code 2 — the email never came
--timeout (bulk senders can take minutes), and confirm the signup email was
actually sent. If the provider is degraded, spawn a fresh inbox with
-p guerrillamail and retry.spawn fails with exit code 1
tossinbox providers. Add --no-failover when you need the
chosen provider's raw failure without the fallback tour. All HTTP calls carry a
hard 20-second timeout, so this always fails fast instead of hanging."corrupt state file" error on any command
~/.tossinbox/state.json — fix it by deleting the file (losing saved inbox
records, not your machine) or point TOSSINBOX_STATE at a fresh path.read --save says the provider does not support attachment downloads
mailtm, mailgw,
tempmailplus; tempmailio only when upstream exposes a URL;
tempmaillol, guerrillamail and maildrop have none.
Re-read the message on a supported provider. Saving the bodies alone
(body.html / body.txt) works on every provider — the error
fires only when the message actually carries attachments.Parallel test runs stomp on each other
TOSSINBOX_STATE=$(mktemp) tossinbox spawn. Nothing else is shared.