EWS - Access All Shared Calendars

15,079

Solution 1

By Shared Calendars do you mean the calendars under the other calendars node in Outlook ?

Other Calendars Node

If so these Items are NavLinks that are stored in the Common Views folder in a Mailbox which is under the NonIPMSubtree (root) see http://msdn.microsoft.com/en-us/library/ee157359(v=exchg.80).aspx. You can use EWS to get the NavLinks from a Mailbox and use the PidTagWlinkAddressBookEID extended property to get the X500 address of the Mailbox these Links refer to and then use Resolve Name to resolve that to a SMTP Address. Then all you need to do is Bind to that folder eg

     static Dictionary<string, Folder> GetSharedCalendarFolders(ExchangeService service, String mbMailboxname)
    {
        Dictionary<String, Folder> rtList = new System.Collections.Generic.Dictionary<string, Folder>();

        FolderId rfRootFolderid = new FolderId(WellKnownFolderName.Root, mbMailboxname);
        FolderView fvFolderView = new FolderView(1000);
        SearchFilter sfSearchFilter = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "Common Views");
        FindFoldersResults ffoldres = service.FindFolders(rfRootFolderid, sfSearchFilter, fvFolderView);
        if (ffoldres.Folders.Count == 1)
        {

            PropertySet psPropset = new PropertySet(BasePropertySet.FirstClassProperties);
            ExtendedPropertyDefinition PidTagWlinkAddressBookEID = new ExtendedPropertyDefinition(0x6854, MapiPropertyType.Binary);
            ExtendedPropertyDefinition PidTagWlinkGroupName = new ExtendedPropertyDefinition(0x6851, MapiPropertyType.String);

            psPropset.Add(PidTagWlinkAddressBookEID);
            ItemView iv = new ItemView(1000);
            iv.PropertySet = psPropset;
            iv.Traversal = ItemTraversal.Associated;

            SearchFilter cntSearch = new SearchFilter.IsEqualTo(PidTagWlinkGroupName, "Other Calendars");
            // Can also find this using PidTagWlinkType = wblSharedFolder
            FindItemsResults<Item> fiResults = ffoldres.Folders[0].FindItems(cntSearch, iv);
            foreach (Item itItem in fiResults.Items)
            {
                try
                {
                    object GroupName = null;
                    object WlinkAddressBookEID = null;

                    // This property will only be there in Outlook 2010 and beyond
                    //https://msdn.microsoft.com/en-us/library/ee220131(v=exchg.80).aspx#Appendix_A_30
                    if (itItem.TryGetProperty(PidTagWlinkAddressBookEID, out WlinkAddressBookEID))
                    {

                        byte[] ssStoreID = (byte[])WlinkAddressBookEID;
                        int leLegDnStart = 0;
                        // Can also extract the DN by getting the 28th(or 30th?) byte to the second to last byte 
                        //https://msdn.microsoft.com/en-us/library/ee237564(v=exchg.80).aspx
                        //https://msdn.microsoft.com/en-us/library/hh354838(v=exchg.80).aspx
                        String lnLegDN = "";
                        for (int ssArraynum = (ssStoreID.Length - 2); ssArraynum != 0; ssArraynum--)
                        {
                            if (ssStoreID[ssArraynum] == 0)
                            {
                                leLegDnStart = ssArraynum;
                                lnLegDN = System.Text.ASCIIEncoding.ASCII.GetString(ssStoreID, leLegDnStart + 1, (ssStoreID.Length - (leLegDnStart + 2)));
                                ssArraynum = 1;
                            }
                        }
                        NameResolutionCollection ncCol = service.ResolveName(lnLegDN, ResolveNameSearchLocation.DirectoryOnly, false);
                        if (ncCol.Count > 0)
                        {

                            FolderId SharedCalendarId = new FolderId(WellKnownFolderName.Calendar, ncCol[0].Mailbox.Address);
                            Folder SharedCalendaFolder = Folder.Bind(service, SharedCalendarId);
                            rtList.Add(ncCol[0].Mailbox.Address, SharedCalendaFolder);


                        }

                    }
                }
                catch (Exception exception)
                {
                    Console.WriteLine(exception.Message);
                }

            }
        }
        return rtList;
    }

