CDO for Exchange Server 2000

[Previous] [Next]

Exchange Server 2000 contains a new version of CDO called CDO for Exchange 2000. This version of CDO builds on OLE DB, meaning that its object model is different from that of previous versions. For example, instead of having navigational objects, such as InfoStore, the new version of CDO relies on ADO for record navigation. Therefore, if you want to query Exchange Server for a specific set of records, you need to rely on ADO. However, if you want to perform collaborative functions on those records, you need to use CDO. You can retrieve items using ADO, and then open and process each item using CDO.

CDO adds collaborative functionality above and beyond that provided by ADO. If you need to create recurring meetings, ADO won't be very helpful—for example, you would have to determine which properties to set to make an appointment recur on the third Tuesday of every month. With CDO, however, you set some properties, save the appointment, and suddenly you have a recurring meeting. CDO does all the hard coding for you behind the scenes.

CDO and ADO were designed to work together. Both object models have the same Fields collection. Furthermore, CDO objects can be bound directly to ADO objects. This allows you to use the same connection with the Exchange server.

CDO Design Goals

Microsoft had a number of design goals in mind for the CDO object library. First, as just discussed, integrating with and extending ADO was key. Second, having learned from previous versions of the CDO object model, the CDO design team knew the model needed to be dual interfaced. Making the CDO object model dual interfaced meant that different development environments, such as Visual Basic, Microsoft Visual C++, and ASP, could take advantage of it. The third goal was that CDO adhere to Internet standards. Internet standards are now critical to CDO since it uses vCard, iCal, Lightweight Directory Access Protocol (LDAP), Multipurpose Internet Mail Extensions (MIME), MIME Encapsulation of Aggregate HTML Documents (MHTML), Simple Mail Transfer Protocol (SMTP), and Network News Transfer Protocol (NNTP). The final and probably most important goal when designing CDO was to make the developer's job easier by providing a rich set of objects on top of OLE DB for building collaborative applications.

CDO for Windows 2000

You might have seen CDO for Windows 2000. Consider this object model the little brother of CDO for Exchange Server 2000. CDO for Windows 2000 provides SMTP and NNTP support. CDO for Windows 2000 also provides support for protocol events such as SMTP events. However, CDO for Windows 2000 does not provide mailbox support or public folder support. CDO for Exchange Server 2000 provides these features and extends CDO for Windows 2000. If you get started with CDO for Windows 2000, you'll have a working knowledge of the basics of CDO for Exchange Server 2000.

CDO Object Model

The CDO object model consists of five main components. Notice I say components rather than objects, since the CDO object model contains dozens of objects. The five main components are messaging, calendaring, contacts, workflow, and management. We'll cover the most common tasks you'll perform with the CDO library in each of these areas, with the exception of management. I won't cover the specific properties and methods of these CDO object model components in great detail. Since the Exchange Server SDK provides extensive documentation on this subject, I'll refer you to the SDK on the companion CD for specific information.

NOTE
To see how you can use the CDO library to perform management tasks, such as setting storage limits and creating stores, look at the CDO for Exchange Management object model on the Exchange Server SDK, included on the companion CD.

Frequently Used Objects in CDO

You'll commonly work with two objects, the Configuration object and the DataSource object, on all CDO objects you use in your applications. Before we look at the most typical CDO functionality you'll use, let's examine these two objects.

Configuration Object

The Configuration object allows you to customize the parameters CDO uses and the way CDO works. For example, using the Configuration object, you could set the e-mail address of the message sender, set the proxy server to use, set the username and password if you require authentication via SMTP or NNTP, or select other configuration options. The following code, taken from the workflow process, sets the sender e-mail address for a meeting request to the notification address you specified in the setup program of the Training application:

 'Create a throwaway appointment set oAppt = CreateObject("CDO.Appointment") set oConfig = CreateObject("CDO.Configuration") strNotificationAddress = GetWorkflowSessionField("notificationaddress") oConfig.Fields(http://schemas.microsoft.com/cdo/ & _ "configuration/sendemailaddress") = strNotificationAddress oConfig.Fields.Update oAppt.Configuration = oConfig 

