Searching for folders in a mailbox by using the EWS Managed API 2.0

Last modified: October 13, 2012

Applies to: EWS Managed API | Exchange Server 2007 Service Pack 1 (SP1) | Exchange Server 2010

Note: This content applies to the EWS Managed API 2.0 and earlier versions. For the latest information about the EWS Managed API, see Web services in Exchange.

You can use the Microsoft Exchange Web Services (EWS) Managed API 1.0 to search for folders in a mailbox.

To search for folders in a mailbox

  1. Define a view along with a page size. The following code shows a FolderView with a page size of 10.

    FolderView view = new FolderView(10);
    

    The page size is required to create a FolderView. Other optional parameters for the FolderView constructor are the Offset and the OffsetBasePoint. The Offset and OffsetBasePoint are used for subsequent paged calls.

  2. Identify the properties to return in the results set. The following code shows a property set that includes the folder identifiers and display name. Additional properties can be added to the results by changing the BasePropertySet to the FirstClassProperties value and by adding individual properties to the PropertySet.

    view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
    view.PropertySet.Add(FolderSchema.DisplayName);
    
  3. Create the search filter. The following code shows a search filter that is used to find folders that contain one or more items.

    SearchFilter searchFilter = new SearchFilter.IsGreaterThan(FolderSchema.TotalCount, 0);
    

    For more information about how to build search filters, see Working with search filters by using the EWS Managed API 2.0.

  4. Identify the traversal method for the search. The following code shows a FolderView with the deep traversal option.

    view.Traversal = FolderTraversal.Deep;
    
  5. Send the request to search the mailbox and get the results. The following code example shows a search that starts at the mailbox root and searches based on the FolderView object named view.

    FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.Root, searchFilter, view);
    
  6. Loop through each folder that is returned in the FindFoldersResults object. The following five strongly typed folders can be returned: SearchFolder, ContactsFolder, TasksFolder, CalendarFolder, Folder. Folders can also have additional classifications set on the FolderClass property; therefore, you might have to process folders based on FolderClass.

  7. Determine whether more folders exist in the result set than were returned in the response. The following code shows the property on the FindFoldersResults object that indicates that there are more folders in the result set.

    if (findFolderResults.MoreAvailable)
    

    Recursively search for more folders by using offsets to page through the search results if the MoreAvailable property is set to true.

Example

The following code example shows how to search a mailbox root for all folders that contain items. The search returns the first 10 folders that contain items. The search performs a deep traversal of the mailbox root so that all folders in the mailbox are included in the search. The search results only return the folder identifier and the folder display name.

// Create a view with a page size of 10.
FolderView view = new FolderView(10);

// Identify the properties to return in the results set.
view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
view.PropertySet.Add(FolderSchema.DisplayName);

// Return only folders that contain items.
SearchFilter searchFilter = new SearchFilter.IsGreaterThan(FolderSchema.TotalCount, 0);

// Unlike FindItem searches, folder searches can be deep traversals.
view.Traversal = FolderTraversal.Deep;

// Send the request to search the mailbox and get the results.
FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.Root, searchFilter, view);

// Process each item.
foreach (Folder myFolder in findFolderResults.Folders)
{
    if (myFolder is SearchFolder)
    {
        Console.WriteLine("Search folder: " + (myFolder as SearchFolder).DisplayName);
    }

    else if (myFolder is ContactsFolder)
    {
        Console.WriteLine("Contacts folder: " + (myFolder as ContactsFolder).DisplayName);
    }

    else if (myFolder is TasksFolder)
    {
        Console.WriteLine("Tasks folder: " + (myFolder as TasksFolder).DisplayName);
    }

    else if (myFolder is CalendarFolder)
    {
        Console.WriteLine("Calendar folder: " + (myFolder as CalendarFolder).DisplayName);
    }
    else
    {
        // Handle a generic folder.
        Console.WriteLine("Folder: " + myFolder.DisplayName);
    }
}

// Determine whether there are more folders to return.
if (findFolderResults.MoreAvailable)
{
    // Make recursive calls with offsets set for the FolderView to get the remaining folders in the result set.

}
' Create a view with a page size of 10.
Dim view As New FolderView(10)

' Identify the properties to return in the results set.
view.PropertySet = New PropertySet(BasePropertySet.IdOnly)
view.PropertySet.Add(FolderSchema.DisplayName)

' Return only folders that contain items.
Dim searchFilter As SearchFilter = New SearchFilter.IsGreaterThan(FolderSchema.TotalCount, 0)

' Unlike FindItem searches, folder searches can be deep traversals.
view.Traversal = FolderTraversal.Deep

' Send the request to search the mailbox and get the results.
Dim results As FindFoldersResults = service.FindFolders(WellKnownFolderName.Root, searchFilter, view)

' Process each item.
Dim folder As Folder
For Each folder In results.Folders
    If TypeOf folder Is SearchFolder Then
        Console.WriteLine("Search folder: " & TryCast(folder, SearchFolder).DisplayName)
    ElseIf TypeOf folder Is ContactsFolder Then
        Console.WriteLine("Contacts folder: " & TryCast(folder, ContactsFolder).DisplayName)
    ElseIf TypeOf folder Is TasksFolder Then
        Console.WriteLine("Tasks folder: " & TryCast(folder, TasksFolder).DisplayName)
    ElseIf TypeOf folder Is CalendarFolder Then
        Console.WriteLine("Calendar folder: " & TryCast(folder, CalendarFolder).DisplayName)
    Else
        ' Handle a generic folder.
        Console.WriteLine("Folder: " & folder.DisplayName)
    End If
