将EWS对话*与Outlook加载项对话匹配 [英] Match EWS Conversation* to Outlook Add-in Conversation*

查看:126
本文介绍了将EWS对话*与Outlook加载项对话匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几年前,我为Outlook编写了一个加载项,该加载项基于Item的ConversationIndex/ConversationId属性将条目添加到数据库中.效果很好,并且在与该消息进行交互的所有客户端中保持统一(例如,鲍勃"可以看到玛丽"已经处理了此消息,因为已经存在带有ConversationIndex的条目).

我现在正尝试将其移动到服务(并通过EWS API进行连接),但是我没有很好的运气将这些属性与来自Outlook的值进行匹配.例如:

Outlook加载项将为我定位的特定电子邮件提供以下值:

ConversationID:     6B6369F5023EA646AA7BC161274BDAE8
ConversationIndex:  0101CF3C7EEC6B6369F5023EA646AA7BC161274BDAE8

但是,从EWS API中,我得到了以下信息:

ConversationID:     AAQkADFhZThkNmJmLTlkODItNDQyZS1hM2YxLTQ2NWNkMTllYjhjOQAQAGtjafUCPqZGqnvBYSdL2ug=
ConversationIndex:  new byte[]{1,1,207,60,126,236,107,99,105,245,2,62,166,70,170,123,193,97,39,75,218,232}

我将第一个识别为Base64编码的字符串,但是解码后的内容看起来并不像我识别(或可以解密)的任何东西.有没有人对此有所了解,或者谁可以帮助使这两个值保持一致?我只能想象这些属性来自交换服务器,但是客户端可能执行了一些清理工作,而EWS API只是给了我原始值(对于XML介质,出于我假定的传输目的,它要减去Base64).

如果有人熟悉或已经做过,我将不胜感激任何指导.

侧面说明:

也许有更好的方法来识别电子邮件,但目前我一直试图保持这两个同义词.修改Outlook加载项并不是一个真正的选择,一旦我将1:1转换迁移到服务器(并删除了加载项),我将可以灵活地更改其工作方式.但是现在我需要它们并排运行.我需要能够从Web服务器上查看Outlook在Outlook中进行的过程,反之亦然.

解决方案

我才发现.

故障

通过更多的谷歌搜索和更多的努力,我相信我可以使用以下命令使它们按1:1对齐:

ConversationId

这显然是一个由几个属性组成的组合值.幸运的是,我能够找到伍德曼发布的重新实现此处使用的nofollow noreferrer>原始算法.通过一些小的修改(使用EWS而不是Outlook),我能够使其正常工作.

会话索引

事实证明,这仅是使用BitConverter的问题(并删除了连字符).轻松自在.

最终结果:

 public static class EwsEmailMessageExtensions
{
    private const int c_ulConvIndexIDOffset = 6;
    private const int c_ulConvIndexIDLength = 16;
    private static ExtendedPropertyDefinition PidTagConversationIndexTracking = new ExtendedPropertyDefinition(0x3016, MapiPropertyType.Boolean);

    // HUGE props to Woodman
    // https://stackoverflow.com/a/21625224/298053
    public static string GetOutlookConversationId(this EmailMessage emailMessage)
    {
        Boolean convTracking;
        if (!emailMessage.TryGetProperty(PidTagConversationIndexTracking, out convTracking))
        {
            convTracking = true;
        }

        var convIndex = emailMessage.ConversationIndex;
        byte[] idBytes;
        if (convTracking && convIndex != null && convIndex.Length > 0)
        {
            // get Id from Conversation index
            idBytes = new byte[c_ulConvIndexIDLength];
            Array.Copy(convIndex, c_ulConvIndexIDOffset, idBytes, 0, c_ulConvIndexIDLength);
        }
        else
        {
            // get Id from Conversation topic
            var topic = emailMessage.ConversationTopic;
            if (string.IsNullOrEmpty(topic))
            {
                return string.Empty;
            }

            if (topic.Length >= 265)
            {
                topic = topic.Substring(0, 256);
            }
            topic = topic.ToUpper();

            using (var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider())
            {
                idBytes = md5.ComputeHash(Encoding.Unicode.GetBytes(topic));
            }
        }

        return BitConverter.ToString(idBytes).Replace("-", string.Empty);
    }

    public static String GetOutlookConversationIndex(this EmailMessage emailMessage)
    {
        var convIndex = emailMessage.ConversationIndex;
        return BitConverter.ToString(convIndex).Replace("-", String.Empty);
    }
}
 

用法:

 // Prep
ExchangeService service = new ExchangeService(...);
Folder inbox = Folder.bind(service, WellKnownFolderName.Inbox);
Item item = /* inbox.FindItems(...).First() */