As you can see in the code, you use the Fields collection on the CDO Configuration object to set your properties. All the properties you can set are contained in the "http://schemas.microsoft.com/cdo/configuration" name space.

Another common scenario that you'll use the Configuration object for is setting the time zone for viewing appointments from Exchange Server. Remember that Exchange Server stores dates in UTC. Any dates you retrieve through ADO will be returned in UTC. However, you can use CDO to change UTC dates to local time zone dates for the client. Sometimes you might want to use a different time zone in your application than the one originally detected by CDO. The Configuration object allows you to do this. The following code changes the time zone to Mountain:

 Dim objAppt As New CDO.Appointment Dim objConfig As New CDO.Configuration objConfig.Fields(cdoTimeZoneID) = cdoMountain objAppt.Configuration = objConfig 

DataSource Object

The DataSource object provides access from CDO objects to data sources, such as the Web Storage System or Active Directory. You can use the DataSource object to open or save items to data sources from CDO. There are six methods on the DataSource object that you should become familiar with: Open, OpenObject, Save, SaveTo, SaveToContainer, and SaveToObject.

Open method

The DataSource object's Open method is similar to the Open method on the ADO Record object. The only difference is that ADO can create items using the Open method, while CDO cannot. This is the syntax for the Open method:

 Open( ByVal SourceURL as String, ByVal ActiveConnection as Object, [ByVal Mode as ConnectModeEnum], [ByVal CreateOptions as RecordCreateOptionsEnum], [ByVal Options as RecordOpenOptionsEnum], [ByVal UserName as String], [ByVal Password as String] ) 

A code example that uses the Open method in conjunction with an ADO Recordset is shown here:

 Dim rs as New Recordset Dim msg as New Message fldr = "file://./backofficestorage/domain/MBX/user/inbox" rs.Open "Select * from " & _ "scope('shallow traversal of " & _ " & fldr & "')" & _ "where urn:schemas:mailheader:subject = 'hello'" rs.MoveFirst msg.DataSource.Open rs("DAV:href"),rs.ActiveConnection 

OpenObject method

You can use the OpenObject method to open data from another object rather than from a data source such as Exchange Server. A common use for OpenObject is to open an embedded message in another message. This is the syntax for OpenObject:

 OpenObject(ByVal Source as Object, ByVal InterfaceName as String) 

The following code sample opens an embedded message within another message. The code assumes you already retrieved the object that represents the embedded message in a variable named oBodyPart.

 oDataSource.OpenObject oBodyPart, "IbodyPart" 

Save method

The Save method writes back data to the currently opened data source. This method is so simple that we won't even look at a code sample. You should, however, call this method if you change any values that need to be written back. You should also make sure you open the data source with the read/write flags; otherwise, you will receive an error.

SaveTo method

The SaveTo method allows you to save an item to a URL you specify. As you will see momentarily, this method differs from the SaveToContainer method, which doesn't let you specify a URL to the item that you want to create. Instead, the SaveToContainer method lets you specify the URL to the container where you want to save the item. When you use SaveToContainer, CDO generates a GUID to identify your item. This is actually quite useful because you do not have to worry about conflicting URLs when saving items. The syntax for the SaveTo method is shown here, along with a code sample:

 SaveTo( ByVal SourceURL as String, ByVal ActiveConnection as Object, [ByVal Mode as ConnectModeEnum], [ByVal CreateOptions as RecordCreateOptionsEnum], [ByVal Options as RecordOpenOptionsEnum], [ByVal UserName as String], [ByVal Password as String] ) 'Assume oMsg is a valid message Set oDataSource = oMsg oDataSource.SaveTo "PATHTOFOLDER/myitem.eml", _ MyCONN, _ adModeReadWrite, _ adCreateOverwrite 

SaveToContainer method

