One of the new features of Microsoft Exchange is the creation of the OLE Messaging library. This set of OLE objects, properties, and methods allows any VBA-compliant development tool to gain access to MAPI services and incorporate them into desktop applications. This chapter shows you how the OLE Messaging library works and how you can use the OLE objects to create MAPI-enabled programs.
This chapter provides an overview of all the OLE Messaging library objects and gives examples of their use. You'll learn about the following objects:
You'll also learn how these objects interact with each other and how to use them to perform several advanced MAPI tasks, including:
When you complete this chapter, you'll understand the OLE Messaging library objects and how to use them to build MAPI-compliant e-mail applications with any VBA-compatible development tool.
The Session object of the OLE Messaging library is the top-most object in the hierarchy. You must create an instance of a MAPI Session object before you can gain access to any other aspects of the MAPI system. The Session object has several properties (including subordinate objects) and a handful of methods that you can invoke.
Table 8.1 shows the Session
Object Methods along with a list of parameters and short descriptions.
Methods | Parameters | Description |
AddressBook | (opt) title as String,
(opt) oneAddress as Boolean, (opt) forceResolution as Boolean, (opt) recipLists as long, (opt) toLabel as String, (opt) ccLabel as String, (opt) bccLabel as String, (opt) parentWindow as Long | Access to session addressbook. |
GetAddressEntry | entryID as String | Direct access to a single entry in the address book. |
GetInfoStore | storeID as String | Direct access to one of the Message storage objects. |
GetFolder | folderID as String,
storeID as String | Direct access to a single folder object in the folders collection. |
GetMessage | messageID as String,
storeID as String | Direct access to a single message in the Messages collection. |
Logoff | (none) | End the current MAPI Session. |
Logon | (opt) profileName as String,
(opt) profilePassword as String, (opt) showDialog as Boolean, (opt) newSession as Boolean, (opt) parentWindow as Long | Start new MAPI Session. |
The most used of these methods are the Logon and Logoff methods. You use these to start and end MAPI sessions. You will also use the AddressBook and GetInfoStore methods frequently in your programs.
If you have not done so yet, load Visual Basic 4.0 and start a new project. Place a single button on the form. Set its index property to 0 and its caption to MAPI &Start. Copy and paste a second command button onto the form and set its caption property to MAPI &End. Now add the code in Listing 8.1 to the Command1_Click event of the buttons.
Listing 8.1. Adding Code to the Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
End Select
'
End Sub
The code in Listing 8.1 calls two subroutines-MAPIStart and MAPIEnd. They each use a form-level variable called objSession. Add this variable to the general declarations section of the form.
Option Explicit
'
Dim objSession As Object ' for mapi session
Now create a new subroutine called MAPIStart and add the code shown in Listing 8.2. This routine initializes the session object and calls the MAPI logon dialog box.
Listing 8.2. Adding the MAPIStart routine.
Public Sub MAPIStart()
'
' start a mapi session
'
On Error GoTo MAPIStartErr
'
Set objSession = CreateObject("MAPI.Session")
objSession.logon
Exit Sub
'
MAPIStartErr:
MsgBox Error$, vbCritical, "MAPIStartErr [" & CStr(Err) & "]"
'
End Sub
It is important that you formally end each MAPI session you begin.
This will ensure that you do not have any stray sessions running
in the background.
Warning |
By default, the MAPI Logon method will attempt to connect you to the first available active session currently running on your workstation. For example, if you have started a MAPI session with your e-mail client and you then run this sample code, MAPI will attach this program to the same MAPI session started by the MAPI client. This could give you unexpected results. That is another reason why you should always close your MAPI sessions when you are exiting your programs. |
Now add a new subroutine to the project called MAPIEnd and add the code shown in Listing 8.3. Notice that this routine sets the objSession variable to Nothing. This is done to clear Visual Basic's memory storage and conserve RAM space.
Listing 8.3. Adding the MAPIEnd routine.
Public Sub MAPIEnd()
'
' end the current session
'
On Error Resume Next
'
objSession.logoff
Set objSession = Nothing
'
End Sub
Save the form as OML.FRM and the project as OML.VBP. You can now run the project and log into and out of a MAPI session. You won't see much, but it works!
You will often need to give your users access to the MAPI Address Book. This is achieved with the AddressBook method of the Session object. Access to the address book gives users the ability to look up names in the address book; add, edit, and delete names from the book; and select one or more addresses as recipients of a message.
Add another command button to the array (Edit | Copy, Edit | Paste) and modify the Command1_Click event to match the code in Listing 8.4. This will call up the MAPI address book.
Listing 8.4. Modifying the Command1_Click event to call the address book.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
End Select
'
End Sub
Now add the MAPIAddrBook routine to the form and enter the code in Listing 8.5.
Listing 8.5. Adding the MAPIAddrBook routine.
Public Sub MAPIAddrBook()
'
' call the address book
'
On Error Resume Next
'
objSession.AddressBook
'
End Sub
Save and run the project. After clicking the MAPI Start button, press the Address Book button. Your screen should look like the one in Figure 8.1.
Figure 8.1 : Displaying the address book.
You can set several parameters when you call the Address Book method. For example, you can set the title of the address book using the Title property. You can also control the number and caption of the recipient selection buttons that appear on the address book. You can even set the address book dialog so that the user can review the addresses but cannot select one.
Listing 8.6 shows you how to modify the code in the MAPIAddrBook routine to set the title and remove all recipient selection buttons.
Listing 8.6. Controlling the appearance of the MAPI address book.
Public Sub MAPIAddrBook()
'
' call the address book
'
On Error Resume Next
'
objSession.AddressBook recipLists:=0, Title:="For Viewing Only"
'
End Sub
When you run the project, your address book will look something like the one in Figure 8.2.
Figure 8.2 : Modified Address Book dialog box.
You can also control the Logon method behavior by passing selected parameters. The most common use for this is automatically logging a user into MAPI without the use of the Logon dialog box. To do this you need to pass the user profile and password and set the ShowDialog flag to false.
Listing 8.7 shows you how to modify the MAPIStart routine to perform an automatic logon. You should change the ProfileName parameter to match your personal Microsoft Exchange logon.
Listing 8.8. Creating an automatic MAPI session logon.
Public Sub MAPIStart()
'
' start a mapi session
'
On Error GoTo MAPIStartErr
'
Set objSession = CreateObject("MAPI.Session")
objSession.logon ProfileName:="MCA", ShowDialog:=False
Exit Sub
'
MAPIStartErr:
MsgBox Error$, vbCritical, "MAPIStartErr [" & CStr(Err) & "]"
'
End Sub
Now let's look at some of the Session
object properties. After reviewing the properties, you can add
another button to the form to display the properties of your MAPI
session. Table 8.2 has a list of the Session
object properties, their type, and a short description.
Properties | Type | Description |
Application | String | Name of the library. Always set to OLE/Messaging. |
Class | Long | Internal identifying code for all MAPI objects. Always set to 0 for Session objects. |
CurrentUser | AddressEntry object | Address object of current user (see "Address Objects" later in this chapter). |
Inbox | Folder object | Folder object where all new unread messages are placed (see "Folder Objects" later in this chapter). |
InfoStores | InfoStores object | InfoStores object collection for this session (see "InfoStore Objects" later in this chapter). |
Name | String | Session name. Always set to the current profile name on Microsoft Exchange system. |
OperatingSystem | String | Name of operating system in use. |
Outbox | Folder object | Folder object where all outgoing messages are placed (see "Folder Objects" later in this chapter). |
Version | String | Version number of OLE Messaging library. Current version is 1.00. |
The Session object has several properties, many of them objects themselves. Using these object properties allows you to gain access to more complex data than standard strings or numbers. You'll inspect the object properties later in the chapter.
Now add another button to the control array (use Edit | Copy, Edit | Paste), set its Caption to "MapiProps" and modify the code in the Command1_Click event to look like the code in Listing 8.9.
Listing 8.9. Updated Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
End Select
'
End Sub
Now create a new subroutine called SessionProps and enter the code that appears in Listing 8.10. This routine creates a message box that displays several of the Session object's properties.
Listing 8.10. Adding the SessionProps code.
Public Sub SessionProps()
'
' get basic session properties
'
On Error GoTo SessionPropsErr
'
Dim cMsg As String
'
cMsg = "Application: " & objSession.Application & Chr(13)
cMsg = cMsg & "Operating System: " & objSession.OperatingSystem & Chr(13)
cMsg = cMsg & "Session Name: " & objSession.Name & Chr(13)
cMsg = cMsg & "Version: " & objSession.Version & Chr(13)
cMsg = cMsg & "Object Class: " & CStr(objSession.Class)
'
MsgBox cMsg
'
Exit Sub
'
SessionPropsErr:
MsgBox Error$, vbCritical, "SessionPropsErr [" & CStr(Err) & "]"
'
End Sub
Save the project again and run it. After clicking on the MAPI Start button, click on the MapiProps button. Your screen should look like the one in Figure 8.3.
Figure 8.3 : Displaying the Session properties.
Now it's time to start inspecting the subordinate objects in the OLE Messaging library.
The first-level subordinate object of the Session object is the InfoStore object. Each InfoStore object represents a separate message store. The MAPI model allows clients to access more than one message storage system at the same time. For example, the Microsoft Exchange shared folders are a separate message store (represented by a separate InfoStore object). The Microsoft Exchange Personal Folders are another separate message store. Users can have any number of message stores connected to their MAPI client.
The InfoStores collection object is an OLE Messaging library object that allows you to view all the connected message stores for the logged-in user. You can use the InfoStores object to locate a particular message store and then access that message store using the InfoStore object.
Note |
Be sure not to confuse the InfoStore object with the InfoStores object. The InfoStore object is the OLE Messaging library object that you use to gain access to the contents of a single message store. The InfoStores object is the OLE Messaging library object you use to gain access to the collection of message stores. In Microsoft OLE naming rules, collection objects are plural (InfoStores) and single objects are not (InfoStore). |
The InfoStores collection
has only a few properties and no methods at all. You cannot add,
modify, or delete InfoStore
objects using the OLE Messaging library interface. Table 8.3 shows
the InfoStores properties
with their type and a short description.
Property name | Type | Description |
Application | String | Name of the library. Always set to OLE/Messaging. |
Class | Long | Internal identifying code for all MAPI objects. Always set to 17 for InfoStores objects. |
Count | Long | The total number of InfoStore objects in the collection. The count starts at 1. |
Item | InfoStore object | Allows access to one of the member InfoStore objects. The Item property accepts an Index value between 1 and the value of Count. |
To test the InfoStores object, add another button to the control array on the form with the caption of InfoStoreColl and modify the Command1_Click event as shown in Listing 8.11.
Listing 8.11. Updated Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
End Select
'
End Sub
Next you'll need to add two new form-level variables to the general declaration section of the form. Your general declaration section should now look like this:
Option Explicit
'
Dim objSession As Object ' for mapi session
Dim objInfoStoreColl As Object ' collection of stores
Dim objInfoStore As Object ' single info store
Now add the SessionInfoStoreColl routine shown in Listing 8.12. This routine gets the InfoStores properties and displays the names of all the message stores in the collection.
Listing 8.12. Adding the SessionInfoStoreColl routine.
Public Sub SessionInfoStoreColl()
'
' show list of available infostores
'
Dim cMsg As String
Dim nCount As Integer
Dim x As Integer
Dim cStoresList As String
'
Set objInfoStoreColl = objSession.InfoStores
cMsg = "Application: " & objInfoStoreColl.Application & Chr(13)
cMsg = cMsg & "Class: " & CStr(objInfoStoreColl.Class) & Chr(13)
cMsg = cMsg & "Count: " & CStr(objInfoStoreColl.Count) & Chr(13)
'
nCount = objSession.InfoStores.Count
cStoresList = "List:" & Chr(13)
For x = 1 To nCount
cStoresList = cStoresList & " " & objSession.InfoStores.Item(x).Name
cStoresList = cStoresList & Chr(13)
Next x
'
MsgBox cMsg & Chr(13) & cStoresList, vbInformation, "InfoStores Collection ÂObject"
'
End Sub
Warning |
The OLE Messaging library does not require message stores to have unique names. If you are using the InfoStores collection object to locate a particular message store, you must be sure that there is not more than one store with that name in the collection! InfoStore objects are assigned a unique unchanging ID value. Once you know the ID value of an InfoStore object, you can locate it using the GetInfoStore method of the Session object. |
Save and run this project. After logging in, press the InfoStoreColl button. Your screen should look similar to the one in Figure 8.4.
Figure 8.4 : Viewing the InfoStores object properties.
Now that you know how to review the InfoStore collection, it's time to learn more about the individual InfoStore objects.
The InfoStore object contains
all the folders and messages defined for a single message store.
InfoStore objects have several
properties and no methods. You cannot use the OLE Messaging library
to add, modify, or delete InfoStore
objects. Table 8.4 shows the important InfoStore
object properties, their types, and their descriptions.
Property name | Type | Description |
Application | String | Name of the library. Always set to OLE/Messaging. |
Class | Long | Internal identifying code for all MAPI objects. Always set to 1 for InfoStore objects. |
ID | String | A unique value that never changes. It is assigned by MAPI when the store is created. |
Index | Long | The count position of the InfoStore in the InfoStores collection. This can be used with the Item property of the InfoStores object. |
Name | String | The display name of the message store. |
ProviderName | String | The name of the message store vendor or programmer. |
RootFolder | Folder object | The starting folder of the message store. |
Now add some code to view the properties of an InfoStore object. First, add another command button to the control array and set its caption to InfoStore. Then modify the Command1_Click routine so that it matches the one in Listing 8.13.
Listing 8.13. Updated Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
End Select
'
End Sub
Now add the InfoStoreProps subroutine and enter the code shown in Listing 8.14.
Listing 8.14. Adding the InfoStoreProps routine.
Public Sub InfoStoreProps()
'
' show the infostore object properties
'
Dim cMsg As String
'
Set objInfoStoreColl = objSession.InfoStores
For Each objInfoStore In objInfoStoreColl
cMsg = "Application: " & objInfoStore.Application & Chr(13)
cMsg = cMsg & "Class: " & CStr(objInfoStore.Class) & Chr(13)
cMsg = cMsg & "ID: " & objInfoStore.ID & Chr(13)
cMsg = cMsg & "Name: " & objInfoStore.Name & Chr(13)
cMsg = cMsg & "ProviderName: " & objInfoStore.ProviderName & Chr(13)
cMsg = cMsg & "RootFolder: " & objInfoStore.RootFolder.Name
'
MsgBox cMsg, vbInformation, "InfoStore Object Properties"
Next
'
End Sub
Note that the InfoStore object is part of what is called a small collection. OLE object collections that are considered to have a limited number of members are called small collections. All small collection objects have an Index property and a Count property. Most of them also have an Item property. Small collection objects support the use of the For Each...Next programming construct.
Save and run the project. After clicking the InfoStore button, you should see a series of dialog boxes showing the properties of each message store available to your client (see Figure 8.5).
Figure 8.5 : Viewing the InfoStore properties.
The next object to review is the Folder object and the Folders collection object.
One of the first level objects below the InfoStore object is the Folder object. The Folder object can hold messages and other folders. Each InfoStore object also has a Folders collection object that contains a list of all the Folder objects in the message store.
There is no limit to the number of messages or folders a Folder object can have. For this reason it is called a large collection object. large collection objects do not have an Index property or a Count property. The only way you can locate all the folders in a message store is to "walk through" the store using a set of methods to get each item. All large collection objects support the use of the GetFirst, GetNext, GetPrevious, and GetLast methods to provide a way to navigate through the collection. You'll use these methods in the next few examples.
The Folders collection object
has only a few properties and methods. Table 8.5 shows the important
Folders collection object
properties and Table 8.6 shows the Folders
collection object methods.
Property name | Type | Description |
Application | String | Name of the library. Always set to OLE/Messaging. |
Class | Long | Internal identifying code for all MAPI objects. Always set to 18 for Folders objects. |
Method name | Parameters | Description |
GetFirst | (none) | Points to the first Folder object in the collection. |
GetLast | (none) | Points to the last Folder object in the collection. |
GetNext | (none) | Points to the next Folder object in the collection. |
GetPrevious | (none) | Points to the previous Folder object in the collection. |
To test the Folders object, add two new variables to the general declaration area of the form. Your form-level variable list should now look like this:
Option Explicit
'
Dim objSession As Object ' for mapi session
Dim objInfoStoreColl As Object ' collection of stores
Dim objInfoStore As Object ' single info store
Dim objFolderColl As Object ' collection of folders
Dim objFolder As Object ' single folder
Now add another command button to the control array and set its Caption property to FolderColl. Then modify the Command1_Click event so that it matches the code in Listing 8.15.
Listing 8.15. Updated Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
End Select
'
End Sub
Now add the new subroutine called FoldersColl and enter the code from Listing 8.16.
Listing 8.16. Adding the FoldersColl routine.
Public Sub FoldersColl()
'
' show the folders collection
'
Dim cMsg As String
'
Set objFolderColl = objSession.InfoStores.Item(1).RootFolder.Folders
'
cMsg = "Application: " & objFolderColl.Application & Chr(13)
cMsg = cMsg & "Class: " & CStr(objFolderColl.Class) & Chr(13)
'
cMsg = cMsg & Chr(13) & "Folders:" & Chr(13)
Set objFolder = objFolderColl.GetFirst
Do Until objFolder Is Nothing
cMsg = cMsg & objFolder.Name & Chr(13)
Set objFolder = objFolderColl.GetNext
Loop
'
MsgBox cMsg, vbInformation, "Folders Collection Object"
'
End Sub
The FoldersColl routine shows the application and class property of the object and then lists all the folder names in the collection. Note that you cannot determine the folder hierarchy from the list returned by the Get methods. The Get methods traverse the folder collection in the order the folders were created, not in the order they are displayed or arranged within the MAPI client.
Save and run the program. Clicking the FoldersColl button should give you a display similar to the one in Figure 8.6.
Figure 8.6 : Viewing the Floders collection object properties.
The Folder object has several
properties and one method. The OLE Messaging library allows you
to modify the Name property
of a Folder object, but you
cannot add or delete a Folder
object from the message store. Table 8.7 contains the list of
important Folder object properties.
Property name | Type | Description |
Application | String | Name of the library. Always set to OLE/Messaging. |
Class | Long | Internal identifying code for all MAPI objects. Always set to 2 for Folder objects. |
Fields | Fields collection object | A collection of user-defined fields added to the folder object. |
FolderID | String | A unique and permanent value that identifies the Folder object in the message store. This value is set by MAPI when the folder is created. |
Folders | Folders collection object | A collection of subfolders that are members of this folder object. |
ID | String | The same as the FolderID property. |
Messages | Messages collection object | A collection of messages that are members of this Folder object. |
Name | String | Display name of the folder. This name does not have to be unique and can be modified through the OLE Messaging library using the Update method of the Folder object. |
StoreID | String | A unique and permanent value that is the same as the ID value of the InfoStore object in which this folder resides. |
Add a new button to the command array and set its Caption property to Fo&lder Object. Then modify the Command1_Click event to match the one in Listing 8.17.
Listing 8.17. Updated Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
End Select
'
End Sub
Now create a new subroutine called FolderProps and add the code shown in Listing 8.18.
Listing 8.18. Adding the FolderProps routine.
Public Sub FolderProps()
'
' inspect the folder object properties
'
Dim cMsg As String
'
Set objFolder = objSession.InfoStores.Item(1).RootFolder
'
cMsg = "Application: " & objFolder.Application & Chr(13)
cMsg = cMsg & "Class: " & CStr(objFolder.Class) & Chr(13)
cMsg = cMsg & "FolderID: " & objFolder.folderID & Chr(13)
cMsg = cMsg & "ID: " & objFolder.ID & Chr(13)
cMsg = cMsg & "Name: " & objFolder.Name & Chr(13)
cMsg = cMsg & "StoreID: " & objFolder.storeID
'
MsgBox cMsg, vbInformation, "Folder Object Properties"
'
End Sub
Save and run the project. Then click the Folder Object button and compare your results with those shown in Figure 8.7.
Figure 8.7 : Viewing the Folder object properties.
The only method available for Folder objects is the Update method. You can use this method to save changes made to the Folder object properties. The only property you can modify is the Name property. If you wish to change the name of an existing folder you can use the following line of code:
objFolder.Name = "New Name" ' modify name
objFolder.Update ' save changes
Note |
The MAPI system will not let you modify the name of the Inbox, Outbox, Sent Items, or Deleted Items folders. Attempting to do this will cause MAPI to return an error to your program. |
There are two folders that are used for almost every MAPI message transaction:
Because these two folders are used so often, the OLE Messaging library has defined them as a property of the InfoStore object. This means you can access the InBox and OutBox folders directly from the InfoStore object.
Note |
The InfoStore object was discussed in the earlier section of this chapter titled "The InfoStore Objects and Collections." |
You can modify the FolderProp routine to access the properties of the Inbox by changing the line that sets the objFolder object.
'
'Set objFolder = objSession.InfoStores.Item(1).RootFolder
Set objFolder = objSession.Inbox
'
Now when you click the Folder Object button, you'll get data on the Inbox folder in message store #1. This works the same way for the Outbox.
The Message object and Messages collection object are the heart of the OLE Messaging library. These objects hold the actual messages composed and received by the MAPI client. You will use the Message objects to read, modify, create, and delete messages from the message store.
The Messages collection object has very few properties and a number of methods. Because the Message collection is a large collection (that is, it has an unlimited number of members), you must use the GetFirst, GetNext, GetPrevious, and GetLast methods to retrieve messages from the collection. You can also add and delete messages within the collection.
Table 8.8 shows the properties for the Messages
collection object.
Property name | Type | Description |
Application | String | Name of the library. Always set to OLE/Messaging. |
Class | Long | Internal identifying code for all MAPI objects. Always set to 19 for Messages objects. |
Table 8.9 shows the list of methods for the Messages
collection object.
Method name | Parameters | Description |
Add | (optional) subject as String,
(optional) text as String, (optional) type as String, (optional) importance as Long | Adds a new, null, message to the collection. |
Delete | (none) | Deletes all messages from the collection. |
GetFirst | (optional) filter as Variant | Returns the first message in the collection. The filter value allows you to collect only messages with a specified Type value. |
GetLast | (optional) filter as Variant | Returns the last message in the collection. The filter value allows you to collect only messages with a specified Type value. |
GetNext | (none) | Returns the next message in the collection. |
GetPrevious | (none) | Returns the previous message in the collection. |
Sort | sortOrder as Long | Sorts the message collection based on the following values:
None = 0, Ascending = 1 Descending = 2 |
To test the Messages collection object, you first need to add two new variables to the general declaration area of the form. Make sure your variables match the ones in Listing 8.19.
Listing 8.19. Declaring the form-level variables.
Option Explicit
'
Dim objSession As Object ' for mapi session
Dim objInfoStoreColl As Object ' collection of stores
Dim objInfoStore As Object ' single info store
Dim objFolderColl As Object ' collection of folders
Dim objFolder As Object ' single folder
Dim objMessageColl As Object ' messages collection
Dim objMessage As Object ' single message
Next add a new button to the control array and set its caption to M&essageColl. Then modify the Command1_Click event to match the code shown in Listing 8.20.
Listing 8.20. The updated Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
Case 8 ' messsage collection
MessagesColl
End Select
'
End Sub
Then add the new MessagesColl subroutine to the project and enter the code from Listing 8.22.
Listing 8.22. Adding the MessagesColl routine.
Public Sub MessagesColl()
'
' inspect the messages collection
'
Dim cMsg As String
Dim nCount As Integer
'
Set objMessageColl = objSession.Inbox.Messages ' get inbox messages
'
cMsg = "Application: " & objMessageColl.Application & Chr(13)
cMsg = cMsg & "Class: " & CStr(objMessageColl.Class) & Chr(13)
'
cMsg = cMsg & Chr(13) & "Inbox Messages:" & Chr(13)
Set objMessage = objMessageColl.GetFirst
Do Until objMessage Is Nothing
nCount = nCount + 1
cMsg = cMsg & CStr(nCount) & " - " & objMessage.subject & Chr(13)
Set objMessage = objMessageColl.GetNext
Loop
'
MsgBox cMsg, vbInformation, "Messages Collection Object"
End Sub
The MessagesColl routine reads the Application and Class properties of the object and then uses the Get methods to build a list of messages currently in the message store inbox.
Save and run the project. Your screen should look similar to the one in Figure 8.8.
Figure 8.8 : Viewing the Messages collection object properties.
You can sort the messages in the collection using the Sort method. Setting the sort order affects how the Get methods access the messages in the collection. The sort order is based on the TimeReceived property of the messages. The sort method can be set for None(0), Ascending(1), or Descending(2). The default SortOrder is None(0). If there is no sort order specified, the Get methods access the messages in the order in which they were added to the message collection.
Tip |
Because the sort order affects the way in which the Get methods access the file, setting the SortOrder to Ascending(1) and performing the GetFirst method on the messages collection will return the same message as setting the SortOrder to Descending(2) and performing the GetLast method on the messages collection. |
Modify the MessageColl routine to ask you for a sort order. Add the lines of code to the routine as indicated in Listing 8.23.
Listing 8.23. Adding the SortOrder lines to the MessageColl routine.
cMsg = cMsg & "Class: " & CStr(objMessageColl.Class) & Chr(13)
' *** add these lines to the routine ***************
nCount = InputBox("Enter Sort Order (0=None, 1=Ascending, 2=Descending):",
ÂMessage Collection Sort")
objMessageColl.Sort nCount
cMsg = cMsg & "Sort Order: " & CStr(nCount) & Chr(13)
nCount = 0 ' clear value
' *** end of added lines ***************************
cMsg = cMsg & Chr(13) & "Inbox Messages:" & Chr(13)
Now when you press the MessageColl button you'll be asked to supply a sort order and then be presented with a different view of the message collection list.
You can delete all the messages in a message collection by invoking the Delete method followed by the Update method on the parent object to save the change. The code below shows how this is done.
Set objMessageColl = objSession.Inbox.Messages ' get inbox messages
objMessageColl.Delete ' dump all messages in the inbox
objSession.Inbox.Update ' make the modification permanent
You'll learn about the Add method in the section on the Message object.
The Message object is the
richest object in the OLE Messaging library system. It has only
a few methods, but they are all quite powerful. They allow you
to delete the message from the collection (Delete),
display a message option dialog box (Options),
display a send dialog box (Send),
and save the modified message properties (Update).
These properties range from handling attachments to flagging a
message as read or unread. Table 8.10 shows the Message
object methods with their parameters and a short description.
Method name | Parameters | Description |
Delete | (none) | Removes a message from the collection. This is a non-recoverable delete. |
Options | (optional) parentWindow as Long | Displays a dialog box that allows users to modify message properties. Not all properties may appear on the dialog box. |
Send | (optional) saveCopy as Boolean,
(optional) showDialog as Boolean, (optional) parentWindow as Long | Sends the message to the recipient(s). Optionally displays a dialog box for the composition and ending of the message. |
Update | (none) | Saves all changes to message properties. Any modifications to properties are not permanent until the Update method is invoked. |
The Message object properties
are extensive and powerful. The properties range from simple Boolean
flags to indicate the importance of a message, to the actual text
body of the message, to the list of binary attachments to the
message. Table 8.11 shows the important Message object properties,
their type, and a short description.
Property name | Type | Description |
Application | String | Name of the library. Always set to OLE/Messaging. |
Attachments | Attachments collection object | The collection of binary attachments to the message. |
Class | Long | Internal identifying code for all MAPI objects. Always set to 3 for Message objects. |
ConversationIndex | String | This is a value that shows the order of the message within the conversation topic. Microsoft Exchange uses an eight-byte value that expresses the time stamp of the message. |
ConversationTopic | String | An identifying string. All messages with the same ConversationTopic value can be grouped together to show relationships. The Windows Messaging client supports the ConversationTopic property in its Folder Views options. |
DeliveryReceipt | Boolean | A flag that indicates the sender wants to receive notification when the message is delivered to the recipient. The default value is False. |
Encrypted | Boolean | A flag to indicate the message has been encrypted. The support of encrypted messages is dependent on the message store. MAPI does not perform message encryption. |
Fields | Fields collection object | A collection of custom, user-defined fields added to the message. You can add any number of fields to your messages. |
FolderID | String | The unique MAPI-assigned value that identifies the folder in which this message resides. |
ID | String | The unique MAPI-assigned value that identifies this message in the message store. This value is assigned when the message is first created and cannot be changed. |
Importance | Long | A flag to indicate the relative importance of this message. Microsoft Exchange supports the following values for this property:
Low(0) Normal(1)-the default High(2) |
ReadReceipt | Boolean | Flag to indicate that the sender wants to be notified when the recipient reads (opens) the message. |
Recipients | Recipients object | A collection of recipient objects. Each recipient object represents one e-mail address to which this message has been sent. A message can have any number of recipients. These recipients do not have to be found in the MAPI address book. |
Sender | AddressEntry object | The AddressEntry object of the user that sent this message. This points to an entry in the Microsoft Exchange address book. |
Sent | Boolean | A flag that indicates that the message has been sent to the recipient(s). When sending a message, this flag is set by MAPI. However, under some cases the programmer can set this value as part of an Update operation on messages sent to shared folders or saved in the message store in some other way. |
Signed | Boolean | A flag indicating that the message has been marked with a digital signature. Message signing is not supplied by MAPI, but is provided by the message store. |
Size | Long | The approximate size of the message (in bytes). |
StoreID | String | The unique MAPI-assigned value that indicates the message store to which this message belongs. |
Subject | String | The subject line of the message. |
Submitted | Boolean | A flag that indicates this message has been submitted for viewing. This property is related to (but not the same as) the Sent property. The submitted property must be set to True for messages sent to shared folders in order for some clients to be able to see them. |
Text | String | The actual body of the message. |
TimeReceived | Variant (Date/Time) | The date and time the message was received. |
TimeSent | Variant (Date/Time) | The date and time the message was sent. These values must be set by the programmer for messages placed in public folders. |
Type | String | Microsoft message type in the form "XXX.?" There are two main message types:
IPM-Interpersonal messages. These are recognized by the MAPI client and displayed in the Inbox when received. Ipc-Interprocess communications. These are not recognized by the MAPI client, but can be processed behind the scenes. |
Unread | Boolean | Flag indicating whether the message has been read. |
Now add another button to the control array and set its caption to MessageProps. Then modify the Command1_Click event as shown in Listing 8.24.
Listing 8.24. Modifying the Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
Case 8 ' messsage collection
MessagesColl
Case 9 ' message properties
MessageProps
End Select
'
End Sub
Next add a new subroutine called MessageProps to the form and enter the code from Listing 8.25.
Listing 8.25. Adding the MessageProps routine.
Public Sub MessageProps()
'
' display message properties
'
Dim cMsg As String
'
' get the inbox message collection
Set objMessageColl = objSession.Inbox.Messages
' get the first message in the inbox
Set objMessage = objMessageColl.GetFirst
'
On Error Resume Next ' when property is missing
'
cMsg = "Application: " & objMessage.Application & Chr(13)
cMsg = cMsg & "Class: " & objMessage.Class & Chr(13)
cMsg = cMsg & "ConversationIndex: " & objMessage.ConversationIndex & Chr(13)
cMsg = cMsg & "ConversationTopic: " & objMessage.conversationtopic & Chr(13)
cMsg = cMsg & "DeliveryReceipt: " & objMessage.DeliveryReceipt & Chr(13)
cMsg = cMsg & "Encrypted: " & objMessage.Encrypted & Chr(13)
cMsg = cMsg & "FolderID: " & objMessage.folderID & Chr(13)
cMsg = cMsg & "ID: " & objMessage.ID & Chr(13)
cMsg = cMsg & "Importance: " & CStr(objMessage.importance) & Chr(13)
cMsg = cMsg & "ReadReceipt: " & objMessage.ReadReceipt & Chr(13)
cMsg = cMsg & "Sent: " & objMessage.Sent & Chr(13)
cMsg = cMsg & "Signed: " & objMessage.Signed & Chr(13)
cMsg = cMsg & "Size: " & CStr(objMessage.Size) & Chr(13)
cMsg = cMsg & "StoreID: " & objMessage.storeID & Chr(13)
cMsg = cMsg & "Subject: " & objMessage.subject & Chr(13)
cMsg = cMsg & "Submitted: " & objMessage.Submitted & Chr(13)
' cMsg = cMsg & "Text: " & objMessage.Text & Chr(13)
cMsg = cMsg & "TimeReceived: " & Format(objMessage.TimeReceived, "general Âdate") & Chr(13)
cMsg = cMsg & "TimeSent: " & Format(objMessage.TimeSent, "general date") & ÂChr(13)
cMsg = cMsg & "Type: " & objMessage.Type & Chr(13)
cMsg = cMsg & "Unread: " & objMessage.Unread
'
MsgBox cMsg, vbInformation, "Message Object Properties"
'
End Sub
The MessageProps routine first selects the session's Inbox message collection and then selects the first message in the collection.
Warning |
This routine crashes with an error if no message is present in the Inbox. If you do not currently have at least one message in the Inbox, fire up an e-mail client and place one there before running this routine. In production applications, you should make sure you trap for such an error to prevent needless (and annoying) crashes. |
Notice the addition of the On Error Resume Next just before the series of statements that retrieve the message properties. This is done in case one or more properties are missing in the selected message. Since MAPI supports messages from several different providers, it is quite likely that some of the properties will contain garbage or nothing at all. You should keep this in mind when writing routines that read Message object properties.
Save and run the project. After starting MAPI and pressing the MessageProps button, you'll see something like the data shown in Figure 8.9. Of course, the actual values of the properties will vary depending on the message you are reading.
Figure 8.9 : Viewing the Message object properties.
It's easy to add new messages to the message collection. The simplest method is to use the Send method of the Message object to invoke the MAPI Send dialog box. From this dialog box, the user can compose, address, and send the message without any additional coding.
Add a new button to the control array and set its caption property to MessageAdd. Then update the Command1_Click event so that it matches the one in Listing 8.26.
Listing 8.26. Updating the Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
Case 8 ' messsage collection
MessagesColl
Case 9 ' message properties
MessageProps
Case 10 ' add a message w/ dialogs
MessageAdd
End Select
'
End Sub
Now add the MessageAdd subroutine and enter the code from Listing 8.27. This will create a new Message object in the message collection and then bring up the MAPI Send dialog box.
Listing 8.27. Adding the MessageAdd routine.
Public Sub MessageAdd()
'
' add a message w/ dialog
'
On Error Resume Next ' skip errors
'
Set objMessageColl = objSession.Outbox.Messages
Set objMessage = objMessageColl.Add
objMessage.Send showdialog:=True
'
End Sub
You can also build the message using Visual Basic code and then call the Send method to address and ship the message. Listing 8.28 shows a new routine MessageMake that codes this.
Listing 8.28. Adding the MessageMake routine.
Public Sub MessageMake()
'
' make a message from code
' then show send dialog
'
On Error Resume Next
'
Set objMessageColl = objSession.Outbox.Messages
Set objMessage = objMessageColl.Add ' add a new message
objMessage.subject = "Creating a Message in Code"
objMessage.Text = "This message was written with VB code."
objMessage.Update ' save the message properties
objMessage.Send showdialog:=True ' show dialog
'
End Sub
After adding this routine, add a new button to the array and set its caption property to MessageMake. Also add another line to the Select Case structure to handle the button selection (see Listing 8.29).
Listing 8.29. Updating the Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
Case 8 ' messsage collection
MessagesColl
Case 9 ' message properties
MessageProps
Case 10 ' add a message w/ dialogs
MessageAdd
Case 11 ' make a message in code
MessageMake
End Select
'
End Sub
You can also set several message options by calling the Options method to bring up the Options dialog box. Modify the code in the MessageMake routine to call the Options method before the Send method. Insert the line shown below into the code just before the objMessage.Send line.
objMessage.Options ' call options dialog
When you save and run the project, press the MessageMake button. You'll see the Options dialog box before you see the Send dialog box. The exact layout and contents of the Options dialog box depend on the type of message you are working with and the available message transports at your workstation (see Figure 8.10).
Figure 8.10 : Viewing the Options dialog box.
You can also compose a complete message, address it, and send it without the use of dialog boxes. However, to do that you need to create at least one recipient object. You learn how to do that in the next section.
The OLE Messaging library defines two address objects-the Recipient object and the AddressEntry object. The two objects are related, but serve different purposes. The purpose of the Recipient object is to provide valid addressing information for the message. The purpose of the AddressEntry object is to gain access to individual records in the MAPI address book.
The next several sections outline the properties and methods of both the Recipient and AddressEntry objects.
The Recipients collection object holds a list of all recipients for a message. Every message has a recipients collection-even if the message has only one recipient in the collection. There are three methods for the collection and a handful of properties. Because the Recipients collection is a small collection, it has Count and Item properties. This also means that the Recipient object supports an Index property.
Table 8.12 shows the Recipients object methods and Table 8.13 shows the object's properties.
Method name | Parameters | Description |
Add | (optional) name as String,
(optional) address as String, (optional) type as Long, (optional) entryID as String | Used to add a new recipient to the collection. |
Delete | (none) | Used to delete all recipients from the collection. |
Resolve | (optional) showDialog as Boolean | Used to validate all Recipient objects in the collection. Can optionally show a dialog box to help resolve ambiguous entries. |
Property name | Type | Description |
Application | String | Name of the library. Always set to OLE/Messaging. |
Class | Long | Internal identifying code for all MAPI objects. Always set to 20 for Recipients objects. |
Count | Long | Total number of Recipient objects in the collection. |
Item | Recipient object | Used to gain access to a particular Recipient object in the collection (using the Recipient Index property). |
Resolved | Boolean | Flag to indicate that all Recipient objects in the collection contain valid addressing information. Set when you call the Resolve method of the object. |
To test the properties of the Recipients collection object, add a new button to the control array and set its caption to RecipColl. Then add a new line in the Command1_Click event to match the code in Listing 8.30.
Listing 8.30. Updating the Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
Case 8 ' messsage collection
MessagesColl
Case 9 ' message properties
MessageProps
Case 10 ' add a message w/ dialogs
MessageAdd
Case 11 ' make a message in code
MessageMake
Case 12 ' recipients collection
RecipColl
End Select
'
End Sub
Before coding the collection routine, you must first add three new variables to the general declaration area of the form. Modify the declaration list to match the code in Listing 8.31.
Listing 8.31. Modifying the form-level declarations.
Option Explicit
'
Dim objSession As Object ' for mapi session
Dim objInfoStoreColl As Object ' collection of stores
Dim objInfoStore As Object ' single info store
Dim objFolderColl As Object ' collection of folders
Dim objFolder As Object ' single folder
Dim objMessageColl As Object ' messages collection
Dim objMessage As Object ' single message
Dim objRecipColl As Object ' recipient collection
Dim objRecipient As Object ' single recipient
Dim objAddrEntry As Object ' addressentry object
Next add the RecipColl subroutine to the project and enter the code in Listing 8.32.
Listing 8.32. Adding the RecipColl routine.
Public Sub RecipColl()
'
' show the recipient collection properties
'
Dim cMsg As String
'
' get the recipient collection
' from the first message in the inbox
Set objMessageColl = objSession.Inbox.Messages
Set objMessage = objMessageColl.GetFirst
'
' get its recipient collection
Set objRecipColl = objMessage.Recipients
'
' get the properties
cMsg = "Application: " & objRecipColl.Application & Chr(13)
cMsg = cMsg & "Class: " & CStr(objRecipColl.Class) & Chr(13)
cMsg = cMsg & "Count: " & CStr(objRecipColl.Count) & Chr(13)
cMsg = cMsg & "Item (Name): " & objRecipColl.Item(1).Name & Chr(13)
cMsg = cMsg & "Resolved: " & objRecipColl.Resolved
'
MsgBox cMsg, vbInformation, "Recipients Collection Object"
'
End Sub
The RecipColl routine locates the first message in the Inbox collection and then displays the Recipients collection object properties. Notice that the routine calls the Name property of the Item object in the collection. The Item(1) property points to the first recipient object in the collection.
In Figure 8.11 you can see the results of a message with three recipients. Your exact results will vary based on the message you select.
Figure 8.11 : Viewing the Recipients collection object properties.
Using the Delete method will remove all the Recipient objects from the collection. After calling the Delete method, you must call the Update method on the Message object to make the changes permanent. Once the recipients are deleted, they cannot be recovered. The following code sample illustrates how to remove all recipients from a collection:
objMessage.Recipients.Delete
objMessage.Update
You can use the Add method to add a new recipient to a message, as explained in the next section.
The Recipient object holds all the information needed to address a message to its destination. Along with the usual properties, the Recipient object has an AddressEntry property. This property points to a valid AddressEntry object. You'll learn more about the AddressEntry object in the next section. The methods for the Recipient object allow you to delete the recipient from the collection and validate the address before attempting to send the message.
Table 8.14 shows the Recipient
object methods, and Table 8.15 shows the Recipient
object properties.
Method name | Parameters | Description |
Delete | (none) | Used to delete the selected recipient from the collection. |
Resolve | (optional) showDialog as Boolean | Used to validate the recipient entry against the MAPI address book. Can optionally show a dialog box to help resolve ambiguous entries. |
Property name | Type | Description |
Address | String | The complete routing address for the target recipient. In the format:
TransportType:EmailAddress. The TransportType is taken from the Type property of the child AddressEntry object. The EmailAddress is taken from the Address property of the AddressEntry object. |
AddressEntry | AddressEntry object | The underlying object that contains detailed information on the recipient, including the exact address and message transport type. |
Application | String | Name of the library. Always set to OLE/Messaging. |
Class | Long | Internal identifying code for all MAPI objects. Always set to 4 for Recipient objects. |
DisplayType | Long | A value that indicates the type of recipient. This is used to control how the message is displayed by client applications. Valid display types are
Local User MAPI performs no special processing based on the DisplayType property. It is up to the programmer to use this property where appropriate. |
Index | Long | A value that indicates the position of the Recipient object in the collection. |
Name | String | The displayable Name property of the underlying AddressEntry object. This is the value shown in the MAPI address book. |
Type | Long | A value indicating the type of recipient for this message. Valid types are
To-Primary addressee |
To view the properties of a Recipient object, add another button to the control array and set its caption property to RecipProps. Then modify the Command1_Click event as shown in Listing 8.33.
Listing 8.33. Updating the Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
Case 8 ' messsage collection
MessagesColl
Case 9 ' message properties
MessageProps
Case 10 ' add a message w/ dialogs
MessageAdd
Case 11 ' make a message in code
MessageMake
Case 12 ' recipients collection
RecipColl
Case 13 ' recipient object
RecipProps
End Select
'
End Sub
Now add the RecipProps subroutine to the form and enter the code from Listing 8.34.
Listing 8.34. Adding the RecipProps routine.
Public Sub RecipProps()
'
' show the recipient object properties
'
Dim cMsg As String
'
' select a message and recipient
Set objMessageColl = objSession.Inbox.Messages
Set objMessage = objMessageColl.GetFirst
Set objRecipient = objMessage.Recipients.Item(1)
'
' now get properties
cMsg = "Address: " & objRecipient.address & Chr(13)
cMsg = cMsg & "Application: " & objRecipient.Application & Chr(13)
cMsg = cMsg & "Class: " & CStr(objRecipient.Class) & Chr(13)
cMsg = cMsg & "DisplayType: " & CStr(objRecipient.DisplayType) & Chr(13)
cMsg = cMsg & "Index: " & CStr(objRecipient.Index) & Chr(13)
cMsg = cMsg & "Name: " & objRecipient.Name & Chr(13)
cMsg = cMsg & "Type: " & CStr(objRecipient.Type)
'
MsgBox cMsg, vbInformation, "Recipient Object Properties"
'
End Sub
You can use the Add method of the Recipients collection object to add a valid recipient to a message. To do this you must have a Message object, access the recipients collection for that message, execute the Add method, and then populate the new Recipient object properties. Once that is done, you must execute the Update method of the message to save all changes.
Add a new button to the control array and set its caption property to RecipAdd. Be sure to modify the Command1_Click event to match the code in Listing 8.35.
Listing 8.35. Modifying the Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
Case 8 ' messsage collection
MessagesColl
Case 9 ' message properties
MessageProps
Case 10 ' add a message w/ dialogs
MessageAdd
Case 11 ' make a message in code
MessageMake
Case 12 ' recipients collection
RecipColl
Case 13 ' recipient object
RecipProps
Case 14 ' add a recipient to a message
RecipAdd
End Select
'
End Sub
Now add the RecipAdd subroutine to the form and enter the code from Listing 8.36.
Listing 8.36. Adding the RecipAdd routine.
Public Sub RecipAdd()
'
' adding a new recipient to a message
'
' add a new message first
Set objMessageColl = objSession.Outbox.Messages
Set objMessage = objMessageColl.Add
objMessage.subject = "New Message"
objMessage.Text = "Added this using VB code"
'
' now add a recipient
Set objRecipColl = objMessage.Recipients
Set objRecipient = objRecipColl.Add
objRecipient.Name = "MCA" ' select a good name
objRecipient.Resolve ' force validation
'
' update and send
objMessage.Update
objMessage.Send showdialog:=True
'
End Sub
The RecipAdd routine first creates a new message in the outbox and then adds a new recipient to the message. Finally, after validating the Recipient object, the routine updates all the changes and calls the Send dialog box (see Figure 8.12).
Figure 8.12 : Viewing the results of adding a recipient to a message.
This routine could easily be modified to complete the send operation without presenting any dialog boxes. If you change the ShowDialog parameter to False, the OLE Messaging library will post the message without interfacing with the user.
The AddressEntry object is a child object of the Recipient object. The AddressEntry object contains all the valid addressing information for a message system. The AddressEntry object is also the object that represents an entry in the MAPI address book. In this way, the AddressEntry object provides a link between the MAPI address book and MAPI messages.
The OLE Messaging library interface allows you to modify or delete
AddressEntry objects from
the MAPI address book. However, there is no Add
method for the AddressEntry
object. You cannot use the OLE Messaging library to create new
entries in the MAPI address book. Table 8.16 shows the AddressEntry
object methods, their parameters, and brief descriptions.
Method name | Parameters | Description |
Delete | (none) | Removes the AddressEntry object from the MAPI address book. |
Details | (opt) parentWindow as Long | Displays a dialog box that allows the user to modify published properties of the AddressEntry. |
Update | (opt) makePermanent as Boolean,
(opt) refreshObject as Boolean | Make changes to the object's properties permanent. |
The AddressEntry object has
a handful of properties. These properties identify the message
transport used to send messages to this location, the actual address,
and other internal properties. Table 8.17 shows the properties
of the AddressEntry object.
Property name | Type | Description |
Address | String | The electronic mail address of the record. |
Application | String | Name of the library. Always set to OLE/Messaging. |
Class | Long | Internal identifying code for all MAPI objects. Always set to 8 for AddressEntry objects. |
DisplayType | Long | A value that indicates the type of recipient. This is used to control how the message is displayed by client applications. Valid display types are
Local User MAPI performs no special processing based on the DisplayType property. It is up to the programmer to use this property where appropriate. |
Fields | Fields collection object | A collection of user-defined properties. This is used by programmers to add additional unique information to AddressEntry objects. |
ID | String | A MAPI-assigned unique value that identifies this address object. |
Name | String | The displayable Name property of the AddressEntry object. This is the value shown in the MAPI address book. |
Type | Long | A value indicating the type of recipient for this message. Valid types are
To-Primary addressee cc-Courtesy copy addressee BC-Blind courtesy copy addressee |
Add a new button to the control array and set its caption to AddrProps. Then modify the Command1_Click event to match the code in Listing 8.37.
Listing 8.37. Modifying the Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
Case 8 ' messsage collection
MessagesColl
Case 9 ' message properties
MessageProps
Case 10 ' add a message w/ dialogs
MessageAdd
Case 11 ' make a message in code
MessageMake
Case 12 ' recipients collection
RecipColl
Case 13 ' recipient object
RecipProps
Case 14 ' add a recipient to a message
RecipAdd
Case 15 ' address entry object
AddrProps
End Select
'
End Sub
Now add the AddrProps subroutine and enter the code in Listing 8.38.
Listing 8.38. Adding the AddrProps routine.
Public Sub AddrProps()
'
' show address entry properties
'
Dim cMsg As String
'
' start a new message
Set objMessageColl = objSession.Outbox.Messages
Set objMessage = objMessageColl.Add
objMessage.subject = "Testing AddressEntry Objects"
objMessage.Text = "Testing the AddrProps routine"
'
' add a recipient
Set objRecipient = objMessage.Recipients.Add
objRecipient.Name = "MCA"
objRecipient.Resolve ' validate it
'
' set addressentry object
Set objAddrEntry = objRecipient.AddressEntry
'
' now get properties of address entry object
cMsg = "Address: " & objAddrEntry.address & Chr(13)
cMsg = cMsg & "Application: " & objAddrEntry.Application & Chr(13)
cMsg = cMsg & "Class: " & CStr(objAddrEntry.Class) & Chr(13)
cMsg = cMsg & "DisplayType: " & CStr(objAddrEntry.DisplayType) & Chr(13)
cMsg = cMsg & "ID: " & objAddrEntry.ID & Chr(13)
cMsg = cMsg & "Name: " & objAddrEntry.Name & Chr(13)
cMsg = cMsg & "Type: " & objAddrEntry.Type
'
MsgBox cMsg, vbInformation, "Address Entry Object Properties"
'
End Sub
When you save and run the project, then click AddrProps, you'll see a set of property information for the message recipient. Although the details will vary, your screen should look like the one in Figure 8.13.
Figure 8.13 : Viewing the AddressEntry properties.
You can use the Details method to invoke a Details dialog box for an AddressEntry object. This is handy for looking up additional information on a known AddressEntry object. Add another button to the control array and set its caption to AddrDetails. Modify the Command1_Click event as shown in Listing 8.39.
Listing 8.39. Updated Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
Case 8 ' messsage collection
MessagesColl
Case 9 ' message properties
MessageProps
Case 10 ' add a message w/ dialogs
MessageAdd
Case 11 ' make a message in code
MessageMake
Case 12 ' recipients collection
RecipColl
Case 13 ' recipient object
RecipProps
Case 14 ' add a recipient to a message
RecipAdd
Case 15 ' address entry object
AddrProps
Case 16 ' address entry details dialog
AddrDetails
End Select
'
End Sub
Now add the AddrDetails subroutine and enter the code from Listing 8.40.
Listing 8.40. Adding the AddrDetails routine.
Public Sub AddrDetails()
'
' show the details of an address entry
'
' first get an existing message
Set objMessageColl = objSession.Inbox.Messages
Set objMessage = objMessageColl.GetFirst
'
' now get the recipient/address entry objects
Set objRecipient = objMessage.Recipients.Item(1)
Set objAddrEntry = objRecipient.AddressEntry
'
' now show the details of the address entry
objAddrEntry.Details
'
End Sub
After accessing the first message in the inbox and getting the AddressEntry of the first Recipient object of the message, this routine invokes the Details method to show a dialog box that allows users to modify the fields of the address book entry (see Figure 8.14).
Figure 8.14 : Viewing the Details dialog box for the AddressEntry object.
You can modify AddressEntry properties without invoking the Details method. For example, you can change the Name property of an existing AddressEntry object. The following code fragment shows how this is done:
objAddrEntry.Name = "New Name"
objAddrEntry.Update(True, True) ' update object and reload data
You can also delete an entry from the MAPI address book by using the Delete method. The following code example shows how this can be done:
objAddrEntry.Delete ' mark for delete
objAddrEntry.Update(True, True) ' update the changes
Warning |
Once a Delete/Update method pair is invoked on an AddressEntry object, it is permanently removed from the address book and cannot be recovered. Use this method sparingly. And when you do provide delete services in your programs, be sure to add a confirmation option dialog box before permanently deleting the object. |
The Attachment objects contain non-text data that is to be sent along with a standard message. Often this is a binary graphic or formatted document file that is shipped from one user to another. The Attachment object methods and properties allow you to read and write attachments to your messages.
There can be multiple attachments for each message. For this reason, the message object has an Attachments collection object associated with it. All attachment objects are part of the Attachments collection.
The Attachments collection object is a child of the Message object and holds all the associated attachments for that message. The Attachments collection is a small collection, so it supports the Count and Item properties and the Attachment object supports the Index property.
Table 8.18 shows the Attachments
collection object methods, and Table 8.19 shows the Attachments
collection object properties.
Method name | Parameters | Description |
Add | (optional) name as String,
(optional) position as Long, (optional) type as Long, (optional) source as String. | Adds a new attachment to the attachments collection. |
Delete | (none) | Removes all attachments from the collection. |
Property name | Type | Description |
Application | String | Name of the library. Always set to OLE/Messaging. |
Class | Long | Internal identifying code for all MAPI objects. Always set to 21 for Attachments objects. |
Count | Long | The total number of attachments in this collection. |
Item | Object | Used to gain access to one of the attachments in the collection based on the Index property of the Attachment object. |
To test the Attachments collection object, add a new command button to the control array and set its caption to AttachColl. Then modify the Command1_Click event to match the code in Listing 8.41.
Listing 8.41. Modifying the Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
Case 8 ' messsage collection
MessagesColl
Case 9 ' message properties
MessageProps
Case 10 ' add a message w/ dialogs
MessageAdd
Case 11 ' make a message in code
MessageMake
Case 12 ' recipients collection
RecipColl
Case 13 ' recipient object
RecipProps
Case 14 ' add a recipient to a message
RecipAdd
Case 15 ' address entry object
AddrProps
Case 16 ' address entry details dialog
AddrDetails
Case 17 ' attachment collection
AttachColl
End Select
'
End Sub
Next you need to add two new variables to the general declaration section of the form. Modify your declarations to match the code in Listing 8.42.
Listing 8.42. Modifying the form-level declarations.
Option Explicit
'
Dim objSession As Object ' for mapi session
Dim objInfoStoreColl As Object ' collection of stores
Dim objInfoStore As Object ' single info store
Dim objFolderColl As Object ' collection of folders
Dim objFolder As Object ' single folder
Dim objMessageColl As Object ' messages collection
Dim objMessage As Object ' single message
Dim objRecipColl As Object ' recipient collection
Dim objRecipient As Object ' single recipient
Dim objAddrEntry As Object ' addressentry object
Dim objAttachColl As Object ' attachment collection
Dim objAttachment As Object ' single attachment
Now add the AttachColl subroutine to the form and enter the code that appears in Listing 8.43.
Listing 8.43. Adding the AttachColl routine.
Public Sub AttachColl()
'
' inspect the attachment collection
' of a message object
'
Dim cMsg As String
Dim x As Integer
'
' first get a message
Set objMessageColl = objSession.Inbox.Messages
Set objMessage = objMessageColl.GetFirst
'
' next get attachment collection of message
Set objAttachColl = objMessage.Attachments
'
' now get properties of the collection
cMsg = "Application: " & objAttachColl.Application & Chr(13)
cMsg = cMsg & "Class: " & CStr(objAttachColl.Class) & Chr(13)
cMsg = cMsg & "Count: " & CStr(objAttachColl.Count) & Chr(13)
'
' now list out attachments
cMsg = cMsg & Chr(13) & "Attachments:" & Chr(13)
For x = 1 To objAttachColl.Count
cMsg = cMsg & CStr(x) & " - " & objAttachColl.Item(x).Name & Chr(13)
Next x
'
MsgBox cMsg, vbInformation, "Attachment Collection Object Properties"
'
End Sub
Warning |
The AttachColl routine will crash if there are no attachments on the first message in the inbox. Be sure to add a single message in the inbox with at least one attachment before you run this routine. You can use your MAPI client to create a new message with attachments and send it to yourself. |
The AttachColl routine accesses the attachments collection of the first message in the inbox and displays its properties. Your output may be different, but it should look something like Figure 8.15.
Figure 8.15 : Viewing the Attachments collection object properties.
You can delete all the attachments in the collection by invoking the Delete method on the Attachments collection object. The delete is not complete until you invoke the Update method on the parent object. And once the delete is complete, you cannot recover the data.
You'll learn about the Add method in the next section on Attachment objects.
The Attachment object contains
all the information about the data file attached to a message.
In fact, the Attachment object
includes the actual data file itself. There are several properties
and three methods to the Attachment
object. Table 8.21 shows you the Attachment
object methods and Table 8.22 shows you the Attachment
object properties.
Method name | Parameters | Description |
Delete | (none) | Removes the attachment from the attachment collection. |
ReadFromFile | fileName as String | Copies the operating system file into the Attachment object. |
WriteToFile | fileName as String | Copies the data from the Attachment object to an operating system file. |
Property name | Type | Access |
Application | String | Name of the library. Always set to OLE/Messaging. |
Class | Long | Internal identifying code for all MAPI objects. Always set to 5 for Attachment objects. |
Index | Long | A value that indicates the position of the attachment in the attachments collection. |
Name | String | The display name of the attachment. |
Position | Long | A value indicating the character position in the message body where the attachment should be displayed. |
Source | String | For OLE-type data, contains the OLE object name (for example, Word.Document). For File-type data, contains a blank. |
Type | Long | The value that indicates the type of attachment. MAPI supports two attachment types: File(0) and OLE(2). |
To review the attachment properties, add a new button to the control array and set its caption to AttachProps. Then modify the Command1_Click event to match the code in Listing 8.44.
Listing 8.44. The modified Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
Case 8 ' messsage collection
MessagesColl
Case 9 ' message properties
MessageProps
Case 10 ' add a message w/ dialogs
MessageAdd
Case 11 ' make a message in code
MessageMake
Case 12 ' recipients collection
RecipColl
Case 13 ' recipient object
RecipProps
Case 14 ' add a recipient to a message
RecipAdd
Case 15 ' address entry object
AddrProps
Case 16 ' address entry details dialog
AddrDetails
Case 17 ' attachment collection
AttachColl
Case 18 ' attachment object properties
AttachProps
End Select
'
End Sub
Now add the AttachProps subroutine and enter the code from Listing 8.45.
Listing 8.45. Adding the AttachProps routine.
Public Sub AttachProps()
'
' view the attachment object properties
'
Dim cMsg As String
'
' select a message with an attachment
Set objMessageColl = objSession.Inbox.Messages
Set objMessage = objMessageColl.GetFirst
Set objAttachColl = objMessage.Attachments
Set objAttachment = objAttachColl.Item(1)
'
' now get properties
cMsg = "Application " & objAttachment.Application & Chr(13)
cMsg = cMsg & "Class: " & CStr(objAttachment.Class) & Chr(13)
cMsg = cMsg & "Index: " & CStr(objAttachment.Index) & Chr(13)
cMsg = cMsg & "Name: " & objAttachment.Name & Chr(13)
cMsg = cMsg & "Position: " & CStr(objAttachment.position) & Chr(13)
cMsg = cMsg & "Source: " & objAttachment.Source & Chr(13)
cMsg = cMsg & "Type: " & CStr(objAttachment.Type)
'
MsgBox cMsg, vbInformation, "Attachment object Properties"
'
End Sub
Save and run this routine. When you click on the AttachProps button, you will see the properties of the attachment. Refer to Figure 8.16 for an example of the output.
Figure 8.16 : Viewing the Attachment object properties.
You can use Visual Basic code to add an attachment directly to a message. This involves setting three properties and invoking the ReadFromFile method. First, add another button to the control array and set its caption to AttachAdd. Then modify the Command1_Click event to match the code in Listing 8.46.
Listing 8.46. Updated Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
Case 8 ' messsage collection
MessagesColl
Case 9 ' message properties
MessageProps
Case 10 ' add a message w/ dialogs
MessageAdd
Case 11 ' make a message in code
MessageMake
Case 12 ' recipients collection
RecipColl
Case 13 ' recipient object
RecipProps
Case 14 ' add a recipient to a message
RecipAdd
Case 15 ' address entry object
AddrProps
Case 16 ' address entry details dialog
AddrDetails
Case 17 ' attachment collection
AttachColl
Case 18 ' attachment object properties
AttachProps
Case 19 ' add attachment
AttachAdd
End Select
'
End Sub
Next, add a new subroutine called AttachAdd and enter the code shown in Listing 8.47.
Listing 8.47. Adding the AttachAdd routine.
Public Sub AttachAdd()
'
' add an attachment to a message
'
' first create a new message
Set objMessageColl = objSession.Outbox.Messages
Set objMessage = objMessageColl.Add
objMessage.subject = "Here's the WIN.INI File"
objMessage.Text = " Here's a copy of the Windows INI File you asked for."
'
' now add an attachment
Set objAttachColl = objMessage.Attachments
Set objAttachment = objAttachColl.Add
objAttachment.Name = "WIN.INI"
objAttachment.position = 0 ' place at start of message
objAttachment.ReadFromFile "C:\WINDOWS\WIN.INI"
'
' now address the message
Set objRecipColl = objMessage.Recipients
Set objRecipient = objRecipColl.Add
objRecipient.Name = "MCA" ' a valid name
objRecipient.Resolve ' validate name
'
' now update and send message
objMessage.Update ' save it all
objMessage.Send showdialog:=True ' let's see it
'
End Sub
Warning |
Be sure to address the message to a valid person in your MAPI address book. It is a good idea to address this message to yourself since you will be reading and saving an attachment in the next section. |
The AttachAdd routine creates a new message, adds the WIN.INI file as an attachment (at the first position in the file), and then addresses the message and sends it. Your screen should look something like the one in Figure 8.17.
Figure 8.17 : Viewing the attachment to the message.
Tip |
You could easily send the message without ever seeing the dialog box by just setting the ShowDialog parameter to False. |
Now you can read the message you just sent yourself. Add one more button to the command array and set its caption to AttachSave. Then modify the Command1_Click event to match the code in Listing 8.48.
Listing 8.48. Updating the Command1_Click event.
Private Sub Command1_Click(Index As Integer)
'
' handle user selections
'
Select Case Index
Case 0 ' mapi start
MAPIStart
Case 1 ' mapi end
MAPIEnd
Case 2 ' call address book
MAPIAddrBook
Case 3 ' session properties
SessionProps
Case 4 ' show infostores collection
SessionInfoStoreColl
Case 5 ' show infostore properties
InfoStoreProps
Case 6 ' folders collection
FoldersColl
Case 7 ' folder object
FolderProps
Case 8 ' messsage collection
MessagesColl
Case 9 ' message properties
MessageProps
Case 10 ' add a message w/ dialogs
MessageAdd
Case 11 ' make a message in code
MessageMake
Case 12 ' recipients collection
RecipColl
Case 13 ' recipient object
RecipProps
Case 14 ' add a recipient to a message
RecipAdd
Case 15 ' address entry object
AddrProps
Case 16 ' address entry details dialog
AddrDetails
Case 17 ' attachment collection
AttachColl
Case 18 ' attachment object properties
AttachProps
Case 19 ' add attachment
AttachAdd
Case 20 ' save attachment
AttachSave
End Select
'
End Sub
Now add the AttachSave subroutine and enter the code from Listing 8.49.
Listing 8.49. Adding the AttachSave routine.
Public Sub AttachSave()
'
' read a message and save the attachment
'
Dim cMsg As String
'
' get the last message in the inbox
Set objMessageColl = objSession.Inbox.Messages
Set objMessage = objMessageColl.GetLast
'
' now save the attachment
Set objAttachColl = objMessage.Attachments
Set objAttachment = objAttachColl.Item(1)
objAttachment.WriteToFile App.Path & "\saved.txt"
'
cMsg = "Attachment: " & objAttachment.Name & Chr(13)
cMsg = cMsg & "Saved as: " & App.Path & "\saved.txt"
'
MsgBox cMsg, vbInformation, "Save Attachment"
'
End Sub
The AttachSave routine reads the last message added to the inbox collection (the one you sent just a moment ago) and retrieves the attachment from the message's attachment collection. The attachment is then saved in the local disk folder as SAVED.TXT (see Figure 8.18).
Figure 8.18 : Saving the attached file.
In production applications, you should add code to the routine to prompt the user for a folder and filename for storing the attachment.
In this chapter, you learned how to use the OLE Messaging library to access features of MAPI. You learned all the major objects, their methods, and their properties.
You also wrote several code examples that inspected and modified objects and their properties. You learned to use the OLE Messaging library to
The OLE Messaging library is a rich and powerful set of commands. In the next several chapters, you'll use the OLE Messaging library to build powerful desktop applications that use the advanced features of MAPI 1.0.