Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get to an Exchange folder by path using EWS

I need to retrieve items from the 'Inbox\test\final' Exchange folder using EWS. The folder is provided by a literal path as written above. I know I can split this string into folder names and recursively search for the necessary folder, but is there a more optimal way that can translate a string path into a folder instance or folder ID?

I'm using the latest EWS 2.0 assemblies. Do these assemblies provide any help, or am I stuck with manual recursion?

like image 769
Daniel Avatar asked Jan 20 '26 20:01

Daniel


2 Answers

You could use an extended property as in this example

private string GetFolderPath(ExchangeService service, FolderId folderId) 
{
    var folderPathExtendedProp = new ExtendedPropertyDefinition(26293, MapiPropertyType.String);
    var folderPropSet = new PropertySet(BasePropertySet.FirstClassProperties) { folderPathExtendedProp };
    var folder = Folder.Bind(service, folderId, folderPropSet);

    string path = null;
    folder.TryGetProperty(folderPathExtendedProp, out path);

    return path?.Replace("\ufffe", "\\");
}

Source: https://social.msdn.microsoft.com/Forums/en-US/e5d07492-f8a3-4db5-b137-46e920ab3dde/exchange-ews-managed-getting-full-path-for-a-folder?forum=exchangesvrdevelopment

like image 56
tstojecki Avatar answered Jan 22 '26 09:01

tstojecki


Since Exchange Server likes to map everything together with Folder.Id, the only way to find the path you're looking for is by looking at folder names.

You'll need to create a recursive function to go through all folders in a folder collection, and track the path as it moves through the tree of email folders.

Another parameter is needed to track the path that you're looking for.

public static Folder GetPathFolder(ExchangeService service, FindFoldersResults results,
                                   string lookupPath, string currentPath)
{
    foreach (Folder folder in results)
    {
        string path = currentPath + @"\" + folder.DisplayName;
        if (folder.DisplayName == "Calendar")
        {
            continue;
        }

        Console.WriteLine(path);

        FolderView view = new FolderView(50);
        SearchFilter filter = new SearchFilter.IsEqualTo(FolderSchema.Id, folder.Id);
        FindFoldersResults folderResults = service.FindFolders(folder.Id, view);
        Folder result = GetPathFolder(service, folderResults, lookupPath, path);
        if (result != null)
        {
            return result;
        }

        string[] pathSplitForward = path.Split(new[] {  "/" }, StringSplitOptions.RemoveEmptyEntries);
        string[] pathSplitBack    = path.Split(new[] { @"\" }, StringSplitOptions.RemoveEmptyEntries);
        string[] lookupPathSplitForward = lookupPath.Split(new[] {  "/" }, StringSplitOptions.RemoveEmptyEntries);
        string[] lookupPathSplitBack    = lookupPath.Split(new[] { @"\" }, StringSplitOptions.RemoveEmptyEntries);

        if (ArraysEqual(pathSplitForward, lookupPathSplitForward) || 
            ArraysEqual(pathSplitBack,    lookupPathSplitBack) || 
            ArraysEqual(pathSplitForward, lookupPathSplitBack) || 
            ArraysEqual(pathSplitBack,    lookupPathSplitForward))
        {
            return folder;
        }
    }
    return null;
}

"ArraysEqual":

public static bool ArraysEqual<T>(T[] a1, T[] a2)
{
    if (ReferenceEquals(a1, a2))
        return true;

    if (a1 == null || a2 == null)
        return false;

    if (a1.Length != a2.Length)
        return false;

    EqualityComparer<T> comparer = EqualityComparer<T>.Default;
    for (int i = 0; i < a1.Length; i++)
    {
        if (!comparer.Equals(a1[i], a2[i])) return false;
    }
    return true;
}

I do all the extra array checking since sometimes my clients enter paths with forward slashes, back slashes, starting with a slash, etc. They're not tech savvy so let's make sure the program works every time!

As you go through each directory, compare the desired path to the iterated path. Once it's found, bubble up the Folder object that it's currently on. You'll need to create a search filter for that folder's id:

FindItemsResults<item> results = service.FindItems(foundFolder.Id, searchFilter, view);

Loop through the emails in results!

foreach (Item item in results) 
{
    // do something with item (email)
}
like image 43
Aaron S. Avatar answered Jan 22 '26 09:01

Aaron S.