The SaveToContainer method, as just discussed, saves the item to a container you specify and assigns a GUID as the identifier for the item. Here is the syntax for the SaveToContainer method, along with a code sample taken from the Training application that saves a new course to the schedule folder:

 SaveToContainer( ByVal ContainerURL as String, ByVal ActiveConnection as Object, [ByVal Mode as ConnectModeEnum], [ByVal CreateOptions as RecordCreateOptionsEnum], [ByVal Options as RecordOpenOptionsEnum], [ByVal UserName as String], [ByVal Password as String] ) with iAppt .Fields("DAV:contentclass").Value = _ "urn:content-classes:trainingevent" .Fields(strSchema & "instructoremail").Value = _ Cstr(Request.Form("email")) .Fields(strSchema & "prereqs").Value = CStr(Request.Form("prereqs")) .Fields(strSchema & "seats").Value = CStr(Request.Form("seats")) .Fields(strSchema & "authorization").Value = _ Cstr(Request.Form("authorization")) .Fields(strSchema & "category").Value = cStr(Request.Form("category")) .Fields("http://schemas.microsoft.com/mapi/proptag/" & _ "x001A001E").Value = "IPM.Appointment" .Fields.Update end with iAppt.DataSource.SaveToContainer strScheduleFolderPath 

SaveToObject method

The SaveToObject method allows you to save data to a run-time object rather than to a data source. SaveToObject works the same way as the OpenObject method, except that you're saving information rather than opening it.

CDO Messaging Tasks

In this section, we'll look at some of the most common CDO messaging tasks you can perform. But first you need to know how MIME works, since CDO leverages MIME to read and store content.

The MIME specification divides a message body into parts separated by boundary tags. This enables a mail reader to discern where the logical breaks between parts occur. The message body parts can contain child parts or data. MIME body parts can have one of two content types: singular parts or multiple parts. The nice thing about CDO is that, unless you really want to, you don't have to deal with the MIME stream itself; CDO provides an easy object model to manipulate MIME. By supporting MIME, CDO allows you to send complex messages, such as embedded messages, as well as messages that contain HTML pages. The following is an example of a MIME message:

 From: "Thomas Rizzo" <thomriz@microsoft.com> To: "Stacy" <stacy@test.com > Subject: Text and HTML Message Date: Tue, 7 Mar 2000 3:32:48 _0700 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_123" ------=_ 123 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable This is a multipart/alternative text & html message. ------=_ 123 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable <HTML> <BODY>This is a multipart/alternative text &amp; html message.</FONT> </BODY></HTML> ------=_123-- 

Now we're ready to discuss the various CDO messaging tasks.

Sending a Standard Message

Sending an e-mail using CDO is straightforward. You simply create the CDO message object, address the message, set the subject and body, and then send the message. We'll look at some of the more complex tasks you can perform with CDO messages in a moment. The code for sending a simple message is shown here:

 set oMsg = createobject("CDO.message") oMsg.To = "stacy@test.com" oMsg.From = "bob@test.com" oMsg.Subject = "Hello world!" oMsg.AutoGenerateTextBody = True oMsg.MimeFormatted = True oMsg.HTMLBody = "<HTML><BODY>This is HTML!</BODY></HTML> oMsg.Send 

Sending an MHTML Message

In addition to sending a simple HTML message, CDO allows you to send a message with an entire Web page embedded in it. The MHTML standard enables you to take HTML content, convert it into MIME, and embed it in an e-mail message. In CDO, creating an MHTML message is as easy as calling a single method: CreateMHTMLBody. This method takes the following parameters: the URL of the Web resource you want to embed; flags that specify any content you don't want to embed, such as sounds or images; and if the Web site that you're embedding requires authentication, a username and password. The following code embeds the Microsoft Exchange Web site into an e-mail and mails it:

 Set oMsg = CreateObject("CDO.Message") oMsg.To = "test@test.com" oMsg.Subject = "Exchange Web site" oMsg.CreateMHTMLBody "http://www.microsoft.com/exchange" oMsg.Send 

Adding an Attachment

CDO makes adding attachments easy too. CDO supports an Addattachment method, which takes as a parameter a URL for the resource you want to add, and if that resource requires authentication, a username and password. If successful, CDO will return to you the MIME body part that corresponds to the new attachment. Adding an attachment is shown here:

 Dim oMsg as New CDO.Message Dim oBp as CDO.IBodyPart Set oBp = oMsg.AddAttachment("http://www.microsoft.com/myfile") Set oBp = iMsg.AddAttachment("c:\docs\my.doc") Set oBp = iMsg.AddAttachment("file://mypublicshare/docs/mydoc.doc") iMsg.Send 