Cheers Glen

Solution 2

You need to specify a searchfilter. this is described here, though im not sure which Schema is the correct one, my guess would be Archieved.

So you would do something like this:

SearchFilter searchFilter = new SearchFilter.IsEqualTo(FolderSchema.Archieved, false);

FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.MsgFolderRoot,searchFilter, view);

Solution 3

Glen post is perfect but binding folder gives error. However i solved this. Instead of this line:

Folder SharedCalendaFolder = Folder.Bind(service, SharedCalendarId);

use the following line for shared folder binding

CalendarFolder calendar = CalendarFolder.Bind(service, new FolderId(WellKnownFolderName.Calendar, OwnerEmailAddress), new PropertySet());

Here OwnerEmailAddress is Email Address of Owner or you can write ncCol[0].Mailbox.Address if using Glen's code.

Share:
15,079
synic
Author by

synic

Updated on June 04, 2022

Comments

  • synic
    synic almost 2 years

    I've got the following code:

        private void ListCalendarFolders(ref List<EBCalendar> items, int offset)
        {
            var pageSize = 100;
            var view = new FolderView(pageSize, offset, OffsetBasePoint.Beginning);
            view.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
            view.PropertySet.Add(FolderSchema.DisplayName);
            view.PropertySet.Add(FolderSchema.EffectiveRights);
    
            view.Traversal = FolderTraversal.Deep;
    
            FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.MsgFolderRoot, view);
            foreach (Folder myFolder in findFolderResults.Folders)
            {
                if (myFolder is CalendarFolder)
                {
                    var folder = myFolder as CalendarFolder;
                    items.Add(EBCalendar.FromEWSFolder(folder));
                }
            }
    
            if (findFolderResults.MoreAvailable)
            {
                offset = offset + pageSize;
                ListCalendarFolders(ref items, offset);
            }
        }
    

    Where service is an ExchangeService instance. Unfortunately, it still lists folders that have been deleted, and it doesn't list shared calendars.

    How can I get it to list all the shared calendars, and how can I get it to not include the folders that have been deleted?

  • synic
    synic almost 10 years
    Thanks! This solves the deleted ones showing. Have any idea about the shared folders not showing up?
  • CSharpie
    CSharpie almost 10 years
    I bellieve you cant do this by using a folder view, instead you need to define a FolderId with the mailbox that is sharing the folder.
  • synic
    synic almost 10 years
    But I don't know the folder ID. I'd like a list of all shared/public/owned folders.
  • CSharpie
    CSharpie almost 10 years
    Ok try with a second FindFolders-Call using WellKnownfolderName.PublicFoldersRoot Maybe the enum supports flags so you might be able to do it in one FindFoldersCall
  • CSharpie
    CSharpie almost 10 years
    Check this questions first Answer aswell stackoverflow.com/questions/13877629/…
  • synic
    synic almost 10 years
    Wow, that's awesome. I'm going to give it a try right now. Thank you!
  • Lee Harrison
    Lee Harrison over 9 years
    I don't seem to have access to the FolderSchema.Archived property. Any ideas? I'm returning all deleted items as well and its not very useful.
  • Dimuthu
    Dimuthu about 8 years
    This works great to obtain shared calendar folders. But now I am having trouble when I try to access the items in shared calendars. Basically I need to get the free/busy state. I was calling service.FindItems(SharedCalendaFolder.Id, iCalenderview) and I got "Access is denied. Check credentials and try again." error. But in outlook web app I am able to see shared calendar events.
  • Glen Scales
    Glen Scales about 8 years
    To Access a Calendar you will need at least Read Access to the calendar I would say you only have FreeBusy rights at the moment so you can only use the GerUseravailiblity operation in that case unless you assign more rights to the calendar folder for your account.
  • KirilStankov
    KirilStankov over 4 years
    Hi, unfortunately, this doesn't work if the shared calendar is not the default Calendar. E.g. user A created a calendar called Public and shared it with user B. The TryGetProperty fails on these items, even though it works with default calendars.
  • strangetimes
    strangetimes over 4 years
    Is there a EWS XML request / response equivalent of this? I'm having the same issue, but not sure how to translate this into XML.