Skip to main content

Command Palette

Search for a command to run...

LOG-2 Week 2: My first lines of code at Mailman

Updated
3 min read

I am writing this blog while in train. It is pass 3 am and I am writing because I can't go to sleep (master RAC).
The environment here right now is unusually not calm, There is a group traveling with teenagers that refuse to sleep, somehow giving me a perfect concoction of dedication to write 😭.

Anyway the week got a pretty kickstart by Stephen (our mentor) who gave us a much needed overview of Mailman as a whole, and all the core developers who have contributed evidently hugely in Mailman.

For my project: Per-list Backup and Restore, Stephen suggested making two buttons for backup and restore into Postorius.
After walking the approach back and forth in detail with Abhilash (my mentor), we came across three options :

  1. Fat UI in Postorius

  2. logic in mailmanclient

  3. logic in Core
    Eventually with the guidance of both my mentors Abhilash and Mark, we landed on putting the logic in Core (the original plan I proposed in my proposal) because it's the only mandatory component where every single Mailman installation will get the feature regardless of which UI they use.
    Postorius will still get buttons, but as a thin relay calling Core's REST endpoint.

The Five Commits I have made so far

Commit 1 (The contract file):
The ZCA Interface src/mailman/interfaces/backup.py declares IBackupManager with two method signatures. Mailman's dependency injection system requires every public utility to declare an interface contract before anything gets implemented.

Commit 2 :
Type coercion and scalar config export Mailman's model uses Python types JSON can't serialize — enums, timedeltas, datetimes, bytes. _coerce_for_json() handles all four. Then export_list_config() iterates every field on the list object and skips excluded ones (rosters, relational objects, moderator_password), and coerces everything else.

Commit 3:
ContentFilter fields Four fields that control attachment filtering live in a separate table and return generators. Wrapping each in list() produces plain string lists that JSON handles fine.

Commit 4:
Member roster -Three rosters, three roles. Email and verified_on come from member.address directly. verified_on is preserved exactly as stored and never force-verified on restore.

Commit 5:
Wiring function export_list() calls all three export functions, assembles a single dict, and writes it to disk with json.dump(). Given a live list object and an output path, the export pipeline produces a complete JSON backup file.

Week 1: What remains

I'll have my University end sems from 9th till 23rd of June After that which leaves me to do a round-trip test to hit Milestone 1 till June 8.
Work on aliases, header-matches, bans, archivers, CLI command, and the restore engine will start after my exams finish.

Navya Khanna
GSoC 2026, GNU Mailman

10 views