所有文件夹中的Exchange Web服务(EWS)FindItems

我使用以下代码查找用户发送的所有电子邮件,但这只搜索主收件箱文件夹,不检查任何子文件夹。 我想搜索所有邮件项目,包括任何子文件夹。

我尝试过WellKnownFolderName.Root和WellKnownFolderName.Inbox,这些只搜索那些文件夹,而不是子文件夹。

private static void SearchItems(string email) { ItemView iv = new ItemView(10); FindItemsResults fiitems = _service.FindItems(WellKnownFolderName.Inbox, "from:username@example.com", iv); foreach (Item item in fiitems) { Console.WriteLine("Subject:\t" + item.Subject); Console.WriteLine("Received At:\t\t" + item.DateTimeReceived.ToString("dd MMMM yyyy")); Console.WriteLine(); } Console.WriteLine("Press Enter to continue"); Console.ReadLine(); } 

我在Glen的博客http://gsexdev.blogspot.com/2011/08/using-allitems-search-folder-from.html上找到了Exchange内AllItems文件夹的一些信息。我已将PowerShell脚本移植到C#,如图所示下面。

  private static void SearchItems() { ExtendedPropertyDefinition allFoldersType = new ExtendedPropertyDefinition(13825, MapiPropertyType.Integer); FolderId rootFolderId = new FolderId(WellKnownFolderName.Root); FolderView folderView = new FolderView(1000); folderView.Traversal = FolderTraversal.Shallow; SearchFilter searchFilter1 = new SearchFilter.IsEqualTo(allFoldersType, "2"); SearchFilter searchFilter2 = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "allitems"); SearchFilter.SearchFilterCollection searchFilterCollection = new SearchFilter.SearchFilterCollection(LogicalOperator.And); searchFilterCollection.Add(searchFilter1); searchFilterCollection.Add(searchFilter2); FindFoldersResults findFoldersResults = _service.FindFolders(rootFolderId, searchFilterCollection, folderView); if (findFoldersResults.Folders.Count > 0) { Folder allItemsFolder = findFoldersResults.Folders[0]; Console.WriteLine("Folder:\t" + allItemsFolder.DisplayName); ItemView iv = new ItemView(1000); FindItemsResults findResults = allItemsFolder.FindItems("System.Message.DateReceived:01/01/2011..01/31/2011", iv); foreach (Item item in findResults) { Console.WriteLine("Subject:\t" + item.Subject); Console.WriteLine("Received At:\t\t" + item.DateTimeReceived.ToString("dd MMMM yyyy")); Console.WriteLine("Is New:\t\t" + item.IsNew.ToString()); Console.WriteLine("Has Attachments:\t\t" + item.HasAttachments.ToString()); Console.WriteLine(); } } Console.WriteLine("Press Enter to continue"); Console.ReadLine(); } 

在http://social.technet.microsoft.com/Forums/en-US/exchangesvrdevelopment/thread/8c71ace4-43d2-4ba2-88f2-16376dad828f上回答。

如果您需要的只是服务器上所有文件夹和子文件夹的集合,您可以在几次调用中分页您的请求并从服务器获取整个文件夹层次结构。 关键是FolderView.Traversal属性。

例如,对于包含约1,300个文件夹的Exchange邮箱,以下代码仅发出2个请求。 只要您保持在服务器限制或低于服务器限制,您就可以将页面大小设置为您喜欢的任何内容。

