MS Exchange and KDE synchronization

I wanted to synchronise my work calendar and contacts (in MS Exchange) to kontact (i.e. KDE akonadi). This page summarises the way I got this working.

This solution uses the ActiveSync and KDE backends, without using Evolution at all. In the examples below, I have assumed that:

  • your Exchange email address is user@example.com
  • your Exchange server login id is workdomain\username
  • your Exchange server URL is https://activesync.example.com
  • you are willing to use @KDE as the context name for the KDE databases and @Work as the context name for the Exchange databases

Note: if you are using Office365, your Exchange server login id is probably your email address, and your Exchange server URL is probably https://outlook.office365.com.

KDE databases

The first thing is to create and identify the KDE databases you want to sync. You can use existing databases or create new ones.

To create a contacts database in Kontact I right clicked and selected Add Address Book and chose VCard Directory. You have to provide a directory name for the cards -- don't use a directory with anything in it. You can change the name by right-clicking on the name and selecting Folder Properties.

To create a calendar database, right click on Akonadi Calendars, in the Calendars pane, and choose Edit... Click on the Manage Calendar Sources button, choose Add and select ICal Calendar File. The filename you specify will be used as the folder name.

Whether you choose an existing folder or create a new one you need to find out the collection ID. To do that use:

syncevolution --print-databases

The output should include KDE Address Book and KDE Calendar sections. These will list all the folders and, for each one, will include a URL like akonadi:?collection=17. Those URLs are used to identify the database in SyncEvolution.

Configuring Exchange Server

The next step is to configure the information that the activesyncd process needs to contact the server. The process depends on the version of SyncEvolution you are running.

For SyncEvolution 1.5.2 and later, this information is configured using gsettings. For example:

OMA="org.meego.activesyncd"

gsettings set $OMA accounts "['user@example.com']"

gsettings set \ 
$OMA.account:/org/meego/activesyncd/account/user@example.com/ \ 
username "workdomain\username"

gsettings set \ 
$OMA.account:/org/meego/activesyncd/account/user@example.com/ \ 
serveruri https://activesync.example.com/Microsoft-Server-ActiveSync 

gsettings set \ 
$OMA.account:/org/meego/activesyncd/account/user@example.com/ \ 
policy-key 0

Note: all the quotes (single and double) are required.

For SyncEvolution versions before 1.5.2, this information is configured in gconf using gconftool. For example:

gconftool --type string -s \ 
/apps/activesyncd/accounts/user@example.com/username \ 
"workdomain\username"

gconftool --type string --set \ 
/apps/activesyncd/accounts/user@example.com/serverUri \ 
https://activesync.example.com/Microsoft-Server-ActiveSync 

Note: the quotes in the first command are important as otherwise the '\' will get lost.

Exchange Databases

If you are running a version of SyncEvolution >= 1.3.99.3, you can test the setup using the command:

syncevolution --print-databases \ 
username=user@example.com backend=eas-events 

You will be prompted for your password and then should see a list of your calendar folders.

syncevolution --print-databases \ 
username=user@example.com backend=eas-contacts 

Will list the contact folders.

If your version of syncevolution does not give useful output for that command, you can retrieve the full list of folders from the server using:

dbus-send --print-reply \ 
--dest=org.meego.activesyncd /EasCommon \ 
org.meego.activesyncd.EasCommon.get_folders \ 
string:'user@example.com' boolean:true 

If this completes successfully, look at the file ~/.cache/activesync/user@example.com/folders. This lists the exchange folders. Find the folders you want to synchronise and note the number in square brackets [] above the folder name. That is the collection ID, which you will need to specify instead of folder name when configuring this version of syncevolution.

Configuring one folder pair

Here is an example of the commands to configure a sync for a contacts folder. First the KDE database (akonadi:?collection=17 in this example):

syncevolution --configure --template none keyring=KDE backend=kde-contacts \ 
database=akonadi:?collection=17 @KDE contacts 

Now the Exchange folder (in this example the folder is called Contacts and has collection ID 2). If you are running a new enough version of syncevolution to understand folder names you can use:

syncevolution --configure syncURL= username=user@example.com
backend=eas-contacts database=Contacts dumpData=0 printChanges=0 \ 
target-config@Work contacts 

