Originally published 2011-11-21 22:25:02

Using Exchange Effectively on Linux

I've just started a new job at a company that uses Exchange for email et al. Exchange works pretty well with Outlook on Windows, and the web UI is pretty good in Internet Explorer, but if you want to use Linux it's a bit trickier. But, I think I have everything working to my liking now, so I thought I should post what I did.

Specifically, the problems to solve with Exchange on Linux are:

  1. What to do with email, especially given that I only really like using Gmail.
  2. What to use for calendaring, with bonus points if it syncs to my Android phone.
  3. How to access the company address book, for email recipient completion.
  4. How to do all this without storing passwords in plaintext.

Email

Email is pretty easy: Exchange exposes IMAP, so I use offlineimap to fetch it, and then index it with notmuch. Notmuch approximates Gmail better than anything else I've seen, and the Emacs interface works well.

My offlineimap config is very plain: it just synchronizes every two minutes. There are only two customized things: a post-sync hook that imports mail into notmuch and tags it, and a python script that fetches my username and password from gnome-keyring. The python script is based on one from Carsten Clasohm, and on his page you will find an accompanying script to add your passwords to the keyring. The only addition I've made is a main method that lets us fetch the username and password; we'll see later why we want this.

I use a special .emacs for notmuch. I start Emacs using an alias: emacs -q -l $HOME/.emacs-notmuch -f notmuch, which loads the config and starts the notmuch module. A few notes on the config:

  • It has some stuff from my normal .emacs, like keybindings and color schemes.
  • It adds some Gmail keybindings that I use a lot. It's by no means an exhaustive set.
  • It sets up authenticated, secured SMTP for sending mail. This was by far the most time-consuming thing to figure out. You can see here why I modified the offlineimap.py script earlier - so I can get the credentials from keyring here!
  • It sets up address lookup using a script called address-lookup. I'll talk about this later on, in the Address Book section.

Calendar

Google actually has a tool that syncs your Outlook calendar with your Google Calendar. It does require that you have Outlook running, so you'll need a Windows VM and a registered Outlook. If you're willing to do that, it's the perfect solution: your calendars get synced, and since your Exchange calendar events are on your Google calendar, they'll show up on your Android phone.

Address Book

Tab completion from emails that are already in your notmuch database is easy: just use Sebastian Spaeth's addrlookup (hint: check out the static-sources branch if you don't want to compile Vala code). However, I wanted to have tab completion of the whole company directory, not just people I've emailed before. This involves three steps.

Step 1: Setup DavMail to provide LDAP access to the Exchange address book. The trickiest part of this was figuring out how to setup DavMail nicely. The best way I found was to use the EWS URL (e.g. https://exchange.example.com/ews/exchange.asmx), NOT the OWA URL that most of the DavMail docs refer to. You can tell DavMail it's talking to EWS with the davmail.enableEws=true config line.

Step 2: Make something talk LDAP to DavMail. I started with the old mutt-ldap.pl script, but made some changes. In particular, this uses my offlineimap.py script to fetch my credentials, and changes the criteria a bit to work better with DavMail's LDAP implementation.

Step 3: Integrate the LDAP script with the notmuch script to search both places. This is my address-lookup script. It searches notmuch, and if it doesn't find anything then it searches LDAP; this keeps it fast for the most-contacted people. To facilitate this, I made some changes to addrlookup so that it returns the number of results it finds.

That's All!

Not so bad, eh? I hope this will help other people deal with Exchange in a sane manner.