Imported from kpihx-labs/mail-proxy (
AGENTS.md). Install upstream withnpx skills add kpihx-labs/mail-proxy. Copyright stays with the author.
mail-proxy ā Agent Context
Project
Non-MCP CLI proxy for IMAP/SMTP mail. The full mail-mcp catalog (25 MCP tools) refactored into
36 flat do actions, built on the exact ADN of tick-proxy ($HOME/Labs/KpihX-Labs/tick_proxy):
single binary, do + admin namespaces, meta+data envelope, docstring-driven --help,
HITL web UI, autosave. No Docker, no MCP transport, no daemon.
Design reference: CONTRACT.md ā read it before touching anything.
Status: š¢ IMPLEMENTED. The registry contains 36 actions and
make checkis the mandatory quality gate.CONTRACT.mdremains the architecture contract.
Overview
mail-proxy do <action> [payload|file] [-o path] [-f json|table] # 36 RPC actions
mail-proxy admin setup|status|reset|purge # ALWAYS JSON
Key Files
| File | Role |
|---|---|
src/mail_proxy/cli.py |
ONE Typer app: do + admin sub-typers, built from the registry |
src/mail_proxy/client.py |
MailClient ā resolved account + lazy IMAP connection + stateless SMTP |
src/mail_proxy/config.py |
~/.config/mail-proxy/.env loader + documented ACCOUNTS catalog + overrides |
src/mail_proxy/models.py |
SHARED types only: Output, OutputMeta, Verification, Status |
src/mail_proxy/doc.py |
Dynamic --help injection from docstrings |
src/mail_proxy/display.py |
Rich output helpers (print_json, print_table) |
src/mail_proxy/logger.py |
stderr logger ā systemd/journald captures (tg-proxy ADN, no file) |
src/mail_proxy/exceptions.py |
MailProxyError, MailAPIError |
src/mail_proxy/hitl.py |
HITL web UI (free port, browser auto-open) |
src/mail_proxy/api/ |
Low-level mail layer: imap.py, smtp.py, models.py (domain models) |
src/mail_proxy/actions/ |
The 36 actions: ActionDef + colocated Pydantic payload + handler |
src/mail_proxy/actions/registry.py |
name ā ActionDef map; duplicates raise at import |
src/mail_proxy/actions/attachments.py |
Attachment download: default ~/Downloads/Mail-Proxy/<account-id>/, explicit file or trailing-slash directory |
src/mail_proxy/admin.py |
Single source of truth for admin logic (setup, status, reset, purge) |
CONTRACT.md |
Architecture contract + full 36-action catalog |
Key Rules
- stdout is pure JSON. Logs, HITL prompts, progress ā stderr.
mail-proxy do ⦠| jqmust never break. - Never write secrets into the repo. The only secret location is
~/.config/mail-proxy/.env(chmod 600).mail-mcp's in-packagesrc/mail_mcp/.envis an anti-pattern that must not be reproduced. - Adding an action = adding ONE
ActionDef. Never register a command directly incli.py. - The docstring IS the documentation. Mandatory sections: description,
Parameters:,Examples:with ā„3 realāoutputs per action (KĻX rule 2026-08-12; ā„5 forraw).doc.pyrenders them into--help; there is no second doc surface. - Envelope always.
{"meta":{"status","comment","edited"},"data":ā¦}ā errors exit 1, admin misuse (--format/-o) exits 2. - Verification is not optional for the 8 declared writes ā
message-move,message-archive/trash/spam,message-mark,label-set,message-delete,folder-delete. It is enforced by the@require_verificationdecorator on the handler ā no flag, no bypass. There is no verification field inmeta: only verified actions add a proof atdata.verification. - No Docker, ever in this repo (explicit KĻX decision, same as
tick-proxy). - Every HITL declaration is visible. A handler requiring review must carry
@require_approval;action_def()derives HITL policy from it. Never usehitl=Truedirectly in a production action definition. - Irreversible HITL starts with a locked preflight. Every delete carries
@require_preflight(check=..., identity_fields=...): it reads every destructive target before a review page can open, then rejects a reviewer-edited target identity. The approved write only acts on the preflighted resource; absent IDs never consume a HITL cycle. - Compose actions (send/reply/forward/draft) always require HITL ā they reach other people or write content to the mailbox. Reversible moves/flag/label changes run without HITL but their read-back verification is mandatory.
Mail gotchas (silent failures ā no error, data simply not applied)
| Operation | Gotcha | Correct approach |
|---|---|---|
| Move/delete UIDs | a stale UID or folder race can leave part of the batch untouched (200-style silent partial failure) | @require_verification read-back on all target UIDs |
| Flag / keyword writes | partial application across UIDs is invisible in the response | verification requires the state on EVERY target UID |
| Raw IMAP commands | a raw command on the shared imapclient connection can corrupt its response parser | raw runs on a dedicated imaplib connection, closed right after |
| Sent copy / bounce probe | the Sent-copy append is best-effort ā it must never fail the send | except Exception around the append; saved_to_sent reports honestly |
| Shell env vs file | os.environ.setdefault means an exported MAIL_* var wins over the file |
document it; change the shell or the file, never both silently |
Admin invariants
admin setupwrites ONLYMAIL_<ID>_LOGIN/MAIL_<ID>_PASS(+ optional overrides) to~/.config/mail-proxy/.env(chmod 600, dir 700). No password ever enters the repo.admin statusprobes IMAP (connect + login) and SMTP (connect + ehlo) with real connections; missing credentials skip the network and report theadmin setuphint.adminnever accepts--formator--output-fileā exit 2 on misuse.admin resetclears the file;admin purgedeletes the config dir and prints theuv tool uninstall mail-proxyhint (never uninstalls from within the running process).
Commands
make check # smoke + ruff check --fix + ruff format + py_compile + pyright + pytest
make smoke # mail-proxy do --help + registry integrity (36 actions, 0 duplicates)
make uv-link # editable install (dev)
make uv-install # uv tool install . --force
make git-push # push to github + gitlab
make release # check ā git-push ā uv-publish
Reference implementations
| Repo | Role |
|---|---|
$HOME/Labs/KpihX-Labs/tick_proxy/ |
ADN source ā CLI shape, doc.py, hitl.py, envelope, autosave, Makefile, registry |
$HOME/Labs/KpihX-Labs/tg_proxy/ |
ADN origin ā the tg-proxy model tick-proxy itself follows |
$HOME/Work/AI/MCPs/mail_mcp/ |
Content source ā 25 tools, IMAP/SMTP core, response shapes. Keep as reference until parity, then archive. |
Evolution Rules
- New feature ā update
TODO.mdfirst, propose before acting. - Significant change ā update
CONTRACT.md+AGENTS.md+README.md+CHANGELOG.md. - Breaking change ā bump version in
pyproject.toml+CHANGELOG.mdentry. - Destructive / architectural ā stop and confirm with KĻX first.
sudorequired ā tmux ops pane, never a rawsudoin an agent shell.- Makefile is the standard task runner ā
make check,make push,make release.