How to get the EntryID of a mailitem that is encrypted

63 Views Asked by At

In a VSTO Outlook C# addin I want to loop through a folder of items that are all encrypted mailitems and get the EntryID or MAPIOBJECT as I plan to send it on to extended MAPI.

foreach (object olObject in folder.Items)
{
    if (olObject is Outlook.MailItem olM)
    {
        //olM.EntryID fails
    }
}

Where mailitems are encrypted with PKI and the private key is stored on a personal card inserted into the PC, the user must have at least opened 1 encrypted mailitem for the OOM to be able to read properties of a mailitem. At the time of looking at the folder items I do not know if this is the case or not.

I have found that if I cast an Outlook.Selection to a mailitem I can then get the entryID. Would there be some way of doing the same with folder.Items?

I also note that mailItem.MAPIOBJECT will also throw an exception if no encrypted items have been viewed by the user.

The problem with hitting this error is not catching it, it is that Outlook takes too long to throw an exception. Is there any way to quickly workout that Outlook cannot read the encrypted items yet?

The only option I see at the moment is to wait for an inspector window to open on a mailitem that was encrypted. The problem with this is that if the user takes their card out then no encrypted mail items can be read.

UPDATE With respect to knowing if Outlook can read encrypted emails or not Dmitry below in the comments has confirmed you cannot, my current strategy is to listen for an inspector window to open with a mailitem that is encrypted. If this is open it means that the user has entered their pin for the card in their reader and supplied Outlook with access to their private key to decrypt that mailitem. From this point all mailitem properties like EntryID or MAPIOBJECT do not error for all mailitems, until either Outlook is closed or the card is pulled from the reader. In this case I am using Net.Pkcs11Interop to detect card readers, cards, certificates events. I am also going to check out the Windows.Devices.SmartCards Namespace in UWP world as this might be a little easier.

2

There are 2 best solutions below

3
Dmitry Streblechenko On BEST ANSWER

Do not just loop through all items in a loop - use MAPIFolder.GetTable to retrieve multiple properties from multiple items in a single call. Besides being able to retrieve the entry ids of encrypted messages, the call will also be be much faster.

6
Eugene Astafiev On

Try to check out the MessageClass property first. Encrypted emails have IPM.Note.SMIME value set.

However, remember that third-party add-ins may encrypt messages without changing the message class or security flags. They will look like a regular email. In that case, you will have to parse the message body to detect them.

Also you may check the PR_SECURITY_FLAGS property value.

    Const PR_SECURITY_FLAGS = "http://schemas.microsoft.com/mapi/proptag/0x6E010003"
    Const SECFLAG_ENCRYPTED As Long = &H1    

    Dim SecFlags As Long

    ' Get current flags value
    SecFlags = oItem.PropertyAccessor.GetProperty(PR_SECURITY_FLAGS)