仅供参考:Exchange Online(Office365)在响应中最多包含1,000个项目。 我没有测试过,所以在查询内部部署的Exchange Server时,我无法说出任何类似的限制。

 Imports Exchange = Microsoft.Exchange.WebServices.Data Friend Module Main Public Sub Main() Dim oService As Exchange.ExchangeService Dim oUsers As Dictionary(Of String, User) oUsers = New Dictionary(Of String, User) oUsers.Add("User1", New User("write.to.me1@my.address.com", "Some-Fancy-Password1")) oUsers.Add("User2", New User("write.to.me2@my.address.com", "Some-Fancy-Password2")) oUsers.ToList.ForEach(Sub(Credential As KeyValuePair(Of String, User)) File.Delete(LOG_FILE_PATH.ToFormat(Credential.Key)) End Sub) oUsers.ToList.ForEach(Sub(Credential As KeyValuePair(Of String, User)) LogFileName = Credential.Key Console.WriteLine("Getting message counts for mailbox [{0}]...", LogFileName) Console.WriteLine() oService = Service.ConnectToService(Credential.Value) GetAllFolders(oService, LOG_FILE_PATH.ToFormat(Credential.Key)) Console.Clear() End Sub) Console.WriteLine() Console.Write("Press any key to exit...") Console.ReadKey() End Sub Private Sub GetAllFolders(Service As Exchange.ExchangeService, LogFilePath As String) Dim oIsHidden As Exchange.ExtendedPropertyDefinition Dim oFolders As List(Of Exchange.Folder) Dim oResults As Exchange.FindFoldersResults Dim lHasMore As Boolean Dim oChild As Exchange.Folder Dim oView As Exchange.FolderView Dim _ nPageSize, nOffSet As Short Dim _ oPaths, oPath As List(Of String) oIsHidden = New Exchange.ExtendedPropertyDefinition(&H10F4, Exchange.MapiPropertyType.Boolean) nPageSize = 1000 oFolders = New List(Of Exchange.Folder) lHasMore = True nOffSet = 0 Do While lHasMore oView = New Exchange.FolderView(nPageSize, nOffSet, Exchange.OffsetBasePoint.Beginning) oView.PropertySet = New Exchange.PropertySet(Exchange.BasePropertySet.IdOnly) oView.PropertySet.Add(oIsHidden) oView.PropertySet.Add(Exchange.FolderSchema.ParentFolderId) oView.PropertySet.Add(Exchange.FolderSchema.DisplayName) oView.PropertySet.Add(Exchange.FolderSchema.FolderClass) oView.PropertySet.Add(Exchange.FolderSchema.TotalCount) oView.Traversal = Exchange.FolderTraversal.Deep oResults = Service.FindFolders(Exchange.WellKnownFolderName.MsgFolderRoot, oView) oFolders.AddRange(oResults.Folders) lHasMore = oResults.MoreAvailable If lHasMore Then nOffSet += nPageSize End If Loop oFolders.RemoveAll(Function(Folder) Folder.ExtendedProperties(0).Value = True) oFolders.RemoveAll(Function(Folder) Folder.FolderClass <> "IPF.Note") oPaths = New List(Of String) oFolders.ForEach(Sub(Folder) oChild = Folder oPath = New List(Of String) Do oPath.Add(oChild.DisplayName) oChild = oFolders.SingleOrDefault(Function(Parent) Parent.Id.UniqueId = oChild.ParentFolderId.UniqueId) Loop While oChild IsNot Nothing oPath.Reverse() oPaths.Add("{0}{1}{2}".ToFormat(Join(oPath.ToArray, DELIMITER), vbTab, Folder.TotalCount)) End Sub) oPaths.RemoveAll(Function(Path) Path.StartsWith("Sync Issues")) File.WriteAllText(LogFilePath, Join(oPaths.ToArray, vbCrLf)) End Sub Private LogFileName As String Private Const LOG_FILE_PATH As String = "D:\Emails\Remote{0}.txt" Private Const DELIMITER As String = "\" End Module Friend Class Service Public Shared Function ConnectToService(User As User) As Exchange.ExchangeService Return Service.ConnectToService(User, Nothing) End Function Public Shared Function ConnectToService(User As User, Listener As Exchange.ITraceListener) As Exchange.ExchangeService Dim oService As Exchange.ExchangeService oService = New Exchange.ExchangeService(Exchange.ExchangeVersion.Exchange2013_SP1) oService.Credentials = New NetworkCredential(User.EmailAddress, User.Password) oService.AutodiscoverUrl(User.EmailAddress, AddressOf RedirectionUrlValidationCallback) If Listener IsNot Nothing Then oService.TraceListener = Listener oService.TraceEnabled = True oService.TraceFlags = Exchange.TraceFlags.All End If Return oService End Function Private Shared Function RedirectionUrlValidationCallback(RedirectionUrl As String) As Boolean With New Uri(RedirectionUrl) Return .Scheme.ToLower = "https" End With End Function End Class Friend Class User Public Sub New(EmailAddress As String) _EmailAddress = EmailAddress _Password = New SecureString End Sub Public Sub New(EmailAddress As String, Password As String) _EmailAddress = EmailAddress _Password = New SecureString Password.ToList.ForEach(Sub(Chr As Char) Me.Password.AppendChar(Chr) End Sub) Password.MakeReadOnly() End Sub Public Shared Function GetUser() As User Dim sEmailAddress As String Dim oUserInput As ConsoleKeyInfo Console.Write("Enter email address: ") sEmailAddress = Console.ReadLine Console.Write("Enter password: ") GetUser = New User(sEmailAddress) While True oUserInput = Console.ReadKey(True) If oUserInput.Key = ConsoleKey.Enter Then Exit While ElseIf oUserInput.Key = ConsoleKey.Escape Then GetUser.Password.Clear() ElseIf oUserInput.Key = ConsoleKey.Backspace Then If GetUser.Password.Length <> 0 Then GetUser.Password.RemoveAt(GetUser.Password.Length - 1) End If Else GetUser.Password.AppendChar(oUserInput.KeyChar) Console.Write("*") End If End While If GetUser.Password.Length = 0 Then GetUser = Nothing Else GetUser.Password.MakeReadOnly() Console.WriteLine() End If End Function Public ReadOnly Property EmailAddress As String Public ReadOnly Property Password As SecureString End Class Friend Class TraceListener Implements Exchange.ITraceListener Public Sub Trace(TraceType As String, TraceMessage As String) Implements Exchange.ITraceListener.Trace File.AppendAllText("{0}.txt".ToFormat(Path.Combine("D:\Emails\TraceOutput", Guid.NewGuid.ToString("D"))), TraceMessage) End Sub End Class