1

I have found ways to use C# to extract information from outlook *.msg files, such as sender, subject, recipients, etc.

I would like to save this information as metadata (properties?) that can be viewed and sorted as columns in Windows Explorer details view.

1: Do msg files already have properties I can use for this purpose?

2: If so, is there an easy way to set these properties using C#?

3: If not, is there a way to register custom properties for msg files, and then set them programatically?

If it comes to option 3, I found the following guide to creating shell extensions: http://www.codeproject.com/Articles/830/The-Complete-Idiot-s-Guide-to-Writing-Shell-Extens

But I haven't started reading it yet, because I'm not sure it's necessary, nor am I sure it would work as a solution.

Thanks!

[ETA some follow-up based on additional research]

Apparently starting with Windows Vista, all properties displayed in Windows Explorer Detail view must be stored within the file itself.

Reading and writing of these properties in Windows Explorer is facilitated through "Property Handlers."

In Windows XP, an alternate option was available through "Column Handler" shell extensions, which allowed metadata to be stored outside of the file and viewed as columns in Windows Explorer. This option was removed beginning in Vista, supposedly because of concerns with losing metadata associated with files when they are transported or stored in a non-NTFS partition. The third party file manager Explorer2 still supports Windows-XP style column handlers in Windows Vista and 7, but it is not possible to view or edit this metadata in Windows Explorer.

As far as I can tell, the Outlook *.msg file format does not have any properties associated with it by default in Windows 7. It may be possible to write a property handler for the file type, but doing so is beyond my skill set.

Jeff MH
  • 21
  • 1
  • 3

2 Answers2

0

i have the same probem, no solution yet but a product (outlook addin, no other stuff installed)messagesave has an advanced option to save data for them to be presented/understood by explorer: author, comments(recipient list), category(A if attachment exists). i see a binary diff of the output of two .msg files (with and without the 'save data' option) and the diff is all over the place. so i am looking at the .msg format spec to see if there's anything I can do there. the .msg file can be viewed in explorer columns even w/o the messagesave installed, and on a flash fat32 drive. so i guess it's indeed stored in the mapi property but i don't know which ones which explorer looks at...

0

This is quite old, but I recently ran into the same issue. I am aware of MessageSave (http://www.techhit.com/messagesave/), however, I already have all the msg files created, and I wanted to just add the Author property to them.

I finally figured out that the solution is to use DSOFile.dll. Opening a msg with DSOFile, and then setting the SummaryProperties.Author property and then subsequently saving the file will set an attribute that Explorer can see and filter on.

While it isn't C# code, here is VBA code that can be used withing Outlook to read a msg, get the Sender, and write it into the Author file property.

You need to get a copy of dsofile.dll form microsoft (they only provide a 32bit version, so if you are using 64-bit Outlook, you'll need a 64-bit version which you can find in google)

  • then register the DLL with 'regsvr32 '
  • then In VBA, add 'DSO OLE Document Properties Reader' to the References

Finally, here is some code to update the MSG file:

Function GetSenderSMTPAddress(mail As Outlook.MailItem) As String
    'Converted from VB to VBA from here: http://stackoverflow.com/questions/24361726/how-can-i-get-the-sender-email-address-using-outlook-mailitem-in-vb-net
    Dim PR_SMTP_ADDRESS As String: PR_SMTP_ADDRESS = "http://schemas.microsoft.com/mapi/proptag/0x39FE001E"
    If mail Is Nothing Then
        Return
    End If
    If mail.SenderEmailType = "EX" Then
        Dim sender As Outlook.AddressEntry: Set sender = mail.sender
        If Not sender Is Nothing Then
            'Now we have an AddressEntry representing the Sender
            If sender.AddressEntryUserType = Outlook.OlAddressEntryUserType.olExchangeUserAddressEntry Or sender.AddressEntryUserType = Outlook.OlAddressEntryUserType.olExchangeRemoteUserAddressEntry Then
                'Use the ExchangeUser object PrimarySMTPAddress
                Dim exchUser As Outlook.ExchangeUser: Set exchUser = sender.GetExchangeUser()
                If Not exchUser Is Nothing Then
                    GetSenderSMTPAddress = exchUser.PrimarySmtpAddress
                    Exit Function
                Else
                    GetSenderSMTPAddress = ""
                    Exit Function
                End If
            Else
                GetSenderSMTPAddress = sender.PropertyAccessor.GetProperty(PR_SMTP_ADDRESS)
                Exit Function
            End If
        Else
            GetSenderSMTPAddress = ""
            Exit Function
        End If
    Else
        GetSenderSMTPAddress = mail.SenderEmailAddress
        Exit Function
    End If
End Function

Sub UpdateMsgAttributes(msgFile As String)

    Dim objDSO As Object
    Dim objVariant As Variant
    Dim oNamespace As NameSpace
    Dim strAuthor As String
    Dim item As Outlook.MailItem

    ' Open the msg in Outlook to get the attributes from the MailItem
    '     Use CreateItemFromTemplate instead of OpenSharedItem
    '     because OpenSharedItem puts a lock on the file, and the lock is only
    '     released at an indeterminate time after releasing the mailitem
    ' Set oNamespace = Application.GetNamespace("MAPI")
    ' Set objVariant = oNamespace.OpenSharedItem(msgFile)
    Set objVariant = Application.CreateItemFromTemplate(msgFile)

    If objVariant.Class = olMail Then
        Set item = objVariant
        strAuthor = item.SenderName & " <" & GetSenderSMTPAddress(item) & ">"
    End If
    objVariant.Close olDiscard
    Set objVariant = Nothing

    ' Reopen the msg with DSOFile to edit its attributes
    Set objDSO = CreateObject("DSOFile.OleDocumentProperties")
    objDSO.Open msgFile
    objDSO.SummaryProperties.author = strAuthor
    objDSO.Save

End Sub