none
Outlook plugin move mail item is slow RRS feed

  • Question

  • I'm working on a plugin for outlook that moves emails to a folder. Is working fine but looks like the move method of MailItem is slow take 4-5 seconds to move 10 emails I'm using something like:

    for (int i = folder.Items.Count; i > 0; i--)
    {
         Outlook.MailItem mi = (Outlook.MailItem)theRootFolder.Items[i];
         if (mi != null)
         {            
                  mi.Move(destFolder);
    
    			Marshal.ReleaseComObject(mi);
    
    			mi = null;         
         }
    }


    looks like after move one email Outlook is trying to read the next one and is spending time doing that

    Thursday, August 13, 2015 12:19 AM

Answers

  • I can only suggest switching to

    1. Extended MAPI (C++ or Delphi only) - IMAPIFolder::CopyMessages (MESSAGE_MOVE) allows to specify multiple entry ids

    2. Redemption (any language) - it exposes RDOItems.MoveMultiple method


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

    • Marked as answer by MariusNY Sunday, August 16, 2015 8:10 PM
    Thursday, August 13, 2015 2:17 AM
  • Hello Marius,

    Don't use multiple dots in the single line of code. Breaking the chain of property and method calls will allow to release all underlying COM objects instantly. Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. This is particularly important if your add-in attempts to enumerate more than 256 Outlook items in a collection that is stored on a Microsoft Exchange Server. If you do not release these objects in a timely manner, you can reach the limit imposed by Exchange on the maximum number of items opened at any one time. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object. Read more about that in the Systematically Releasing Objects article.

    Outlook.Items items = folder.Items;
    for (int i = items.Count; i > 0; i--)
    {
         Outlook.MailItem mi = items[i] as Outlook.MailItem;
         if (mi != null)
         {            
                 object moved = mi.MovedestFolder);                 
           	     Marshal.ReleaseComObject(moved);
       	     moved = null;          
    	     Marshal.ReleaseComObject(mi);
       	     mi = null;         
         }
    }

    If it doesn't help you may consider using a low-level API - Extended MAPI on secondary threads to do the job in parallel.

    • Marked as answer by MariusNY Sunday, August 16, 2015 8:10 PM
    Thursday, August 13, 2015 9:12 AM

All replies

  • Try to cache the Items collection before entering the loop:

    Outlook.Items items = folder.Items;
    for (int i = items.Count; i > 0; i--)
    {
         Outlook.MailItem mi = (Outlook.MailItem)items[i];
         if (mi != null)
         {            
                 mi.Move(destFolder);
    	     Marshal.ReleaseComObject(mi);
       	     mi = null;         
         }


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

    Thursday, August 13, 2015 12:53 AM
  • Thanks Dmitry, I have same result 
    Thursday, August 13, 2015 1:26 AM
  • I can only suggest switching to

    1. Extended MAPI (C++ or Delphi only) - IMAPIFolder::CopyMessages (MESSAGE_MOVE) allows to specify multiple entry ids

    2. Redemption (any language) - it exposes RDOItems.MoveMultiple method


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

    • Marked as answer by MariusNY Sunday, August 16, 2015 8:10 PM
    Thursday, August 13, 2015 2:17 AM
  • Hello Marius,

    Don't use multiple dots in the single line of code. Breaking the chain of property and method calls will allow to release all underlying COM objects instantly. Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. This is particularly important if your add-in attempts to enumerate more than 256 Outlook items in a collection that is stored on a Microsoft Exchange Server. If you do not release these objects in a timely manner, you can reach the limit imposed by Exchange on the maximum number of items opened at any one time. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object. Read more about that in the Systematically Releasing Objects article.

    Outlook.Items items = folder.Items;
    for (int i = items.Count; i > 0; i--)
    {
         Outlook.MailItem mi = items[i] as Outlook.MailItem;
         if (mi != null)
         {            
                 object moved = mi.MovedestFolder);                 
           	     Marshal.ReleaseComObject(moved);
       	     moved = null;          
    	     Marshal.ReleaseComObject(mi);
       	     mi = null;         
         }
    }

    If it doesn't help you may consider using a low-level API - Extended MAPI on secondary threads to do the job in parallel.

    • Marked as answer by MariusNY Sunday, August 16, 2015 8:10 PM
    Thursday, August 13, 2015 9:12 AM
  • Dmitry,

    You do not release all underlying COM objects in the code.

    The Move method of the MailItem class returns an Object value that represents the item which has been moved to the designated folder. So, it should be released as well.

    Thursday, August 13, 2015 9:14 AM
  • That was an example. Releasing or not releasing objects has (almost) no effect on how fast or slow your code runs. If anything, it will make the code slower.

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

    Thursday, August 13, 2015 3:24 PM
  • An example should demonstrate how to release COM objects instantly, but it doesn't in fact.
    Friday, August 14, 2015 2:51 PM
  • An example should be relevant to what the OP asks. If you think in this particular case releasing COM objects is important, go ahead and mention it.


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

    Friday, August 14, 2015 4:31 PM
  • I always try to cover as much details as possible, even if they are not related to the original question.
    Friday, August 14, 2015 4:38 PM
  • Good for you.

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

    Friday, August 14, 2015 7:18 PM