简体   繁体   English

Exchange Web 服务 (EWS) 在所有文件夹中查找项目

[英]Exchange Web Services (EWS) FindItems within All Folders

I am using the following code to find all the emails sent from a user, however this only searches the main Inbox folder and doesn't check any sub-folders.我正在使用以下代码查找用户发送的所有电子邮件,但这只会搜索主收件箱文件夹,而不会检查任何子文件夹。 I would like to search all the mail items including any sub-folders.我想搜索所有邮件项目,包括任何子文件夹。

I have tried the WellKnownFolderName.Root and WellKnownFolderName.Inbox , and these only search those folders, not the sub-folders.我试过WellKnownFolderName.RootWellKnownFolderName.Inbox ,这些只搜索那些文件夹,而不是子文件夹。

private static void SearchItems(string email)
{
    ItemView iv = new ItemView(10);
    FindItemsResults<Item> 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();
}

I have found some information on the AllItems folder within Exchange over at Glen's blog .在 Glen 的博客上找到了有关 Exchange 中AllItems文件夹的一些信息。 I have ported the PowerShell script to C# as shown below.我已将 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<Item> 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();
}

If all you need is a collection of all folders and subfolders on the server, You can page your requests and get the entire folder hierarchy from the server in just a few calls.如果您只需要服务器上所有文件夹和子文件夹的集合,您可以分页请求并通过几次调用从服务器获取整个文件夹层次结构。 The key is the FolderView.Traversal property.关键是FolderView.Traversal属性。

For example, for an Exchange mailbox with ~1,300 folders the code below only makes 2 requests.例如,对于具有约 1,300 个文件夹的 Exchange 邮箱,以下代码仅发出 2 个请求。 You can set your page size to whatever you like, as long as you stay at or below the server limit.只要您保持或低于服务器限制,您就可以将页面大小设置为任何您喜欢的大小。

FYI: Exchange Online (Office365) caps at a maximum of 1,000 items in a response.仅供参考:Exchange Online (Office365) 的响应上限为 1,000 个项目。 I haven't tested, so I can't speak for any similar limits when querying an on-premises Exchange Server.我没有测试过,所以在查询本地 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在大文件夹上使用FindItems的Exchange Web Services - Exchange Web Services using FindItems on large folders 如果联系人在GAL中,则Exchange Web服务(EWS)FindItems无效 - Exchange Web Service (EWS) FindItems does not work if contact is in GAL Exchange EWS,日历FindItems与FindAppointments? - Exchange EWS, Calendar FindItems vs FindAppointments? 如何使用Exchange Web服务托管API列出这些文件夹中的所有文件夹和文件? - How to list all folders and files in those folders using Exchange Web Services Managed API? EWS(Exchange Web服务)-向约会添加内联附件 - EWS (Exchange Web Services) - Add inline attachment to appointment 在iOS应用程序中访问Microsoft Exchange Server Web服务(EWS)API - Accessing Microsoft Exchange Server Web Services (EWS) API in an iOS application Window 服务应用程序、Exchange Web 服务、EWS 错误 - Window Service Application, Exchange Web Services, EWS error 在Exchange Web服务(EWS)中处理事件时标识项类型 - Identify item type when handling event in Exchange Web Services (EWS) 在 C# 中连接到 Exchange Web 服务 (EWS) 后出现错误 - Errors appear after connecting to Exchange Web Services (EWS) in C# Microsoft Exchange Folders.findItems 结果限制为 1000 - Microsoft Exchange Folders.findItems results limited to a 1000
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM