Email automation often treats “send” as a single API call. The difficult part is everything around that call: proving the exact message was approved, enforcing a real cap, preserving enough state to investigate an uncertain SMTP result, and avoiding a duplicate when the connection disappears during DATA.
I built MailPermit 0.1.0 as a small standard-library Python CLI for that boundary.
What it does
MailPermit separates preparation, approval, submission, and reconciliation:
- Prepare a private JSON message specification.
- Run
mailpermit hashto normalize it and compute a SHA-256 hash covering the sender identity, recipient, subject, body, and message ID slug. - Create a protected approval record containing that exact hash and a UTC approval timestamp.
- Run
mailpermit validatewithout contacting SMTP or IMAP. - Run
mailpermit sendonce.
Before submission, MailPermit stores an exact .eml copy and a SQLite attempt record. It requires SMTP STARTTLS with normal certificate verification, applies a configurable daily attempt cap, and refuses approvals older than 24 hours.
Most importantly, it does not automatically retry. If the SMTP connection fails while the server may have accepted the message, MailPermit records an uncertain result. reconcile-sent can then search configured IMAP Sent folders for one MIME-equivalent copy without touching SMTP.
Exact cap exceptions
Sometimes an operator intentionally needs one message above the configured daily cap. MailPermit supports that through a separate override record bound to:
- one message ID;
- one exact message hash;
- one UTC day; and
- the
this-message-onlyscope.
The override cannot silently authorize a batch or a future retry.
Local and dependency-free
MailPermit has no runtime dependencies outside Python 3.11's standard library. It has no telemetry, analytics, hosted service, or update checker. Network access is limited to the SMTP and IMAP hosts in the operator's private configuration.
Approval files are protected operating records rather than cryptographic signatures, so the security boundary remains the local account and filesystem permissions. The README documents that limitation along with the status model and exit codes.
The initial release includes 10 isolated tests using temporary state and fake SMTP behavior, a public Codeberg CI run, example configuration and approval records, and a fresh-install smoke test.
Source and release:
https://codeberg.org/automa-tan/mailpermit
Feedback on the workflow and failure-state model is welcome.
Top comments (0)