IMAP-Postfächer wachsen mit der Zeit. Irgendwann hat man tausende Mails im Posteingang und in Sent, die Suche wird langsam und die Übersicht geht verloren. cleanup-maildir ist ein Python-Script das Mails nach Alter automatisch in Archiv-Ordner sortiert. Es läuft als Cronjob und arbeitet direkt auf dem Maildir-Verzeichnis.

Installation

# FreeBSD
pkg install cleanup-maildir

# Debian/Ubuntu
pip install cleanup-maildir

Grundlegender Aufruf

Alle Mails die älter als 365 Tage sind aus der Inbox ins Archiv verschieben:

# Inbox archivieren
sudo -u vmail cleanup-maildir --age=365 \
  --archive-folder='Archive.Inbox' \
  --maildir-root='/var/mail/vhosts/example.com/user' \
  archive ''

# Gesendete archivieren
sudo -u vmail cleanup-maildir --age=365 \
  --archive-folder='Archive.Sent' \
  --maildir-root='/var/mail/vhosts/example.com/user' \
  archive 'Sent/'

--age=365 fasst nur Mails an die älter als ein Jahr sind. --archive-folder gibt den Zielordner im IMAP-Postfach an. archive ist der Modus (alternativ delete). Der leere String '' steht für die Inbox, 'Sent/' für die gesendeten Mails.

Das Script legt automatisch Unterordner nach Jahr und Monat an. Die Struktur im Postfach sieht dann so aus:

Archive/
├── Inbox/
│   ├── 2024-01/
│   ├── 2024-02/
│   └── ...
└── Sent/
    ├── 2024-01/
    ├── 2024-02/
    └── ...

Cronjob

Als Cronjob einmal pro Nacht laufen lassen. Wichtig ist dass der Cronjob als der Benutzer läuft der Zugriff auf die Maildir-Verzeichnisse hat:

# /etc/crontab
30 3 * * * vmail cleanup-maildir --age=365 --archive-folder='Archive.Inbox' --maildir-root='/var/mail/vhosts/example.com/user' archive ''

Mehrere Postfächer mit LDAP

Bei mehreren Postfächern will man nicht für jeden Benutzer einen eigenen Cronjob-Eintrag pflegen. Ein Wrapper-Script kann die Benutzer, Maildir-Pfade und die Option ob archiviert werden soll aus dem LDAP holen. Das LDAP-Attribut (z.B. autoarchive=1) steuert pro Benutzer ob die Archivierung aktiv ist. So lässt sich die Archivierung zentral verwalten ohne auf jedem Mailserver Cronjobs anzupassen.

Python 3.11+ und kaputte Header

Ab Python 3.11 nutzt cleanup-maildir den strikten RFC-Header-Parser aus email.policy.default. Das führt zu einem Problem: Mails mit fehlerhaften Headern (z.B. Microsoft Exchange Message-IDs wie <[b378dfc5...]@microsoft.com>) lassen das Script mit einem IndexError abstürzen. Alle Mails nach der fehlerhaften werden nicht mehr verarbeitet.

Den Fix dafür habe ich als Pull Request eingereicht. Ein _safe_header()-Wrapper fängt Parse-Fehler ab und überspringt kaputte Header, statt das ganze Script abzubrechen. Bei mir hat das Script vorher bei Mail #8 aufgehört, danach liefen alle 2.986 Mails sauber durch.

Fragen? Einfach melden.