Next
If results.MoreAvailable Then
    'Make recursive calls with offsets set for the FolderView to get the remaining folders in the result set.
End If

The following example shows the XML that is sent by the FindFolders method.

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
               xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
               xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2010" />
  </soap:Header>
  <soap:Body>
    <m:FindFolder Traversal="Deep">
      <m:FolderShape>
        <t:BaseShape>IdOnly</t:BaseShape>
        <t:AdditionalProperties>
          <t:FieldURI FieldURI="folder:DisplayName" />
        </t:AdditionalProperties>
      </m:FolderShape>
      <m:IndexedPageFolderView MaxEntriesReturned="10" Offset="0" BasePoint="Beginning" />
      <m:Restriction>
        <t:IsGreaterThan>
          <t:FieldURI FieldURI="folder:TotalCount" />
          <t:FieldURIOrConstant>
            <t:Constant Value="0" />
          </t:FieldURIOrConstant>
        </t:IsGreaterThan>
      </m:Restriction>
      <m:ParentFolderIds>
        <t:DistinguishedFolderId Id="root" />
      </m:ParentFolderIds>
    </m:FindFolder>
  </soap:Body>
</soap:Envelope>

The following example shows the XML that is returned by using the FindFolders method. The FolderIdId and ChangeKey attributes have been shortened to preserve readability.

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="14"
               MinorVersion="0"    MajorBuildNumber="639"
               MinorBuildNumber="20" Version="Exchange2010"
               xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"
               xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xm="" lns:xsd="http://www.w3.org/2001/XMLSchema" />
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <m:FindFolderResponse
               xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
               xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:FindFolderResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:RootFolder IndexedPagingOffset="10" TotalItemsInView="11"
               Include="" sLastItemInRange="false">
            <t:Folders>
              <t:SearchFolder>
                <t:FolderId Id="AQMkAGEyYzQ” ChangeKey="BwAAABYAAA” />
                <t:DisplayName>AllItems</t:DisplayName>
              </t:SearchFolder>
              <t:SearchFolder>
                <t:FolderId Id="AQMkAGEyYzQ” ChangeKey="BwAAABYAAA" />
                <t:DisplayName>
                  NoArchiveTagSearchFolder8534F96D-4183-41fb-8A05
                  -9B7112AE2100
                </t:DisplayName>
              </t:SearchFolder>
              <t:SearchFolder>
                <t:FolderId Id="AQMkAGEyYzQ” ChangeKey="CAAAABYAAA" />
                <t:DisplayName>Unread Mail</t:DisplayName>
              </t:SearchFolder>
              <t:Folder>
                <t:FolderId Id="AQMkAGEyYzQ” ChangeKey="AQAAABYAAA" />
                <t:DisplayName>Freebusy Data</t:DisplayName>
              </t:Folder>
              <t:Folder>
                <t:FolderId Id="AQMkAGEyYzQ" ChangeKey="AQAAABYAAA" />
                <t:DisplayName>Recoverable Items</t:DisplayName>
              </t:Folder>
              <t:Folder>
                <t:FolderId Id="AQMkAGEyYzQ" ChangeKey="AQAAABYAAA" />
                <t:DisplayName>Deletions</t:DisplayName>
              </t:Folder>
              <t:CalendarFolder>
                <t:FolderId Id="AQMkAGEyYzQ" ChangeKey="AgAAABQAAA" />
                <t:DisplayName>Calendar</t:DisplayName>
              </t:CalendarFolder>
              <t:ContactsFolder>
               <t:FolderId Id="AQMkAGEyYzQ” ChangeKey="AwAAABYAAA " />
                <t:DisplayName>Contacts</t:DisplayName>
              </t:ContactsFolder>
              <t:Folder>
                <t:FolderId Id="AQMkAGEyYzQ" ChangeKey="AQAAABYAAA" />
                <t:DisplayName>Deleted Items</t:DisplayName>
              </t:Folder>
              <t:Folder>
                <t:FolderId Id="AQMkAGEyYzQ" ChangeKey="AQAAABQAAA" />
                <t:DisplayName>Inbox</t:DisplayName>
              </t:Folder>
            </t:Folders>
          </m:RootFolder>
        </m:FindFolderResponseMessage>
      </m:ResponseMessages>
    </m:FindFolderResponse>
  </s:Body>
</s:Envelope>

This example assumes that the ExchangeService object named service is correctly configured for connecting to the user’s Client Access server.

Compiling the code

For information about compiling this code, see Getting started with the EWS Managed API 2.0.

Robust programming

  • Write appropriate error handling code for common search errors.

  • Review the client request XML that is sent to the Exchange server.

  • Review the server response XML that is sent from the Exchange server.

  • Set the service binding as shown in Setting the Exchange service URL by using the EWS Managed API 2.0. Do not hard code URLs because if mailboxes move, they might be serviced by a different Client Access server. If the client cannot connect to the service, retry setting the binding by using the AutodiscoverUrl(String) method.

  • Set the target Exchange Web Services schema version by setting the requestedServerVersion parameter of the ExchangeService constructor. For more information, see Versioning EWS requests by using the EWS Managed API 2.0.

Security

  • Use HTTP with SSL for all communication between client and server.

  • Always validate the server certificate that is used for establishing the SSL connections. For more information, see Validating X509 certificates by using the EWS Managed API 2.0.

  • Do not include user names and passwords in trace files.

  • Verify that Autodiscover lookups that use HTTP GET to find an endpoint always prompt for user confirmation; otherwise, they should be blocked.