VSTO:在Outlook规则移动邮件之前使用newmailex处理邮件

我为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) { }
            }

        }

未经测试的想法:如果您可靠地获取NewMailEx事件,请使用用户财产或里程标记具有GUID的邮件,然后使用搜索。

这可能无法正常工作,因为在规则移动邮件之前您可能无法进入。

正如您已经计算出项目移动时的EntryId更改。

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


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源,微软在家中,任务,笔记,联系人,日历,发送项目,发件箱)。

链接地址: http://www.djcxy.com/p/21477.html

上一篇: VSTO: process mail using newmailex before outlook rules move mail

下一篇: Solution for VB6 to broadcast Webcam