Mailnews Exchange Support: basic mail infrastructure

This post is intended mostly as a status update on my effort to add Microsoft Exchange Server support to the Mozilla mailnews products, including Thunderbird and SeaMonkey.

In my last report, I was testing and updating the old Mozilla SOAP framework for use in communicating with Exchange Web Services (EWS). Using the framework in a Thunderbird 3.0 environment, I could talk to the BING search SOAP interface. It took a couple of more weeks to resolve issues associated with communicating with EWS. There were a number of features missing from the old Mozilla SOAP, most importantly:

  • attributes in SOAP elements.
  • arrays of choices with unlimited number of elements. The property bag of the previous interface can’t handle multiple items with the same name, so I did my own “property list” replacement for it.
  • authenticated access to the SOAP service.

I’ve successfully sent a “Get Folder” call to an Exchange Server. The code to define the specific Exchange call looks like this:

let getFolder = new EwsGetFolder;
getFolder.invoke(responseListener);

function EwsGetFolder()
{
 // defaults
 this.FolderBaseShape = "Default";
 this.FolderIds = "inbox";
}

EwsGetFolder.prototype = new SoapBase(kMessages2007sp1Schema);

EwsGetFolder.prototype.invoke =
  function EwsGetFolder_invoke(aSOAPResponseListener)
{
 let FolderShapeList =
   objectPropertyList({BaseShape: this.FolderBaseShape});
 let FolderIdsList = objectPropertyList(
     {DistinguishedFolderId: objectPropertyList(
       {$attributes: objectPropertyList({Id: this.FolderIds}) })});
 let soapCall = Cc["@mozilla.org/xmlextras/soap/call;1"]
                  .createInstance(Ci.nsISOAPCall);
 let parameters = [];
 let FolderShapeType =
   this._schema.collection.getType(
     'FolderResponseShapeType',
     'http://schemas.microsoft.com/exchange/services/2006/types');
 let FolderIdsType =
   this._schema.collection.getType(
     'NonEmptyArrayOfBaseFolderIdsType',
     'http://schemas.microsoft.com/exchange/services/2006/types');
 parameters.push(
   new soapParameter(
     "FolderShape",
     FolderShapeList,
     FolderShapeType,
     "http://schemas.microsoft.com/exchange/services/2006/messages"));
 parameters.push(
   new soapParameter(
     'FolderIds',
     FolderIdsList,
     FolderIdsType,
     "http://schemas.microsoft.com/exchange/services/2006/messages"));
 soapCall.encode(
   Ci.nsISOAPMessage.VERSION_1_1,
   'GetFolder',
   this._schema.targetNamespace,
   0, null, // header blocks
   parameters.length, parameters);
 soapCall.transportURI = kAccount.url;
 soapCall.asyncInvoke(aSOAPResponseListener,
                      kAccount.user, kAccount.password);
}

So I can now successfully do SOAP communication to an Exchange Server (2007 SP1), using the standard Exchange schemas to encode the messages. There is still much needed to clean this up, but I’ve got enough working for now.

So now I turn my attention to the setup of a new account type in Thunderbird. This is the same issue that jcranmer is working on, but he is specifically trying to do everything in javascript, while I am content (for now) to work partly in C++. So I have to build the darn thing.

Ah, the Mozilla build system. Gotta love it. You have to know the difference between :, ::, :=, =~, (), {}, in a zillion different languages (perl, python, autoconf, automake, bash, make at least). When it works, it works like magic. But sometimes you wave your magic wand, say your magic incantation, and nothing happens. That’s what makes it so hard. You spend hours seeing if you can get the spell to work, but sometimes you just have to give up and do it the old fashioned way, knowing that there is probably some trivial change you could have done to make the magic work. But I guess I have no right to complain. Everyone said to NOT do it this way, but did I listen? I’ve been in build hell for a week.

But it turned out to be just build purgatory! Now that I am out, what wonders heaven holds! I can use a real debugger on my code, and not Venkman and dump()! The vast majority of the existing mailnews code is in C++, so I can see what local folders, IMAP, and newsgroups do, and very easily adapt it to my needs. I can subclass the existing implementations!

So as of today, I have a series of subclassed C++ files that contain what will be the future EWS-based objects – though I have not attempted yet to glue them to EWS, just simulations. I have new C++ files for the folder, message service, incoming server, and summary database – along with some basic unit tests. (This is very similar to the approach that the RSS implementation takes).

So what can I do? I can just display an account, its subfolders, and a message header (all simulated not real). It looks like this:

As you can see, I have not faced the issue yet of registering my protocols, so when I click on the message I get a complaint. I’ll be doing that next, along with trying to get the real information from EWS instead of this simulation.

OK, I know, you are not impressed – one simulated message, and that does not even work?  “Everything is hard to do in Thunderbird” is my defense, so cut me some slack, all right?

rkent