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