Skip to content

Mail Commands

Mail commands live under broodnet mail. All commands connect to your mailbox over IMAP or SMTP using credentials stored in your local config.

broodnet mail inbox lists messages in INBOX with optional pagination, sort order, and flag filters. By default, messages are returned most-recent first.

FlagDefaultDescription
--limit <number>20Number of messages to fetch. Must be a positive integer.
--offset <number>0Number of matching messages to skip. By default, the newest. Used with --limit to page through results.
--sort <direction>newestSort order for the listing. Allowed values: newest, oldest.
--unreadShow only unread messages.
--read / --seenShow only read messages.
--important / --flaggedShow only messages the user has marked as important.
--answeredShow only messages that have been answered.
--unansweredShow only messages that have not been answered.
--mailbox <address>active mailboxMailbox address to use when multiple are configured.
--jsonPrint a structured JSON envelope with the full listing (messages, total, pagination, filters, sort) as data.

Filters combine with AND — e.g. --unread --important returns messages that are both unread and important. Contradictory pairs (such as --unread --read or --answered --unanswered) are rejected before any server call. Invalid sort values are also rejected before any server call.

Use --offset with --limit to page through results. With the default --sort=newest, pages are counted from the most recent matching message. With --sort=oldest, pages are counted from the oldest matching message.

Terminal window
# First page of 20 (default)
broodnet mail inbox
# Second page of 20
broodnet mail inbox --limit=20 --offset=20
# First page from oldest to newest
broodnet mail inbox --sort=oldest
# Third page of 50
broodnet mail inbox --limit=50 --offset=100

Filters are applied before pagination, so --offset advances through the filtered set in the selected sort direction. If --offset lands past the last match, the command returns an empty result without error.

In interactive terminals, the default output is a table preceded by a summary line showing the current page range, the total number of matching messages, and any active filters.

showing 1-20 of 142 · filters: unread, important
UID FLAGS FROM SUBJECT DATE
...

The summary adapts to the result:

  • inbox is empty — no messages at all and no filters active
  • no messages match · filters: unread — filters are active but nothing matches
  • showing 0 of 42 · offset 100 is past end--offset landed past the last match
ColumnDescription
UIDStable message identifier used by mail open, mail mark, and mail delete
FLAGS unseen · seen · answered · flagged · forwarded
FROMSender
SUBJECTSubject line
DATEMessage date

With --json, data is the full listing envelope so callers can drive pagination and surface totals without re-parsing the table:

  • messages — page of message summaries (uid, flags, from, subject, date)
  • total — total number of messages matching the active filters (before pagination)
  • limit — page size used for this listing
  • offset — offset used for this listing
  • sort — sort direction applied to the listing: newest or oldest
  • filters — the filter set the server applied, e.g. { "seen": false, "flagged": true }. Empty object means no filters were applied.
Terminal window
# Default: latest 20 messages
broodnet mail inbox
# Larger page
broodnet mail inbox --limit=50
# Paginate: second page of 20
broodnet mail inbox --limit=20 --offset=20
# Oldest first
broodnet mail inbox --sort=oldest
# Only unread messages
broodnet mail inbox --unread
# Only important (flagged) messages
broodnet mail inbox --important
# Unread AND important
broodnet mail inbox --unread --important
# Unanswered messages, as JSON
broodnet mail inbox --unanswered --json

broodnet mail open <uid> fetches a message from INBOX by its UID, marks it as read, and prints it.

If the requested UID does not exist, the command exits non-zero with error: message <uid> not found. In --json mode, the error envelope uses code: "NOT_FOUND".

FlagRequiredDescription
<uid>yesMessage UID — get it from broodnet mail inbox
--mailbox <address>noMailbox address to use when multiple are configured
--rawnoPrint the full raw message source including all headers
--jsonnoPrint a structured JSON envelope with the message as data

