1
votes

I have an Outlook COM add-in (C#, Visual Studio 2012) that extends the standard form with additional message properties. The add-in works with Outlook 2010, 2013 and 2016.

The requirements for the add-in dictate that it supports reading and writing a set of properties in namespace PS_INTERNET_HEADERS. I follow the guidelines in http://blogs.technet.com/b/exchange/archive/2009/04/06/3407221.aspx to have such headers on incoming messages promoted to MAPI properties.

But as I understand it, all such headers will become MAPI string properties, right?! But several of these headers actually have more natural types. One the headers is an RFC5322 date-time header and will have a value like 'Wed, 28 Sep 2016 06:27:00 GMT'. Having such a header mapped to a MAPI property of type PT_UNICODE is not optimal as you cannot sort messages based on it, you cannot really use it in searches, etc.

Is there a good solution to this problem?

The only idea I have is to do some kind of mapping from properties in namespace PS_INTERNET_HEADERS to properties in namespace PS_PUBLIC_STRINGS. That would would also have the nice side-effect that properties will be included when printing messages. But if I have to go down that road, I need some kind of hook for doing the mapping. I can of course loop through all messages in a message store, listen for new messages coming in, listen for changed messages, etc - but it does not feel like a good solution. I guess I could also write an Exchange Transport Agent, but I would really like to keep logic on the client side.

Any suggestions?

Edit after Dmitry's comment:

For outgoing messages, I have to use properties in namespace PS_INTERNET_HEADERS since such messages are eventually transported by SMTP (outside Exchange) to other systems. In detail, I have to adhere to https://www.rfc-editor.org/rfc/rfc6477. As a side-effect, Exchange will for incoming messages promote such headers to properties in namespace PS_INTERNET_HEADERS. And that's all working fine.

But even in that case, I would like to follow your suggestion to extract properties explicitly in my code and write some new ones in namespace PS_PUBLIC_STRINGS. The challenge as I see it is which hook to use for running that code. Users should be able to use the mapped properties as columns in views, for sorting, for filtering, for search, inbox rules, etc. I can sweep entire message stores to do that mapping, I can listen for various Outlook object model events, but in the end I have a hard time seeing how I can avoid users to temporarily see messages that my code haven't treated yet.

I have an old add-in written in C++ using Extended MAPI with a similar challenge. On start-up, for each inbox in each IMsgStore it sweeps the entire inbox (potentially a quite expensive operation) and then subscribes to changes using IMAPIFolder::GetContentsTable and then IMAPITable::Advise. But my experience is that I will get table notifications TABLE_ERROR or TABLE_RELOAD now and then and will have to do another sweep. For IMsgStore::Advise I guess similar challenges are present?! In a C# context, I could use the events in Redemption class RDOStore (e.g. OnMessageModified) , but I assume that class uses IMsgStore::Advise?!

1
Yes, your assumptions are correct. But you should be able to modify the view to show properties in the PS_INTERNET_HEADERS namespace. They don't need to be PS_PUBLIC_STRINGS - the view XML uses DASL property names.Dmitry Streblechenko
I have the view in place, no problem. Also installed a plain old .cfg file with property definitions. But my problem remains: string properties containing date-time values can be shown, but you cannot use them for sorting, filtering, and similar things - that's my real issue.Lars Iversen
Then you really have to choice but to set the PT_SYSTIME property explicitly in your code...Dmitry Streblechenko
And the best hook for running that code? The above-mentioned events?Lars Iversen
IMAPITable::Advise would do the job. What I'd do differently is add an extra Boolean property to stamp the messages that you did process (whether the custom property was extracted or not) . This way you will only have to query for message in the Inbox folder where the property is not set using RES_EXISTS restriction.Dmitry Streblechenko

1 Answers

1
votes

No, the property type will never to converted. It always stay as a string. Why not read the internet headers from the PR_TRANSPORT_MESSAGE_HEADERS property (DASL name http://schemas.microsoft.com/mapi/proptag/0x007D001F) and extract the properties explicitly in your code? You will have full control over which properties are extracted and how they are converted.