Free Busy Interop for Exchange

Revision as of 23:14, 15 May 2009 by Bobby (talk | contribs) (give troubleshooting link a heading)


In many cases ZCS is deployed in an environment where there is a mix of Zimbra server and 3rd party servers. In such environments, typically the users are partitioned into a group using Zimbra servers and a group using 3rd party servers. When a user wants to schedule a meeting with other users, the free/busy schedules of the other users are readily available only if the attendees are in the same group as the organizer.

Some calendaring software allows limited interop with 3rd party systems. For example, Outlook allows downloading the free/busy schedule for a user from a web server. However, configuring URL for each attendees can be a tedious task. It would be desirable if Zimbra server can provide server to server free/busy sync with 3rd party servers. Then the Zimbra users will be able to query the free/busy schedule of users on other system, such as Exchange 2003/2007 or Domino server, the same way they would query the Zimbra users.

Zimbra should also support pushing free/busy schedule of Zimbra users to the 3rd party server, if the 3rd party server supports such features.

Free/busy Provider Framework

Zimbra provides a framework where the interop with any 3rd party system can be added via an extension. Through the extension, Zimbra server can query the free/busy schedule of users on 3rd party system, and also propagate free/busy schedule of a Zimbra user to the 3rd party system. The mechanism is described later in the document.

Interop with Exchange 2003

Zimbra server has a default implementation of Exchange free busy provider. The Zimbra server can pull the free/busy schedule of a user on Exchange, and also push the free/busy schedule of a Zimbra user to the Exchange server. The retrieval of free/busy (Exchange to Zimbra) is done via a REST interface on the Exchange server. The propagation of free/busy (Zimbra to Exchange) is done via WebDAV interface on the Exchange server. In both cases, Zimbra needs to authenticate to the Exchange server via HTTP basic authentication or HTML form based authentication ala OWA.

In order to enable the default Exchange free busy interop implementation, the following conditions need to be met.