Adding Mail Headers

You can now access mail headers directly from CDO. Most of the properties that you'll want to access in the mail header already are exposed as top-level properties in CDO. For example, you could look in the mail header to see who a message is from and who it will be sent to. However, CDO already has two properties that perform this service for you: From and To. You instead might want to access the mail headers for a message you're having a problem with, if CDO doesn't provide an object for the header you're interested in or if you want to get and set custom headers. The following code sets some built-in and custom headers in an e-mail message:

 Dim oMsg as New CDO.Message Dim oFlds as ADODB.Fields Set oFlds = oMsg.Fields With oFlds .Item("urn:schemas:httpmail:to") = "test@test.com" .Item("urn:schemas:httpmail:from") = "stacy@test.com" .Item("urn:schemas:mailheader:mycustomheader") = "test" .Update End With 

Resolving Addresses

Before adding addresses to the To, CC, or BCC properties on a CDO Message object, you might want to resolve the address against a directory or the Contacts folder to make sure the address is correct. The way to resolve addresses is to use the CDO Addressee object. This object has a number of properties such as the DisplayName or EmailAddress properties that you can fill out to try and resolve an address. The names of these properties clue you in to what values should go in them. Once you create the Addressee object and fill in one of the two properties described above, you can call the CheckName method, which takes either an LDAP path to your Active Directory or the file path to a Contacts folder contained in Exchange Server 2000.

If the address can be resolved without ambiguous names, you can use some other properties on the Addressee object to get more information about the person. For example, the DirURL property returns either the Active Directory path or the File path to a contact, depending on whether you are validating the address against the Active Directory or the Contacts folder. You can also call the ResolvedStatus property, which will contain a 0 for unresolved, 1 for resolved, and 2 for ambiguous. If you get an ambiguous address, you can use the AmbiguousNames property to return the Addressees collection, which is made of Addressee objects that are ambiguous with respect to your current Addressee object.

The following sample shows you how to use the properties and methods just described:

 Dim oAddressee as New CDO.Addressee 'Use the Display Name oAddressee.DisplayName = "Thomas Rizzo" 'Use the Active Directory oAddressee.CheckName "LDAP://thomriznt5srv" if oAddressee.ResolvedStatus = 1 then 'Resolved msgbox oAddressee.DirURL & vblf & oAddressee.EmailAddress end if 'Use the E-mail Address Dim oAddressee2 as New CDO.Addressee oAddressee2.EmailAddress = "thomriz@thomriznt5dom.microsoft.com" 'Use a Contact folder oAddressee2.CheckName "file://./backofficestorage/" & _ "thomriznt5dom.microsoft.com/public folders/contacts" if oAddressee2.ResolvedStatus = 2 then 'Ambiguous set oAddressees = oAddressee2.AmbiguousNames for each otmpAddressee in oAddressees 'Scroll through the ambiguous addressees msgbox otmpAddressee.EmailAddress next end if 

CDO Calendaring Tasks

The new version of CDO provides some invaluable calendaring features. For example, if you have the correct permissions, you can open other users' calendars and perform operations on those calendars. Also, you can use public folder calendars. Plus, CDO directly supports iCalendar, which allows you to send meeting requests in a standard format that other clients can understand. The following sections show you the most common tasks you'll perform with the CDO calendaring component.

Creating Appointments

Creating appointments by using CDO is as easy as creating a new CDO Appointment object, specifying some properties, and using the Datasource interface on the Appointment object to save the appointment into a folder. This process is shown in the following sample:

 Dim oAppt As New Appointment sCalendarURL = "file://./backofficestorage/thomriz.com/MBX/User/Calendar/" 'Set the appointment properties oAppt.StartTime = #2/14/2000 12:30:00 PM# oAppt.EndTime = #2/14/2000 1:30:00 PM# oAppt.Subject = "Shop for Valentine's Day present!" oAppt.Location = "Gift Store" oAppt.TextBody = "Don't forget this year!!!!" 'Save the appointment oAppt.DataSource.SaveToContainer sCalendarURL 

