Vorbedingung: In einem lokalen Maildir sind Mails eines GMX-Accounts gespeichert, welche in der Vergangenheit über POP3 (mit fetchmail) runtergeladen wurden. Das lokale Maildir ist über einen lokalen Courier-IMAP-Server zugänglich (Maildir++). Lokal wurden die Mails in einer Ordnerstruktur verwaltet. Auf GMX-Seite wurden die Mails parallel analog verwaltet, wobei allerdings keine direkte Synchronisation erfolgte.
Nun sollen beide Seiten einmalig mit imapsync
synchronisiert und später in den regulären offlineimap
-Abgleich eingebunden werden. Verwendet wurde dabei imapsync
in der Version 1.286 und offlineimap
in der Version 6.0.3
Im Folgendenden wird beschrieben wie ein solches Vorhaben aussehen kann. Es ist kein komplettes Howto sondern spiegelt lediglich die Erfahrungen wieder, die während der Migration gemacht wurden.
imapsync
wird zweimal aufgerufen: Zuerst wird von GMX in Richtung lokales Maildir abgeglichen, dann umgekehrt. Das ist notwendig, um auf beiden Seiten die jeweils nicht vorhandenen Mails zu kopieren. , dann lokal auf GMX, um unterschiedliche Header anzugleichen. Da Flags in beide Richtungen synchronisiert werden sollen und hier kein Mirror betrieben wird, ist der imapsync – +FLAGS
-Fix nicht notwendig hier.
Bei der --folder
-Option muß der ganze Pfad auf dem jeweiligen Quell-Server angegeben werden. Im Fall vom lokalen Courier-Server wäre das z.B. --folder 'INBOX.gmx.folderxyz'
. Auf den angegebenen Foldernamen wendet imapsync
nun zunächst das Präfix und den Seperator des Ziel-Servers an, bevor regextrans2
zum Einsatz kommt.
imapysync
erkennt bei Courier automatisch den Prefix und den Seperator, da Courier ihn über das IMAP-Protokoll bekanntgibt. Nicht so bei GMX. Deshalb muß für den GMX-Server imapsync darüber manuell in Kenntnis setzen. Ist GMX z.B. der Quellserver, geschieht dies mit --prefix1 ''
und --sep1 '/'
.
Da auf dem Courier-Server in das Unterverzeichnis gmx
synchronisiert werden soll, ist dort --prefix2 INBOX.gmx.
anzugeben.
Beim Abholen der Mails über POP3 und IMAP werden unterschiedliche Header erzeugt. So fügt fetchmail
z.B. seine eigenen Received- oder Content-Length-Header ein. Interessanterweise unterscheidet sich auch der Spezial-GMX-Header X-GMX-UID
je nachdem über welchen Weg – POP3 oder IMAP – die Mail heruntergeladen wurde. Aus diesem Grund ist es notwendig die Identifizierung auf zwei Header zu beschränken, die normalerweise nicht geändert werden sollten und hoffentlich auch eindeutig sind (siehe aber auch den vorherigen Blogpost zu dem Thema): Date
und Message-Id
. Mit --useheader Message-ID --useheader Date
zieht imapsync
nur diese beiden Header für den Hashwert heran. Zusätzlich gibt man noch --skipsize --nofoldersizes
an, weil sich wie gesagt die Größen der Mails unterscheiden können.
Die Verbindung zu GMX sollte natürlich verschlüsselt erfolgen, deshalb unbedingt die --ssl1
bzw. --ssl2
– Option benutzen. Lokal benötigen wir keine Verschlüsselung, allerdings kann es notwendig sein CRAM-MD5 mit --noauthmd5
abzuschalten, falls Courier nicht explizit dafür konfiguriert wurde.
Die vollständige Kommandozeilen lauten für die Richtung GMX -> lokal:
$ imapsync --host1 imap.gmx.net --user1 user@gmx.de --sep1 '/' --prefix1 '' -ssl1 \ --host2 localhost --user2 localuser --prefix2 INBOX.gmx. \ --skipsize --nofoldersizes --noauthmd5 --useheader Message-ID --useheader Date --debug \ --folder ablage/2009 2>&1 | tee out.txt
und für die Richtung lokal -> GMX:
$ imapsync --host1 localhost --user1 gal \ --host2 imap.gmx.net --user2 user@gmx.de --sep2 '/' --prefix2 '' --regextrans2 's/gmx\///' --ssl2 \ --skipsize --nofoldersizes --noauthmd5 --useheader Message-ID --useheader Date --debug \ --folder 'INBOX.gmx.ablage.2009' 2>&1 | tee out.txt
Zunächst bietet es sich aber an, zusätzlich --dry
zu setzen und die Ausgabe in einer Datei zu speichern. Verdächte Stellen sind auffindbar, indem man darin nach "Skip" oder "Warn" sucht.
Nachdem durch das wechselseitige Synchronisieren GMX->lokal, lokal->GMX aller Ordner zunächst für eine einheitliche Datenbasis gesorgt wurde, kann man nun daran gehen eine laufende Synchronisation mit offlineimap
einzurichten.
offlineimap
synchronisiert Mails nicht anhand ihrer Inhalte (die Message-ID ist letztlich auch Inhalt der Mail) sondern anhand der UIDs in IMAP. Deshalb müssen nun (nach vorheriger Sicherung!) die lokalen Ordner gelöscht werden, damit offlineimap initial den Stand des GMX-IMAP-Servers lokal kopieren kann.
Konfiguration für offlineimap:
In .offlineimaprc
:
[general] pythonfile = ~/bin/oimaptransfolder.py ... [Repository gmx-local] type = Maildir localfolders = ~/Maildir sep = . [Repository gmx-remote] type = IMAP remotehost = imap.gmx.net ssl = yes remoteuser = user@gmx.de remotepass = ** maxconnections = 1 holdconnectionopen = no nametrans = oimaptransfolder_gmx folderfilter = lambda foldername: foldername in [ 'INBOX', 'Gesendet', 'Spamverdacht', 'Entw&APw-rfe', 'ablage/2000', 'ablage/2001', 'ablage/2002', 'ablage/2003', 'ablage/2004', 'ablage/2005', 'ablage/2006', 'ablage/2007', 'ablage/2008', 'ablage/2009', 'gesendet_ablage/2000-2002', 'gesendet_ablage/2003', 'gesendet_ablage/2004', 'gesendet_ablage/2005', 'gesendet_ablage/2006', 'gesendet_ablage/2007', 'gesendet_ablage/2008', 'gesendet_ablage/2009' ]
"Entw&APw-rfe" ist die UTF-7-Codierung für "Entwürfe". IMAP verwendet UTF-7, um Umlaute zu kodieren. Ein entsprechend kodierter Ordner wird auch im lokalen Maildir benutzt, was von Vorteil ist, da Courier auch für die Speicherung der Ordnernamen im Dateisystem UTF-7 verwendet.
oimaptransfolder_gmx
ist die Funktion, die die Folder-Namen umsetzt vom GMX-IMAP-Server auf das lokale Maildir-Datei-System. Ich habe sie zusammen mit anderen Mappings in ~bin/oimaptransfolder.py
definiert. Die Datei sind in etwa so aus:
import re def oimaptransfolder_webde(foldername): if(foldername == "INBOX"): retval = ".webde" else: retval = ".webde." + foldername return retval def oimaptransfolder_gmx(foldername): if(foldername == "INBOX"): retval = ".gmx" else: retval = ".gmx." + foldername retval = re.sub("/", ".", retval) return retval