Command-line client for Italian PEC (Posta Elettronica Certificata) — built for AI agents and developers.
Project description
pec-cli
Command-line client for PEC (Posta Elettronica Certificata — Italian
certified email), built for both humans and AI agents. Designed to be
context-efficient: the default output strips empty fields, and --json
produces NDJSON suitable for piping into LLMs or jq.
Talks to the standard IMAP/SMTP endpoints exposed by Italian PEC providers (Aruba, Legalmail/InfoCert, Namirial, Register.it, Poste Italiane, Pec.it), all over SSL/TLS.
Part of MayAI CLI.
Requirements
- Python 3.11+
- A working PEC account from one of the supported providers
Installation
From PyPI (recommended):
pip install mayai-pec-cli
The package installs a single pec command on your PATH.
From source:
git clone https://github.com/mayai-it/pec-cli.git
cd pec-cli
make install
For local development (adds pytest, ruff):
make dev
Quick start
# 1. Authenticate (password prompted interactively, never passed as a flag)
pec auth login --address mia@pec.it --provider aruba
# 2. Verify
pec auth status
# 3. List the 20 most recent PECs in the inbox as NDJSON
pec --json list
# 4. Filter to unread, since a given date
pec --json list --unread --from 2025-01-01 --limit 50
# 5. Read a single message and save its attachments to ./attachments
pec get 1234 --save-attachments ./attachments
# 6. Inspect the parsed PEC certification (daticert.xml) for a message
pec get 1234 --cert --json
# 7. Trace the full receipt chain for an original message id
pec trace 'opec123.20260321102500.12345.67.1.1@pec.it'
# 8. Send a PEC with an attachment
pec send --to dest@pec.it --subject "Oggetto" --file body.txt --attach doc.pdf
Command reference
| Command | Description |
|---|---|
pec auth login --address ADDR --provider P |
Prompt for password, verify via IMAP, save credentials in the system keyring (Fernet-encrypted file as fallback). |
pec auth status |
Show whether credentials are present. |
pec auth logout |
Delete saved credentials (keyring entry + any local encryption key). |
pec list [--folder F] [--unread] [--from YYYY-MM-DD] [--limit N] |
List PEC messages (default folder inbox, default limit 20). |
pec get <id> [--folder F] [--save-attachments DIR] [--cert] |
Fetch a single PEC by IMAP UID; --cert includes the parsed daticert.xml certification; --save-attachments writes attachments to DIR. |
pec trace <message-id> [--folder F] [--limit N] |
Find every receipt in the folder whose daticert.xml references this message id, ordered chronologically (accettazione → presa-in-carico → avvenuta-consegna / errore-consegna). |
| `pec send --to ADDR --subject S (--body T | --file F) [--attach F] [--cc ADDR] [--dry-run]` |
Global flags
These work in any position (before or after the subcommand):
| Flag | Effect |
|---|---|
--json |
Emit one JSON object per line (NDJSON). |
--verbose |
Log IMAP/SMTP timings and certification metadata to stderr. |
-h, --help |
Show help for the current command. |
Exit codes
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Application error (network, send failure, bad arguments) |
2 |
Not authenticated — run pec auth login |
Supported providers
| Provider | --provider |
IMAP | SMTP |
|---|---|---|---|
| Aruba PEC | aruba |
imaps.pec.aruba.it:993 |
smtps.pec.aruba.it:465 |
| Legalmail (InfoCert) | legalmail |
imapmail.legalmail.it:993 |
smtpmail.legalmail.it:465 |
| Namirial | namirial |
imap.namirialpec.it:993 |
smtp.namirialpec.it:465 |
| Register.it | register |
imap.pec.register.it:993 |
smtp.pec.register.it:465 |
| Poste Italiane | poste |
imappec.poste.it:993 |
smtppec.poste.it:465 |
| Pec.it | pec.it |
imap.pec.it:993 |
smtp.pec.it:465 |
All providers use implicit SSL/TLS (IMAPS:993 / SMTPS:465). Username is the full PEC address; the password is the one provided by the PEC provider.
Authentication
PEC is plain IMAP/SMTP with SSL — there's no OAuth. pec auth login:
- Prompts you for the password on stderr (never echoed, never on argv).
- Verifies it by opening an IMAP connection and logging in.
- Stores the password in the system keyring — macOS Keychain, Linux
Secret Service, or Windows Credential Locker (DPAPI) — under the service
name
mayai-cli-pecand the PEC address as the username. - Writes a small metadata file at
~/.config/mayai-cli/pec/credentials.json(mode0600) recording the address, provider, and where the password lives.
On headless boxes or CI where no keyring backend is available, the CLI
transparently falls back to Fernet encryption: a 32-byte key at
~/.config/mayai-cli/pec/key.bin (mode 0600) encrypts the password inside
credentials.json. Existing installs that still have a key.bin are
migrated to the keyring on the next pec auth login (and key.bin is then
removed).
pec auth logout clears the keyring entry and removes the on-disk files.
The password is never written to plain disk and never accepted via a
command-line flag.
Output format
- Default — compact human-readable text. Empty / null fields are stripped so terminal output stays scannable.
--json— NDJSON. One object per line; lists stream one element per line so consumers can process incrementally.--verbose— adds protocol timing lines on stderr (e.g.imap: connected to imaps.pec.aruba.it:993 as mia@pec.it (284ms)), and surfaces the PEC certification attachments (daticert.xml,postacert.eml,smime.p7s/p7m) that are normally hidden.
Errors always go to stderr, prefixed with error:.
What pec list returns
Each row carries the IMAP UID (id), a normalized ISO date, the sender, the
subject, the PEC type (accettazione, consegna, errore, preavviso, …)
when present, and read/attachment flags.
What pec get returns
The full message — from, to, cc, subject, date, plain-text body
(HTML body too with --verbose), and the attachment list with each
attachment's filename and size in bytes.
PEC messages that carry a daticert.xml certification (every receipt and
every sent PEC) get an extra pec_cert_type field in the default output,
e.g. "avvenuta-consegna". Pass --cert to also include the fully parsed
certification (tipo, mittente, destinatari, data, identificativo,
riferimento_message_id, oggetto, optional errore):
pec get 1234 --cert --json
By default the PEC certification files (daticert.xml, postacert.eml,
smime.p7s, smime.p7m) are filtered out of both the listed attachments
and the saved files; pass --verbose to include them. Use
--save-attachments DIR to write attachments to disk under DIR
(created if it doesn't exist).
What pec trace returns
pec trace <message-id> scans recent PECs in a folder (default inbox,
--limit 200), reads each daticert.xml, and returns the chain whose
riferimento_message_id matches the given id, sorted chronologically:
{
"message_id": "opec123.20260321102500.12345.67.1.1@pec.it",
"events": [
{"id": "204", "tipo": "accettazione", "data": "2026-03-21T10:25:00+01:00", "...": "..."},
{"id": "205", "tipo": "presa-in-carico", "data": "2026-03-21T10:25:04+01:00", "...": "..."},
{"id": "206", "tipo": "avvenuta-consegna","data": "2026-03-21T10:25:07+01:00", "...": "..."}
],
"count": 3
}
The argument is the certified identificativo of the original message — the
same value pec get --cert returns under pec_cert.identificativo. Surround
or strip <...> brackets as you wish; the CLI normalizes them.
Development
make dev # install with dev extras
make test # run pytest
make lint # run ruff
make clean # remove caches and build artifacts
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mayai_pec_cli-0.1.0.tar.gz.
File metadata
- Download URL: mayai_pec_cli-0.1.0.tar.gz
- Upload date:
- Size: 22.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c755d21a2c1f9f76c2bddf17a86a03c66f933aa68edf6bb041c252e526585b80
|
|
| MD5 |
ae5dd4936320f563f54b0ce8f7cbdcd6
|
|
| BLAKE2b-256 |
0594c77f217fa981a1ee9116108981868a7d805ecd30a03ba2d703dd814ffedb
|
File details
Details for the file mayai_pec_cli-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mayai_pec_cli-0.1.0-py3-none-any.whl
- Upload date:
- Size: 24.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc98e1a584fe16e9d284d8ad44ee399ade1a74a39eef2ba845e2af3be271bddf
|
|
| MD5 |
d1c6828c71e21061d1d3af58adcce276
|
|
| BLAKE2b-256 |
a50c893c3e893b9dcd332a703aeca9fbe5bf93432027bf9115652efe5a754565
|