我需要使用EWS从“Inbox \ test \ final”Exchange文件夹中检索项目。该文件夹由文字路径提供,如上所述。我知道我可以将此字符串拆分为文件夹名称并递归搜索必要的文件夹,但是有更优化的方法可以将字符串路径转换为文件夹实例或文件夹ID吗?
我正在使用最新的EWS 2.0程序集。这些程序集是否提供任何帮助,或者我是否遇到手动递归?
答案 0 :(得分:2)
由于Exchange Server喜欢将所有内容与Folder.Id一起映射,因此找到您要查找的路径的唯一方法是查看文件夹名称...
您需要创建一个递归函数来遍历文件夹集合中的所有文件夹,并在路径通过电子邮件文件夹树时跟踪路径。
需要另一个参数来跟踪您正在寻找的路径。
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;
}
我做了所有额外的数组检查,因为有时候我的客户输入带有正斜杠,反斜杠,斜杠开头等的路径。他们并不精通技术,所以让我们确保每个程序都有效时间!
在浏览每个目录时,将所需路径与迭代路径进行比较。一旦发现它当前在其上的Folder对象冒泡。您需要为该文件夹的ID:
创建搜索过滤器FindItemsResults results = service.FindItems(foundFolder.Id,searchFilter,view);
在结果中循环播放电子邮件!
foreach(Item item in results)
{
// do something with item (email)
}
答案 1 :(得分:0)
您可以使用此示例中的扩展属性
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", "\\");
}
答案 2 :(得分:0)
这是我的递归下降实现,它尝试在到达目标文件夹的途中获取尽可能少的信息:
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);
}
对于以'/'分隔的路径,可以按以下方式调用:
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);
}
答案 3 :(得分:0)
不,您不需要递归,您可以高效地直接进入文件夹。这使用与 Tom 相同的扩展属性,并使用它来应用搜索过滤器:
using Microsoft.Exchange.WebServices.Data; // from nuget package "Microsoft.Exchange.WebServices"
...
private static Folder GetOneFolder(ExchangeService service, string folderPath)
{
var propertySet = new PropertySet(BasePropertySet.IdOnly);
propertySet.AddRange(new List<PropertyDefinitionBase> {
FolderSchema.DisplayName,
FolderSchema.TotalCount
});
var pageSize = 100;
var folderView = new FolderView(pageSize)
{
Offset = 0,
OffsetBasePoint = OffsetBasePoint.Beginning,
PropertySet = propertySet
};
folderView.Traversal = FolderTraversal.Deep;
var searchFilter = new SearchFilter.IsEqualTo(ExchangeExtendedProperty.FolderPathname, folderPath);
FindFoldersResults findFoldersResults;
var baseFolder = new FolderId(WellKnownFolderName.MsgFolderRoot);
var localFolderList = new List<Folder>();
do
{
findFoldersResults = service.FindFolders(baseFolder, searchFilter, folderView);
localFolderList.AddRange(findFoldersResults.Folders);
folderView.Offset += pageSize;
} while (findFoldersResults.MoreAvailable);
return localFolderList.SingleOrDefault();
}
...
public static class ExchangeExtendedProperty
{
/// <summary>PR_FOLDER_PATHNAME String</summary>
public static ExtendedPropertyDefinition FolderPathname { get => new ExtendedPropertyDefinition(0x66B5, MapiPropertyType.String); }
}
路径需要以反斜杠作为前缀,即。 \Inbox\test\final
。