Windows DevCenter    
 Published on Windows DevCenter (http://www.windowsdevcenter.com/)
 See this if you're having trouble printing code examples


Dave's Top Ten CDO Tips

by Dave Grundgeiger
09/26/2000

Collaboration Data Objects (CDO) are the modern way for Visual Basic programmers to create professional, messaging-enabled applications. CDO provides a rich interface to Microsoft's Messaging API (MAPI) in the form of an object model, which is a programming concept especially familiar to Visual Basic programmers. CDO is intuitive, but does have some "gotchas." Collected here are the top ten tips I recommend you keep in mind as you write messaging-enabled applications with CDO.

(Note that I use the term "CDO" here to refer specifically to CDO 1.x, the Visual Basic- and VBScript-friendly "wrapper" for MAPI, and not the broader collection of messaging technologies referred to as a whole as "CDO.")

  1. Use the IsSameAs method to compare CDO objects.
  2. CDO is a wrapper to MAPI, which is itself an object-oriented interface to message stores, transport mechanisms, and address book databases. This can occasionally result in unexpected behavior. For example, an application may wish to determine whether two object references, say CdoMessage1 and CdoMessage2, refer to the same message. The following naive implementation of such a check won't work reliably:

    ' This won't work.
    If CdoMessage1 Is CdoMessage2 Then
        ' Do something.
    End If

    The reason is that the two object references (CdoMessage1 and CdoMessage2) may refer to different CDO Message objects, yet those CDO Message objects may both wrap the same MAPI message object. In this case, the If statement shown will fail (because the two references do indeed point to different objects), but we would prefer for the statement to succeed (because the two objects wrap the same MAPI object). To handle this situation, most CDO objects implement the IsSameAs method. The syntax of this method is:

    bResult = CdoObject1.IsSameAs(CdoObject2)

    The IsSameAs method returns True either if CdoObject1 and CdoObject2 refer to the same CDO object, or if they refer to different CDO objects that in turn wrap the same MAPI object. The CDO objects that implement the IsSameAs method are AddressEntry, AddressEntryFilter, AddressList, AppointmentItem, Attachment, Folder, InfoStore, MeetingItem, Message, MessageFilter, and Recipient.

  3. Understand the MAPI architecture.
  4. Because CDO is built on top of MAPI, it is profoundly influenced by the MAPI architecture. The more you learn about MAPI, the better CDO programmer you will be. To learn more about the MAPI architecture, browse the MAPI Programmer's Reference in the MSDN Library, and Inside MAPI (Microsoft Press), by Irving De la Cruz and Les Thaler. Although both of these sources are heavily C++ oriented, they can't be beat for deep-down, bare-metal MAPI wisdom. Without being too self-serving, I also suggest my book: CDO and MAPI Programming with Visual Basic: Developing Mail and Messaging Applications.

  5. Understand when to use which messaging technology.
  6. There are quite a few options available to messaging developers. Here's a rundown on when to use each one:

  7. Make use of Web-based information sources.
  8. If you get stuck while developing collaboration applications, don't despair; there is a lot of help available on the Internet. Here are some sites to get you started:

  9. Catch errors raised by CDO.
  10. CDO makes good use of Visual Basic's error handling mechanism to report unusual events. For example, if the user presses Cancel on a MAPI-provided logon dialog box, a CdoE_USER_CANCEL error is raised in the Visual Basic code that attempted the logon. Errors can also be raised when attempting to access provider-specific MAPI properties through CDO's Fields collection. If the user has a service provider that doesn't support the requested property, then an error is raised, even if there were no errors during development. Good code handles such errors.

    For example, below is a function that uses CDO to show the user's address book. This function assumes a global variable, gCdoSession, which should contain a logged-in CDO Session object, and a module-level variable, mCdoMessage, which should contain a CDO Message object. The function causes the address book to be displayed, and then loads the Message object's Recipients collection with the recipients that were selected in the address book. If the user clicks the Cancel button in the address book window, CDO raises a CdoE_USER_CANCEL error, which is handled by simply exiting the function. Note that if an error other than CdoE_USER_CANCEL is raised, it is re-raised to the outside world by the function's error handler.

    Private Sub ShowAddressBook()

        On Error GoTo ErrorHandler

        mCdoMessage.Recipients = gCdoSession.AddressBook( _
            Recipients:=mCdoMessage.Recipien ts, Title:="Select Names", _
            RecipLists:=3)

        Exit Sub

    ErrorHandler:

        If Err.Number <> CdoE_USER_CANCEL Then
            Err.Raise Err.Number
        End If

    End Sub ' ShowAddressBook

  11. Beware of opening attachments programmatically.
  12. Hackers have discovered that programmable email is a great way to spread viruses. If the attacker can get the victim to somehow run an infected program, that program not only can damage the victim's system, it can use features, such as CDO, to email itself to additional victims. If you're writing an application that has the ability to open attached documents, be very careful to check an attachment's file type before opening it. Alert the user to potentially dangerous situations and, if possible, provide the ability to turn off attachment capability entirely in your application.

  13. Declare typed variables to reference CDO objects, rather than using dot notation.
  14. For example, instead of this one-liner:

    Debug.Print CdoSession.Inbox.Messages.Item(1).Subject

    code this longer, but better alternative:

    Dim CdoFolder As MAPI.Folder
    Dim CdoMessages As MAPI.Messages
    Dim CdoMessage As MAPI.Message

    Set CdoFolder = CdoSession.Inbox
    Set CdoMessages = CdoFolder.Messages
    Set CdoMessage = CdoMessages.Item(1)
    Debug.Print CdoMessage.Subject

    There are several reasons for this:

  15. Use filters to reduce the size of a collection to be searched.
  16. An inefficient way to find message items of interest is to iterate one by one through a CDO Messages collection, testing each Message object to see if it meets some criteria. A far better way to achieve the same result is to use CDO's MessageFilter object and let MAPI do the work for you. By setting properties on a MessageFilter object, its corresponding Messages collection shows only the message items that meet your criteria. Don't underestimate the importance of this mechanism. Consider a client accessing an email server over a dial-up line. Iterating through an entire Messages collection requires that all messages be transported over the dial-up line. In contrast, using a MessageFilter object causes only those messages that pass the filter to be transported over the dial-up line.

    For example, this code snippet shows how to retrieve only those messages having a message class of "IPM.MyMessageClass":

    ' CdoSession previously Dim'ed and Set.

    Dim CdoFolder As MAPI.Folder
    Dim CdoMessages As MAPI.Messages
    Dim CdoMessageFilter As MAPI.MessageFilter
    Dim CdoMessage As MAPI.Message

    Set CdoFolder = CdoSession.Inbox
    Set CdoMessages = CdoFolder.Messages
    Set CdoMessageFilter = CdoMessages.Filter

    ' Constrain the Messages collection.
    CdoMessageFilter.Type = "IPM.MyMessageClass"
    CdoMessageFilter.Unread = True

    For Each CdoMessage In CdoMessages
        ' Do something with the message.
    Next CdoMessage

    ' Clean up.
    Set CdoMessage = Nothing
    Set CdoMessageFilter = Nothing
    Set CdoMessages = Nothing Set CdoFolder = Nothing

  17. If you're doing CDO from a Web application, become familiar with IIS security mechanisms.
  18. Internet Information Server (IIS) has a flexible security mechanism that can seem difficult to work with until you become familiar with it. For example, you might have a Web-based CDO application that accesses users' Exchange mailboxes. This application might work successfully for months, only to break when you move IIS and Exchange onto separate machines to get better performance. You discover that the application works fine when Exchange is on the same machine as IIS, but you get access restrictions when IIS tries to access Exchange on a remote machine. Then you discover that if the servers are running Windows 2000, rather than NT, the problem goes away. What's going on? The answer lies in the way Windows NT and Windows 2000 handle user authentication, and in the way IIS piggybacks onto that authentication mechanism. The only way to work these issues out is to become familiar with the mechanism yourself.

    For more information, see Configuring Security for Internet Information Server, in the MSDN library.

  19. If your Web-based CDO application keeps generating an ASP 0115 error, restart your Web site and examine your CDO logon/logoff code.
  20. CDO is very picky about security context when logging on to a CDO session and then off again. Review the documentation for the CDO Rendering Library Application object's ImpID property and Impersonate method for details. Once the wrong security context is used for logging off, further attempts to use CDO result in the ASP 0115 error. At this point, the only remedy is to shut down and restart the site.

Dave Grundgeiger is a consultant at Tara Software in Madison, Wisconsin, where he spends his days immersed in Microsoft DNA technologies. He is a proficient C++ and Visual Basic designer/developer, specializing in multitier vertical market business solutions using Visual Basic, IIS, MTS/COM+, and SQL Server. Dave's research interests include Artificial Intelligence, with emphasis on Natural Language Processing. He is particularly interested in applying AI techniques in real-world business applications. In addition to writing CDO & MAPI Programming with Visual Basic for O'Reilly, Dave has written for MSDN Magazine and C/C++ Users Journal.


O'Reilly & Associates will soon release (October 2000) CDO & MAPI Programming with Visual Basic.

Copyright © 2009 O'Reilly Media, Inc.