VSTO: process mail using newmailex before outlook rules move mail

outlookvsto

I am creating an addon for Outlook 2007 that reads a mail item when it is received, and then rewrites it. The addon works great, and rewrites the mail for items that do not have an Outlook rule that moves them into another folder. If there is a rule, it is still fine about 50% of the time. The other 50% of the time, the rule moves the mail item before my addon finishes. I get the following error:

"The operation cannot be performed because the object has been deleted."

I am using NewMailEx event to call my rewriting function:

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

In Outlook 2007, NewMailEx gives an entryID for the mail. This entryID is used initially to figure out which mail object to use:

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; }

I thought that I could take this entryID (which the above code works), and iterate through all of my folders (on exchange as well as on my computer) looking for the same mail id. When I finally iterate to where the mail is, the moved mail's EntryID is very different from the entryIDCollection.

Maybe I'm going about this the wrong way. Does anyone know how to stop the event from propagating until I am done, or how to track down the moved email?

Here is my code for traversing the folders in case anyone's curious:

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

        }

Best Answer

Untested Idea : If you are reliably getting the NewMailEx Event, mark the Mail with a user property or mileage with a GUID and then use Search for that.

This may not work as you may not be able to get in before the Rule moves the mail.

As you have worked out the EntryId changes whe the item is moved.

Other way you need to look at MAPI props to get the PR_SEARCH_KEY that dosent change when mail is moved around.

Related Topic