Creating Meeting Requests and Checking Free/Busy Information

In addition to creating appointments in a calendar, you can create meeting requests. To do so, create an appointment and then add the names of the desired attendees. When generating a meeting request, you can also retrieve the free/busy information for all attendees. The following code creates a meeting request, finds the first available slot of free/busy time for an attendee, and sends the meeting request to the attendee:

 Dim oAppt As New CDO.Appointment Dim oAttendee As CDO.Attendee Dim oAddressee As New CDO.Addressee oAddressee.EmailAddress = "bobw@thomriznt5dom.extest.microsoft.com" 'Check the address against the local directory 'You could also specify any LDAP path oAddressee.CheckName ("LDAP://thomriznt5dom.extest.microsoft.com") If oAddressee.ResolvedStatus = cdoResolved Then 'Create an hour meeting sometime on March 7th 'Get the free/busy information. strFB = oAddressee.GetFreeBusy(CDate("3/7/2000 9:00:00 AM"), _ CDate("3/7/2000 5:00:00 PM"), 60) 'Returns a string of 0,1,2,3 '0 - Free, 1 - Tenative, 2 - Busy, 3 - OOF, 4 - No F/B data 'Find the first free spot by looking for 0 bFoundFB = False For i = 1 To 8 'Look for a free spot If Mid(strFB, i, 1) = 0 Then dStart = DateAdd("h", i, CDate("3/7/2000 8:00 AM")) dEnd = DateAdd("h", 1, dStart) bFoundFB = True Exit For End If Next If bFoundFB = True Then Dim oConfig As New CDO.Configuration oConfig.Fields("http://schemas.microsoft.com/cdo/" & _ "configuration/sendemailaddress") = _ "thomriz@thomriznt5dom.extest.microsoft.com" oConfig.Fields("http://schemas.microsoft.com/cdo/" & _ "configuration/calendarlocation") = _ "file://./backofficestorage/" & _ "thomriznt5dom.extest.microsoft.com/MBX/thomriz/calendar" oConfig.Fields.Update oAppt.Configuration = oConfig oAppt.StartTime = dStart oAppt.EndTime = dEnd oAppt.Subject = "Meeting" oAppt.Location = "Your office" oAppt.TextBody = "Meeting with you!" Set oAttendee = oAppt.Attendees.Add oAttendee.Address = oAddressee.EmailAddress oAttendee.Role = cdoRequiredParticipant Set oCalMsg = oAppt.CreateRequest oCalMsg.Message.Send strCalendarURL = _ "file://./backofficestorage/" & _ "thomriznt5dom.extest.microsoft.com/MBX/thomriz/calendar" 'Save to organizer calendar oAppt.DataSource.SaveToContainer strCalendarURL End If End If 

Notice that the code uses the Addressee object. This object allows you to create and resolve addresses using LDAP with a directory server. Once the attendee is resolved, the free/busy information is retrieved for the attendee by using the GetFreeBusy method. This method takes the start time, end time, and the interval in minutes that you want to break the free/busy information into.

The code then checks for the first time when the attendee is free. Next, the code creates an appointment, fills out the appropriate fields, and then calls the CreateRequest method. This method returns a CalendarMessage object. You can then call the contained Message object's methods, such as Send. Finally, the code then saves the appointment to the calendar.

Creating Recurring Meeting Requests

