Synchronisation Baikal (CalDAV und CardDAV) mit MS Office Outlook

Artikel von: Rainer B.
Eigentlich dachte ich, dass es ein einfaches Standardproblem sein sollte, für das es bereits Lösungen gibt, als ich 2013 ein iPhone und ein iPad in Betrieb nahm und Termine und Kontakte mit Outlook 2007 synchronisieren wollte. Die Erfahrungen, die ich bei Test verschiedener Produkte machte, waren jedoch deprimierend. Im besten Falle ließ sich die Software nicht installieren, in schlimmeren Fällen kommt es bei der Synchronisation zu Datenverlusten.
Auch die von Dietmar Olaf in seinem sehr guten Übersichtsartikel vom 19.01.2014 erwähnten Produkte funktionierten nicht in meiner Umgebung (aktuell: Synology DS1512+ unter DSM 6.0.2, Baikal 0.2.7, Windows 10 Pro x64, MS Office Outlook 2007), wobei OutlookDAV noch mit massiven Datenverlusten und keinerlei Support (obwohl Kaufprodukt) für mich am schlechtesten abschnitt.
Frustriert habe ich das Thema zunächst auf Eis gelegt, bis ich Ende 2015 in der c’t einen kleinen Artikel über Outlook CalDAV Synchronizer las. Um das Ergebnis vorweg zu nehmen: diese Software ist die bisher einzige, die in der beschriebenen Umgebung funktioniert und keine Datenverluste zeigt.
Installation von Outlook CalDAV Synchronizer
Vorbemerkung:
Beim eigenen Mail- und Kalender-System verfügen selbst eingefleischte IT-Profis oft über kein Test-System. Aber Achtung: das sind alles Produktivdaten und Verfälschung oder Verlust können sehr ärgerlich sein. Daher gelten hier 2 Grundregeln ganz besonders:
Datensicherung und Test der Ergebnisse
Zur Sicherung reicht es, die .pst-Datei von Outlook zu kopieren, wenn Outlook gerade nicht läuft. Dies sollte nach jeder nennenswerten Veränderung an Software und Synchronisations-Setup erfolgen. Es mag lästig sein, wenn man am Ende 25 Sicherungskopien zu je 1 GB herumstehen hat, aber besser 25 zu viel als eine zu wenig. Die hier gemachten Erfahrungen haben gezeigt, dass schlechte Synchronisationsprogramme durchaus in der Lage sind, erhebliche Teile der Termindaten zu löschen oder zu verändern. Wenn bei 1000 Termineinträgen 10% auf diese Weise gelöscht oder beschädigt werden, ist es außerordentlich mühsam, dies manuell herauszufinden. Daher ist nach jeder Synchronisation ein vollständiger Test durch Vergleich der Outlook-Daten vorher/nachher bzw. durch Vergleich der Outlook-Daten mit den Baikal-Daten erforderlich.
Voraussetzungen für dieses Installationsbeispiel:
Baikal auf Syno-NAS, ein User mit einem (default-)Kalender und einem (default-)Adressbuch eingerichtet
Windows-PC mit MS Office Outlook
Mobiles Gerät mit direktem Zugriff auf Baikal (in diesem Fall ein iPhone5 und ein iPad Air)
Ablauf von Installation und Test:
Sicherheitshalber bei POP3-Konten den automatischen eMail-Abruf in Outlook deaktivieren (nach den Tests natürlich wieder aktivieren). Sonst kann es vorkommen, dass während der Tests unbeabsichtigt eMails abgerufen und auf dem Mail-Server gelöscht werden. Wenn dann im Test etwas schief geht und die Sicherungskopie zurückgespielt wird, wären solche eMails verloren.
Sicherheitskopie der Outlook-Datei Outlook.pst anlegen.
Datei outlook00.ics aus der produktiven Outlook-Datei ziehen (s.u. Testhilfsmittel).
Download der Software von Sourceforge [https://sourceforge.net/projects/outlookcaldavsynchronizer/files/latest/download].
Installation erfolgt durch Starten der Datei CalDavSynchronizer.Setup.msi.
Die danach durchzuführenden Einstellungen sind recht einfach.
Die General Settings wurden im Standard belassen.
In den Synchronization Profiles muss jeweils eines für CalDAV und eines CardDAV angelegt werden. Dabei müssen im Wesentlichen die Baikal-URLs angegeben werden, so wie es der Installation unter DSM entspricht
https://<Syno Servername oder IP>/baikal/cal.php/calendars/<Username>/default/
https://<Syno Servername oder IP>/baikal/card.php/addressbooks/<Username>/default/
ergänzt um Username und Password.
Synchronization interval wurde auf manuell eingestellt, um die Kontrolle über die Synchronisation zu behalten. Dies wurde auch im Produktivbetrieb beibehalten.
Zunächst wird Synchronization Mode auf Outlook -> Server (Replicate) eingestellt und die erste Synchronisation durchgeführt, später im laufenden Betrieb wird Outlook <-> Server (Two-Way) eingestellt.
Nach der ersten Synchronisation wird das Ergebnis geprüft. Durch den gewählten Synchronization Mode sollte der Baikal-Kalender mit dem Outlook-Kalender übereinstimmen. Zur Überprüfung wird wiederum aus Outlook die Datei outlook01.ics erzeugt. Zusätzlich wird baikal01.ics als Dump aus Baikal erzeugt (s.u. Testhilfsmittel). Jetzt muss outlook00.ics mit outlook01.ics und outlook01.ics mit baikal01.ics verglichen werden. Alle 3 ics-Dateien sollten in den wesentlichen Daten übereinstimmen, wobei die verschiedenen Programme im Rahmen vom RFC2445 und RFC5545 z.T. unterschiedliche Darstellungsvarianten für die VEVENT-Einträge verwenden.
Im nächsten Schritt werden auf dem mobilen Gerät Termine editiert:
- neuen Termin erstellen
- neuen Serientermin erstellen
- Zeit und Test in einem Termin ändern
- Zeiten und Text in einem Serientermin ändern
- Termin löschen
- Terminserie löschen
Danach wird nach Änderung des Synchronization Mode auf bidirektional erneut synchronisiert.
Eine Schnellkontrolle ergibt der Blick in Outlook: sind die 6 Änderungen dort angekommen oder nicht.
Zur eigentlichen Überprüfung werden outlook02.ics aus Outlook und baikal02.ics aus Baikal erzeugt. Jetzt sollten die Termine in diesen beiden Dateien wieder übereinstimmen und die Unterschiede zwischen 01 und 02 sollten genau die 6 durchgeführten Änderungen sein.
Im nächsten Schritt werden im Outlook Termine editiert:
- neuen Termin erstellen
- neuen Serientermin erstellen
- Zeit und Test in einem alten Outlook-Termin ändern
- Zeiten und Text in einem alten Outlook-Serientermin ändern
- Zeit und Test in einem neuen iPhone-Termin ändern
- Zeiten und Text in einem neuen iPhone-Serientermin ändern
- alter Outlook-Termin löschen
- alte Outlook-Terminserie löschen
- neuen iPhone-Termin löschen
- neue iPhone-Terminserie löschen
Danach wird synchronisiert.
Eine Schnellkontrolle auf dem Mobilgerät: sind die 10 Änderungen dort angekommen oder nicht.
Zur eigentlichen Überprüfung werden outlook03.ics aus Outlook und baikal03.ics aus Baikal erzeugt. Jetzt sollten die Termine in diesen beiden Dateien wieder übereinstimmen und die Unterschiede zwischen 02 und 03 sollten genau die 10 Änderungen sein.
Diese Testprozedur kann dann noch mit weiteren Varianten (Vergangenheitstermine, Termine mit Mime-Anlagen, Sommer-/Winterzeit etc.) in gleicher Weise fortgesetzt werden bis alle im Kalender vorkommenden Konstellationen geprüft sind.
Der Abgleich der Kontakte geschieht analog. Aufgrund des geringeren Mengengerüsts wurde hier jedoch immer nur manuell verglichen.
Nachdem alle diese Prüfungen erfolgreich durchlaufen wurden, konnte ein Produktivbetrieb beginnen. Hierzu wurde erneut eine Sicherungskopie der Outlook-Datei angelegt.
Danach wird die vor der Installation gezogene Sicherheitskopie der pst-Datei restauriert und CalDavSynchronizer erneut installiert. In Baikal wird der User gelöscht und mit Kalender und Adressbuch neu eingerichtet. Jetzt wieder outlookA.ics aus Outlook ziehen als Startdatensatz zum Vergleich. Dann erfolgt zunächst die Einweg-Synchronisation mit nachfolgendem Ziehen von outlookB.ics aus Outlook. Jetzt kann auf bidirektionale Synchronisation umgestellt werden und der Produktivbetrieb beginnt.
Nach einer Woche wurde zur Überprüfung outlookC.ics gezogen und geprüft, ob die Abweichungen durch bewusst vorgenommene Termineingaben erklärbar sind. Nach einem Monat wird dies dann durch outlookD.ics nochmals geprüft.
Im Ergebnis verlief der Produktivbetrieb ohne Abweichungen, so dass die Software wirklich freigegeben werden kann. Jetzt muss man sich nur noch angewöhnen, im Outlook am Anfang und Ende zu synchronizieren.
Testhilfsmittel:
Zur Durchführung der Prüfungen nach den jeweiligen Testschritten werden einige Programme als Hilfsmittel benötigt:
Dump Outlook-Termine in ics-Datei:
Zur Speicherung aller Outlook Termine in einer ics-Datei bietet Outlook zwar keine Funktion über die Benutzeroberfläche an, aber es gibt eine VBS-Funktion als Methode SaveAsICal zu GetCalendarExporter, die eine solche Datei erzeugen kann. Folgendes Outlook-Makro wurde zur Erzeugung verwendet:
Public Sub ExportEntireCalendar() ‚ ‚ ExportEntireCalendar ‚ 21.01.2014 RB ‚ Export des Kalenders als ICS-Datei ‚ ‚ Quelle: ‚ http://msdn.microsoft.com/de-de/library/ff862395.aspx ‚ Dim icsDatei As String icsDatei = <Ausgabedatei.ics> Dim oNamespace As NameSpace Dim oFolder As Folder Dim oCalendarSharing As CalendarSharing On Error GoTo ErrRoutine ‚ Get a reference to the Calendar default folder Set oNamespace = Application.GetNamespace(„MAPI“) Set oFolder = oNamespace.GetDefaultFolder(olFolderCalendar) ‚ Get a CalendarSharing object for the Calendar default folder. Set oCalendarSharing = oFolder.GetCalendarExporter ‚ Set the CalendarSharing object to export the contents of ‚ the entire Calendar folder, including attachments and ‚ private items, in full detail. With oCalendarSharing .CalendarDetail = olFullDetails .IncludeWholeCalendar = True .IncludeAttachments = True .IncludePrivateDetails = True .RestrictToWorkingHours = False End With ‚ Export calendar to an iCalendar calendar (.ics) file. oCalendarSharing.SaveAsICal icsDatei GoTo EndRoutine ErrRoutine: Select Case Err.Number Case 287 ‚ &H0000011F ‚ The user denied access to the Address Book. ‚ This error occurs if the code is run by an ‚ untrusted application, and the user chose not to ‚ allow access. MsgBox „Access to Outlook was denied by the user.“, _ vbOKOnly, Err.Number & “ – “ & Err.Source Case -2147467259 ‚ &H80004005 ‚ Export failed. ‚ This error typically occurs if the CalendarSharing ‚ method cannot export the calendar information because ‚ of conflicting property settings. MsgBox Err.Description, vbOKOnly, Err.Number & “ – “ & Err.Source Case -2147221233 ‚ &H8004010F ‚ Operation failed. ‚ This error typically occurs if the GetCalendarExporter method ‚ is called on a folder that doesn’t contain calendar items. MsgBox Err.Description, vbOKOnly, Err.Number & “ – “ & Err.Source Case Else ‚ Any other error that may occur. MsgBox Err.Description, vbOKOnly, Err.Number & “ – “ & Err.Source End Select EndRoutine: On Error GoTo 0 Set oCalendarSharing = Nothing Set oFolder = Nothing Set oNamespace = Nothing End SubDump Baikal in ics-Datei:
Als „lightweight“ CalDAV und CardDAV Anwendung verfügt Baikal über keine Import-/Export-Funktionalität. Der Export in eine ics-Datei kann jedoch leicht durch kleine Programme durchgeführt werden.
Grundsätzlich kann der Export über die reguläre CalDAV- bzw. CardDAV-Schnittstelle erfolgen. Dann benötigt man Tools, die diese Schnittstellen bedienen. Für CardDAV gibt es die carddav-util von Lukasz Janyst, für CalDAV wurde ein entsprechendes Tool bei einer ersten Recherche nicht gefunden. Die Grundfunktionen wären allerdings in den Python-Paketen caldav 0.4.0 und pyCardDAV 0.7.0 vorhanden.
Alternativ kann ein Export auch durch direkten Zugriff auf den Baikal-Datenspeicher durchgeführt werden, wie es hier vorgenommen wird. Hierbei muss allerdings unterschieden werden, ob Baikal mit einer SQLite- oder MySQL-Datenbank arbeitet.
Dump Baikal von SQLite-DB in ics-Datei:
Zunächst muss die SQLite-Datenbank kopiert werden, da diese eigentlich nicht für den Multiuser-Betrieb geeignet ist. Diese steht üblicherweise im Verzeichnis
\\< Syno Servername oder IP >\web\baikal.app\Specific\db\db.sqlite
Die Kopie der Datenbank kann dann mittels folgenden Skripts ausgelesen und in eine ics-Datei geschrieben werden:
.open baikal-kopie.sqlite .header off .once baikal99.ics select calendardata from calendarobjects; .quitSpeichert man dieses Script in einer Datei dumpBaikal.sql, dann kann der Dump durch folgendes Windows Commandscript erfolgen:
rem Extract Baikal Kalender.cmd rem 02.10.2014 RB rem rem Extrahiert den Kalender aus Baikal als .ics-Datei rem copy \\< Syno>\web\baikal.app\Specific\db\db.sqlite baikal-kopie.sqlite sqlite3 < dumpBaikal.sqlDiese einfache Lösung setzt allerdings voraus, dass es in Baikal nur einen Kalender gibt, ansonsten erzeugt man eine Kalender-Melange.
Der Dateiname baikal99.ics muss natürlich jeweils angepasst werden.
Dump Baikal von MySQL-DB in ics-Datei:
Wenn Baikal mit einer MySQL-DB arbeitet (unter DSM ist das MariaDB), reichen die Standard-Anwendungen (z.B. phpMyAdmin oder MySQLWorkbench) nicht aus, da diese die BLOBs, in denen die ics-Daten stehen, nicht zusammenhängend ausgeben. Daher ist ein kleines Skript erforderlich, beliebige Programmiersprache, in diesem Fall wurde Python gewählt. Das Skript wurde auch gleich so ausgelegt, dass Baikal mehrere Kalender und Adressbücher enthalten kann. Zur Durchführung wurde aus dem Synology-Server ein User eingerichtet, der auf die Baikal-Datenbank Lesezugriff hat.
# dumpBaikal.py # # 29.11.2015 RB # Entlädt Baikal Kalender und Adressbücher # import sys import os from mysql.connector import connection # ———————————————————— # Programmeinstellungen ===> anpassen # ———————————————————— baikalServer = ‚<servername>‘ baikalDB = ‚Baikal‘ baikalUser = ‚<username>‘ baikalPass = ‚<password>‘ ausgabeVZ = ‚<Verzeichnis zur Ausgabe der Ergebnisse>‘ # ———————————————————— # Hauptprogramm # ———————————————————— cnx=connection.MySQLConnection(user=baikalUser, password=baikalPass, host=baikalServer, database=baikalDB) # ———————————————————— # Kalender # ———————————————————— curs=cnx.cursor(buffered=True) curt=cnx.cursor() queryText = ‚SELECT id, principaluri, displayname FROM calendars‘ curs.execute(queryText) for (id1, pu1, dn1) in curs: outName = ‚baikal-‚ + str(id1) + ‚.ics‘ outFile = os.path.join(ausgabeVZ, outName) n = 0 with open(outFile, ‚w‘, encoding=’utf-8′) as out: queryText = ‚SELECT id, calendardata FROM calendarobjects WHERE calendarid=‘ + str(id1) curt.execute(queryText) for (id2, cdata) in curt: n += 1 zdata = cdata.decode(‚utf-8‘).split(‚\r\n‘) for z in zdata: out.write(z + ‚\n‘) print(outName, dn1,‘: ‚, n, ‚Termineinträge‘) curs.close() curt.close() # ———————————————————— # Adressbücher # ———————————————————— curs=cnx.cursor(buffered=True) curt=cnx.cursor() queryText = ‚SELECT id, principaluri, displayname FROM addressbooks‘ curs.execute(queryText) for (id1, pu1, dn1) in curs: outName = ‚baikal-‚ + str(id1) + ‚.vcf‘ outFile = os.path.join(ausgabeVZ, outName) n = 0 with open(outFile, ‚w‘, encoding=’utf-8′) as out: queryText = ‚SELECT id, carddata FROM cards WHERE addressbookid=‘ + str(id1) curt.execute(queryText) for (id2, cdata) in curt: n += 1 zdata = cdata.decode(‚utf-8‘).split(‚\r\n‘) for z in zdata: out.write(z + ‚\n‘) print(outName, dn1,‘: ‚, n, ‚Adressbucheinträge‘) curs.close() curt.close() cnx.close()Die so erhaltenen Dateien müssen nur noch umbenannt werden oder man schreibt in das Programm noch eine Abfrage der Nummer und ändert die Dateinamenskonvention.
Wichtig: Im Multiuser Betrieb ist die Nutzung dieser Dump-Programme aus Gründen des Datenschutzes ohne Zustimmung betroffenen User illegal.
ics-Dateivergleich:
Zum Vergleich der verschiedenen ics-Dateien wurde vor allem Excel mit entsprechenden Makros verwendet, um in der Auswertung sehr flexibel zu sein. Darstellung würde den Rahmen dieses Beitrags allerdings überschreiten.
Zusammenfassung
Im Ergebnis kann festgehalten werden, dass Outlook CalDAV Synchronizer in der oben beschriebenen Umgebung zuverlässig zwischen Outlook und Baikal synchronisiert. Die Installation ist vergleichsweise einfach. Die Umstellung sollte allerdings immer mit entsprechenden Datensicherungen und Tests begleitet werden.
R.B.