Skip to content

feat(mail): add batch subcommand, docs, and CHANGELOG (0.2.6) - #18

Merged
bscott merged 1 commit into
masterfrom
feat/mail-batch
Aug 8, 2026
Merged

feat(mail): add batch subcommand, docs, and CHANGELOG (0.2.6)#18
bscott merged 1 commit into
masterfrom
feat/mail-batch

Conversation

@bscott

@bscott bscott commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Supersedes #13, carrying forward only its unique portion.

#13 bundled three features. Two of them — the PM_CLI_BRIDGE_PASSWORD env var (#8) and the mail list server-side filtering / envelope fields / field selection (#9) — landed independently via #14 and #16, which conflicted with #13 across five files. Rather than resolve duplicate implementations of shipped features, this PR keeps only the batch command, which nothing else covers.

mail batch (closes #10)

Runs multiple label/unlabel/archive/move/flag/delete operations over a single IMAP session, avoiding a connect + auth round-trip per operation. Reads a JSON array from stdin or --file.

Validation happens up front, before any connection is opened — malformed input can't leave a mailbox half-mutated. Verified end-to-end:

$ echo '[{"op":"bogus","uids":["uid:1"]}]' | pm-cli mail batch --json
{"error": "operation 0: unknown op \"bogus\" (valid: label, unlabel, archive, move, flag, delete)", "success": false}

$ echo '[{"op":"label","uids":["uid:1"],"label":"Work\r\nX"}]' | pm-cli mail batch --json
{"error": "operation 0 (label): invalid mailbox/label name ...: contains IMAP special characters", "success": false}

CRLF/wildcard injection into mailbox and label names is rejected, input is capped at 10MB, and errors pass through safetext.SanitizeForTerminal.

Two defects fixed from #13

  1. --help-json escaping. The batch examples used \" inside backtick raw string literals, so literal backslashes leaked into the agent-facing schema. Now emits valid JSON.
  2. docs/commands.md field name. Listed seq as a --fields value; the implementation that actually shipped in feat(mail list): server-side unread/flagged filtering, envelope fields, and field selection #16 uses seq_num.

Also included

Verification

gofmt -l, go vet ./..., go test ./... clean. --help-json smoke-tested for correct rendering and version.

🤖 Generated with Claude Code

Carries forward the unique portion of #13. The env-var and mail-list
work in that PR landed independently via #14 and #16, so only the batch
command remains; this drops the duplicated implementations rather than
conflicting with what shipped.

mail batch runs multiple label/unlabel/archive/move/flag/delete
operations over a single IMAP session, avoiding a connect and auth
round-trip per operation. All operations are validated up front, so
malformed input fails before any connection is opened or any mailbox is
mutated. Names containing IMAP special characters or CRLF are rejected,
and input is capped at 10MB.

Also fixes two defects from #13:
  - The --help-json examples used \" inside raw string literals, which
    emitted literal backslashes into the agent-facing schema.
  - docs/commands.md listed `seq` as a --fields name; the implementation
    that shipped in #16 uses `seq_num`.

Adds a CHANGELOG covering everything in 0.2.6 and bumps the version.

Closes #10.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@bscott
bscott merged commit a97b754 into master Aug 8, 2026
1 check passed
@bscott
bscott deleted the feat/mail-batch branch August 8, 2026 23:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: mail batch subcommand for multi-op IMAP sessions

1 participant