How to examine every incoming email of all folders

Category: outlook for developers

Question

Hong (MA, USA) on Sun, 24 Nov 2019 16:44:30


My outlook hosts multiple emails, hence multiple folders.   I am trying to inspect every incoming email by modifying an official example:

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            //The only supported name space type is "MAPI". The GetNameSpace method is functionally equivalent to the Session property.
            outlookNameSpace = this.Application.GetNamespace("MAPI");

            foreach (Folder folder in outlookNameSpace.Folders)
            {
                if (folder.DefaultItemType == OlItemType.olMailItem)
                {
                    Debug.WriteLine("Folder: " + folder.Name);
                    items = folder.Items;
                    items.ItemAdd +=
                        new Outlook.ItemsEvents_ItemAddEventHandler(items_ItemAdd);
                }
            }
        }

        void items_ItemAdd(object Item)
        {
            Debug.WriteLine("---------- items_ItemAdd has been called----------------------");
  
        }

items_ItemAdd  is never called despite the following code outputs all correct email addresses:

 Debug.WriteLine("Folder: " + folder.Name);

Could anyone shed some light on this?


Hong

Replies

Dmitry Streblechenko _MVP_ on Sun, 24 Nov 2019 16:59:08


items in your code is a single variable, and you overwrite its value on each iteration. You need to create a wrapper class that will store the Items object as a property and provide the event handler, You can then create a list (List<MyItemWrapper>) and store your wrappers there - this will ensure that each Items collection is alive and can raise events.

That being said, opening each and every folder and tracking their events is a bad idea.

Hong (MA, USA) on Sun, 24 Nov 2019 17:08:24


Thank you.

What would you suggest to inspect each incoming email?

I am just sick and tired of spam emails with HTML format which inspection is not supported by Outlook filters. 

Dmitry Streblechenko _MVP_ on Sun, 24 Nov 2019 17:17:29


Why are you setting up the event handlers on *all* folders instead of just the Inbox?

Hong (MA, USA) on Sun, 24 Nov 2019 17:30:25


Perhaps I have misunderstood the meaning of "Inbox" for add-in.   Each folder corresponds to an email address (e.g. myid@domainA.net, myid@domainB.com, myid@domainC.org...) and there is an Inbox in each folder in my Outlook.

I am using the aforementioned code because the code from the official sample failed to catch any emails except those for myid@msn.com:

Outlook.NameSpace outlookNameSpace;
Outlook.MAPIFolder inbox;
Outlook.Items items;

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
    outlookNameSpace = this.Application.GetNamespace("MAPI");
    inbox = outlookNameSpace.GetDefaultFolder(
            Microsoft.Office.Interop.Outlook.
            OlDefaultFolders.olFolderInbox);

    items = inbox.Items;
    items.ItemAdd +=
        new Outlook.ItemsEvents_ItemAddEventHandler(items_ItemAdd);
}

void items_ItemAdd(object Item)
{
       Debug.WriteLine("---------- items_ItemAdd has been called----------------------");
}

Dmitry Streblechenko _MVP_ on Sun, 24 Nov 2019 17:36:31


Namespace.Folders collection contains top level folders of each store in the profile. Those folders do not contain any items.

If you want all Inbox folders, loop through all stores in the Namespace.Stores collection and for each store call Store.GetDefaultFolder(olFolderInbox).

But the code above should work fine for the primary store in the profile.


Dmitry Streblechenko (MVP)
http://www.dimastr.com/redemption
Redemption - what the Outlook
Object Model should have been
Version 5.5 is now available!


Hong (MA, USA) on Sun, 24 Nov 2019 18:16:48


It works!  Thank you.

However, I do not understand why it works only when Outlook starts.   Subsequent incoming emails do not trigger items_ItemAdd().  My intention is inspecting every email all the time. 

Dmitry Streblechenko _MVP_ on Sun, 24 Nov 2019 18:46:32


I am not sure what you mean - do you mean you start your code when Outlook is *not* running? In that case it probably won't download any new emails until you open its UI.

Hong (MA, USA) on Sun, 24 Nov 2019 19:15:26


Yes, it is what I meant:

  1. Outlook is closed.
  2. Start the add-in from VS and this opens OL.
  3. OL immediately starts downloading email as usual, and every email is inspected by the add-in as expected. 
  4. A few minutes later, OL receives more emails, but none is inspected by the add-in.

However, everything appears to work well now after I added a dummy List<Items> listItems:

        Outlook.NameSpace outlookNameSpace;

        List<Items> listItems = new List<Items>();
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            //The only supported name space type is "MAPI". The GetNameSpace method is functionally equivalent to the Session property.
            outlookNameSpace = this.Application.GetNamespace("MAPI");
            foreach (Store store in outlookNameSpace.Stores)
            {

                MAPIFolder mapifolderInbox = store.GetDefaultFolder(
                    Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
                Debug.WriteLine("Folder: " + mapifolderInbox.Name);
                Items items = mapifolderInbox.Items;
                items.ItemAdd +=
                    new Outlook.ItemsEvents_ItemAddEventHandler(items_ItemAdd);
                
                //Hope to keep items from garbage collection.
                listItems.Add(items);
            }
        }

        void items_ItemAdd(object Item)
        {
            Debug.WriteLine("---------- items_ItemAdd has been called----------------------");

            Outlook.MailItem mail = (Outlook.MailItem)Item;
            if (Item != null)
            {
                Debug.WriteLine("----------" + mail.Subject + "----------------------");
            }

        }

Dmitry Streblechenko _MVP_ on Sun, 24 Nov 2019 19:43:28


Do you define items variable on the global (class) level?

Hong (MA, USA) on Sun, 24 Nov 2019 20:52:31


No, it is defined locally.  I originally thought the references of the event handlers would prevent them from garbage collection. Now, I use the class level listItems to hold them.

This is my first add-in in quite a few years.  It seems that Microsoft is deprecating this type of add-ins.  Though I make this primarily for my own use. I would love to put it somewhere in case it is useful for others.