Drop the backup-and-destroy headline framing (the script only ever exports; removal is the caller's opt-in) and cut the ELI5 hand-holding aimed at someone who isn't the admin of this box. Collapse exit codes to a table, demote removal to a short exit-code-gated snippet. No code change.
2.8 KiB
mm3-hk-export
Export a private HyperKitty (Mailman 3) list archive to mbox from the command line — the CLI equivalent of the web UI's Download button.
Why
HyperKitty ships no hyperkitty_export command; the only built-in export is the
web Download view. This drives the same Email.as_bytes() path through the
mailman-web wrapper, so the output is byte-for-byte identical — no web login, no
DB reconstruction. It has to be mailman-web, not mailman-wrapper: the archive
lives in the HyperKitty DB, not core.
Requirements
Run as root — mailman-web drops to the web user to read the archive, then
the script publishes the result as root. Uses mailman-wrapper to report a
list's archive_policy when there's nothing to export.
Usage
mm3-hk-export [-z|--gzip] <list@domain> [output]
output defaults to ./<localpart>.mbox (.mbox.gz with -z). -z gzips the
stream to match the web .mbox.gz byte-for-byte (deterministic header, mtime=0).
mm3-hk-export announce@lists.example.com /root/mm3/announce.mbox
mm3-hk-export --gzip announce@lists.example.com /root/mm3/announce.mbox.gz
Exit codes
Never writes a partial or empty file. The exit code reports whether a backup was produced:
| Exit | Meaning |
|---|---|
0 |
archive written (wrote N messages to …) |
3 |
nothing to archive — empty list, or no archive at all (reports archive_policy: never vs nothing-yet) |
2 |
usage / bad address |
1 |
error (e.g. mailman-web failed) |
3 is distinct from 0 so a caller can tell "backed up" from "nothing to back
up" and refuse to destroy an uncaptured list.
Gating a removal on the backup
The script only exports. To remove a list after a verified backup, gate it on the exit code yourself:
mm3-hk-export "$addr" "/root/mm3/$list.mbox" \
|| { echo "no backup; keeping $addr" >&2; exit 1; }
mailman-wrapper members "$addr" > "/root/mm3/$list.members"
mailman-wrapper remove "$addr"
Export before remove, never remove on a non-zero exit. (Core's remove
leaves the HyperKitty archive untouched anyway — separate DB — but a failed
export must still halt the destroy.)
Caveats
- Reconstruction, not the original bytes. HyperKitty rebuilds each message
from parsed fields (
From,To,Subject,Date,Message-ID,In-Reply-To, body, attachments);Cc,References,List-*, andX-*are lost. Inherent to HyperKitty — the web download is identical. - Large lists. Streamed via a DB iterator, so no memory blow-up like the web export.
- Re-import. Valid mbox; re-importable with
hyperkitty_import. - Handoff. The web user builds the archive in
/var/tmp; root verifies it by SHA-256 and publishes atomically, so a swap, truncation, or corruption before publish is caught and nothing is published. A compromisedmailman-webis out of scope.