// Implmentation
EmailMessage emailMessage = item as EmailMessage;
if (emailMessage != null)
{
   String conversationId = emailMessage.GetOutlookConversationId();
   String conversationIndex = emailMessage.GetOutlookConversationIndex();
   /* ... */
}
 

I wrote an add-in for Outlook years ago that adds entries to a database based on the Item's ConversationIndex/ConversationId properties. This works great and remains uniform across all clients interacting with the messages (e.g. "Bob" can see that "Mary" already processed this message because an entry with the ConversationIndex already exists).

I'm now trying to move this piece to a service (and connect via the EWS API) but I'm not having good luck matching these properties with the values coming from Outlook. For example:

The Outlook Add-In will give me the following values for a specific email I'm targeting:

ConversationID:     6B6369F5023EA646AA7BC161274BDAE8
ConversationIndex:  0101CF3C7EEC6B6369F5023EA646AA7BC161274BDAE8

However, from the EWS API I get the following:

ConversationID:     AAQkADFhZThkNmJmLTlkODItNDQyZS1hM2YxLTQ2NWNkMTllYjhjOQAQAGtjafUCPqZGqnvBYSdL2ug=
ConversationIndex:  new byte[]{1,1,207,60,126,236,107,99,105,245,2,62,166,70,170,123,193,97,39,75,218,232}

I recognize the first as a Base64 encoded string, however what I get decoded doesn't look like anything I recognize (or can decipher). Is there anyone familiar with this, or who can help to get these two values to align? I can only imagine these properties come from the exchange server is some fashion, but the Client probably performs some cleansing whereas the EWS API just gives me the raw value (less the Base64 for what I presume transport purposes given the XML medium).

If anyone is familiar with this or has done it before I would greatly appreciate any guidance.

Side Note:

There are probably better ways to identify emails but for now I'm stuck with trying to keep these two synonymous. Modifying the outlook add-in isn't really an option, and once I migrate a 1:1 translation to the server (and drop the add-in) I'll have flexibility changing how it work. But for now I need them to run side-by-side. I need to be able to see processes made within Outlook from the web server and vise-versa.

解决方案

Just found out (I think).

Breakdown

With more Googling and a bit more effort I believe I was able to make them align 1:1 using the following:

ConversationId

This is apparently an assembled value made up of several properties. Luckily I was able to find a method Woodman posted re-implementing the original algorithm used by Outlook here. With some minor modifications (to work with EWS instead of Outlook) I was able to get it to work.

ConversationIndex

This turned out to simply be a matter of using the BitConverter (and removing the hyphens). Easy peasy.

Final Result:

public static class EwsEmailMessageExtensions
{
    private const int c_ulConvIndexIDOffset = 6;
    private const int c_ulConvIndexIDLength = 16;
    private static ExtendedPropertyDefinition PidTagConversationIndexTracking = new ExtendedPropertyDefinition(0x3016, MapiPropertyType.Boolean);

    // HUGE props to Woodman
    // https://stackoverflow.com/a/21625224/298053
    public static string GetOutlookConversationId(this EmailMessage emailMessage)
    {
        Boolean convTracking;
        if (!emailMessage.TryGetProperty(PidTagConversationIndexTracking, out convTracking))
        {
            convTracking = true;
        }

        var convIndex = emailMessage.ConversationIndex;
        byte[] idBytes;
        if (convTracking && convIndex != null && convIndex.Length > 0)
        {
            // get Id from Conversation index
            idBytes = new byte[c_ulConvIndexIDLength];
            Array.Copy(convIndex, c_ulConvIndexIDOffset, idBytes, 0, c_ulConvIndexIDLength);
        }
        else
        {
            // get Id from Conversation topic
            var topic = emailMessage.ConversationTopic;
            if (string.IsNullOrEmpty(topic))
            {
                return string.Empty;
            }

            if (topic.Length >= 265)
            {
                topic = topic.Substring(0, 256);
            }
            topic = topic.ToUpper();

            using (var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider())
            {
                idBytes = md5.ComputeHash(Encoding.Unicode.GetBytes(topic));
            }
        }

        return BitConverter.ToString(idBytes).Replace("-", string.Empty);
    }

    public static String GetOutlookConversationIndex(this EmailMessage emailMessage)
    {
        var convIndex = emailMessage.ConversationIndex;
        return BitConverter.ToString(convIndex).Replace("-", String.Empty);
    }
}

Usage:

// Prep
ExchangeService service = new ExchangeService(...);
Folder inbox = Folder.bind(service, WellKnownFolderName.Inbox);
Item item = /* inbox.FindItems(...).First() */

// Implmentation
EmailMessage emailMessage = item as EmailMessage;
if (emailMessage != null)
{
   String conversationId = emailMessage.GetOutlookConversationId();
   String conversationIndex = emailMessage.GetOutlookConversationIndex();
   /* ... */
}

这篇关于将EWS对话*与Outlook加载项对话匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