--raw and --json are independent flags: --raw controls what content is printed (parsed view vs full RFC822 source), --json controls how it is printed (plain text vs JSON envelope).

  • Default — prints a compact header (from / to / subject / date, plus Cc / Bcc when present) followed by the message body. If the message has no plain-text part, the body is automatically converted from its HTML content.
  • --raw — prints the full raw message source as received from the server.
  • --json — prints a JSON envelope with the parsed message as data.
  • --raw --json — prints a JSON envelope whose data is { uid, raw }. The raw RFC822 source has everything; the envelope carries only the UID alongside it.

With --json (without --raw), data includes:

  • uid — message UID
  • flags{ seen, answered, flagged, forwarded } booleans
  • from — formatted primary sender
  • to — formatted primary recipient
  • cc / bcc / replyTo — arrays of formatted addresses; empty when the message has none
  • subject — subject line
  • date — ISO 8601 timestamp
  • body — plain-text body (falls back from HTML if needed)

With --raw --json, data is { uid, raw } — no parsed fields.

Terminal window
broodnet mail open 1234
broodnet mail open 1234 --json
broodnet mail open 1234 --raw
broodnet mail open 1234 --raw --json

broodnet mail watch is a shortcut for mail inbox + mail open: it waits for the latest message and opens it, with output identical to broodnet mail open <uid>. Designed for flows where you trigger an email (sign up, request an OTP, invite a teammate) and want the contents on stdout without copying a UID.

Two explicit timers, both fixed:

  • 60-second past window. If the newest message in the inbox arrived within the last 60 seconds, the command opens it immediately.
  • 60-second poll budget. Otherwise, the command checks the inbox every 3 seconds for up to 60 seconds and opens the first new message that arrives.

If nothing new arrives within the poll budget, the command exits non-zero with error: no new message arrived within 60s.

FlagRequiredDescription
--mailbox <address>noMailbox address to use when multiple are configured
--jsonnoPrint a structured JSON envelope with the message as data

On success, the output matches broodnet mail open <uid> exactly — compact headers followed by the text body. In interactive terminals, a one-line progress notice is written to stderr while polling (suppressed in --json mode so JSON consumers get clean stdout).

On timeout, error: no new message arrived within 60s is written to stderr and the command exits with code 1.

If a newly detected message disappears before it can be opened, the command surfaces the same not-found response as mail open: message <uid> not found with code: "NOT_FOUND" in --json mode.

Terminal window
# Wait for an OTP right after signing up
broodnet mail watch
# Pipe the body to another tool (e.g. extract a code)
broodnet mail watch | grep -Eo '[0-9]{6}' | head -1
# Agent-friendly: JSON envelope on stdout
broodnet mail watch --json
# Watch a specific mailbox
broodnet mail watch --mailbox=agent@example.com

broodnet mail send sends an email from your active mailbox over SMTP. The message body comes from --body or stdin.

FlagRequiredDescription
--to <addresses>yesRecipient addresses, comma-separated
--subject <text>noEmail subject; if omitted, the message is sent with an empty subject
--body <text>noInline message body; if omitted, reads from stdin
--from <address>noSender address — defaults to the configured from default, then the mailbox address
--cc <addresses>noCC recipients, comma-separated
--bcc <addresses>noBCC recipients, comma-separated
--jsonnoPrint a structured JSON envelope with the send result as data

Broodnet mailboxes can only send to addresses within the same organization. External addresses are blocked at the infrastructure level and cannot be bypassed — this applies to SMTP, CLI, API, and MCP equally. See Sending Email for the full policy.

The body is read from --body if provided. Otherwise from stdin — pipe, redirect, or heredoc all work.

Terminal window
# Inline body
broodnet mail send --to=alice@example.com --body="Hello world"
# Piped body
echo "Hello world" | broodnet mail send --to=alice@example.com
# Redirected file
broodnet mail send --to=alice@example.com --subject="Report" < report.txt
# Heredoc
broodnet mail send --to=alice@example.com --subject="Hello" <<'EOF'
Line one
Line two
EOF
Terminal window
# Basic
broodnet mail send --to=alice@example.com --body="Hi!"
# With subject
broodnet mail send --to=alice@example.com --subject="Hello" --body="Hi!"
# With CC and BCC
echo "Notes" | broodnet mail send --to=alice@example.com --cc=bob@example.com --bcc=carol@example.com --subject="Notes"
# From a specific mailbox
echo "Hi" | broodnet mail send --from=agent@org.broodnet.email --to=alice@example.com --subject="Hi"
# JSON output
echo "Done" | broodnet mail send --to=alice@example.com --subject="Done" --json

