none
[E2013][EWS - AutoGen][JAVA][Outlook Contacts vs Personas]

    Question

  • How to get ONLY user's outlook contacts using EWS API for exchange 2013? ( and NOT any other persona/unified contacts/auto generated/aggregated contacts)

    Contacts are managed in different folders internally, but then how to query specific contacts folder when using EWS API ? (Note: We cannot use display name of folders).

    Tuesday, October 09, 2012 12:16 PM

Answers

  • Thanks Glen for your inputs. I have just found a clue on how to solve this problem while I was analyzing some other scenario/problem.

    To fetch all contacts of a user, Currently we are starting from “DistinguishedFolderIdNameType.contacts” and then fetch contacts from this root contacts folder including all sub-folders (deep traversal). All is fine for exchange server versions 2007 and 2010 as there are no special unexpected sub folders under contacts folder like in 2013.

    What happens with exchange 2013 due to various new features, is that there are some additional unexpected special folders shown as sub-folders of contacts folder (DistinguishedFolderIdNameType.contacts) e.g. with folder classes IPF.Contact.MOC.QuickContacts”, “IPF.Contact.RecipientCache”, “IPF.Contact.OrganizationalContacts, and these are the special folders which are returning unexpected contacts (non-outlook contacts) for my use-case.

    For all outlook contacts (non-persona, non-auto/quick, non-unified), folderclass for all holding folders is IPF.Contact as expected. So, a kind of business decision based on expected folder class can be made not to fetch unexpected contacts depending upon required scenario/use-case. Good thing is that folder-classes are localization independent, and consistent across exchange server versions. And our application also do not support user-defined folder classes.


    Thanks, Nimesh

    Tuesday, October 16, 2012 12:00 PM

