So there’s a bug/limitation/pile-o-crap in CDO (the programmatic interface to use MAPI (the programmatic interface to get at & use Outlook or Exchange stuff)). A key bit from the MSDN CDO reference:
Calendar folders are not supported in the public folders store provided with Microsoft® Exchange, and AppointmentItem objects are stored as Message objects. An attempt to read IsRecurring in this case returns CdoE_NO_SUPPORT.
This has majorly stunk for me, since I’m doing a project which needs to dump out some Exchange Public Calendars’ AppointmentItems, and to use their StartDate and EndDate properties. Common refrains to this song and dance:
Public member ‘StartDate’ on type ‘Message’ not found.
and Public member ‘EndDate’ on type ‘Message’ not found.
- Ok, I’ll follow the guru’s advice, and explicitly force it to an AppointmentItem:
ctype(oMsg, MAPI.AppointmentItem)
… Nope, I still hear: Specified cast is not valid.
- But wait, what’s the
oMsg.Type
?? IPM.Appointment
is my answer. Well… (dead end).
Fortunately there’s this: MAPI Property Tags. I can get at those two properties via CdoPR_START_DATE and CdoPR_End_DATE.
Solution:
DIM dtStartDate as Date = oMsg.Fields(MAPI.CdoPropTags.CdoPR_START_DATE).Value
DIM dtEndDate as Date = oMsg.Fields(MAPI.CdoPropTags.CdoPR_End_DATE).Value
Not really properties, but something to work with at least.
UPDATE:
I hit the same problem with getting the users who originally posted and last modified an item, except worse — they seem to be documented nowhere. I reverse-engineered the fields collection (dumped the data, looked for what I wanted, found the matching ID, converted to a hexadecimal property tag), and found them:
CONST CDoPR_RE_PostedBy = &H3FF8001F
CONST CDoPR_RE_ModifiedBy = &H3FFA001F
DIM strPostedBy as String = oMsg.Fields(CDoPR_RE_PostedBy).Value
DIM strModifiedBy as String = oMsg.Fields(CDoPR_RE_ModifiedBy).Value
I don’t see these tags in the CDO Property Tag list, and google searches for them come back empty. (That said, consider my discovery subject to change with future versions.)
Too bad there also seems to be no way to use these property tags with a MessageFilter, or to get RecurrencePattern.
Unfortunately, this is part of a bigger problem. I’m not sure, but I suspect CDO was simply never finished. Get this: If you want to open a user-created folder, there’s no way to do so directly by name. The normal method, getFolder()
, only accepts a 76-digit FolderID! There is a solution, but ain’t pretty.
Here’s another bonus from that same link:
If your application is running as a Microsoft® Windows NT® service, you cannot access the Microsoft Exchange Public Folders through the normal hierarchy because of a notification conflict. You must use the InfoStore objects Fields property to obtain the Microsoft Exchange property PR_IPM_PUBLIC_FOLDERS_ENTRYID, property tag &H66310102. This represents the top-level public folder and allows you to access all other public folders through its Folders property.
…And yes, that seems to apply to ASP.net applications.
Another gem (this seems so ludicrous that I want to doubt it): CDO MAPI in ASP.net needs to run with impersonation, even if the authenticated user has a matching Exchange account. It did fix my problem, though, so there’s some more anecdotal evidence. (Perhaps it’s actually the old Windows domain double-hop bug?)
In general, I’ve noticed CDO seems to require a whole lot of Hex flags to do simples operation like open a message object. …Well, a whole lot for what should is supposed to be object-oriented code. I’ve been wrapping up most of these basic operations with a class, but the vast amount of CDO hacks contained are too ugly to be seen here anytime soon.
SO, Lemsons and the rest of the Exchange Team, have you touched CDO in the last 5 years??? It sure seems to be a stunted and abandoned technology.
good resource:
CDO Live (almost as outdated as CDO itself, though)