【问题标题】:VSTO: process mail using newmailex before outlook rules move mailVSTO:在 Outlook 规则移动邮件之前使用 newmailex 处理邮件
【发布时间】:2011-01-19 02:36:43
【问题描述】:

我正在为 Outlook 2007 创建一个插件,它会在收到邮件时读取它,然后重写它。该插件效果很好,并为没有将它们移动到另一个文件夹的 Outlook 规则的项目重写邮件。如果有规则,大约 50% 的时间仍然可以。另外 50% 的时间,规则会在我的插件完成之前移动邮件项目。我收到以下错误:

“无法执行该操作,因为该对象已被删除。”

我正在使用 NewMailEx 事件来调用我的重写函数:

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
    this.Application.NewMailEx += new Outlook.ApplicationEvents_11_NewMailExEventHandler(olApp_NewMail);
}

在 Outlook 2007 中,NewMailEx 提供邮件的 entryID。此 entryID 最初用于确定要使用的邮件对象:

Outlook.NameSpace outlookNS = this.Application.GetNamespace("MAPI");
Outlook.MAPIFolder mFolder = this.Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
Outlook.MailItem mail;
try
{
    mail = (Outlook.MailItem)outlookNS.GetItemFromID(entryIDCollection, Type.Missing);
}
catch (Exception e) { Debug.WriteLine("exception with non-mail item " + entryIDCollection + ": " + e.ToString()); return; }

我认为我可以使用这个 entryID(上面的代码可以使用),并遍历我的所有文件夹(在交换机上以及在我的计算机上)寻找相同的邮件 ID。当我最终迭代到邮件所在的位置时,移动邮件的 EntryID 与 entryIDCollection 非常不同。

也许我做错了。有谁知道如何在我完成之前阻止事件传播,或者如何追踪移动的电子邮件?

如果有人好奇,这是我遍历文件夹的代码:

        try
        {
            mail.Subject = new_subj;
            mail.Body = "";
            mail.HTMLBody = text;
            mail.ClearConversationIndex();
            mail.Save();
        }
        catch (Exception ex)
        {
            //It wasn't caught in time, so we need to find the mail:
            ArrayList unreadFolders = new ArrayList();
            foreach (Outlook.Folder f in outlookNS.Folders) unreadFolders.Add(f);

            while (unreadFolders.Count > 0)
            {
                Outlook.Folder currentFolder = unreadFolders[0] as Outlook.Folder;
                Debug.WriteLine("reading folder: " + currentFolder.Name);
                unreadFolders.RemoveAt(0);


                foreach (Outlook.Folder f in currentFolder.Folders) unreadFolders.Add(f);

                try
                { 
                    Outlook.Items items = currentFolder.Items.Restrict("[UnRead] = true");
                    for (int itemNum = 1; itemNum <= items.Count; itemNum++)
                    {
                        if (!(items[itemNum] is Outlook.MailItem)) continue;
                        Outlook.MailItem m = items[itemNum];
                        if (m.EntryID == entryIDCollection)
                        {
                            m.Subject = new_subj;
                            m.Body = "";
                            m.HTMLBody = text;

                            m.ClearConversationIndex();
                            m.Save();
                            return;
                        }

                    }
                }
                catch (Exception exc) { }
            }

        }

