blog · git · desktop · images · contact & privacy · gopher


Mail-Synchronisation: Mutt, Maildir und Git

Ich bin ja mittlerweile der Meinung, dass es nichts gibt, was man mit Git nicht machen kann. ;)

Ein häufiges Problem von Leuten, die an mehreren Rechnern arbeiten, ist: "Wie synchronisiere ich meine Mails?" Irgendwelche Hürden gibt es da immer, IMAP ist auch nicht überall verfügbar und so weiter. Und dann wäre da noch das Problem, dass man häufig nicht nur einen Mail-Account hat, sondern mehrere.

Wenn man eine MDA/MUA-Kombination nutzt, die Maildir oder ein anderes textbasiertes Format beherrscht, dann kann eine verteilte Versionierung wie Git hier eine Lösung darstellen. Muss auch nicht Git sein, wenn man das nicht mag -- die Hauptsache ist, dass es verteilt arbeitet. Da ich Mutt und Maildirs eh schon nutze, war der Grundstein also gelegt.

Die Sache ist denkbar einfach: Das Maildir-System ist so aufgebaut, dass jede Mail in einer einzelnen Datei gespeichert wird. Schreibt man eine Mail oder empfängt man eine (von welchem Account auch immer), dann gibt es eine neue Datei und fertig. Diese kann man dann in seine Versionierung stecken, welche wiederum dafür sorgt, dass dieser Vorgang auf anderen Rechnern reproduzierbar ist.

Durch die Tatsache, dass Git verteilt arbeitet, können die Branches auch weit auseinanderlaufen und man braucht keinen dauerhaften Zugang zu einem zentralen Server. Gemerged kriegt man das schon wieder.

Schritt für Schritt.

"git init" in ~/Mail und diesen Inhalt nach .gitignore:

.*/tmp/*
.*/new/*

Das hat den Sinn, dass Mails erst dann in die Versionierung aufgenommen werden, wenn sie das cur-Verzeichnis erreichen. Normalerweise passiert das dann, wenn man sich entschieden hat, diese Mail zu behalten. Sprich, Spam kann man vorher löschen, ohne dass dieser auch im Repository landet.

Mutt die Maildirs (ohne ".git") bekanntgeben. Das käme in die ~/.muttrc:

mailboxes `find ~/Mail -maxdepth 1 -type d -name ".*" -and -not -name ".git" -printf "+%f "; echo ""`

Statt direktem Aufruf von Mutt folgendes nutzen:

#!/bin/bash

mutt -y

cd ~/Mail
git add .
git ci -a -m "Auto-Commit by $(hostname)"

Heißt also, nach jedem Mutt-Aufruf wird der aktuelle Stand weggeschrieben.

So lange habe ich das noch nicht in Betrieb und vielleicht habe ich etwas übersehen -- aber ich glaube durchaus, dass das eine solide Lösung ist.

– Nachtrag vom 11.06.2011: Auch jetzt noch habe ich das genau so in Betrieb und auch noch das Repo von damals. Im Moment nehmen drei Rechner an der Synchronisation teil. Das reine Git-Repo hat eine Größe von etwa 460MB (gemessen direkt nach einem git gc), unkomprimiert brauchen die gut 32'000 Mails etwa 860MB. Funktioniert tadellos.

– Nachtrag vom 08.09.2015: Ist immer noch in Betrieb und das Repo reicht auch nach wie vor bis zum 15. November 2009 zurück. Mittlerweile bemisst .git 845MB und die Mails im Working Directory 1.1GB. Das ist natürlich viel und die Hälfte könnte ich mir sparen, wenn ich das Repo nicht hätte. Andererseits leide ich mit der 256GB großen SSD nicht unter Platzmangel, so what. Performance-Probleme gibt es auch genau gar keine.

– Nachtrag vom 30.09.2017: Das Repo von 2009 hat soeben sein Lebensende erreicht. Im Alltag gab es keine Probleme, aber bevor ich Backups meiner Systeme mache, lasse ich über alle Git-Repos ein „git fsck --full --strict“ laufen, um zu prüfen, ob ich auch sinnvolle Daten sichere. Diese Operation hat beim Mail-Repo jetzt mehr als 16 GB RAM benötigt. Im Laptop habe ich nur 16 GB RAM. Daher habe ich (nach einmaliger manueller Sicherung des ganzen Konstrukts) das alte „.git“ weggeworfen und neu erstellt. Beim Grundprinzip bleibe ich jedoch, weil mir keine bessere Variante bekannt ist – außer vielleicht, überall ZFS zu verwenden, aber das ist mir unter Linux auf dem Desktop zu anstrengend.