views:

468

answers:

4

Hi all, I'm writing an add-in for Outlook to parse all mails within a folder by clicking on a custom context menu button. I've got the button hooked up, but when trying to use the foreach loop within the folder to check the mail items it only seems to check the first one.

I grab the folder details here:

void Application_FolderContextMenuDisplay(Office.CommandBar CommandBar, ***MAPIFolder Folder***)

I then pass it to a parser:

public void checkFolder(MAPIFolder folder)
    {
        MailParser parser = new MailParser();
        foreach (MailItem item in folder.Items)
        {
            parser.parseMail(item);
        }
    }

It's the foreach here that seems to fail.

Any ideas? This is driving me nuts.

A: 

I'm guessing that MAPIFolder.Items isn't strongly typed, yet you're iterating over it as if it is. I'd suggest going with:

foreach(object item in folder.Items)
{
  if (item is MailItem)
    parser.parseMail((MailItem)item);
}
JustLoren
A: 

foreach is useful for a collection that implements the IEnumerable interface. According to MSDN, it would appear that particular Items collection does not implement IEnumerable. Try using a for loop instead:

int c = folder.Items.Count
for (i=0;i<=c;i++)
{
   //Do your thing
}
Dave Swersky
+1  A: 

I'm not extremely familiar with the outlook object model, but at a glance I would say the problem is you're incorrectly assuming that all of the items in a folder are MailItem instances. They could also be objects like ContactItem. You need to explicitly check to see if the value is a MailItem like so

foreach ( object current in folder.Items ) {
  MailItem mi = current as MailItem;
  if ( mi != null ) { 
    parser.parseMail(mi);
  }
}
JaredPar
+1  A: 

You should be using the Microsoft.Office.Interop.Outlook.Extensions.Linq API, which allows the type safe retrieval of items:

public void checkFolder(MAPIFolder folder)
{
    MailParser parser = new MailParser();
    IQueryable<Mail> query = folder.Items.AsQueryable<Mail>();
    foreach (MailItem wrappedItem in query)
    {
        parser.parseMail(wrappedItem.Item);
    }
}

Here the the Mail type is a subclass of OutlookItemBase<TaskItem>. It has an Item property which returns the MailItem COM object. It will also safely filter out non-compatible types without throwing an exception, so you don't have to add null checks.

The Extensions API also solve the missing base class problem for the items, so you can finally access UserProperties and such through the non-generic OutlookItem base class. Also the API supports some attributes, which can add some performance boost to the Linq queries, by executing them on Outlook side, instead over COM. Unfortunately they are not well documented.

dadinn