To create a recurring meeting request, you simply add a RecurrencePattern object to the appointment and set some properties on it. If you want to get more complex, you can add an Exception object to the RecurrencePattern object to specify that a certain date should be excluded from the meeting request. The following code shows how to create a simple recurring meeting request:

 Dim oAppt As New CDO.Appointment Dim oAttendee As CDO.Attendee Dim oAddressee As New CDO.Addressee Dim oRP As CDO.IRecurrencePattern oAddressee.EmailAddress = "bobw@thomriznt5dom.extest.microsoft.com" 'Check the address against the local directory. 'You could also specify any LDAP path. oAddressee.CheckName ("LDAP://thomriznt5dom.extest.microsoft.com") If oAddressee.ResolvedStatus = cdoResolved Then Dim oConfig As New CDO.Configuration oConfig.Fields("http://schemas.microsoft.com/cdo/" & _ "configuration/sendemailaddress") = _ "thomriz@thomriznt5dom.extest.microsoft.com" oConfig.Fields("http://schemas.microsoft.com/cdo/" & _ "configuration/calendarlocation") = _ "file://./backofficestorage/" & _ "thomriznt5dom.extest.microsoft.com/MBX/thomriz/calendar" oConfig.Fields.Update oAppt.Configuration = oConfig oAppt.StartTime = dStart oAppt.EndTime = dEnd oAppt.Subject = "Meeting" oAppt.Location = "Your office" oAppt.TextBody = "Meeting with you!" Set oRP = oAppt.RecurrencePatterns.Add("ADD") 'Make it weekly oRP.Frequency = cdoWeekly oRP.Interval = 1 oRP.Instances = 10 Set oAttendee = oAppt.Attendees.Add oAttendee.Address = oAddressee.EmailAddress oAttendee.Role = cdoRequiredParticipant Set oCalMsg = oAppt.CreateRequest oCalMsg.Message.Send strCalendarURL = _ "file://./backofficestorage/" & _ "thomriznt5dom.extest.microsoft.com/MBX/thomriz/calendar" 'Save to organizer calendar oAppt.DataSource.SaveToContainer strCalendarURL End If 

The code creates the RecurrencePattern object by using the RecurrencePatterns collection on the Appointment object. The Add method of this collection has only two values that you can pass to its parameter: ADD and DELETE. Once the new RecurrencePattern object has been added to the collection, the code sets the properties on the object to make the recurrence weekly, specifying only 10 recurrences. If you do not specify the instances, CDO will make the meeting occur indefinitely.

Creating Exceptions

You can create exceptions to your recurring meetings or appointments by using the CDO Exceptions and the Exception object. I'll show you a simple example here of adding a single Exception to a recurring appointment, but you can do more complex operations with the CDO Exception object. The following code sample uses the CDO Exceptions collection to add a new exception to a recurring meeting. You can also delete and modify exceptions using the CDO Exceptions collection.

 Set oException = oAppt.Exceptions.Add("Add") oException.StartTime = "5/2/2000 10:00AM" oException.EndTime = "5/2/2000 11:00 AM" 

Responding to a Meeting Request

You can use CDO calendaring to accept, decline, or mark tentative a meeting request. Since this operation is quite easy, I'll just show you the code. This code sample assumes that the meeting request you want to process is in your Inbox and is already assigned to the oAppt object:

 Set oMsg = oAppt.Accept 'You can then modify the response message by modifying oMsg oMsg.Message.Send 'Save the appointment to your calendar oAppt.DataSource.SaveTo URLTOYOURCALENDAR 

Opening Other User's Mailbox Folders

To open another user's folder or folders, all you need to do is pass in the path to that folder either to a Record object or to a query that returns an ADO Recordset. The following example opens up Neil Charney's Calendar folder. To open another user's folder, you must have permissions on that user's folders.

 Dim oRecord as New ADODB.Record oRecord.Open "file://./backofficestorage/domain/MBX/neilc/calendar/" 

Working with Time Zones

One the first issues you have to deal with when working with CDO calendaring functionality, and even when working with ADO, is the storage of dates in UTC in Exchange. CDO will offset the UTC date to the local time zone specified in the CDO Configuration object. If you do not explicitly set a time zone, CDO will use the time zone of the machine. This functionality is different from the way in which ADO handles time zones; ADO does no offset at all and will return the date in UTC. You can run into some very strange debugging issues if you forget this fact—if you create event registrations or calendar appointments using ADO and then look at those items through CDO, you will see different dates.

