Outlook Item Events
Outlook has many events that occur at the Outlook item level. We refer to Item events in this section, but there is no Item object per se in the Outlook object model. Instead, you will find Item events on each of the 15 Outlook object model objects listed in Table 10-1.
Item Addition, Deletion, and Change Events
Several events are raised when Outlook items are added, deleted, or changed:
- Items.ItemRemove is raised when an item is deleted from the Items collection associated with a folderfor example, when an item is deleted from the collection of items in the Inbox folder. It is raised once for each item removed from the collection. Unfortunately, the item removed from the collection is not passed as a parameter to this event and is difficult to determine unless you store the previous state of the items in the folder in some way. This event is also not raised if more than 16 items are deleted at once or when the last item in a folder is deleted if the folder is in a PST file. You can work around these limitations by using the FolderChange event described in the "Folder Change Events" section earlier in this chapter. For example, you could store the number of items in the folder in a variable and when handling the FolderChange event determine whether the number of items in the folder have decreased.
- Items.ItemChange is raised when an item is changed in the Items collection associated with a folderfor example, when an item is changed in the collection of Outlook items in the Inbox folder. Outlook passes the Outlook item that has changed as an object parameter to this event.
- Items.ItemAdd is raised when an item is added to the Items collection associated with a folderfor example, when an item is added to the collection of Outlook items in the Inbox folder. It is raised once for each item that is added to the collection. Outlook passes the Outlook item that was added as an object parameter to this event. Unfortunately, this event is not raised if a large number of items are added at once. You can work around this limitation by using the FolderChange event described in the "Folder Change Events" section earlier in this chapter. For example, you could store the state of the items in the folder that you want to monitor for changes and when handling the FolderChange event determine whether the new state of the items in the folder matches the state you have stored.
- Item.BeforeDelete is raised on an Outlook item when the item is deleted. However, the item must be deleted from an Inspector windowthe event is not raised if you just delete the item from a folder. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to TRue by your event handler to prevent Outlook from deleting the item
Listing 10-5 shows some VSTO Outlook add-in code that handles these events. To get to an individual MailItem to handle the Item.BeforeDelete event, the code first gets the NameSpace object. The NameSpace object is accessed by calling the Application.Session property. The NameSpace object has a method called GetDefaultFolder that returns a MAPIFolder to which you can pass a member of the enumeration OlDefaultFolders to get a standard Outlook folder. In Listing 10-5, we pass olFolderInbox to get a MAPIFolder for the Inbox. We then use the Items collection associated with the Inbox's MAPIFolder to connect our event handlers to as well as to get an individual MailItem to handle the Item.BeforeDelete event for.
Listing 10-5. A VSTO Add-In That Handles Item Addition, Change, and Delete Events
namespace OutlookAddin1 { public partial class ThisApplication { Outlook.MailItem mailItem; Outlook.Items items; private void ThisApplication_Startup(object sender, EventArgs e) { Outlook.NameSpace ns = this.Session; Outlook.MAPIFolder inbox = ns. GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox); foreach (object o in inbox.Items) { mailItem = o as Outlook.MailItem; if (mailItem != null) { break; } } if (mailItem == null) { MessageBox.Show("Couldn't find a mail item to connect to."); } else { mailItem.BeforeDelete += new Outlook.ItemEvents_10_BeforeDeleteEventHandler( MailItem_BeforeDelete); MessageBox.Show(String.Format( "Connected to the mail item with subject {0}.", mailItem.Subject)); } items = inbox.Items; items.ItemRemove += new Outlook.ItemsEvents_ItemRemoveEventHandler( Items_ItemRemove); items.ItemChange += new Outlook.ItemsEvents_ItemChangeEventHandler( Items_ItemChange); items.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler( Items_ItemAdd); } void MailItem_BeforeDelete(object item, ref bool cancel) { MessageBox.Show(String.Format( "The mail item {0} cannot be deleted.", mailItem.Subject)); cancel = true; } void Items_ItemRemove() { MessageBox.Show("An item is about to be removed."); } void GenerateItemMessage(object item, string operation) { Outlook.MailItem mailItem = item as Outlook.MailItem; if (mailItem != null) { MessageBox.Show(String.Format( "MailItem {0} was just {1}.", mailItem.Subject, operation)); } else { MessageBox.Show(String.Format( "An Outlook item was just {0}.", operation)); } } void Items_ItemChange(object item) { GenerateItemMessage(item, "changed"); } void Items_ItemAdd(object item) { GenerateItemMessage(item, "added"); } } }
Copy, Paste, Cut, and Delete Events
Outlook raises several events when Outlook items are copied, cut, or pasted. These events are raised on an Explorer object. An Explorer object has a Selection property that returns the current selected items in the Explorer. Because many of the Explorer events telling you that a copy, cut, or paste is about to occur do not pass the items that are being acted upon, you must examine the Selection object to determine the items that are being acted upon:
- Explorer.BeforeItemCopy is raised before one or more Outlook items are copied. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to true by your event handler to prevent the item or items from being copied.
- Explorer.BeforeItemCut is raised before one or more Outlook items are cut. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to true by your event handler to prevent the item or items from being cut.
- Explorer.BeforeItemPaste is raised before one or more Outlook items are pasted. Outlook passes a clipboardContent parameter as an object. If the clipboard contains Outlook items that have been cut or copied, you can cast the clipboardContent parameter to a Selection object and examine what is about to be pasted. Outlook next passes a target parameter of type MAPIFolder. This represents the destination folder to which the item or items will be pasted. Outlook also passes by reference a bool cancel parameter. The cancel parameter can be set to true by your event handler to prevent the item or items from being pasted.
Listing 10-6 shows a VSTO Outlook add-in that handles these events. It uses a helper function called GenerateItemsMessage that iterates over the items in a Selection object and displays a dialog with the subject of each MailItem selected.
Listing 10-6. A VSTO Add-In That Handles Copy, Cut, and Paste Events
namespace OutlookAddin1 { public partial class ThisApplication { Outlook.Explorer explorer; private void ThisApplication_Startup(object sender, EventArgs e) { explorer = this.ActiveExplorer(); explorer.BeforeItemCopy += new Outlook.ExplorerEvents_10_BeforeItemCopyEventHandler( Explorer_BeforeItemCopy); explorer.BeforeItemCut += new Outlook.ExplorerEvents_10_BeforeItemCutEventHandler( Explorer_BeforeItemCut); explorer.BeforeItemPaste += new Outlook.ExplorerEvents_10_BeforeItemPasteEventHandler( Explorer_BeforeItemPaste); } void GenerateItemsMessage(Outlook.Selection selection, string operation) { System.Text.StringBuilder b = new System.Text.StringBuilder(); b.AppendFormat("Items to be {0}: ", operation); foreach (object o in selection) { Outlook.MailItem mi = o as Outlook.MailItem; if (mi != null) { b.AppendFormat("MailItem: {0} ", mi.Subject); } else { b.AppendLine("Other Outlook item"); } } MessageBox.Show(b.ToString()); } void Explorer_BeforeItemCopy(ref bool cancel) { GenerateItemsMessage(explorer.Selection, "copied"); } void Explorer_BeforeItemCut(ref bool cancel) { GenerateItemsMessage(explorer.Selection, "cut"); } void Explorer_BeforeItemPaste(ref object clipboardContent, Outlook.MAPIFolder target, ref bool cancel) { if (clipboardContent is Outlook.Selection) { Outlook.Selection selection = clipboardContent as Outlook.Selection; GenerateItemsMessage(selection, "pasted"); } else { MessageBox.Show("The clipboard is not a Selection object."); } } } }
Property Change Events
A typical Outlook item has many associated properties, such as CreationTime, Importance, LastModificationTime, and so on. All the properties associated with an Outlook item are contained by the ItemProperties property. When any of these properties are changed, Outlook raises the PropertyChange event. It is also possible to define additional custom properties and associate them with an Outlook item. When custom properties are changed, Outlook raises the CustomPropertyChange event:
- Item.PropertyChange is raised when a property of an Outlook item is changed. Outlook passes a name parameter as a string that represents the name of the property that was changed.
- Item.CustomPropertyChange is raised when a user-defined property of an Outlook item is changed. Outlook passes a name parameter as a string that represents the name of the user-defined property that was changed.
Open, Read, Write, and Close Events
Outlook raises events when an Outlook item is opened, written to, or closed:
- Item.Read is raised when an Outlook item is displayed from within either an Explorer or Inspector view. This event has nothing to do with the Read or Unread status of an item, just whether it is being displayed in a view.
- Item.Open is raised when an Outlook item is opened in an Inspector view. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to TRue by your event handler to prevent the item from being opened.
- Item.Write is raised when an Outlook item is saved after being modified. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to true by your event handler to prevent the item or items from being written to.
- Item.Close is raised when an Outlook item is closed after being opened in an Inspector view. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to TRue by your event handler to prevent the item or items from being closed.
Close is the name of both a method and an event on Outlook item objects. Because of this collision, you will not see the Close event in Visual Studio's pop-up menu of properties, events, and methods associated with an Outlook item. Furthermore, a warning displays at compile time when you try to handle this event. To get Visual Studio's pop-up menus to work and the warning to go away, you can cast the Explorer object to the ItemEvents_10_Event, as shown in Listing 10-7. |
Listing 10-7 shows a VSTO Outlook add-in that handles these events.
Listing 10-7. A VSTO Add-In That Handles Open, Read, Write, and Close Events
namespace OutlookAddin1 { public partial class ThisApplication { Outlook.MailItem mailItem; private void ThisApplication_Startup(object sender, EventArgs e) { Outlook.NameSpace ns = this.Session; Outlook.MAPIFolder inbox = ns.GetDefaultFolder( Outlook.OlDefaultFolders.olFolderInbox); foreach (object o in inbox.Items) { mailItem = o as Outlook.MailItem; if (mailItem != null) { break; } } if (mailItem == null) { MessageBox.Show("Couldn't find a mail item to connect to."); } else { MessageBox.Show(String.Format( "Connected to the mail item with subject {0}.", mailItem.Subject); mailItem.Read += new Outlook.ItemEvents_10_ReadEventHandler( MailItem_Read); mailItem.Open += new Outlook.ItemEvents_10_OpenEventHandler( MailItem_Open); mailItem.Write += new Outlook.ItemEvents_10_WriteEventHandler( MailItem_Write); ((Outlook.ItemEvents_10_Event)mailItem).Close += new Outlook.ItemEvents_10_CloseEventHandler( MailItem_Close); } } void MailItem_Read() { MessageBox.Show("Read"); } void MailItem_Open(ref bool cancel) { MessageBox.Show("Open"); } void MailItem_Write(ref bool cancel) { MessageBox.Show("Write"); } void MailItem_Close(ref bool cancel) { MessageBox.Show("Close"); } } }
E-mail Events
Outlook raises several e-mail-related events when new mail is received, when an Outlook item is sent by e-mail, or when an Outlook item is forwarded or replied to:
- Application.NewMail is raised when new items are received in the Inbox, including mail messages, meeting requests, and task requests.
- Application.NewMailEx is raised when new items are received in the Inbox, including mail messages, meeting requests, and task requests. An enTRyIDs parameter is passed as a string. The entryIDs parameter contains a comma-delimited list of the entry IDs of the Outlook items that were received. An entry ID uniquely identifies an Outlook item.
- Application.ItemSend is raised when an Outlook item is sentfor example, when the user has an Outlook item open in an Inspector window and clicks the Send button. An item parameter is passed as an object that contains the Outlook item being sent. Outlook also passes by reference a bool cancel parameter. The cancel parameter can be set to TRue by your event handler to prevent the item from being sent.
- Item.Send is raised when an Outlook item is sentfor example, when the user has an Outlook item open in an Inspector window and clicks the Send button. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to TRue by your event handler to prevent the item from being sent.
- Item.Reply is raised when an Outlook item is replied to. A response parameter is passed as an object and represents the Outlook item that was created as a response to the original Outlook item. Outlook also passes by reference a bool cancel parameter. The cancel parameter can be set to TRue by your event handler to prevent the item from being replied to.
- Item.ReplyAll is raised when an Outlook item is replied to using the Reply All button. A response parameter is passed as an object and represents the Outlook item that was created as a response to the original Outlook item. Outlook also passes by reference a bool cancel parameter. The cancel parameter can be set to true by your event handler to prevent the item from being replied to.
- Item.Forward is raised when an Outlook item is forwarded. A response parameter is passed as an object and represents the Outlook item that was created to forward the original Outlook item. Outlook also passes by reference a bool cancel parameter. The cancel parameter can be set to TRue by your event handler to prevent the item from being forwarded.
Listing 10-8 shows a VSTO Outlook add-in that handles these events.
Listing 10-8. A VSTO Add-In That Handles E-mail Events
namespace OutlookAddin1 { public partial class ThisApplication { Outlook.MailItem mailItem; private void ThisApplication_Startup(object sender, EventArgs e) { this.NewMail += new Outlook.ApplicationEvents_11_NewMailEventHandler( ThisApplication_NewMail); this.NewMailEx += new Outlook.ApplicationEvents_11_NewMailExEventHandler( ThisApplication_NewMailEx); this.ItemSend += new Outlook.ApplicationEvents_11_ItemSendEventHandler( ThisApplication_ItemSend); Outlook.NameSpace ns = this.Session; Outlook.MAPIFolder inbox = ns.GetDefaultFolder( Outlook.OlDefaultFolders.olFolderInbox); foreach (object o in inbox.Items) { mailItem = o as Outlook.MailItem; if (mailItem != null) { break; } } if (mailItem == null) { MessageBox.Show("Couldn't find a mail item."); } else { MessageBox.Show(String.Format( "Connected to the mail item {0}.", mailItem.Subject)); ((Outlook.ItemEvents_10_Event)mailItem).Send += new Outlook.ItemEvents_10_SendEventHandler( MailItem_Send); ((Outlook.ItemEvents_10_Event)mailItem).Reply += new Outlook.ItemEvents_10_ReplyEventHandler( MailItem_Reply); ((Outlook.ItemEvents_10_Event)mailItem).ReplyAll += new Outlook.ItemEvents_10_ReplyAllEventHandler( MailItem_ReplyAll); ((Outlook.ItemEvents_10_Event)mailItem).Forward += new Outlook.ItemEvents_10_ForwardEventHandler( MailItem_Forward); } } void GenerateItemMessage(object item, string operation) { Outlook.MailItem mi = item as Outlook.MailItem; if (mi != null) { MessageBox.Show(String.Format( "MailItem {0} will be {0].", mi.Subject, operation)); } else { MessageBox.Show(String.Format( "An Outlook item will be {0}.", Operation)); } } void ThisApplication_NewMail() { MessageBox.Show("New mail was received"); } void ThisApplication_NewMailEx(string entryIDCollection) { MessageBox.Show(String.Format( "NewMailEx: {0}.", entryIDCollection)); } void ThisApplication_ItemSend(object item, ref bool cancel) { GenerateItemMessage(item, "sent"); } void MailItem_Send(ref bool cancel) { MessageBox.Show("MailItem Send"); } void MailItem_Reply(object response, ref bool cancel) { GenerateItemMessage(response, "generated as a reply"); } void MailItem_ReplyAll(object response, ref bool cancel) { GenerateItemMessage(response, "generated as a reply to all"); } void MailItem_Forward(object forward, ref bool cancel) { GenerateItemMessage(forward, "generated as a forward"); } } }
Attachment Events
Outlook raises events when attachments are added to an Outlook item and when attachments associated with an Outlook item are read or saved:
- Item.AttachmentAdd is raised when an attachment is added to an Outlook item. Outlook passes an attachment parameter that represents the attachment that was added.
- Item.AttachmentRead is raised when an attachment attached to an Outlook item is opened for reading. Outlook passes an attachment parameter that represents the attachment that was read.
- Item.BeforeAttachmentSave is raised when an attachment attached to an Outlook item is about to be saved. Outlook passes an attachment parameter that represents the attachment that is about to be saved. Outlook also passes by reference a bool cancel parameter. The cancel parameter can be set to true by your event handler to prevent the attachment from being saved.
Custom Action Events
Outlook enables you to associate custom actions with an Outlook item. A custom action is given a name and some default behaviorfor example, you can create a custom action whose default behavior is to act on the original item or to create a new reply to the existing item. You can also set whether the action is shown as a button or a menu command or both. When the custom action is invoked from the menu or toolbar, the CustomAction event is raised on the associated Outlook item.
Figure 10-2 shows a custom action that has been associated with an Outlook mail item called My custom action. Outlook displays the custom action in the Action menu when an Inspector window is opened on the mail item. It also displays the custom action as a toolbar button.
- Item.CustomAction is raised when a custom action associated with an Outlook item is invoked. Outlook passes an action parameter as an object that represents the custom action that was invoked. This parameter can be cast to an Action object. Outlook passes a response parameter as an object that represents the Outlook item created because of the custom action. Outlook also passes by reference a bool cancel parameter. The cancel parameter can be set to true by your event handler to prevent the custom action from being invoked.
Figure 10-2. A custom action called My custom action.
Listing 10-9 shows a VSTO Outlook add-in that creates a custom action called My custom action. The CustomAction event is handled to set the subject when the custom action is invoked.
Listing 10-9. A VSTO Add-In That Creates a Custom Action and Handles a Custom Action Event
namespace OutlookAddin1 { public partial class ThisApplication { Outlook.MailItem mailItem; private void ThisApplication_Startup(object sender, EventArgs e) { Outlook.NameSpace ns = this.Session; Outlook.MAPIFolder inbox = ns.GetDefaultFolder( Outlook.OlDefaultFolders.olFolderInbox); foreach (object o in inbox.Items) { mailItem = o as Outlook.MailItem; if (mailItem != null) { break; } } if (mailItem == null) { MessageBox.Show("Couldn't find a mail item."); } else { MessageBox.Show(String.Format( "Connected to the mail item {0}.", mailItem.Subject)); mailItem.CustomAction += new Outlook.ItemEvents_10_CustomActionEventHandler( MailItem_CustomAction); Outlook.Action action = mailItem.Actions.Add(); action.Name = "My custom action"; action.ShowOn = Outlook.OlActionShowOn.olMenuAndToolbar; action.ReplyStyle = Outlook.OlActionReplyStyle.olLinkOriginalItem; } } void MailItem_CustomAction(object action, object response, ref bool cancel) { Outlook.Action action = (Outlook.Action)action; Outlook.MailItem mailItem = (Outlook.MailItem)response; if (action.Name == "My custom action") { mailItem.Subject = "Created by my custom action"; } } } }