Parse winmail.dat (TNEF/MAPI) in VB.NET

In previous section, I introduced how to verify digital signature and decrypt email. In this section, I will introduce how to parse winmail.dat (TNEF stream) in VB.NET.

Introduction

When an Outlook user composes and sends a message using either Rich Text Format or HTML Format, Outlook automagically generates a file, winmail.dat, and attaches it to the end of the email. The winmail.dat contains the rich text body and original attachments. To parse winmail.dat (TNEF stream) file, we should use ParseTNEF method.

Note

Remarks: All of examples in this section are based on first section: A simple VB.NET project. To compile and run the following example codes successfully, please click here to learn how to create the test project and add reference to your project.

[VB.NET Example - Parse winmail.dat (TNEF stream)]

The following example codes demonstrate how to parse MAPI winmail.dat.

Note

To get the full sample projects, please refer to Samples section.

Imports System.Collections
Imports System.Text
Imports System.IO
Imports EAGetMail 'imports EAGetMail namespace

Module Module1
    Private Sub ParseEmail(ByVal emlFile As String)
        Dim oMail As New Mail("TryIt")
        oMail.Load(emlFile, False)

        If oMail.IsEncrypted Then
            Try
                ' This email is encrypted, we decrypt it by user default certificate.
                ' you can also use specified certificate like this
                ' Dim oCert As New Certificate()
                ' oCert.Load("c:\test.pfx", "pfxpassword", _
                '  Certificate.CertificateKeyLocation.CRYPT_USER_KEYSET)
                ' oMail = oMail.Decrypt( oCert )
                oMail = oMail.Decrypt(Nothing)
            Catch ep As Exception
                Console.WriteLine(ep.Message)
            End Try
        End If

        If oMail.IsSigned Then
            Try
                ' This email is digital signed.
                Dim cert As EAGetMail.Certificate = oMail.VerifySignature()
                ' You can add the certificate to your certificate storage like this
                ' cert.AddToStore( _
                '    Certificate.CertificateStoreLocation.CERT_SYSTEM_STORE_CURRENT_USER, _
                '  "addressbook" )
                ' then you can use send the encrypted email back to this sender.
                Console.WriteLine("This email contains a valid digital signature.")
            Catch ep As Exception
                Console.WriteLine(ep.Message)
            End Try
        End If

        ' Parse Mail From/Sender
        Console.WriteLine("From: {0}", oMail.From.ToString())

        ' Parse Mail To/Recipient
        Dim addrs As MailAddress() = oMail.[To]
        For i As Integer = 0 To addrs.Length - 1
            Console.WriteLine("To: {0}", addrs(i).ToString())
        Next

        ' Parse Mail CC
        addrs = oMail.Cc
        For i As Integer = 0 To addrs.Length - 1
            Console.WriteLine("To: {0}", addrs(i).ToString())
        Next

        ' Parse Mail Subject
        Console.WriteLine("Subject: {0}", oMail.Subject)

        ' Parse Mail Text/Plain body
        Console.WriteLine("TextBody: {0}", oMail.TextBody)

        ' Parse Mail Html Body
        Console.WriteLine("HtmlBody: {0}", oMail.HtmlBody)

        ' Parse Attachments
        Dim atts As Attachment() = oMail.Attachments
        For i As Integer = 0 To atts.Length - 1
            Dim att As Attachment = atts(i)

            ' This attachment is in OUTLOOK RTF format(TNEF), decode it here.
            If [String].Compare(att.Name, "winmail.dat") = 0 Then
                Dim tatts As Attachment() = Nothing
                Try
                    tatts = Mail.ParseTNEF(att.Content, True)
                Catch ep As Exception
                    Console.WriteLine(ep.Message)
                End Try

                Dim y As Integer = tatts.Length
                For x As Integer = 0 To y - 1
                    Dim tatt As Attachment = tatts(x)
                    Console.WriteLine("winmail.dat: {0}", tatt.Name)
                Next
                Continue For
            End If
            Console.WriteLine("Attachment: {0}", att.Name)
        Next
    End Sub

    Sub Main()
        ' Create a folder named "inbox" under current directory
        ' to save the email retrieved.
        Dim curpath As String = Directory.GetCurrentDirectory()
        Dim mailbox As String = [String].Format("{0}\inbox", curpath)

        ' If the folder is not existed, create it.
        If Not Directory.Exists(mailbox) Then
            Directory.CreateDirectory(mailbox)
        End If

        ' Get all *.eml files in specified folder and parse it one by one.
        Dim files As String() = Directory.GetFiles(mailbox, "*.eml")
        For i As Integer = 0 To files.Length - 1
            ParseEmail(files(i))
        Next

    End Sub