Time zones play an important role in the Training application when setup creates event registrations for the survey and creating course notification events. To use ADO to create the event registrations so that the events fire daily at 10 PM local time on the server, the application has to figure out the offset from 10 PM local time to UTC time. The following code does this by leveraging CDO to create an appointment at 10 PM local time. The code then retrieves that appointment using ADO, which returns the start time for the appointment at UTC, not at 10 PM local time. The code then figures out the offset between UTC and local time on the server by using the DateDiff function. This information is used by the application event handlers to make sure that the ADO query to find all items created in the last 24 hours finds those items with the correct date and time. You need to figure out the UTC offset because Exchange stores the creation dates of items in UTC. Otherwise, you will not really query for items created in the past 24 hours in local time.

 'Figure out start time for timer events. 'Since the start time needs to be UTC, we need to figure 'out the local server time and then figure out the UTC 'time to tell the event to fire so that it is 10 PM. Dim oAppt As CDO.Appointment Set oAppt = CreateObject("CDO.Appointment") oAppt.Subject = "Delete me" If DateDiff("n", Now, Date & " 10:00 PM") < 60 Then If DateDiff("n", Now, DateAdd("h", 1, Date & " 10:00 PM")) <= 60 Then 'We're passing 10 PM for the current day dDate = DateAdd("d", 1, Date) Else dDate = Date End If Else dDate = Date End If oAppt.StartTime = DateValue(dDate) & " 10:00 PM" oAppt.EndTime = DateAdd("n", 60, oAppt.StartTime) strTime = TimeValue(oAppt.StartTime) 'Dump the appt into the root folder oAppt.DataSource.SaveToContainer strPath strdeletehref = oAppt.Fields("DAV:href").Value Set oAppt = Nothing 'Get it back Dim oDeleteRecord As New ADODB.Record oDeleteRecord.Open strdeletehref, , adModeReadWrite strNow = oDeleteRecord.Fields("urn:schemas:calendar:dtstart").Value 'Figure out the offset from UTC to the local time zone. 'This is needed for the survey notification event handler 'so that it knows how much to offset its query for items created 'during the current day. strDate = oDeleteRecord.Fields("urn:schemas:calendar:dtstart").Value strLocDate = dDate & " " & strTime iDiff = DateDiff("h", strDate, strLocDate) 'Delete it oDeleteRecord.DeleteRecord 

CDO Contact Tasks

CDO implements a Person object for working with contacts in both the Exchange Server store and Active Directory. Using this object, you can create and query contact objects in Exchange Server and Active Directory. CDO will handle all the property mapping between Exchange Server and Active Directory. The CDO Person object is very straightforward, so instead of telling you all the properties you can set on this object, I'll just show you some code samples.

Creating a Contact in Exchange Server

Creating a contact in Exchange Server is as easy as creating a CDO Person object, setting several properties, and then calling SaveToContainer. The following code shows these steps:

 Dim oPerson As New CDO.Person strContactURL = _ "file://./backofficestorage/thomriznt5dom.extest.microsoft.com/" & _ "public folders/group contacts/" oPerson.FirstName = "Thomas" oPerson.LastName = "Rizzo" oPerson.Company = "Microsoft" oPerson.WorkStreet = "1 Microsoft Way" oPerson.WorkCity = "Redmond" oPerson.WorkState = "WA" oPerson.WorkPostalCode = "98052" oPerson.Email = "thomriz@microsoft.com" oPerson.WorkPhone = "425 555 1212" oPerson.Email2 = "test@test.com" 'Save the Person objectto the folder oPerson.DataSource.SaveToContainer strContactURL 

Creating a Contact in Active Directory

Creating a contact in Active Directory is similar to creating a contact in an Exchange Server folder. The only difference is that you provide an LDAP URL rather than a file URL, as shown here:

 strContactURL = "LDAP://thomriznt5srv/cn=tomrizzo,cn=users," & _ "dc=extest,dc=microsoft,dc=com" oPerson.FirstName = "Thomas" oPerson.LastName = "Rizzo" oPerson.Company = "Microsoft" oPerson.WorkStreet = "1 Microsoft Way" oPerson.WorkCity = "Redmond" oPerson.WorkState = "WA" oPerson.WorkPostalCode = "98052" oPerson.Email = "thomriz@microsoft.com" oPerson.WorkPhone = "425 555 1212" oPerson.Email2 = "test@test.com" 'Save the Person object to the folder oPerson.DataSource.SaveToContainer strContactURL 

Saving Your Contact as a vCard

