Work with winmail.dat (TNEF Parser)


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. EAGetMail provides the TNEF parser to decode the winmail.dat. With this feature, you application has the highly compatibility with the outlook email.

Example

[Visual Basic 6.0, Visual C++] The following example demonstrates how to deal with the winmail.dat attachment. To get the full samples of EAGetMail, please refer to Samples section.

[Visual Basic 6.0]
Private Sub ParseTNEF()
On Error GoTo ErrorHandle
    Dim oMail As New EAGetMailObjLib.Mail
    Dim oTools As New EAGetMailObjLib.Tools
    
    oMail.LicenseCode = "TryIt"
    oMail.LoadFile "c:\test.eml", False
    Dim tempFolder As String
    tempFolder = "c:\temp"
    
    Dim i, Count
    Dim atts
    atts = oMail.Attachments
    i = LBound(atts)
    Count = UBound(atts)
    If (Count >= i) Then
        If Not oTools.ExistFile(tempFolder) Then
            oTools.CreateFolder (tempFolder)
        End If
        
        For i = LBound(atts) To Count
            Dim att As Attachment
            Set att = atts(i)
            'this attachment is in OUTLOOK RTF format, decode it here.
            If LCase(att.Name) = "winmail.dat" Then
                Dim tatts
                tatts = oMail.ParseTNEF(att.Content, True)
                For x = LBound(tatts) To UBound(tatts)
                        Dim tatt As Attachment
                        Set tatt = tatts(x)
                        Dim tattname As String
                        tattname = tempFolder & "\" & tatt.Name
                        tatt.SaveAs tattname, True
                Next
                
            Else
                Dim attname
                attname = tempFolder & "\" & att.Name
                att.SaveAs attname, True
            End If
        Next
    End If
    Exit Sub
ErrorHandle:
    MsgBox Err.Description

End Sub


[Visual C++] //if you do not use MFC, please add this line to support CString type. #include <atlstr.h> #include "eagetmailobj.tlh" using namespace EAGetMailObjLib; void ParseTNEF() { IMailPtr oMail = NULL; CString tempFolder = _T("c:\\temp"); try { oMail.CreateInstance(__uuidof(EAGetMailObjLib::Mail)); oMail->LicenseCode = _T("TryIt"); oMail->LoadFile(_T("c:\\test.eml"), VARIANT_FALSE); LONG UBound = 0, LBound = 0; _variant_t atts = oMail->Attachments; SAFEARRAY *psa = atts.parray; SafeArrayGetLBound(psa, 1, &LBound); SafeArrayGetUBound(psa, 1, &UBound); INT count = UBound-LBound+1; ::CreateDirectory(tempFolder.GetString(), NULL); for(long i = LBound; i <= UBound; i++) { _variant_t vtAtt; SafeArrayGetElement(psa, &i, &vtAtt); IAttachmentPtr pAtt; vtAtt.pdispVal->QueryInterface(__uuidof(IAttachment), (void**)&pAtt); CString name = (TCHAR*)pAtt->Name; //this attachment is in OUTLOOK RTF format, decode it here. if(name.CompareNoCase(_T("winmail.dat")) == 0) { //this attachment is in OUTLOOK RTF format, decode it here. _variant_t tatts; try { tatts = oMail->ParseTNEF(pAtt->Content, VARIANT_TRUE); } catch(_com_error &ep) { MessageBox(NULL, (TCHAR*)ep.Description(), NULL, MB_OK); continue; } long XLBound = 0, XUBound = 0; SAFEARRAY* tpsa = tatts.parray; SafeArrayGetLBound(tpsa, 1, &XLBound); SafeArrayGetUBound(tpsa, 1, &XUBound); for(long x = XLBound; x <= XUBound; x++) { _variant_t vttAtt; SafeArrayGetElement(tpsa, &x, &vttAtt); IAttachmentPtr ptAtt; vttAtt.pdispVal->QueryInterface(__uuidof(IAttachment), (void**)&ptAtt); CString tattname = tempFolder; tattname.Append(_T("\\")); tattname.Append((TCHAR*)ptAtt->Name); ptAtt->SaveAs(tattname.GetString(), VARIANT_TRUE); } continue; } CString attname = tempFolder; attname.Append(_T("\\")); attname.Append((TCHAR*)pAtt->Name); pAtt->SaveAs(attname.GetString(), VARIANT_TRUE); } } catch(_com_error &ep) { MessageBox(NULL, (TCHAR*)ep.Description(), _T("Error"), MB_OK); } }

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:

