Get to an Exchange folder by path using EWS

坚强是说给别人听的谎言 提交于 2020-01-24 09:49:07

问题


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?


回答1:


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)
}



回答2:


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




回答3:


Here's my recursive descent implementation, which attempts to fetch as little information as possible on the way to the target folder:

private readonly FolderView _folderTraversalView = new FolderView(1) { PropertySet = PropertySet.IdOnly }; 

private Folder TraceFolderPathRec(string[] pathTokens, FolderId rootId)
{
  var token = pathTokens.FirstOrDefault();
  var matchingSubFolder = _exchangeService.FindFolders(
    rootId, 
    new SearchFilter.IsEqualTo(FolderSchema.DisplayName, token), 
    _folderTraversalView)
    .FirstOrDefault();
  if (matchingSubFolder != null && pathTokens.Length == 1) return matchingSubFolder;
  return matchingSubFolder == null ? null : TraceFolderPathRec(pathTokens.Skip(1).ToArray(), matchingSubFolder.Id);
}

For a '/'-delimited path, it can be called as follows:

public Folder TraceFolderPath(string folderPath)
{ // Handle folder names with '/' in them
  var tokens = folderPath
    .Replace("\\/", "<slash>")
    .Split('/')
    .Select(t => t.Replace("<slash>", "/"))
    .ToArray();
  return TraceFolderPathRec(tokens, WellKnownFolderName.MsgFolderRoot);
}


来源:https://stackoverflow.com/questions/13251684/get-to-an-exchange-folder-by-path-using-ews

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!