I'm trying to write an app that will monitor a few mailboxes and when mail is found grab some info from each item and then once I have a list of the items I can take the appropriate actions.
But no matter how I approach it I'm hitting the Exchange enforced 255 RPC connections limit.
I'm absolutely stuck as to what is causing the error - as far as I can see I've got everything tied up in one method and am calling Marshal.ReleaseComObject.... I'm even accepting the performance hit of opening and closing the Outlook Application handle itself.
Any advice would be massively appreciated... (I can't seem to figure out why my code looks wrong in the preview so for safety's sake I've put it on pastebin too... http://pastebin.com/m637eb95)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Interop.Outlook;
using Microsoft.Office.Interop;
using System.Runtime.InteropServices;
namespace HandleMailingResponses
{
class OutlookFolderTableScraper
{
public List<OutlookItem> GetItemsFromFolder(string folderName)
{
List<OutlookItem> returnList = new List<OutlookItem>();
Application outlookHandle = new Application();
NameSpace outlookNamespace = outlookHandle.GetNamespace("MAPI");
Folders rootOutlookFolders = outlookNamespace.Folders;
outlookNamespace.Logon(null, null, null, true);
Folder requestedRoot = enumerateFolders(rootOutlookFolders, folderName);
Folders theseFolders = requestedRoot.Folders;
Folder thisInbox = enumerateFolders(theseFolders, "Inbox");
Marshal.ReleaseComObject(requestedRoot);
requestedRoot = null;
Marshal.ReleaseComObject(rootOutlookFolders);
rootOutlookFolders = null;
string storeID = thisInbox.StoreID;
Table thisTable = thisInbox.GetTable("",OlTableContents.olUserItems);
//By default each item has the columns EntryID, Subject, CreationTime, LastModificationTime and MessageClass
//we can add any of the other properties the MailItem or ReportItem object would have....
Columns theseColumns = thisTable.Columns;
theseColumns.Add("SenderEmailAddress");
Marshal.ReleaseComObject(thisInbox);
thisInbox = null;
outlookNamespace.Logoff();
Marshal.ReleaseComObject(outlookNamespace);
outlookNamespace = null;
outlookHandle.Quit();
Marshal.ReleaseComObject(outlookHandle);
outlookHandle = null;
int count = 0;
while (!thisTable.EndOfTable)
{
Row thisRow = thisTable.GetNextRow();
object[] theseValues = (object[]) thisRow.GetValues();
Console.WriteLine("processed {0}",count++);
//get the body from this item
string messageClass = (string)theseValues[4];
string entryID = (string)theseValues[0];
string body = getItemBody(entryID,storeID, messageClass);
returnList.Add(new OutlookItem((string)theseValues[5], (string)theseValues[1], body, messageClass, entryID));
}
return returnList;
}
private string getItemBody(string entryID, string storeID, string messageClass)
{
Application outlookHandle = new Application();
NameSpace outlookNamespace = outlookHandle.GetNamespace("MAPI");
outlookNamespace.Logon(null, null, null, true);
string body;
if (messageClass.ToLower().StartsWith("report"))
{
ReportItem thisItem = (ReportItem)outlookNamespace.GetItemFromID(entryID, storeID);
body = thisItem.Body;
thisItem.Close(OlInspectorClose.olDiscard);
//release this com reference
int releaseResult;
do
{
releaseResult = Marshal.ReleaseComObject(thisItem);
} while (releaseResult != 0);
}
else
{
MailItem thisItem = (MailItem)outlookNamespace.GetItemFromID(entryID, storeID);
body = thisItem.Body;
thisItem.Close(OlInspectorClose.olDiscard);
//release this com reference
int releaseResult;
do
{
releaseResult = Marshal.ReleaseComObject(thisItem);
} while (releaseResult != 0);
}
outlookNamespace.Logoff();
outlookNamespace = null;
outlookHandle.Quit();
outlookHandle = null;
GC.Collect();
GC.WaitForPendingFinalizers();
return body;
}
/// <summary>
/// Iterates through an Outlook.Folders object searching for a folder with the given name
/// </summary>
/// <param name="rootFolder">An Outlook.Folder object</param>
/// <param name="targetFolder"></param>
/// <returns></returns>
private Folder enumerateFolders(Folders rootFolders, string targetFolder)
{
Folder returnFolder = null;
System.Collections.IEnumerator thisEnumerator = rootFolders.GetEnumerator();
while (thisEnumerator.MoveNext())
{
Folder f = (Folder)thisEnumerator.Current;
string name = f.Name;
if (targetFolder.ToLower().Equals(name.ToLower()))
{
returnFolder = f;
break;
}
}
ICustomAdapter adapter = (ICustomAdapter)thisEnumerator;
Marshal.ReleaseComObject(adapter.GetUnderlyingObject());
adapter = null;
return returnFolder;
}
}
}