[Visual Basic 6.0]
Private Sub ParseAttachment()
On Error GoTo ErrorHandle
    Dim oMail As New EAGetMailObjLib.Mail
    Dim oTools As New EAGetMailObjLib.Tools
    
    oMail.LicenseCode = "TryIt"
    oMail.LoadFile "c:\test.eml", False
    Dim tempFolder As String
    tempFolder = "c:\temp"
    
    ' Decode winmail.dat (TNEF) automatically'
    oMail.DecodeTNEF
    
    If Not oTools.ExistFile(tempFolder) Then
        oTools.CreateFolder (tempFolder)
    End If
    
    Dim i, atts
    Set atts = oMail.AttachmentList

    For i = 0 To atts.Count - 1
        Dim att As Attachment
        Set att = atts.Item(i)
        Dim attname
        attname = tempFolder & "\" & att.Name
        att.SaveAs attname, True
    Next

    Exit Sub
ErrorHandle:
    MsgBox Err.Description
    
End Sub


[VBScript] Sub ParseAttachment() Dim oMail Set oMail = CreateObject("EAGetMailObj.Mail") Dim oTools Set oTools = CreateObject("EAGetMailObj.Tools") oMail.LicenseCode = "TryIt" oMail.LoadFile "c:\test.eml", False Dim tempFolder tempFolder = "c:\temp" ' Decode winmail.dat (TNEF) automatically oMail.DecodeTNEF Dim i, atts Set atts = oMail.AttachmentList If Not oTools.ExistFile(tempFolder) Then oTools.CreateFolder (tempFolder) End If For i = 0 To atts.Count - 1 Dim att Set att = atts.Item(i) Dim attname attname = tempFolder & "\" & att.Name att.SaveAs attname, True Next End Sub
[Visual C++] //if you do not use MFC, please add this line to support CString type. #include <atlstr.h> #include "eagetmailobj.tlh" using namespace EAGetMailObjLib; void ParseAttachment() { IMailPtr oMail = NULL; CString tempFolder = _T("c:\\temp"); try { oMail.CreateInstance(__uuidof(EAGetMailObjLib::Mail)); oMail->LicenseCode = _T("TryIt"); oMail->LoadFile(_T("c:\\test.eml"), VARIANT_FALSE); // Decode winmail.dat (TNEF) automatically oMail->DecodeTNEF(); IAttachmentCollectionPtr attachments = oMail->AttachmentList; ::CreateDirectory(tempFolder.GetString(), NULL); for(long i = 0; i < attachments->Count; i++) { IAttachmentPtr pAtt = attachments->GetItem(i); CString name = (TCHAR*)pAtt->Name; CString attname = tempFolder; attname.Append(_T("\\")); attname.Append((TCHAR*)pAtt->Name); pAtt->SaveAs(attname.GetString(), VARIANT_TRUE); } } catch(_com_error &ep) { MessageBox(NULL, (TCHAR*)ep.Description(), _T("Error"), MB_OK); } }
[Delphi] procedure ParseEmail(fileName: WideString); Var oMail: TMail; i: Integer; addrs: IAddressCollection; addr: IMailAddress; atts: IAttachmentCollection; att: IAttachment; begin oMail := TMail.Create(Application); oMail.LicenseCode := 'TryIt'; oMail.LoadFile(fileName, false); // Decode winmail.dat (TNEF) automatically oMail.DecodeTNEF(); // Parse email sender ShowMessage('From: ' + oMail.From.Address); // Parse email to recipients addrs := oMail.ToList; for i := 0 To addrs.Count - 1 do begin addr := addrs.Item[i]; ShowMessage('To: ' + addr.Address); End; // Parse email cc recipients addrs := oMail.CcList; for i := 0 To addrs.Count - 1 do begin addr := addrs.Item[i]; ShowMessage('Cc: ' + addr.Address); end; // Parse email subject ShowMessage('Subject: ' + oMail.Subject); // Parse email text body ShowMessage('Text body: ' + oMail.TextBody); // Parse email HTML body ShowMessage('HTML body: ' + oMail.HtmlBody); // Parse attachment atts := oMail.AttachmentList; for i := 0 To atts.Count - 1 do begin att := atts.Item[i]; ShowMessage(att.Name); end; end;

See Also

Using EAGetMail POP3 & IMAP4 ActiveX Object
Registration-free COM with Manifest File
User Authentication and SSL Connection
Enable TLS 1.2 on Windows XP/2003/2008/7/2008 R2
Using Gmail IMAP4 OAUTH
Using Gmail/GSuite Service Account + IMAP4 OAUTH
Using Office365 EWS OAUTH
Using Office365 EWS OAUTH in Background Service
Using Hotmail IMAP4 OAUTH
Digital Signature and E-mail Encryption/Decryption
Unique Identifier (UIDL) in POP3 and IMAP4 protocol
Parse Bounced Email (delivery-report)
EAGetMail ActiveX Object References
EAGetMail POP3 & IMAP4 Component Samples

Online Tutorials

Parse winmail.dat (TNEF/MAPI) in VB6 - Tutorial
Parse winmail.dat (TNEF/MAPI) in Delphi - Tutorial
Parse winmail.dat (TNEF/MAPI) in VC++ - Tutorial