EWS Managed Api 中的电子邮件对话/电子邮件线程支持(针对 Exchange 2010 左右)
Posted
技术标签:
【中文标题】EWS Managed Api 中的电子邮件对话/电子邮件线程支持(针对 Exchange 2010 左右)【英文标题】:Email Conversations / Email Threading support in EWS Managed Api (against Exchange 2010 or so) 【发布时间】:2014-06-12 14:33:42 【问题描述】:EWS 托管 API 具有一些用于检索和管理电子邮件对话(又名电子邮件线程的功能)。不幸的是,其中很大一部分仅适用于新版本的 Exchange(2013 等)
Outlook 确实针对旧 版本的 Exchange 实施电子邮件线程。也许它通过自己管理线程来做到这一点(Outlook 是一个 桌面 应用程序,电子邮件被复制到本地机器上,因此它们可以很容易地按 Conversation Topic 等进行分组.).
现在,如何在网络应用程序中支持电子邮件线程?在 Exchange 客户端中支持此功能通常会做什么? 支持我的意思是:
检索前 10 个对话快照,然后检索接下来的 10 个对话快照 - 即,支持分页(按需检索页面) - 此数据将用于构建 主视图 检索对话中的所有电子邮件 - 即按需检索对话的子项) - 此数据将用于构建对话的详细视图 .EWS 托管 API 等问题:
EWS 托管 API 中没有 Conversation.Bind(conversationId) ExchangeService.FindItems(filter for ConversationTopic == "some topic") 绝对不可靠(因为可能有不同的对话具有相同的主题) ExchangeService.FindItems(filter for ConversationId == "QWERYUIO") - 我不知道如何使用它:) 是否可以通过 ConversationId 搜索电子邮件? ExchangeService.GetConversationItems() 等函数仅“适用于以 Exchange Online 和从 Exchange Server 2013 开始的 Exchange 版本为目标的客户端。”我现在使用的是什么(作为一种解决方法):
-
使用 ExchangeService.FindConversation() 检索(按需)对话页面
对于检索到的页面中的每个对话,读取 Conversation.GlobalIds 属性
构建包含所有 GlobalIds 值的聚合(数组) - 通过连接所有对话的 Conversation.GlobalIds
进行 Exchange 调用以将 ID 绑定到电子邮件 (ExchangeService.BindToItems)
对电子邮件执行 group-by 操作(从概念上讲,它是一个分组操作,但实现不是简单的 group-by 调用 - 电子邮件不能按 ConversationId 分组 em>,因为在使用 Exchange 2010 时该属性不可用,尽管文档没有指定这一点)
使用数据一步构建 UI(主视图的对话列表,详细视图的电子邮件组 em> 每个对话)等。
上述实现的一些问题
我在调用ExchangeService.BindToItems 操作时从服务器检索大量数据- 性能不是很好,但也不是很差。当然,最好仅在用户想要访问特定对话的详细视图 时检索电子邮件。一个可能的技巧:将 GlobalIds 数组保存在隐藏字段中的某个位置,然后使用它来获取电子邮件以构建 详细视图。我知道 GET 请求的大小有限,但是...关于电子邮件对话/电子邮件线程,没有人知道哪个支持什么:
Here 它说 FindConversation(ViewBase, FolderId) 适用于以 Exchange Online 和从 Exchange Server 2013 开始的 Exchange 版本为目标的客户端。另一方面,here 写道,ExchangeService.FindConversation() 函数可用于从 Exchange 2010 开始的 Exchange 版本,包括 Exchange Online。 This 也很有趣:适用于:EWS 托管 API | Exchange Server 2010 Service Pack 1 (SP1),但请确保您有一个 Exchange 2013 或 Exchange Online 服务帐户,其主要版本为 15 或更高版本。 :) Here 它说 Item.ConversationId 属性在从 Exchange 2010 开始的 Exchange 版本中可用,包括 Exchange Online。 但不是 :)注意:我不太确定是否支持 Item.ConversationId,因为我手头没有代码,现在无法执行测试。因此,在针对 Exchange 2010 使用 EWS 托管 API 时,如果该属性仍然可用,请原谅我。
总之, 您对在 Web 应用程序中使用针对 Exchange 2010 服务器的 EWS 托管 API 实现电子邮件对话/电子邮件线程功能有任何想法吗?
非常感谢您有耐心阅读这么长的帖子:)
一些参考资料:
http://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.exchangeservice_methods%28v=exchg.80%29.aspx http://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.conversation_members%28v=exchg.80%29.aspx http://msdn.microsoft.com/en-us/library/office/gg274407%28v=exchg.80%29.aspx http://msdn.microsoft.com/en-us/library/office/jj220497%28v=exchg.80%29.aspx
Implementing Outlook 2010's group by conversation using EWS and Exchange 2007 Exchange Webservice Managed API - Find items by extended properties
【问题讨论】:
微软的文档一直都是漏洞百出。但听起来您想要 Exchange Server 2013 的功能,但需要 2010 版本。如果这些功能在 2010 年不可用(未实现)或不满意/不可靠,您将别无选择,只能自己重新实现它们。特别是,检测消息线程可以使用JWZ threading algorithm - 希望您会找到一个 .NET 实现并将其添加到您的项目中。 我没有完整的答案,但我可以解决您对“关于电子邮件对话/电子邮件线程,没有人知道哪个支持”中的文档问题列表的一些困惑什么:”列表。在阅读文档时,您必须注意它是指 EWS 技术,在这种情况下名称为“FindConversation 操作”,或者如果它指的是 EWS Managed API (EWSMA) 技术,在这种情况下它称为 FindOperation方法。您的最后一个要点是关于 EWS 功能的页面,该功能于 2010 年推出。 【参考方案1】:我已经解决了您在 cmets 中遇到的一些文档问题,因此我将尝试在这里回答您真正的编码问题。
要获得您的主视图,ExchangeService.FindConversation 是正确的使用方法。它通过将结果限制为 view 参数指定的会话数来支持分页。您可以按需调用它以获得越来越旧的结果。
要获取详细视图,因为 ExchangeService.GetConversationItems 在 Ex2010 上不可用,您可以将 ExchangeService.FindItems 与 IsEqualTo SearchFilter 一起使用,以搜索具有匹配 ConversationId 的项目(请参见下面的代码)。有关搜索过滤器的更多信息,请点击此处:How to: Use search filters with EWS in Exchange。
在下面的方法中,我通过指定一个属性集来限制 FindItems 调用的属性,而不是返回所有属性。如果要返回所有属性,只需删除设置 PropertySet 的行。
static void forumFindConversationItem(ExchangeService service)
ItemView view = new ItemView(10);
//Remove the following line if you want to get all the properties for each message. This will limit the properties returned in your results (and save time).
view.PropertySet = new PropertySet(EmailMessageSchema.Subject, EmailMessageSchema.DateTimeReceived);
SearchFilter.IsEqualTo conversationFilter =
new SearchFilter.IsEqualTo(EmailMessageSchema.ConversationId, "AAQkADIwM2ZlM2ZlLWMwYjctNDg2Ny04MDU0LTVkMTFmM2IxY2ZjZQAQANEDR7V/30dphLiNOLSTuxE=");
FindItemsResults<Item> results = service.FindItems(WellKnownFolderName.Inbox, conversationFilter, view);
一旦您拥有每个 ItemID(由上面的代码返回),您就可以使用 Bind 方法获取每个项目的所有属性。
希望对您有所帮助。当 MSDN 上的方法的版本问题更新后,我会跟进。
【讨论】:
谢谢,我想我明天有机会试试这个:) 按 ConversationId 过滤适用于 Exchange2013,但不适用于 Exchange2010_SP2,因为它会传递此错误:“该属性不能用于此类限制。”。该服务似乎不喜欢在 EmailMessageSchema.ConversationId 属性上看到过滤器:( Andrei- 我想让您知道文档已更新。 ExchangeService methods 及其链接的参考页面现在表明 Exchange 2010 SP1 中仅支持一种 FindConversation 方法(FindConversation(ViewBase, FolderId))。此外,How to: Get conversation items 中的适用于行已更新(已删除 Exchange 2010)。 并且How to: Work with conversations by using EWS in Exchange 有一个版本差异部分(位于页面底部),列出了与以前版本的当前差异。【参考方案2】:更一般地说,ConversationID 似乎存在问题,因为它被普遍理解并实际用于 Exchange 本身。这可能会影响您(或任何人)的发展。
我一直在生产一个电子邮件票务程序,并使用 ConversationID 将电子邮件聚集在一个线程中以便于查看。
但现在似乎有些电子邮件不在同一个线程上——是的,它们共享相同的主题和发件人地址,并且在相同的日期/时间左右发送——但它们不会出现在每个主题的引用中其他(例如,一个电子邮件正文响应一个较旧的电子邮件正文是多少个“电子邮件线程”)——然而这些不同的电子邮件具有相同的确切 ConversationID,即使一个正文与另一个正文无关。
事实上,即使日期/时间不是很接近,例如来自同一个人的“今日想法”电子邮件,有时也会使用相同的 ConversationID 进行分组。在这种情况下,这听起来可能很有用,但在发薪人员发送“RE:401k”的业务案例中就没那么有用了。
需要明确的是,这不是区分大小写的过度匹配,这是我之前使用 Item.ExchangeID 时的疏忽(如果您考虑大小写,这是唯一的)。即使考虑到案例,完全不同的电子邮件线程也具有完全相同的 ConversationID。
这表明我不能依赖 ConversationID 作为 GROUP BY 子句,而必须使用一些额外的自定义代码。
【讨论】:
以上是关于EWS Managed Api 中的电子邮件对话/电子邮件线程支持(针对 Exchange 2010 左右)的主要内容,如果未能解决你的问题,请参考以下文章
如果地址是别名,如何使用 ews-java-api 识别收件人电子邮件?