DocumentationFundamentals

Create & poll email addresses from the CLI

Use the relay CLI to create inbound email addresses and consume the messages they receive. Create an address in one command (with an optional sender filter), then poll the bucket for parsed emails as JSON — one-shot, follow mode, or piped into jq.

The relay CLI can create inbound email addresses and consume the messages they receive, without opening the dashboard. It's the quickest way to grab a throwaway inbox, wire an address into a script, or watch mail arrive in your terminal.

Two commands do the work:

  • relay email create — create an inbound address (optionally on a fresh throwaway bucket).
  • relay events — pull the parsed emails from the bucket as they arrive.

You need the CLI installed and authenticated first — see Install the CLI. All commands accept a bucket by name or ID.

Create an address

The fastest path — no arguments — creates a throwaway bucket and prints a ready-to-use address:

$ relay email create
Inbound email address created.

  Address:  [email protected]
  Bucket:   email-c8e44869  (9bf342ce-9582-42ea-8662-ac73d60e2db6, created for you)
  Input:    eb9649a3-b781-4158-be69-bb210596e759

Poll it with:
  relay events --bucket email-c8e44869 --follow

The address is the input's ID at your environment's inbound domain (<input-id>@in.webhookrelay-mail.com). Send mail to it and every message is parsed into JSON and stored on the bucket.

Attach the address to an existing bucket with --bucket, and restrict who may send with --filter-from (repeatable; exact-match sender allowlist):

# Into an existing bucket, only accept mail from one sender
relay email create --bucket signups --filter-from [email protected]

# Several allowed senders, drop attachments, give it a name
relay email create --bucket signups \
  --name "stripe-receipts" \
  --filter-from [email protected] \
  --filter-from [email protected] \
  --no-attachments

For scripts, --json prints the address and IDs as JSON:

$ relay email create --bucket signups --name stripe-receipts --filter-from [email protected] --json
{
  "email_address": "[email protected]",
  "input_id": "15a51b42-7de4-42ff-8628-4645565fa8b1",
  "bucket_id": "9bf342ce-9582-42ea-8662-ac73d60e2db6",
  "bucket_name": "signups",
  "allowed_senders": ["[email protected]"]
}

# Capture just the address
$ ADDR=$(relay email create --json | jq -r .email_address)
When you don't pass --bucket, relay email create provisions a throwaway bucket for the address. If the address can't be created afterwards, that throwaway bucket is cleaned up automatically — a bucket you pass with --bucket is never removed.

relay email create flags

FlagDescription
-b, --bucket <name|id>Bucket to attach the address to. A throwaway bucket is created if omitted.
--name <string>Friendly name for the email input.
--filter-from <addr>Only accept mail from this sender (repeatable; exact, case-insensitive match).
--no-attachmentsDrop attachments instead of storing them.
--jsonOutput the created address as JSON.

List addresses in a bucket

Lost an address? List a bucket's inbound addresses:

$ relay email list --bucket signups
ADDRESS                                                        NAME             FILTER              STATUS
[email protected]  stripe-receipts  [email protected]  -
[email protected]  -                any sender          -

Add --json for the full objects (including email_input policy).

Poll for email

relay events consumes the bucket's pull-delivery queue: each call returns the emails that haven't been delivered yet and marks them delivered, so repeated calls drain the queue. Inbound emails show up with their sender and subject:

$ relay events --bucket signups
ID                                    AGE        FROM                SUBJECT
373e52cb-764e-4f0f-9c8f-6b1e2a0d9f11  6 seconds  [email protected]  Your receipt

Use --follow (like tail -f) to block and print new emails as they land:

relay events --bucket signups --follow

Pull a larger batch, look further back, or restrict to a single output:

# Up to 50 per poll, looking back 1 hour
relay events --bucket signups --limit 50 --max-age 1h

# Only events routed to a specific output
relay events --bucket signups --output out_1a2b

Scripting

--json emits the full event objects; --body emits just the parsed-email JSON (one per line), which is handy for piping into jq:

# Extract sender + subject of each email
relay events --bucket signups --json | jq '.[].body | fromjson | {from, subject}'

# Stream raw parsed emails
relay events --bucket signups --body

# Only the event IDs (e.g. to feed into `relay inspect`)
relay events --bucket signups -q

relay events flags

FlagDescription
-b, --bucket <name|id>Bucket to consume from (required).
--output <id>Only consume events for this output ID.
--limit <n>Max events per poll (max 100; CLI default 20).
--max-age <dur>How far back to look for undelivered events (Go duration, e.g. 1h; server default 24h).
-f, --followKeep polling and print new events as they arrive.
--interval <dur>Poll interval when following (default 2s).
--jsonOutput full event objects as JSON.
--bodyPrint only the raw event bodies (parsed email JSON).
--format <tmpl>Pretty-print events using a Go template.
-q, --quietOnly display event IDs.

How polling works

relay events is a consuming queue: returning an email to you is its delivery, so each row is marked delivered (RECEIVED → SENT) before the response is sent and won't appear on the next poll. This makes it a reliable "process each email once" channel:

  • The queue drains — keep polling (or use --follow) until you get an empty page.
  • If you consumed an email but failed to handle it, correct the outcome afterwards with relay api (PUT /v1/logs/{id}) so it can be retried.
  • For a non-destructive view of everything a bucket received, use relay logs and relay inspect instead — they read the audit log without consuming.
Did this page help you?