1. There should be a single AD in the system or Global Catalog is available. 2. Zimbra server can access HTTP(S) port of IIS on at least one of the Exchange server. 3. The Web interface to Exchange public folders (http://server/public/) needs to be available via IIS. 4. Zimbra users need to be provisioned as a contact on Active Directory using the same administrative group for each mail domain. 5. The Exchange username must be provisioned in the account attribute zimbraForeignPrincipal for all the Zimbra users.

The conditions 4 and 5 are required only for Zimbra → Exchange free/busy replication. With the first three condition met, Exchange → Zimbra free/busy lookup is still possible.

After creating the contacts, the legacyExchangeDN attribute can be verified by running ADSI Edit tool, open the contact object. Search for the attribute legacyExchangeDN for the contact. For example the attribute value would be:

legacyExchangeDN : /o=First Organization/ou=First Administrative Group/cn=Recipients/cn=james

The substrings left and right of /cn=Recipients are important, and need to be consistent across the Zimbra contacts. The left part /o=First Organization/ou=First Administrative Group corresponds to the domain attribute zimbraFreebusyExchangeUserOrg. The value of cn corresponds to the Exchange account name specified in zimbraForeignPrincipal.

There are five global configuration variables on Zimbra to enable the interop with Exchange server.

  • zimbraFreebusyExchangeAuthUsername
  • zimbraFreebusyExchangeAuthPassword
  • zimbraFreebusyExchangeAuthScheme
  • zimbraFreebusyExchangeURL
  • zimbraFreebusyExchangeUserOrg

The zimbraFreebusyExchangeAuthUsername and zimbraFreebusyExchangeAuthPassword attributes are used to authenticate against Exchange server on REST and WebDAV interface. The zimbraFreebusyExchangeAuthScheme attribute can be set to basic or form, depending on how Exchange server is configured. When set to basic, Zimbra will attempt HTTP basic authentication. When set to form, it will POST HTML form to /exchweb/bin/auth/owaauth.dll to get the auth Cookie set. The zimbraFreebusyExchangeURL attribute should be set to the URL of the Exchange server. The zimbraFreebusyExchangeUserOrg attribute is the first part of the administrative group. Typically they are set to /o=First Organization/ou=First Administrative Group. Note that the value Org is from the legacyExchangeDN attribute of the user, not the DN of the user object.

Use the zmprov CLI tool to set the global configuration variables. For example, assuming the user zimbra exists on the Exchange server on with the password changeme:

# zmprov mcf zimbraFreebusyExchangeAuthUsername zimbra
# zmprov mcf zimbraFreebusyExchangeAuthPassword changeme
# zmprov mcf zimbraFreebusyExchangeAuthScheme basic
# zmprov mcf zimbraFreebusyExchangeURL
# zmprov mcf zimbraFreebusyExchangeUserOrg "/o=First Organization/ou=First Administrative Group"

Add the Zimbra account to Exchange account mapping to the zimbraForeignPrincipal attribute. Note that zimbraForeignPrincipal is a multi value attribute. Be careful not to wipe out the existing values when adding a new one. Use the prefix ad: in front of the Exchange account username to indicate the usage for Active Directory.

# zmprov ma zimbraForeignPrincipal ad:james

If there is more than one mail domain, zimbraFreebusyExchangeUserOrg can be set for each domain.

# zmprov md zimbraFreebusyExchangeUserOrg "/o=AnotherDomain/ou=First Administrative Group"

Interop with Exchange 2007


Complex Exchange Environment

If the Exchange environment does not meet the requirement for above, the default Exchange provider needs to be extended to work in such environment. Zimbra provides a Java interface.


The interface requires one method.

public ServerInfo getServerInfo(String emailAddr);

The resolver implementation should take an email address of a user on AD, then return ServerInfo object. If the user is not found in AD it should return null. ServerInfo is defined as:

    public static class ServerInfo {
        public String url;
        public String org;
        public String cn;
        public String authUsername;
        public String authPassword;
        public AuthScheme scheme;  // basic or form

Finally, the bootstrapping of the exchange provider can be done via ZimbraExtension. Following is an example to illustrate how this can be implemented.

    public class FbExtension implements ZimbraExtension {
        public void init() {
            ExchangeFreeBusyProvider.registerResolver(new ExchangeUserResolver() {
                public ServerInfo getServerInfo(String emailAddr) {
                    ServerInfo info = new ServerInfo();
                    info.url = "";
                    info.authUsername = "zimbra";
                    info.authPassword = "changeme";
                    info.scheme = AuthScheme.basic;
           = "/o=First Organization/ou=First Administrative Group";
           = emailAddr;
                    if (emailAddr.indexOf('@') > 0)
               = emailAddr.substring(0, emailAddr.indexOf('@'));
                    return info;
            }, 0);
        public void destroy() {
        public String getName() {
            return "ExtensionFbProvider";

Interop with Other Non-Exchange Systems

Zimbra can handle other 3rd party system by extending the FreeBusyProvider framework.

    public abstract class FreeBusyProvider {
        public abstract FreeBusyProvider getInstance();
        public abstract String getName();
        // free/busy lookup from 3rd party system
        public abstract void addFreeBusyRequest(Request req) throws FreeBusyUserNotFoundException;
        public abstract List<FreeBusy> getResults();
        // propagation of Zimbra users free/busy to 3rd party system
        public abstract boolean registerForMailboxChanges();
        public abstract boolean handleMailboxChange(String accountId);
        public abstract long cachedFreeBusyStartTime();
        public abstract long cachedFreeBusyEndTime();

The API allows batching of lookup requests. The framework invokes addFreeBusyRequest() for each non-Zimbra users. The provider implementation should throw FreeBusyUserNotFoundException when the user is not found. This allows for multiple FreeBusyProviders to co-exist in the system. The framework will then call getResults(), and at that point the provider returns a set of FreeBusy for the batched requests.

If the provider can handle propagation of Zimbra users free/busy, it should declare it so by returning true on registerForMailboxChanges(). Then the framework will call handleMailboxChange() for each providers when a change in the mailbox that could result in recalculation of free/busy is detected. cachedFreeBusyStartTime() and cachedFreeBusyEndTime() are millis since epoch to indicate the interval of free/busy that can be cached in the 3rd party system. For example the basic Exchange free/busy provider caches free/busy from the beginning of the month, for two months.



Verified Against: Unknown Date Created: 10/15/2008
Article ID: Date Modified: 2009-05-15

Try Zimbra

Try Zimbra Collaboration with a 60-day free trial.
Get it now »

Want to get involved?

You can contribute in the Community, Wiki, Code, or development of Zimlets.
Find out more. »

Looking for a Video?

Visit our YouTube channel to get the latest webinars, technology news, product overviews, and so much more.
Go to the YouTube channel »

Jump to: navigation, search