Chapter 8

The OLE Messaging Library


CONTENTS


Introduction

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

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.

The Session Object Methods

Table 8.1 shows the Session Object Methods along with a list of parameters and short descriptions.

Table 8.1. Session object methods.
MethodsParameters 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.

Using the MAPI Logon and Logoff Methods

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!

Accessing the MAPI Address Book

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.

Automating the Session Logon

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

The Session Object Properties

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.

Table 8.2. Session object properties.
PropertiesType Description
Application StringName of the library. Always set to OLE/Messaging.
Class LongInternal 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 StringSession name. Always set to the current profile name on Microsoft Exchange system.
OperatingSystem StringName of operating system in use.
Outbox Folder object Folder object where all outgoing messages are placed (see "Folder Objects" later in this chapter).
Version StringVersion 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 InfoStore Objects and Collections

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

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.

Table 8.3. The InfoStores collection object properties.
Property nameType Description
Application StringName of the library. Always set to OLE/Messaging.
Class LongInternal identifying code for all MAPI objects. Always set to 17 for InfoStores objects.
Count LongThe 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

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.

Table 8.4. The InfoStore object properties.
Property nameType Description
Application StringName of the library. Always set to OLE/Messaging.
Class LongInternal identifying code for all MAPI objects. Always set to 1 for InfoStore objects.
ID StringA unique value that never changes. It is assigned by MAPI when the store is created.
Index LongThe count position of the InfoStore in the InfoStores collection. This can be used with the Item property of the InfoStores object.
Name StringThe display name of the message store.
ProviderName StringThe 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.

The Folder Objects and Collections

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

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.

Table 8.5. The Folders collection object properties.
Property nameType Description
Application StringName of the library. Always set to OLE/Messaging.
Class LongInternal identifying code for all MAPI objects. Always set to 18 for Folders objects.

Table 8.6. The Folders collection object methods.
Method nameParameters 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

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.

Table 8.7. The Folder object properties.
Property nameType Description
Application StringName of the library. Always set to OLE/Messaging.
Class LongInternal 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 StringA 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 StringThe same as the FolderID property.
Messages Messages collection object A collection of messages that are members of this Folder object.
Name StringDisplay 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 StringA 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.

The Inbox and OutBox Folders

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 Objects and Collections

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

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.

Table 8.8. The Messages collection object properties.
Property nameType Description
Application StringName of the library. Always set to OLE/Messaging.
Class LongInternal 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.

Table 8.9. The Messages collection object methods.
Method nameParameters 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 VariantReturns the first message in the collection. The filter value allows you to collect only messages with a specified Type value.
GetLast (optional) filter as VariantReturns 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

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.

Table 8.10. The Message object methods.
Method nameParameters 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.

Table 8.11. The Message object properties.
Property nameType Description
Application StringName of the library. Always set to OLE/Messaging.
Attachments Attachments collection object The collection of binary attachments to the message.
Class LongInternal identifying code for all MAPI objects. Always set to 3 for Message objects.
ConversationIndex StringThis 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 StringAn 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 BooleanA flag that indicates the sender wants to receive notification when the message is delivered to the recipient. The default value is False.
Encrypted BooleanA 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 StringThe unique MAPI-assigned value that identifies the folder in which this message resides.
ID StringThe 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 LongA 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 BooleanFlag 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 BooleanA 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 BooleanA 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 LongThe approximate size of the message (in bytes).
StoreID StringThe unique MAPI-assigned value that indicates the message store to which this message belongs.
Subject StringThe subject line of the message.
Submitted BooleanA 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 StringThe 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 StringMicrosoft 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 BooleanFlag 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.

Adding a New Message

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 Recipient Objects and Collections and the Address Object

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

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.

Table 8.12. The Recipients collection object methods.
Method nameParameters 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.

Table 8.13. The Recipients collection object properties.
Property nameType Description
Application StringName of the library. Always set to OLE/Messaging.
Class LongInternal identifying code for all MAPI objects. Always set to 20 for Recipients objects.
Count LongTotal 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 BooleanFlag 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

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.

Table 8.14. The Recipient object methods.
Method nameParameters 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.

Table 8.15. The Recipient object properties.
Property nameType Description
Address StringThe 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 StringName of the library. Always set to OLE/Messaging.
Class LongInternal identifying code for all MAPI objects. Always set to 4 for Recipient objects.
DisplayType LongA 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
Distribution List
Shared Folder
Agent
Organization
Private Distribution List
Remote User

MAPI performs no special processing based on the DisplayType property. It is up to the programmer to use this property where appropriate.

Index LongA value that indicates the position of the Recipient object in the collection.
Name StringThe displayable Name property of the underlying AddressEntry object. This is the value shown in the MAPI address book.
Type LongA value indicating the type of recipient for this message. Valid types are

To-Primary addressee
cc-Courtesy copy addressee
BC-Blind courtesy copy 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

Adding a Recipient Object to a Collection

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

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.

Table 8.16. The AddressEntry object methods.
Method nameParameters 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.

Table 8.17. The AddressEntry object properties.
Property nameType Description
Address StringThe electronic mail address of the record.
Application StringName of the library. Always set to OLE/Messaging.
Class LongInternal identifying code for all MAPI objects. Always set to 8 for AddressEntry objects.
DisplayType LongA 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
Distribution List
Shared Folder
Agent
Organization
Private Distribution List
Remote 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 StringA MAPI-assigned unique value that identifies this address object.
Name StringThe displayable Name property of the AddressEntry object. This is the value shown in the MAPI address book.
Type LongA 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.

Accessing the AddressEntry Details Dialog Box

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 and Collections

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

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.

Table 8.19. The Attachments collection object methods.
Method nameParameters 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.

Table 8.20. The Attachments collection object properties.
Property nameType Description
Application StringName of the library. Always set to OLE/Messaging.
Class LongInternal identifying code for all MAPI objects. Always set to 21 for Attachments objects.
Count LongThe total number of attachments in this collection.
Item ObjectUsed 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

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.

Table 8.21. The Attachment object methods.
Method nameParameters 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.

Table 8.22. The Attachment object properties.
Property nameType Access
Application StringName of the library. Always set to OLE/Messaging.
Class LongInternal identifying code for all MAPI objects. Always set to 5 for Attachment objects.
Index LongA value that indicates the position of the attachment in the attachments collection.
Name StringThe display name of the attachment.
Position LongA value indicating the character position in the message body where the attachment should be displayed.
Source StringFor OLE-type data, contains the OLE object name (for example, Word.Document). For File-type data, contains a blank.
Type LongThe 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.

Adding an Attachment to a Message

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.

Saving a Message Attachment to Disk

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.

Summary

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.