If you are using an older version of syncevolution, use the collection ID instead of the folder name:

syncevolution --configure syncURL= username=user@example.com
backend=eas-contacts database=2 dumpData=0 printChanges=0 \ 
target-config@Work contacts 

And then configure the link between the two:

syncevolution --configure --template none peerIsClient=1 \ 
syncURL=local://@Work username= sync=two-way \ 
work@KDE contacts 

Note that (if you are specifying --template none, as in the examples above) there is nothing special about the source name contacts. I tend to use the folder name or something similar.

Additional folder pairs

Other folder pairs are configured similarly. Calendar folders require that you specify the backends kde-calendar and eas-events instead of kde-contacts and eas-contacts.

Here is an example of setting up a Calendar folder called Calendar:

syncevolution --configure --template none keyring=KDE backend=kde-calendar \ 
database=akonadi:?collection=19 @KDE calendar

syncevolution --configure syncURL= username=user@example.com
backend=eas-events database=Calendar dumpData=0 printChanges=0 \ 
target-config@Work calendar

syncevolution --configure --template none peerIsClient=1 \ 
syncURL=local://@Work username= sync=two-way \ 
work@KDE calendar 

And an example of a second contacts folder Contacts/Personal:

syncevolution --configure --template none keyring=KDE backend=kde-contacts \ 
database=akonadi:?collection=21 @KDE personal 

syncevolution --configure syncURL= username=user@example.com
backend=eas-contacts database=Contacts/Personal \ 
dumpData=0 printChanges=0 \ 
target-config@Work personal

syncevolution --configure --template none peerIsClient=1 \ 
syncURL=local://@Work username= sync=two-way \  
work@KDE personal 

Syncing

The first sync will have to be a slow sync:

syncevolution --sync=slow work@KDE

Subsequent syncs can be fast:

syncevolution work@KDE

Problems

There are a few potential issues you may hit:

  1. If you find that the Sync reports error 403, then see bug 59265. I have submitted a patch for the problem but it has not yet been incorporated at the time of writing.

  2. Occasionally the server will get into a mode where it requires a FolderSync. If this happens, you can force the folder sync using one of the commands in the Exchange Databases section. If you can reproduce the problem, please file a bug report with the information on how to reproduce it.

Comments

Hi, this howto looks great. But I've got stuck at the early beginning of it, in section Exchange Databases:

The command "syncevolution --print-databases username=user@example.com backend=eas-events" prints out only "(): default", so I tried the "dbus-send ..." fallback and it fails with an error:

Error org.meego.activesyncd.Error.Failed: HTTP request failed: 401 - Unauthorized

I do not fully udnerstand the activesyncd debugging log, but it seems that gnome-keyring is required to authenticate (see below). Is it so? Or is there an other possibility to provide the password to the command?

Thanks for any hints, Jan

(process:14142:0x1b83e00): activesyncd-DEBUG:eas_common_get_folders--
...
(process:14142:0x1b918a0): libeas-DEBUG:getPasswordFromKeyring++
(process:14142:0x1b83e00): libeas-DEBUG:mainloop_password_fetch++
(process:14142:0x1b83e00): libeas-DEBUG:mainloop_password_fetch--
(process:14142:0x1b83e00): Gkr-Message:secret service operation failed: The name org.freedesktop.secrets was not provided by any .service files
(process:14142:0x1b83e00): libeas-DEBUG:getPasswordCallback++
(process:14142:0x1b83e00): libeas-DEBUG:getPasswordCallback--
(process:14142:0x1b918a0): libeas-DEBUG:getPasswordFromKeyring--
(process:14142:0x1b918a0): libeas-WARNING **:GnomeKeyring failed to find password [6]
...
(process:14142:0x1b918a0): libeas-*** CRITICAL ***:Failed with status [401] : Unauthorized

It is possible to store the password in the gconf database:

gconftool --type string -s \ /apps/activesyncd/accounts/user@example.com/password "your password"

I think activesyncd will then still try to use GNOME keyring (or more specifically, the org.freedesktop.secrets D-Bus service, which is implemented by later versions of KWallet, as far as I know) to store the password permanently. I don't know what will happen if storing the password fails - it might just continue syncing and leave the password as plain text in the gconf database.