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属性的文档 。
这样,服务响应非常小 – 它只包含一个项目,但它(响应)也包含总计数…这就是你想要的,对吧?
以下是获取邮箱总未读计数的代码。
- 查找具有深度遍历的所有文件夹
- 将每个文件夹的属性集限制为id,unreadcount,displayname(用于信息目的)
- 某些文件夹(如日历,联系人)没有此属性,因此处理该案例
此代码段的限制:
- 如果邮箱在信息存储顶部包含超过1000个文件夹,则您将无法获得完整的未读计数
- 要处理这种情况,请在循环中执行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; } }