【问题讨论】:

    标签: outlook vsto


    【解决方案1】:

    76mel 的回答效果很好!我发布我的结果代码,以防其他人想做类似的事情(我是新手,不确定发布大量代码的规则,如果违反规则,请见谅):

    private string getPRSearchKey(Outlook.MailItem m)
    {
        return m.PropertyAccessor.BinaryToString(m.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x300B0102"));
    }
    
    private void olApp_NewMail(string entryIDCollection)
    {
        Outlook.NameSpace outlookNS = this.Application.GetNamespace("MAPI");
        Outlook.MAPIFolder mFolder = this.Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
        Outlook.MailItem mail;
    
        string pr_search_key;
        string old_subj;
        string old_body;
        try
        {
            mail = (Outlook.MailItem)outlookNS.GetItemFromID(entryIDCollection, Type.Missing);
            pr_search_key = getPRSearchKey(mail);
            //save the pr_search_key, subject, and body before the mailItem gets moved
            // then we can work on it without worrying about them disappearing
            old_subj = mail.Subject;
            old_body = mail.Body;
        }
        catch (Exception e) { Debug.WriteLine("exception with non-mail item " + entryIDCollection + ": " + e.ToString()); return; }
    
        //
        // ... do stuff with the mail's body and subject
        //
    
        try
        {
            mail.Subject = new_subj;
            mail.Body = "";
            mail.HTMLBody = text;
    
            mail.ClearConversationIndex();
            mail.Save();
        }
        catch (Exception ex)
        {
            //It wasn't caught in time, so we need to find the mail:
            ArrayList unreadFolders = new ArrayList();
            foreach (Outlook.Folder f in outlookNS.Folders) unreadFolders.Add(f);
    
            while (unreadFolders.Count > 0)
            {
                Outlook.Folder currentFolder = unreadFolders[unreadFolders.Count-1] as Outlook.Folder;
                Debug.WriteLine("reading folder: " + currentFolder.Name);
                unreadFolders.RemoveAt(unreadFolders.Count - 1);
    
    
                foreach (Outlook.Folder f in currentFolder.Folders) unreadFolders.Add(f);
    
                try
                { 
                    Outlook.Items items = currentFolder.Items.Restrict("[UnRead] = true");
                    for (int itemNum = 1; itemNum <= items.Count; itemNum++)
                    {
                        if (!(items[itemNum] is Outlook.MailItem)) continue;
                        Outlook.MailItem m = items[itemNum];
                        if (getPRSearchKey(m) == pr_search_key)
                        {
                            m.Subject = new_subj;
                            m.Body = "";
                            m.HTMLBody = text;
    
                            m.ClearConversationIndex(); //don't think this works
                            m.Save();
                            return;
                        }
    
                    }
                }
                catch (Exception exc) { }
            }
    
        }
    }
    

    顺便说一句,我可能会改变的是我将跳过查询某些文件夹以加快速度(日记、已删除邮件、垃圾邮件、草稿、RSS 源、Microsoft 在家、任务、笔记、联系人、日历、已发送项目、发件箱)。

    【讨论】:

    • 另外,有时当我收到 newmailex 时,邮件已经被移动(后来才发现)。我修改了我的第一个 catch 语句,如果 pr_search_key == "",抓取所有未读邮件,看看我是否已经修改了它们……有点烦人。我看到的另一个问题是,当我的计算机从睡眠中醒来时,收到的任何新电子邮件都不会发送 newmailex,因此所有这些都被遗漏了。很烦人
    • 这个答案很老了,但你还在用这个吗? schemas.microsoft.com/mapi/proptag/0x300B0102 似乎不再工作了。
    • 不,抱歉。几年前我换公司时停止使用这个。对不起,我帮不上忙
    【解决方案2】:

    未经测试的想法:如果您可靠地获得了 NewMailEx 事件,请使用用户属性或里程标记邮件,然后使用搜索。

    这可能不起作用,因为您可能无法在规则移动邮件之前进入。

    正如您计算出的,EntryId 会随着项目的移动而发生变化。

    您需要查看 MAPI 道具以获取 PR_SEARCH_KEY 的其他方式,当邮件移动时会发生变化。

    【讨论】:

    • 太好了,做到了!当消息进来时,我让它抓住了 PR_SEARCH_KEY。我还抓住了正文和主题。然后我修改了主题和正文。当我尝试更新正文/主题时,它失败了,然后我让它搜索文件夹并找到匹配的邮件。虽然 PR_SEARCH_KEY 不是唯一的 IF 邮件项目被复制(两个副本可能共享相同的 PR_SEARCH_KEY),但这很好,因为当它进来时,我还没有制作任何副本。我试图对此投赞成票,但我太新了,无法投票:(我将在下面发布我的代码(用完评论字符)
    猜你喜欢
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多