With --json, the result envelope includes:

  • messageId — server-assigned message ID
  • to — list of accepted recipient addresses
  • rejected — list of addresses the server rejected
  • subject — the subject as sent; empty string when omitted

broodnet mail mark <uid...> sets or clears supported IMAP flags on one or more messages without opening or deleting them.

FlagRequiredDescription
<uid...>yesOne or more message UIDs to update
--seennoMark the selected messages as read
--unseennoMark the selected messages as unread
--flaggednoMark the selected messages as flagged
--unflaggednoRemove the flagged marker from the selected messages
--mailbox <address>noMailbox address to use when multiple are configured
--jsonnoPrint a structured JSON envelope with affected UIDs as data

At least one flag change is required. Contradictory pairs are rejected before any server call:

  • --seen --unseen
  • --flagged --unflagged

Different flag families can be combined in one call, for example --seen --flagged.

With --json, data includes:

  • marked — the list of UIDs submitted for update
Terminal window
broodnet mail mark 1234 --seen
broodnet mail mark 10 11 12 --flagged
broodnet mail mark 1234 --seen --flagged
broodnet mail mark 1234 --unflagged --mailbox=agent@example.com
broodnet mail mark 1234 --seen --json

broodnet mail delete <uid...> permanently deletes one or more messages by UID. Deletion is immediate and irreversible — messages are expunged from the server.

FlagRequiredDescription
<uid...>yesOne or more message UIDs to delete
--mailbox <address>noMailbox address to use when multiple are configured
--yesnoSkip confirmation prompt. Required in non-interactive mode.
--jsonnoPrint a structured JSON envelope with deleted UIDs as data

In interactive terminals, the command prompts for confirmation before deleting. Pass --yes to skip the prompt. In non-interactive environments (scripts, CI), --yes is required — the command will fail without it.

Terminal window
broodnet mail delete 1234
broodnet mail delete 10 11 12
broodnet mail delete 1234 --mailbox=agent@example.com
broodnet mail delete 1234 --yes

broodnet mail config views or updates per-mailbox defaults. The only configurable default is the sender address (from), which mail send uses when --from is not passed.

FlagRequiredDescription
--from <address>noSet the default sender for this mailbox. Must be verified. Omit to view current config.
--mailbox <address>noMailbox to view or update (defaults to active mailbox)

The --from value must be a valid email address or Display Name <email> format, and must be a verified sender for the mailbox. If validation fails, the command exits with an error and the config is unchanged.

Running broodnet mail config with no flags prints the current config for the active mailbox.

Terminal window
# View current defaults
broodnet mail config
# Set a default sender
broodnet mail config --from='Agent Bot <agent@acme.com>'
# Set defaults for a specific mailbox
broodnet mail config --mailbox=agent@broodnet.com --from=agent@acme.com
# View as JSON
broodnet mail config --json

broodnet mail status shows the current state of a mailbox: its address, configured sender default, connection settings, last sync time, and live storage usage.

FlagRequiredDescription
--syncnoForce a sync from the server before displaying
--mailbox <address>noMailbox to inspect (defaults to active mailbox)

Storage is shown as used / quota MiB (percent%). If the server is unreachable, the command still prints the locally cached config — storage is omitted.

With --json, data includes:

  • mailbox — the mailbox address
  • from — configured sender default, or null
  • host / port — connection settings
  • lastSync — ISO 8601 timestamp of the last sync, or null
  • storage{ quotaUsed, quota, percentInUse, unit: "MiB" }, or null if unavailable
Terminal window
broodnet mail status
broodnet mail status --sync
broodnet mail status --mailbox=agent@example.broodnet.com
broodnet mail status --json