All replies

  • You have to programatically retrieve the folder through EWS. 

    Then do the following against the retrieved folder:

    if (folder is ContactsFolder)
    {
       ContactsFolder fldContacts = folder as ContactsFolder;
       FindItemsResults<Item> contactItems = service.FindItems(fldContacts.Id, 
                                                                new ItemView(int.MaxValue));
       foreach (Contact contact in contactItems.Items)
       {
          console.write("DisplayName=" + contact.DisplayName);
          console.write(contact.Id.UniqueId.ToString());
          console.write(“”);
     }//foreach contact
    
    Its up to you what properties and methods on each contact you want to use and how to display/process them
    Tuesday, October 09, 2012 7:41 PM
  • Seems my question was mis-understood. Let me put it in more details:

    With exchange 2013, if I would start with root contacts folder and then traverse through all subfolders to fetch all contact items, I do not only get outlook contacts but also other linked/aggregated/auto generated (e.g. when an email is sent to someone, corresponding contact is auto created by exchange). This was not the case with earlier versions of exchange as exchange 2013 have new concepts called persona, unified contact store etc introduced.

    Now, these all different contacts are internally managed in different folders, e.g. my contacts folder, allcontacts folder, mycontactsextended folder etc. Now, if I see them I find that contacts in "my contacts" folder are the one "outlook contacts" and not from any other sources. To be backward compatible with earlier exchange versions, I also need to fetch contacts only from outlook and not from any other source/way.

    But, how can my EWS Java application, identify exactly which contacts folder to query only and not any other folder ? I cannot use display name, so based only on folderId, how can my application determine that this folder corresponds to correct folder I want to fetch all contacts from ? My application should laso handle that all manually created outlook contacts subfolders are also queried to fetch outlook specific contacts.

    Wednesday, October 10, 2012 8:04 AM
  • I wouldn't use the folderID as a constant identifier, because if the folder is moved somewhere else (either programatically or by a user), it gets a new ID assigned to it.   What I noticed in EWS/Exchange is that folders are identified by a folder pair.  That is, the target folder's name AND the parent folder it belongs to.  The parent folder is used to qualify the folder you are searching for, so you can tell folders of the same name apart.

    You use this pair in findfolder searches to find the exact folder you want.  The "parent folder" doesn't have to be exact; it can be any folder in the target folder's path.  Find the parent folder first using a deep traversal from the mailbox root and get its ID.  Then, find the target folder by specifying the found parent folder's ID as the first parameter (search start point) in a second findfolder search.  If you know the parent folder exactly, then you can do a shallow search for the target folder from the parent folder.   But, it is the combination of the parent and target folder names that uniquely identifies a particular folder because all folders at the root of a parent must have unique names.

    Wednesday, October 10, 2012 1:11 PM
  • but "folder name (displayname of folder)" for same folder would be different in each language, like in English it is "My contacts" and in Deutsch "Meine Kontakten" etc. This is one of the major reasons not to use displayname of folders for making application business decisions, because folder names are localized based on a language that is first used to connecto to mailbox.

    Thanks, Nimesh

    Wednesday, October 10, 2012 2:13 PM
  • Well, I'm new to EWS and am experimenting with it and documenting my results.  I've seen the ID change on folders I move, because the move operation essentially creates a new destination folder which causes the new ID.   All the examples I've come across (including Microsoft's) are using the display names in findfolder searches, and are using the starting folder parameter to qualify which folder is being sought.

    I understand the problem in localization, but that's what resource strings are for (to specify a known search term in another given language).  I haven't seen any property or method on the EWS Folder class that allows it to have different spellings for different localizations, and believe the name will remain fixed regardless of the localization (on the server side).  I don't know if this is true for the built-in system folders (Inbox, Deleted Items, etc), however those can be referred to by built-in enums shipped with EWS.

    Perhaps the localization you are referring to is being done only on the Outlook side and not on the server side mailbox?

    Wednesday, October 10, 2012 2:27 PM
  • If you only want the Contacts folder (and this will work on any version of Exchange regardless of localization) and your using the Generated Proxies then you just use the DistinguishedFolderIdType Enum for Contact eg

                FindItemType findRequest = new FindItemType();
                findRequest.Traversal = ItemQueryTraversalType.Shallow;
    
                // Define which item properties are returned in the response.
                ItemResponseShapeType itemProperties = new ItemResponseShapeType();
                itemProperties.BaseShape = DefaultShapeNamesType.AllProperties;
    
                // Add properties shape to request.
                findRequest.ItemShape = itemProperties;
    
                // Define the folders to search. 
                DistinguishedFolderIdType[] folderIDArray = new DistinguishedFolderIdType[1];
                folderIDArray[0] = new DistinguishedFolderIdType();
                folderIDArray[0].Id = DistinguishedFolderIdNameType.contacts;
                findRequest.ParentFolderIds = folderIDArray;
    
                FindItemResponseType findResponse = serviceBinding.FindItem(findRequest);

    On older versions of Exchange if you want to do what the Persona operations do is you can do a FindFolder operation with a Deep traversal then look at the FolderClass of Each folder to see if its IPF.Contact which will tell you if the folder has contacts and then query that folder. What happens on 2013 is there is a SearchFolder created call AllContacts (in the Non_IPM_Subtree) which does the aggregation on the Exchange side eg

    Cheers
    Glen

    Wednesday, October 10, 2012 8:54 PM
  • Thanks Glen for your inputs. My need is little different, I do not want to query root contacts folder, but I want the contacts only from "mycontacts" folder because the contacts in "mycontacts" folder are outlook contacts (not aggregated/persona/unified). With exchange 2013, mycontacts is a sub-folder of root contacts folder. 

    We use 2007_SP_1 EWS schema, and with it "DistinguishedFolderIdNameType" has only "contacts" folder but not "mycontacts", but If I use exchange 2013 schema reference for "DistinguishedFolderIdNameType" on link "http://msdn.microsoft.com/en-us/library/exchange/jj191225(v=exchg.150).aspx" then I can also query only "mycontacts" folder.

    I want non-persona, non-aggreagated, non-unified contacts (only outlook contacts) for all exchange server versions (2007, 2010 and 2013).


    Thanks, Nimesh

    Thursday, October 11, 2012 8:15 AM
  • > , I do not want to query root contacts folder, but I want the contacts only from "mycontacts" folder because the contacts in "mycontacts" folder are outlook contacts (not aggregated/persona/unified).

    The Mycontacts folder is still just a searchfolder under the NON_IPM_Root (have a look at the type you get back in the response) or if you look at the mailbox with a mapi editor its this folder

    There is another MyContacts in a Mailbox which in just a NavBar shortcut which existed in other version of Outlook/Exchange

    The  DistinguishedFolderIdNameType.contacts; will allways return the actual Mailboxes Contacts Folder and will work on any version of Exchange

    >>"We use 2007_SP_1 EWS schema, and with it "DistinguishedFolderIdNameType" has only "contacts" folder but not "mycontacts", but If I use exchange 2013 schema reference for "DistinguishedFolderIdNameType" on link "http://msdn.microsoft.com/en-us/library/exchange/jj191225(v=exchg.150).aspx" then I can also query only "mycontacts" folder."

    The mycontacts searchfolder is a Exchange 2013 feature so you wont find this olderversions of Exchanges. My suggestion however is you test this yourself and check against what you can see in a Mapi editor like MFCMapi where your looking at the raw mailbox content.

    Cheers
    Glen

    Thursday, October 11, 2012 9:48 AM
  • Thanks Glen for your inputs. I have just found a clue on how to solve this problem while I was analyzing some other scenario/problem.

    To fetch all contacts of a user, Currently we are starting from “DistinguishedFolderIdNameType.contacts” and then fetch contacts from this root contacts folder including all sub-folders (deep traversal). All is fine for exchange server versions 2007 and 2010 as there are no special unexpected sub folders under contacts folder like in 2013.

    What happens with exchange 2013 due to various new features, is that there are some additional unexpected special folders shown as sub-folders of contacts folder (DistinguishedFolderIdNameType.contacts) e.g. with folder classes IPF.Contact.MOC.QuickContacts”, “IPF.Contact.RecipientCache”, “IPF.Contact.OrganizationalContacts, and these are the special folders which are returning unexpected contacts (non-outlook contacts) for my use-case.

    For all outlook contacts (non-persona, non-auto/quick, non-unified), folderclass for all holding folders is IPF.Contact as expected. So, a kind of business decision based on expected folder class can be made not to fetch unexpected contacts depending upon required scenario/use-case. Good thing is that folder-classes are localization independent, and consistent across exchange server versions. And our application also do not support user-defined folder classes.


    Thanks, Nimesh

    Tuesday, October 16, 2012 12:00 PM