EWS会计算所有文件夹中未读电子邮件的数量

我正在尝试从特定用户那里获取Exchange的未读电子邮件数量。

我可以从收件箱中获得大量电子邮件,如下所示:

SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false)); ItemView view = new ItemView(int.MaxValue); FindItemsResults findResults = service.FindItems(WellKnownFolderName.Inbox, sf, view); int unreadCount = 0; foreach (EmailMessage i in findResults) { unreadCount++; } label1.Text = unreadCount.ToString(); 

这很好用。
我也能够获得所有子文件夹的收件箱:

 FindFoldersResults findResults1 = service.FindFolders( WellKnownFolderName.Inbox, new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep }); foreach (Folder folder in findResults1.Folders) { Console.WriteLine(folder.DisplayName); } 

问题是我无法将这两者结合在一起。
我知道我可以做嵌套的foreach循环,但我想避免这种情况。

我发现了这些问题: 所有文件夹中的Exchange Web服务(EWS)FindItems ,但它至少需要使用Outlook 2010才能创建AllItems文件夹。

我知道我可以创建SearchFilterCollection ,但是如何添加规则以便它在Inbox和所有子文件夹中搜索未读的电子邮件?

编辑:

这是我到目前为止尝试做的事情:

 private int getEmailCount() { int unreadCount = 0; FolderView viewFolders = new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep, PropertySet = new PropertySet(BasePropertySet.IdOnly) }; ItemView viewEmails = new ItemView(int.MaxValue) { PropertySet = new PropertySet(BasePropertySet.IdOnly) }; SearchFilter unreadFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false)); FindItemsResults findResults = service.FindItems(WellKnownFolderName.Inbox, unreadFilter, viewEmails); unreadCount += findResults.Count(); FindFoldersResults inboxFolders = service.FindFolders(WellKnownFolderName.Inbox, viewFolders); foreach (Folder folder in inboxFolders.Folders) { findResults = service.FindItems(folder.Id, unreadFilter, viewEmails); unreadCount += findResults.Count(); } return unreadCount; } 

基本上这是有效的,但是当我创建了多个子文件夹时,它开始工作得很慢。
我可以做一个而不是多个查询来获得相同的结果吗?

我搜索了一下并创建了这个函数:

  public void getEmailCount(Action callback) { int unreadCount = 0; FolderView viewFolders = new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep, PropertySet = new PropertySet(BasePropertySet.IdOnly) }; ItemView viewEmails = new ItemView(int.MaxValue) { PropertySet = new PropertySet(BasePropertySet.IdOnly) }; SearchFilter unreadFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false)); SearchFilter folderFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "AllItems")); FindFoldersResults inboxFolders = service.FindFolders(WellKnownFolderName.Root, folderFilter, viewFolders); if (inboxFolders.Count() == 0)//if we don't have AllItems folder { //search all items in Inbox and subfolders FindItemsResults findResults = service.FindItems(WellKnownFolderName.Inbox, unreadFilter, viewEmails); unreadCount += findResults.Count(); inboxFolders = service.FindFolders(WellKnownFolderName.Inbox, viewFolders); foreach (Folder folder in inboxFolders.Folders) { findResults = service.FindItems(folder.Id, unreadFilter, viewEmails); unreadCount += findResults.Count(); } } else //AllItems is avilable { foreach (Folder folder in inboxFolders.Folders) { FindItemsResults findResults = service.FindItems(folder.Id, unreadFilter, viewEmails); unreadCount += findResults.Count(); } } callback(unreadCount); } 

基本上它检查我们是否有可用的AllItems文件夹。
如果YES则我们执行一个简单查询,返回所有未读消息。
如果NO那么我们循环收件箱内的所有文件夹。 这个速度较慢,取决于我们拥有多少个文件夹和级别。

欢迎任何修复和改进:)

不确定这是你在寻找什么,但是…获取未读电子邮件的数量( 收件箱 / 草稿等):

 int x = Folder.Bind(yourService, WellKnownFolderName.Inbox).UnreadCount; int y = Folder.Bind(yourService, WellKnownFolderName.Drafts).UnreadCount; return x + y; 

在这种情况下,服务被调用两次,但调用是按顺序发出的 – 不够好

但是,您可以同时发出这两个请求并增加应用的响应时间

请参阅本教程或任何解释如何实例化两个TPL 任务的教程,将它们发送到任务调度程序等待两个( WaitAll() )完成,最后检索它们的结果:)

并且,如果您想在应用一些自定义filter(而不是简单的“未读”filter)后获取电子邮件数量,请确保您的ItemView对象是ItemView(1)而不是 ItemView(int.MaxValue) 。 然后,得到总数:

 int n = findItemsResults.TotalCount; 

请参阅TotalCount属性的文档 。

这样,服务响应非常小 – 它只包含一个项目,但它(响应)也包含总计数…这就是你想要的,对吧?

以下是获取邮箱总未读计数的代码。

  1. 查找具有深度遍历的所有文件夹
  2. 将每个文件夹的属性集限制为id,unreadcount,displayname(用于信息目的)
  3. 某些文件夹(如日历,联系人)没有此属性,因此处理该案例

此代码段的限制:

  1. 如果邮箱在信息存储顶部包含超过1000个文件夹,则您将无法获得完整的未读计数
  2. 要处理这种情况,请在循环中执行finditems,直到没有更多具有相同逻辑的项目为止

这使得只有一个查找文件夹可以调用并处理结果。

 public static int GetTotalUnreadCount(ExchangeService ewsConnector) { int pagedView = 1000; FolderView fv = new FolderView(pagedView) { Traversal = Microsoft.Exchange.WebServices.Data.FolderTraversal.Deep }; fv.PropertySet = new PropertySet(BasePropertySet.IdOnly, FolderSchema.UnreadCount, FolderSchema.DisplayName); FindFoldersResults findResults = ewsConnector.FindFolders(WellKnownFolderName.MsgFolderRoot, fv); int totalUnreadCount = 0; foreach (Folder f in findResults.Folders) { try { totalUnreadCount += f.UnreadCount; Console.WriteLine("Folder [" + f.DisplayName + "] has [" + f.UnreadCount.ToString() + "] unread items."); } catch(Exception ex) { Console.WriteLine("Folder [" + f.DisplayName + "] does not have the unread property."); } } Console.WriteLine("Mailbox has [" + totalUnreadCount.ToString() + "] unread items."); return totalUnreadCount; } 

获取文件夹及其计数的代码示例。 在此示例中,我们列出了所有第一级文件夹,并将其添加到公共类文件夹列表中,其中包含NewMessageCount对象。 Key是Folder.Bind(myService,folder.Id).UnreadCount部分。

 public List ListFolders() { try { List myFolders = new List(); Common.MailFolder myFolder; List myExchangeFolders = new List(); FolderView myView = new FolderView(10); myView.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties, FolderSchema.DisplayName, FolderSchema.Id); myView.Traversal = FolderTraversal.Shallow; FindFoldersResults myResults = myService.FindFolders(WellKnownFolderName.MsgFolderRoot, myView); foreach (Folder folder in myResults) { myFolder = new Common.ICE.MailFolder(); myFolder.NewMessageCount = Folder.Bind(myService, folder.Id).UnreadCount; myFolder.FolderId = folder.Id.ToString(); myFolder.FolderName = folder.DisplayName; myFolders.Add(myFolder); } return myFolders; } catch (Exception ex) { Logger.Log.Error("Exchange Helper - List Folders", ex, Utility.GetUserId()); return null; } }