将属性从命名空间 PS_INTERNET_HEADERS 映射到 PS_PUBLIC_STRINGS

Mapping properties from namespace PS_INTERNET_HEADERS to PS_PUBLIC_STRINGS

我有一个 Outlook COM add-in(C#,Visual Studio 2012),它使用额外的消息属性扩展了标准表单。 add-in 适用于 Outlook 2010、2013 和 2016。

add-in 的要求表明它支持在命名空间 PS_INTERNET_HEADERS 中读取和写入一组属性。我遵循 http://blogs.technet.com/b/exchange/archive/2009/04/06/3407221.aspx 中的指导方针,对提升为 MAPI 属性的传入消息设置此类 header。

但据我了解,所有这些 header 都会成为 MAPI 字符串属性,对吧?!但是这些 header 中的几个实际上具有更自然的类型。其中一个 headers 是一个 RFC5322 date-time header,其值类似于 'Wed, 28 Sep 2016 06:27:00 GMT'。将这样的 header 映射到 PT_UNICODE 类型的 MAPI 属性 并不是最佳选择,因为您无法根据它对消息进行排序,也无法在搜索等方面真正使用它。

这个问题有好的解决办法吗?

我唯一的想法是做某种从命名空间 PS_INTERNET_HEADERS 中的属性到命名空间 PS_PUBLIC_STRINGS 中的属性的映射。这也将有一个很好的 side-effect,即在打印消息时将包含属性。但如果我必须走那条路,我需要某种挂钩来进行映射。我当然可以遍历消息存储中的所有消息、监听传入的新消息、监听更改的消息等——但感觉这不是一个好的解决方案。我想我也可以编写一个 Exchange 传输代理,但我真的很想在客户端保留逻辑。

有什么建议吗?

根据 Dmitry 的评论进行编辑:

对于外发邮件,我必须使用命名空间 PS_INTERNET_HEADERS 中的属性,因为此类邮件最终由 SMTP(Exchange 外部)传输到其他系统。详细的,我要坚持https://www.rfc-editor.org/rfc/rfc6477。作为 side-effect,Exchange 将针对传入消息将此类 header 提升为命名空间 PS_INTERNET_HEADERS 中的属性。这一切都很好。

但即使在那种情况下,我也愿意按照您的建议在我的代码中显式提取属性并在命名空间 PS_PUBLIC_STRINGS 中编写一些新属性。在我看来,挑战在于 运行 该代码使用哪个钩子。用户应该能够将映射的属性用作视图中的列,用于排序、过滤、搜索、收件箱规则等。我可以扫描整个消息存储来进行映射,我可以监听各种 Outlook object模型事件,但最后我很难看到如何避免用户暂时看到我的代码尚未处理的消息。

我有一个旧的 add-in 使用扩展 MAPI 用 C++ 编写的类似挑战。在 start-up 上,对于每个 IMsgStore 中的每个收件箱,它会扫描整个收件箱(可能是一个非常昂贵的操作),然后使用 IMAPIFolder::GetContentsTable 和 IMAPITable::Advise 订阅更改。但我的经验是,我会时不时地收到 table 通知 TABLE_ERROR 或 TABLE_RELOAD,并且必须再次扫描。对于 IMsgStore::Advise 我想也存在类似的挑战?!在 C# 上下文中,我可以使用 Redemption class RDOStore 中的事件(例如 OnMessageModified),但我假设 class 使用 IMsgStore::Advise?!

不,属性 类型永远不会转换。它始终保持为字符串。为什么不从 PR_TRANSPORT_MESSAGE_HEADERS 属性(DASL 名称 http://schemas.microsoft.com/mapi/proptag/0x007D001F)中读取互联网 headers 并在您的代码中显式提取属性?您将完全控制提取哪些属性以及如何转换它们。