Releases: mayai-it/pec-cli
Releases · mayai-it/pec-cli
v0.2.0 — Safeguards, retry, 5 new commands, 86% coverage
Added
- New read/manage commands and corresponding MCP tools:
pec search QUERY [--field subject|from|body|all] [--folder F] [--from-date DATE]pec_searchMCP tool
pec list-folders [--counts]+pec_list_foldersMCP toolpec mark-read <id>+pec_mark_readMCP toolpec mark-unread <id>+pec_mark_unreadMCP toolpec move <id> --to FOLDER [--from FOLDER]+pec_moveMCP tool
(validates destination, uses IMAPMOVEwithCOPY+EXPUNGEfallback)
- Safety guards on
pec send(CLI): interactive TTY confirmation,
--yesflag for non-TTY contexts (exit code3otherwise),
--dry-runfor validation-only. - Safety guards on
pec_send(MCP): requiredconfirm_legal_send=True,
per-session rate limit (3 sends per recipient per 5 minutes),
dry_run=Truemode, recipient regex + non-empty body validation. - Deterministic
Message-IDfor SMTP sends (SHA-256 of
from|to|cc|subject|body|minute-bucket) — enables PEC providers to
deduplicate accidental retries. - Retry with exponential backoff on transient IMAP / SMTP failures
(1s, 2s, 4s, ...capped at 30s, max 3 retries). New module
pec_cli/retry.pyexposingwith_retryandwith_retry_predicate. - Tests: 30 → 195 (195 passing in ~1.3s). Coverage: 30 % → 86 %.
- CI matrix: 3 OS × 3 Python = 9 jobs + dedicated
auditjob
(pip-audit). - mypy strict + extra flags (
disallow_subclassing_any,
strict_equality,extra_checks), blocking in CI. - Italian
README.it.md, separatedocs/(AUTHENTICATION, PROVIDERS,
FAQ), CONTRIBUTING.md, GitHub issue templates (bug + feature).
Changed
- README polished (278 → 257 lines), decorative emoji removed,
Engineering notes + Quality bar sections added. - Installation flow simplified:
pip installis the primary path;
make installmoved to the Development section. - Retroactive
v0.1.0git tag created on the commit that actually
shipped themayai-pec-cli==0.1.0PyPI release.
Fixed
email.utils.parsedate_to_datetimeraisesValueErroron Python 3.10+
instead of returningNone— the existingif parsed is Nonefallback
was dead code and would have crashed on malformed dates. Replaced with
try/except (ValueError, TypeError). Found by mypywarn_unreachable.imap.uid("search", None, ...)was stringifyingNoneto"None"on
the wire (lenient servers tolerated it but it's not protocol-correct).
Now passes criteria directly.- SMTP retry predicate ordering:
smtplib.SMTPExceptioninherits from
OSError, so the initialisinstance(..., OSError)check was matching
permanent 5xx errors and looping on them. Predicate reordered to check
SMTPResponseExceptionfirst.
Security
- XML parsing in
pec_cli/daticert.pynow usesdefusedxml(was
xml.etree). Defense in depth against XXE and billion-laughs
payloads — daticert blobs are network-sourced even if the certification
chain is trusted. starlette>=1.0.1pinned directly in project dependencies
(PYSEC-2026-161 affectsstarlette<1.0.1, transitively pulled in by
themcpSDK with a loose>=0.27constraint).- Removed 4 superfluous
# type: ignore[import-not-found]comments on
keyring imports — the[[tool.mypy.overrides]]block makes them
redundant, and silent ignores hide real type problems.