InfiniTec - Henning Krauses Blog

Don't adjust your mind - it's reality that is malfunctioning

Enumerating Sharepoint Connections in a mailbox with EWS

An interesting question on StackOverflow came up recently: Is it possible to get the SharePoint lists which are connected to an Exchange Mailbox? The data which is synchronized with Outlook is stored in a PST file on the local disk – so no interaction with Exchange on this end. But if a user logs on from another computer, the SharePoint list the user has subscribed to are synchronized there as well. So the configuration seems to be stored in the mailbox somewhere. And indeed, they are. Outlook creates a message item in the associated folder table in the users inbox. Associated items are not visible from Outlook, but they can be accessed using MAPI or EWS. It turns out that Outlook saves the SharePoint connections similar to the RSS feeds. So a good starting point is to have a look at the Sharing Message Object Protocol Specification which lists the properties used for these items.

The SharePoint configuration items have a MessageClass of IPM.Sharing.Index.In, and the property PidLidSharingProviderGuidProperty is set to {0006F0AD-0000-0000-C000-000000000046}.

The configuration data is stored on a few properties. The following method lists all SharePoint connections connected to a mailbox:

   1:  using System;
   2:  using System.Net;
   3:  using Microsoft.Exchange.WebServices.Data;
   4:   
   5:  namespace ExchangeTest
   6:  {
   7:      internal class Program
   8:      {
   9:          private static readonly Guid PropertySetSharing = new Guid("{00062040-0000-0000-C000-000000000046}");
  10:   
  11:          private static readonly ExtendedPropertyDefinition PidLidSharingProviderGuidProperty =
  12:              new ExtendedPropertyDefinition(PropertySetSharing, 0x8A01, MapiPropertyType.CLSID);
  13:   
  14:          private static readonly ExtendedPropertyDefinition SharingRemotePathProperty =
  15:              new ExtendedPropertyDefinition(PropertySetSharing, 0x8A04, MapiPropertyType.String);
  16:   
  17:          private static readonly ExtendedPropertyDefinition SharingLocalNameProperty =
  18:              new ExtendedPropertyDefinition(PropertySetSharing, 0x8A0F, MapiPropertyType.String);
  19:   
  20:          private static readonly ExtendedPropertyDefinition SharingRemoteNameProperty =
  21:              new ExtendedPropertyDefinition(PropertySetSharing, 0x8A05, MapiPropertyType.String);
  22:   
  23:          private static readonly ExtendedPropertyDefinition SharingBrowseUrlProperty =
  24:              new ExtendedPropertyDefinition(PropertySetSharing, 0x8A51, MapiPropertyType.String);
  25:   
  26:          private static readonly ExtendedPropertyDefinition SharingRemoteTypeProperty =
  27:              new ExtendedPropertyDefinition(PropertySetSharing, 0x8A1D, MapiPropertyType.String);
  28:   
  29:          private static readonly Guid SharePointProviderId = new Guid("{0006F0AD-0000-0000-C000-000000000046}");
  30:   
  31:          public static void Main(string[] args)
  32:          {
  33:              var service = new ExchangeService(ExchangeVersion.Exchange2010)
  34:                            {Credentials = new NetworkCredential(test@contoso.com, "Password!")};
  35:              
  36:              service.AutodiscoverUrl(test@contoso.com, url => true);
  37:   
  38:              var folder = Folder.Bind(service, WellKnownFolderName.Inbox);
  39:              var filter = new SearchFilter.SearchFilterCollection(LogicalOperator.And,
  40:                                                                   new SearchFilter.IsEqualTo(ItemSchema.ItemClass,
  41:                                                                                              "IPM.Sharing.Index.In"),
  42:                                                                   new SearchFilter.IsEqualTo(PidLidSharingProviderGuidProperty,
  43:                                                                                              SharePointProviderId.ToString()));
  44:              var view = new ItemView(512)
  45:                         {
  46:                             Traversal = ItemTraversal.Associated,
  47:                             PropertySet = new PropertySet(BasePropertySet.IdOnly,
  48:                                                           SharingRemotePathProperty, SharingBrowseUrlProperty,
  49:                                                           SharingLocalNameProperty, SharingRemoteNameProperty,
  50:                                                           SharingRemoteTypeProperty)
  51:                         };
  52:   
  53:              var items = folder.FindItems(filter, view);
  54:              foreach (var item in items)
  55:              {
  56:                  Console.Out.WriteLine("RemotePath = {0}", item.GetValueOrDefault<string>(SharingRemotePathProperty));
  57:                  Console.Out.WriteLine("BrowseUrl = {0}", item.GetValueOrDefault<string>(SharingBrowseUrlProperty));
  58:                  Console.Out.WriteLine("LocalName = {0}", item.GetValueOrDefault<string>(SharingLocalNameProperty));
  59:                  Console.Out.WriteLine("Remotename = {0}", item.GetValueOrDefault<string>(SharingLocalNameProperty));
  60:                  Console.Out.WriteLine("Type = {0}", item.GetValueOrDefault<string>(SharingRemoteTypeProperty));
  61:                  Console.Out.WriteLine(new string('=', 80));
  62:              }
  63:          }
  64:      }
  65:   
  66:      public static class ItemExtension
  67:      {
  68:          public static T GetValueOrDefault<T>(this Item item, PropertyDefinitionBase property, T defaultValue = default(T))
  69:          {
  70:              T result;
  71:              return item.TryGetProperty(property, out result) ? result : defaultValue;
  72:          }
  73:      }
  74: }

This method dumps the configuration of all SharePoint connections to the console.

To use this method, you’ll need .NET 4. If you are running .NET 2.0, you’ll have to adapt it.

Additionally, this won't work with Exchange 2007, because EWS in that version does not allow a FindItems call on the associated items table. WebDAV is the API of choice in this case.


Posted by Henning Krause on Wednesday, July 13, 2011 9:05 PM, last modified on Wednesday, July 13, 2011 9:05 PM
Permalink | Post RSSRSS comment feed