|
Transport Neutral Encapsulation Format (TNEF) is a proprietary email attachment format used by Microsoft Outlook when when sending a message using either Rich Text Format or HTML Format. An attached file with TNEF encoding is most often named winmail.dat or win.dat, and has a MIME type of "application/ms-tnef".
The Winmail.dat contains the rich text body, MAPI properties information, and original attachments. The given library provides the TNEF Reader to decode the Winmail.dat file and save the attached files to the disk.
The TNEF (winmail.dat) file format is described in the [MS-OXTNEF]: Transport Neutral Encapsulation Format (TNEF) Data Algorithm document at Microsoft Knowledge Base. It includes a set of variable-length blocks, named as attributes. There is a number of different attributes that stores the MAPI, text information, and file attachments. Some attributes consist of another structures - properties. All the necessary information is stored in both the attribute and property structures.
The other attributes contain an information about the attachment file name, MIME type, content disposition, and other useful information. Also, there is a set of attributes and properties that contains the MAPI information: the message subject, recipients, etc. The rich text body (RTF-formatted) is stored in a separated property and may be compressed using the proprietary RTF-compression algorithm.
|
In this article, we introduce the code that extracts the message attachments, with the original file names, and the message body, including HTML, text, and RTF.
Currently, the RFT compression algorithm has not been implemented yet and we are planning to add it later in this series.
Download on GitHub
The TTnefReader is a class that includes algorithms for reading and decoding the whole TNEF structure. It provides the ability to walk through the attributes and properties, and read the encoded information to the native Delphi types: strings, integers, and streams.
This class provides the low-level access to the TNEF data and allows extracting any MAPI, attachments, and other data, included in the input Winmail.dat file.
The usage of this class is relatively complicated. You need to create an instance of TTnefReader, supply the input stream, and enumerate the included attributes using the NextAttribute iterator method. Depending on the attribute type, you can read data using the simple ReadString / ReadBytes / ReadInt32 methods, or using the TTnefPropertyReader class for reading the TNEF properties and MAPI information.
// [Delphi]
reader := TTnefReader.Create(ASource);
try
while reader.NextAttribute do
begin
if reader.AttributeLevel = alAttachment then
begin
//further reading
//...
if reader.AttributeTag = agAttachData then
begin
content := TFileStream.Create('filename.ext', fmCreate);
attachDataAttr := TAttachDataAttribute.Create(reader, content);
try
attachDataAttr.Load;
finally
attachDataAttr.Free;
content.Free;
end;
end;
//...
end;
end;
finally
reader.Free;
end; |
There is one more class that simplifies the attachment extraction task: TTnefAttachmentParser. This class internally utilizes the TTnefReader and provides the Parse method that reads data from the provided stream and stores the extracted attachments to the destination folder. Since the information about the attachment file names is stored in the separated TNEF attributes, we need to extract it before creating the destination stream and reading the attachment content. The TTnefAttachmentParser class does all this work. There is a special helper class, TAttachmentInfo, that keeps the extracted attachment-related information.
The example below demonstrates how to use the TTnefAttachmentParser class in your code:
// [Delphi]
parser := TTnefAttachmentParser.Create;
stream := TFileStream.Create('winmail.dat', fmOpenRead);
try
parser.Parse(stream, 'c:\downloads\tnef\');
finally
stream.Free;
parser.Free;
end; |
You can use the TTnefAttachmentParser class as a starting point for developing your own functionality, extracting more information from the TNEF structure, saving attachments to memory or the database storage. When using together with E-mail reading Software, such as SMTP client from the Clever Internet Suite library, or any other third-party or the standard Indy Software, you can convert the MS Outlook-specific incoming mail to the most commonly used MIME format.
An example of retrieving a MS Outlook mail and extracting the included attachments is shown below:
// [Delphi]
procedure TForm1.btnRetriveMailClick(Sender: TObject);
var
pop: TclPop3;
msg: TclMailMessage;
msgNo: Integer;
parser: TTnefAttachmentParser;
stream: TStream;
begin
pop := TclPop3.Create(nil);
msg := TclMailMessage.Create(nil);
parser := TTnefAttachmentParser.Create;
try
msg.OnSaveAttachment := msgSaveAttachment;
pop.Server := 'mailhost';
pop.UserName := 'user@domain.com';
pop.Password := 'secret';
msgNo := 1;
pop.Open;
pop.Retrieve(msgNo, msg);
pop.Close;
if FileExists('winmail.dat') then
begin
stream := TFileStream.Create('winmail.dat', fmOpenRead);
try
parser.Parse(stream, 'c:\downloads\tnef\');
finally
stream.Free;
end;
end;
finally
parser.Free;
msg.Free;
pop.Free;
end;
end; |
// [Delphi]
procedure TForm1.msgSaveAttachment(Sender: TObject; ABody: TclAttachmentBody;
var AFileName: string; var AData: TStream; var Handled: Boolean);
begin
if (AFileName = 'winmail.dat') or (AFileName = 'win.dat') then
begin
AData := TFileStream.Create('winmail.dat', fmCreate);
Handled := True;
end;
end; |
If you want to keep the Winmail.dat file in memory, you need to create a TMemoryStream instance instead of TFileStream, and use one more event - OnAttachmentSaved. This event is necessary to access the extracted Winmail.dat content.
Download on GitHub
Clever Internet Suite Download
Ask a Question
The TNEF parser library is distributed under the GNU LESSER GENERAL PUBLIC LICENSE Version 3.
COPYING.txt
COPYING.LESSER.txt
Sergey Shirokov
Clever Components team
www.clevercomponents.com
|