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