End Module

Parse TNEF (winmail.dat) by DecodeTNEF method

In EAGetMail 4.5, a new method named DecodeTNEF is introduced. It is easier to parse TNEF attachment. Please have a look at the following example codes:

Imports System.Collections
Imports System.Text
Imports System.IO
Imports EAGetMail 'imports EAGetMail namespace

Module Module1
    Private Sub ParseEmail(ByVal emlFile As String)
        Dim oMail As New Mail("TryIt")
        oMail.Load(emlFile, False)

        If oMail.IsEncrypted Then
            Try
                ' This email is encrypted, we decrypt it by user default certificate.
                ' you can also use specified certificate like this
                ' Dim oCert As New Certificate()
                ' oCert.Load("c:\test.pfx", "pfxpassword", _
                '  Certificate.CertificateKeyLocation.CRYPT_USER_KEYSET)
                ' oMail = oMail.Decrypt( oCert )
                oMail = oMail.Decrypt(Nothing)
            Catch ep As Exception
                Console.WriteLine(ep.Message)
            End Try
        End If

        If oMail.IsSigned Then
            Try
                ' This email is digital signed.
                Dim cert As EAGetMail.Certificate = oMail.VerifySignature()
                ' You can add the certificate to your certificate storage like this
                ' cert.AddToStore( _
                '    Certificate.CertificateStoreLocation.CERT_SYSTEM_STORE_CURRENT_USER, _
                '  "addressbook" )
                ' then you can use send the encrypted email back to this sender.
                Console.WriteLine("This email contains a valid digital signature.")
            Catch ep As Exception
                Console.WriteLine(ep.Message)
            End Try
        End If

        ' Decode winmail.dat (TNEF) and RTF body automatically
        oMail.DecodeTNEF()

        ' Parse Mail From/Sender
        Console.WriteLine("From: {0}", oMail.From.ToString())

        ' Parse Mail To/Recipient
        Dim addrs As MailAddress() = oMail.[To]
        For i As Integer = 0 To addrs.Length - 1
            Console.WriteLine("To: {0}", addrs(i).ToString())
        Next

        ' Parse Mail CC
        addrs = oMail.Cc
        For i As Integer = 0 To addrs.Length - 1
            Console.WriteLine("To: {0}", addrs(i).ToString())
        Next

        ' Parse Mail Subject
        Console.WriteLine("Subject: {0}", oMail.Subject)

        ' Parse Mail Text/Plain body
        Console.WriteLine("TextBody: {0}", oMail.TextBody)

        ' Parse Mail Html Body
        Console.WriteLine("HtmlBody: {0}", oMail.HtmlBody)

        ' Parse Attachments
        Dim atts As Attachment() = oMail.Attachments
        For i As Integer = 0 To atts.Length - 1
            Dim att As Attachment = atts(i)
            Console.WriteLine("Attachment: {0}", att.Name)
        Next
    End Sub

    Sub Main()
        ' Create a folder named "inbox" under current directory
        ' to save the email retrieved.
        Dim curpath As String = Directory.GetCurrentDirectory()
        Dim mailbox As String = [String].Format("{0}\inbox", curpath)

        ' If the folder is not existed, create it.
        If Not Directory.Exists(mailbox) Then
            Directory.CreateDirectory(mailbox)
        End If

        ' Get all *.eml files in specified folder and parse it one by one.
        Dim files As String() = Directory.GetFiles(mailbox, "*.eml")
        For i As Integer = 0 To files.Length - 1
            ParseEmail(files(i))
        Next

    End Sub
End Module

Next Section

At next section I will introduce how to convert email to HTML page and display it in Web browser.

Appendix

Comments

If you have any comments or questions about above example codes, please click here to add your comments.