Programming MicrosoftВ® OutlookВ® and Microsoft Exchange 2003, Third Edition (Pro-Developer)
The Outlook object model has changed in some major ways to support new functionality available through the Outlook 2003 user interface. The following sections examine these changes to the object model.
Application Object
The Application object has one new event called NewMailEx . One major complaint about the original NewMail event was that the event does not pass the items that are newly received. Instead, you have to troll the Inbox to figure out what items have been received since the last time your application was notified. To address this concern, the NewMailEx event passes a comma-delimited string of the EntryIDs for the new items received in your Inbox. This event doesn't work if you're working in the classic offline mode of Outlook or if Outlook is not running. When you restart Outlook, any new mail received after the startup of Outlook will fire the event, but any mail received while Outlook was closed will not fire it. If you need to capture every item coming into a mailbox, even if Outlook is closed, you should look at transport event sinks or store event sinks in Exchange Server. The following code shows how to use this new event:
Private Sub oApplication_NewMailEx(ByVal EntryIDCollection As String) 'Try to retrieve the list of items that were just received 'The list is a comma delimited collection of short-term EntryIDs Set oNamespace = oApplication.GetNamespace("MAPI") arrItems = Split(EntryIDCollection, ",") For i = LBound(arrItems) To UBound(arrItems) Set oItem = oNamespace.GetItemFromID(arrItems(i)) MsgBox oItem.Subject Set oItem = Nothing Next End Sub
Conflicts Collection, Conflict Item, and AutoResolvedWinner
Outlook 2003 features automatic resolution of conflicts using algorithms contained in Outlook. Outlook provides a Conflicts collection for every item type, such as AppointmentItem or MailItem , so you can determine whether an item is in conflict and what alternatives there are to the item. From the Conflicts collection, you can retrieve the Conflict item, if one exists. Conflict items are the losers of the automatic resolution in Outlook. The other way you can figure out the winner of a conflict in Outlook is to use the AutoResolvedWinner property, which is available on every item. This Boolean property is True if the item is the winner, False if the item is not the winner. Note that you cannot use AutoResolvedWinner in a Find or Restrict operation, nor can you use SetColumns with it because this property is a computed property. Instead, you have to manually scan a folder to determine whether any items have AutoResolvedWinner set to True .
You can use the Item property on the Conflict item to retrieve the item represented by the Conflict object. If you look at the Type property on the Conflict item, you will get the type of the item, not a conflict type. For example, in a conflict between appointment items, if you are looking at the loser of the conflict and you ask for the type, Appointment will be returned.
To replace a winner with an alternative item, you must delete the original item and move the other item to the folder where you want it to be. You must perform this operation programmatically because there is a hidden folder named Conflicts that contains all alternative versions of an item that is in conflict.
The following code shows how to use the new conflict features of the Outlook object model:
Set oApplication = GetObject("", "Outlook.Application") Set oNamespace = oApplication.GetNamespace("MAPI") Dim oCalendar As Outlook.MAPIFolder 'One way to find all conflicts in a folder 'is to scan the entire folder and look 'at the Conflicts collection Set oCalendar = oNamespace.GetDefaultFolder(olFolderCalendar) For Each oItem In oCalendar.Items Set oConflicts = oItem.Conflicts If oConflicts.Count > 0 Then MsgBox oItem.Subject & " has a conflict!" MsgBox "Displaying original item" oItem.Display i = 1 For Each oConflict In oConflicts 'Display each version MsgBox "Display conflict item #" & i oConflict.Item.Display i = i + 1 Next End If Next 'Another way is to search for True in the AutoResolvedWinner 'property For Each oItem In oCalendar.Items If oItem.AutoResolvedWinner = True Then MsgBox oItem.Subject & " was the autoresolved winner!" End If Next End Sub
MeetingWorkspaceURL Property
To support the Windows SharePoint Services (WSS) integration features in Outlook 2003, the AppointmentItem and MeetingItem objects have a new read-only string property named MeetingWorkspaceURL , which corresponds to the URL of a shared WSS Web site used for planning and tracking the results of the meeting. Please note that you cannot use the Find, Restrict, or SetColumns methods with this property. The following code finds all items in a calendar that have a meeting workspace associated with them:
Set oApplication = GetObject("", "Outlook.Application") Set oNamespace = oApplication.GetNamespace("MAPI") Dim oCalendar As Outlook.MAPIFolder 'MeetingWorkspaceURL code Set oCalendar = oNamespace.GetDefaultFolder(olFolderCalendar) For Each oItem In oCalendar.Items If oItem.MeetingWorkspaceURL <> "" Then MsgBox oItem.Subject & " has a meeting workspace at: " & _ oItem.MeetingWorkspaceURL End If Next
ContactItem Object Changes
To support the addition of pictures to contacts, the ContactItem object has two new methods and a new property. The AddPicture method takes the path to a picture file to add to the contact. HasPicture is a Boolean property that returns True if the contact includes a picture or False if it does not. The RemovePicture method removes the picture from the contact. You must save the contact after making any changes to it, or else your changes will be lost. The following code demonstrates these methods and the property. (To test this code, be sure to update the names and picture path to values that are valid on your system.)
Set oApplication = GetObject("", "Outlook.Application") Set oNamespace = oApplication.GetNamespace("MAPI") 'ContactItem Code Dim oContacts As Outlook.MAPIFolder Set oContacts = oNamespace.GetDefaultFolder(olFolderContacts) 'Create a new contact Dim oContact As Outlook.ContactItem Set oContact = oContacts.Items.Add oContact.FirstName = "Tom" oContact.LastName = "Rizzo" 'Add a picture 'This supports local paths and network paths oContact.AddPicture "\thomriznt52\f$\checkoutui.bmp" MsgBox oContact.HasPicture 'Save the item oContact.Save For Each oItem In oContacts.Items If oItem.HasPicture = True Then MsgBox oItem.Subject & " has a picture!" 'Remove the picture oItem.RemovePicture oItem.Save End If Next
Explorer Object
With WSS integration, you can select WSS folders to add to your Outlook user interface. You can also select multiple calendar folders to display in the Outlook user interface. To support these capabilities, the Explorer object model has three additions. The first is the Deselectfolder method, which takes a MAPIFolder object. The MAPIFolder object should correspond to the WSS folder linked to Outlook or to an Outlook folder that is linked to the user interface, such as a calendar folder. You can usually find the linked SharePoint folders in the SharePoint Folders hierarchy in your folder list. This method will deselect the folder and remove it from the user interface.
The next addition is the IsFolderSelected method, which takes a MAPIFolder object and returns a Boolean value indicating whether the folder is selected in the user interface. The final addition is the SelectFolder method, which takes a MAPIFolder object and displays and selects the folder in the user interface. Here's some sample code:
'Explorer Code 'Get the WSS PST file in Outlook Dim oFolder As Outlook.MAPIFolder Dim oEventCalendar As Outlook.MAPIFolder Dim oExplorer As Outlook.Explorer Set oExplorer = oApplication.ActiveExplorer 'Get the Event Calendar folder Set oEventCalendar = oNamespace.Folders("Mailbox - Thomas " & _ "Rizzo").Folders("Event Calendar") If oExplorer.IsFolderSelected(oEventCalendar) Then 'Deselect it oExplorer.DeselectFolder oEventCalendar Else 'Select it oExplorer.SelectFolder oEventCalendar End If Set oFolder = oNamespace.Folders("Mailbox - Thomas Rizzo") For Each oFolder In oFolder.Folders 'See if it's selected If oExplorer.IsFolderSelected(oFolder) Then MsgBox oFolder.Name & " is selected in the UI!" End If Next
MailItem Object
To support some of the new features in Outlook, the MailItem object has been updated with some new properties. The first property is EnableSharedAttachments , which is Boolean. If you set this property to True , the Attachment Options pane (shown in Figure 6-9) will appear when a user attempts to add an attachment to a mail item. You can put attachments from Outlook into a shared workspace so all recipients can collaborate on the documents. If you specify False , this pane will not appear.
The next property is the FlagIcon property. This property corresponds to the new quick-flag capabilities of Outlook, which let you specify a red, blue, green, or other color flag on your items.
To support the new IP fax features in Office, Outlook has two new fax properties. The IsIPFax property returns a Boolean specifying whether the item is an IPFax. The HasCoverSheet property returns a Boolean that specifies whether the fax has a cover sheet; if it does, the message body will display the cover sheet.
To support digital rights management (DRM) features, the MailItem object has some a new property called Permission . This property allows you to set the security on an Outlook item before sending it. The possible values are olDoNotForward , olUnrestricted , and olTemplate . The first one is self-explanatory. The second one, olUnrestricted , is the default and means that no restrictions are on the message. The final one, olTemplate , cannot be set as a value. This is the value when the received DRM protected message has been protected with an admin-defined template.
The final two properties solve one of the biggest pains in Outlook, which is retrieving the e-mail address and e-mail type of a sender without having to use CDO. Outlook now has the SenderEmailAddress string property and the SenderEmailType string property, which you can use to quickly retrieve address information about the sender of an e-mail message. These properties are also supported on the MeetingItem and PostItem objects.
The following code shows these additions in use in Outlook:
Dim oInbox As Outlook.MAPIFolder Set oInbox = oNamespace.GetDefaultFolder(olFolderInbox) Dim oMailItem As Outlook.MailItem Set oMailItem = oInbox.Items.GetFirst 'Return the sender properties MsgBox oMailItem.SenderEmailAddress & " type: " & _ oMailItem.SenderEmailType 'Create a new mailitem and disable shared attachments 'And add a flag icon Dim oNewItem As Outlook.MailItem Set oNewItem = oApplication.CreateItem(olMailItem) 'Disable shared attachments oNewItem.EnableSharedAttachments = False 'Add a flag icon oNewItem.FlagIcon = olOrangeFlagIcon 'Display it and add an attachment manually oNewItem.Display
MAPIFolder Object
To support WSS integration and the ability to show only unread item counts for a folder, the MAPIFolder object has two new properties. The first is IsSharePointFolder , a Boolean that is set to True if the folder is linked to a SharePoint folder and is set to False if the folder is not. The second property is ShowItemCount , which takes one of two values: olShowTotalItemCount (2) or olShowUnreadItemCount (1) . The following code illustrates the use of these properties:
'MAPIFolder Code for WSS Integration Dim oMAPIFolder As Outlook.MAPIFolder Set oMAPIFolder = oNamespace.GetDefaultFolder(olFolderInbox) MsgBox oMAPIFolder.ShowItemCount oMAPIFolder.ShowItemCount = olShowTotalItemCount 'Find all our SharePoint folders 'These are usually stored under the SharePoint Folders hierarchy Dim oFolder As Outlook.MAPIFolder Set oFolder = oNamespace.Folders("SharePoint Folders") For Each oFolder In oFolder.Folders If oFolder.IsSharePointFolder Then MsgBox oFolder.Name & " is a SharePoint folder." End If Next
MeetingItem Object
The MeetingItem object also supports the additions we've looked at for other objects. These include the FlagIcon property, the MeetingWorkspaceURL property, the SenderEmailAddress property, and the SenderType property.
Namespace Object
The Namespace object has a new method and a new property. The method, AddStoreEx , is an enhanced version of the AddStore method. It takes the path to a .pst file to add to Outlook; if that .pst file does not exist, Outlook creates it. The second new parameter to this method is the store type, which can be olStoreANSI (3) , olStoreDefault (1) , or olStoreUnicode (2) . Because Outlook now supports Unicode stores, this parameter had to be added to the method.
The new property of the Namespace object is the Exchange ConnectionMode property. (If you are running the beta of Outlook, you will see this as an older property called ConnectionMode . This property corresponds to Outlook's new online, low-bandwidth, cached, and offline modes. It returns the mode that Outlook is currently in, which can be olNoExchange (0) , olOffline (100) , olDisconnected (200) , olConnectedHeaders (300), olConnected (400), or olOnline (500) . The modes require some explaining. The olNoExchange mode is obvious ”there is no Exchange Server. The olOffline mode means classic offline mode or the new cached Exchange mode. The olDisconnected mode is when you are using cached mode with a disconnected connection to your Exchange Server. olConnectedHeaders is returned if you are using cached Exchange mode but are in the Dialup/Slow Connection mode. The olConnected mode is when you are using cached Exchange mode in the LAN/Fast Connection mode. The olOnline mode is returned if you are using the classic online mode.
The following code shows how to use these additions to the Namespace object:
'Namespace Code strText = "" Select Case oNamespace.ConnectionMode Case olNoExchange: strText = "No Exchange Server!" Case olOffline: strText = "Offline" Case olDisconnected: strText = "Disconnected" Case olConnectedHeaders: strText = "Connected Headers" Case olConnected: strText = "Connected via LAN" Case olOnline: strText = "Online" End Select MsgBox "Current mode is " & oNamespace.ConnectionMode & " - " & strText 'Add a new unicode store oNamespace.AddStoreEx "c:\mynewstore.pst", olStoreUnicode
One other change in the Namespace object is the addition of the olFolderJunk constant to the GetDefaultFolder and GetSharedDefaultFolder methods to support the new Junk e-mail folder.
PostItem Object
The PostItem object has two new properties, SenderEmailAddress and SenderEmailType .
Search Object
To support saved search folders, the Search object has a new Save method. This method takes a single parameter, which is the name of the search folder you want to create that contains the current search in the Search object. The following code creates a new search and saves the search as a search folder:
Outlook Bar Changes
The object model of the Outlook Bar has not changed, but be aware that the object model works only with the Shortcuts portion of the Outlook Bar user interface. Therefore, you cannot change any part of the Outlook Bar user interface other than the shortcuts section. Also, if you have any code that leverages the Outlook bar object model, you should recheck it to be sure it works in Outlook 2003.