CDO allows you to access or create vCard information for your contacts. vCard is a standard way of describing contact information on the Internet. CDO vCard support allows you to send or save your contacts to any compliant vCard system. You get the vCard information by using the GetVCardStream method, which returns the information about a contact in vCard format to an ADO Stream object. The following code uses the GetVCardStream method to retrieve the vCard information and print it to the screen for a contact:

 Dim oPerson as New CDO.Person oPerson.DataSource.Open "file://./backofficestorage/domain/folder/name.eml" oPerson.GetVCardStream.SaveToFile "c:\vcard.txt" 

The output from running the preceding code, which is contained in the text file vcard.txt, is shown here:

 BEGIN:VCARD VERSION:2.1 N:Rizzo;Thomas FN:Thomas Rizzo ORG:Microsoft Corporation TITLE:Product Manager NOTE;ENCODING=QUOTED-PRINTABLE:=0D=0A TEL;WORK;VOICE:(425) 555-1212 ADR;WORK:;;1 Microsoft Way;Redmond;WA;98052;United States of America LABEL;WORK;ENCODING=QUOTED- PRINTABLE:1 Microsoft Way=0D=0ARedmond, WA 98052=0D=0AUnited States of America URL: URL:http://www.microsoft.com/exchange EMAIL;PREF;INTERNET:thomriz@microsoft.com REV:20000410T033803Z END:VCARD 

CDO Folder Tasks

CDO provides a Folder object that allows you to create or access folders contained in the Exchange database. Using the Folder object, you can retrieve the number of read and unread items contained in the folder. You will interact most with the Folder object's properties. These properties include the following: Configuration, ContentClass, DataSource, Description, DisplayName, EmailAddress, Fields, HasSubFolders, ItemCount, UnreadItemCount, and VisibleCount.

Most of these properties are straightforward. The only one that really needs explaining is the VisibleCount property. This property is the total number of hidden items in the folder. Hidden items are created in the associated Contents table. These items can be created by setting the DAV:ishidden property to True.

Creating a Folder

To create a folder using the CDO Folder object, you need to first create a CDO Folder object and then use the Datasource property to save the folder. The following example shows you how to create a folder using CDO:

 Dim oFolder As New CDO.Folder oFolder.Description = "This is my folder" oFolder.ContentClass = "urn:content-classes:contactfolder" oFolder.Fields("http://schemas.microsoft.com/exchange" & _ "/outlookfolderclass") = "IPF.Contact" oFolder.Fields.Update oFolder.DataSource.SaveTo "file://./backofficestorage/" & _ "thomriznt5dom.extest.microsoft.com/public folders/my contact folder" 

Mail-Enabling Folders

With the addition of new top-level hierarchies, Exchange Server 2000 does not, by default, mail-enable folders in the new hierarchies. Therefore, you will want to mail-enable the folders either through the administrative UI or programmatically. To programmatically mail-enable a folder is quite easy. All you need to do is use the IMailRecipient interface from the CDO for Exchange Management library. To retrieve the interface, set a variable to the IMailRecipient interface. Then set the value of that variable to be your CDO folder. Call the MailEnable method on the folder. Make the changes to the properties on the IMailRecipient interface. For example, set up the alias, establish the smtp e-mail address, and decide whether the new address should be hidden from the address book. Once you are finished setting the properties, just save the folder back to the Exchange database. Remember that you will need to open the folder in the read/write mode using the CDO Folder object, as shown in the following code:

 Dim oFolder As New CDO.Folder Dim oRecip As CDOEXM.IMailRecipient oFolder.DataSource.Open "file://./backofficestorage/" & _ "thomriznt5dom.extest.microsoft.com/public folders/my contact folder", _ , adModeReadWrite Set oRecip = oFolder oRecip.MailEnable oRecip.SMTPEmail = "contacts@domain.com" oRecip.HideFromAddressBook = False oRecip.Alias = "My Contacts Folder" oFolder.DataSource.Save 



Programming Microsoft Outlook and Microsoft Exchange
Programming Microsoft Outlook and Microsoft Exchange, Second Edition (DV-MPS Programming)
ISBN: 0735610193
EAN: 2147483647
Year: 2000
Pages: 184

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net