Welcome to NavWin!
  

Introduction

I once had to write a programming which scanned our Microsoft Outlook support e-mail folder in order to get some support traffic KPI’s. This was to be done in C#. The basic code to do this was readily available on the Internet but all examples suffered from the same major problem. After scanning a certain number of e-mails you got this error.

"Cannot display the folder. Your server administrator has limited the number of items you can open simultaneously. Try closing messages you have opened or removing attachments and images from unsent messages you are composing."

 

The basic loop was fine, but interacting with the COM marshalling layer was somehow holding open every instance of the e-mails you accessed. It took a couple of weeks to find a solution (which was basically piecing together all the other ideas that are out there and following them methodically). The following code worked for me and made the e-mail scan extremely robust (albeit somewhat slower). How much of it is truly needed, I have never bothered to find out. It works so I left it alone!

private static void ReleaseRemoteObject(object item)

{

    if (item == null)

        return;

 

    Marshal.ReleaseComObject(item);

    while (Marshal.FinalReleaseComObject(item) != 0)

    {

    }

    GC.Collect();

    GC.WaitForPendingFinalizers();

}

You can then make convenient access functions such as this:

private static void ReleaseRemoteObject(ref object item)

{

    ReleaseRemoteObject(item);

    item = null;

}

private static void ReleaseRemoteObject(ref Microsoft.Office.Interop.Outlook.PostItem item)

{

    ReleaseRemoteObject(item);

    item = null;

}

private static void ReleaseRemoteObject(ref Microsoft.Office.Interop.Outlook.Folder item)

{

    ReleaseRemoteObject(item);

    item = null;

}

private static void ReleaseRemoteObject(ref Microsoft.Office.Interop.Outlook._NameSpace item)

{

    ReleaseRemoteObject(item);

    item = null;

}

private static void ReleaseRemoteObject(ref Microsoft.Office.Interop.Outlook.Application item)

{

    ReleaseRemoteObject(item);

    item = null;

}

private static void ReleaseRemoteObject(ref Microsoft.Office.Interop.Outlook.NameSpace item)

{

    ReleaseRemoteObject(item);

    item = null;

}

 

Your main code loop may look something like this (note you will need a project reference to this Microsoft assembly Microsoft.Office.Interop.Outlook to make it compile).

public void ReadMail(string supportFolder, DateTime earliestDateFilter)

{

    Microsoft.Office.Interop.Outlook.Application app = null;

    Microsoft.Office.Interop.Outlook.NameSpace ns = null;

    Microsoft.Office.Interop.Outlook.Folder inboxFolder = null;

    Microsoft.Office.Interop.Outlook.Folder subFolder = null;

    Microsoft.Office.Interop.Outlook.Folder subFolder2 = null;

 

    try

    {

 

        app = new Microsoft.Office.Interop.Outlook.Application();

        ns = app.GetNamespace("MAPI");

        ns.Logon(null, null, false, false);

 

        inboxFolder = (Microsoft.Office.Interop.Outlook.Folder)ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olPublicFoldersAllPublicFolders);

        subFolder2 = (Microsoft.Office.Interop.Outlook.Folder)inboxFolder.Folders["Support"];

        subFolder = (Microsoft.Office.Interop.Outlook.Folder)subFolder2.Folders["Internet E-mail"];

 

        object item = null;

        Microsoft.Office.Interop.Outlook.PostItem postItem = null;

 

        for (int i = 1; i <= subFolder.Items.Count; i++)

        {

 

            try

            {

                postItem = null;

                item = subFolder.Items[i];

 

                postItem = item as PostItem;

                if (postItem != null)

                {

                    DateTime receiveTime = postItem.ReceivedTime;

 

                    if (postItem.ReceivedTime < earliestDateFilter)

                    {

                        break; // e-mails are returned in date order (most recent first)

                    }

 

                    string sFrom = postItem.SenderEmailAddress;

 

                    //DO YOUR CUSTOM PROCESSING HERE

                }

            }

            catch

            {

                throw;

            }

            finally

            {

                ReleaseRemoteObject(ref postItem);

                ReleaseRemoteObject(ref item);

            }

 

        } // for     

    }

    catch

    {

        throw;

    }

    finally

    {

        // release objects in the reverse order of assigning them

        ReleaseRemoteObject(ref subFolder);

        ReleaseRemoteObject(ref subFolder2);

        ReleaseRemoteObject(ref inboxFolder);

        if (ns != null)

        {

            ns.Logoff();

        }

        ReleaseRemoteObject(ref ns);

        ReleaseRemoteObject(ref app);

    }

 

}

 

 

Hope it helps you.