Parse Email Body, Attachment and Convert Email to HTML page in Delphi

In previous section, I introduced how to parse winmail.dat. In this section, I will introduce how to parse email body and attachment, then convert email to a HTML page and display it using Web browser in Delphi.

Introduction

After the email was converted to HTML page, you can browse it with web browser. You can get everything in the HTML page such as From, To, Cc, Subject, Date, Attachments and Embedded images.

Note

Remarks: All of examples in this section are based on first section: A simple Delphi 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.

[Delphi Example - Convert email to HTML]

The following example codes demonstrate how to use EAGetMail POP3 component to convert email to HTML page.

Note

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

unit Unit1;

interface

uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls, StrUtils, EAGetMailObjLib_TLB; // Add EAGetMail unit

type
    TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);

        procedure ConvertMailToHtml(fileName: WideString);
        procedure GenerateHtmlForEmail(htmlName: WideString;
                emlFile: WideString; tempFolder: WideString);
    private
        { Private declarations }
    public
        { Public declarations }
    end;

const
    MailServerPop3 = 0;
    MailServerImap4 = 1;

    CRYPT_MACHINE_KEYSET = 32;
    CRYPT_USER_KEYSET = 4096;
    CERT_SYSTEM_STORE_CURRENT_USER = 65536;
    CERT_SYSTEM_STORE_LOCAL_MACHINE = 131072;

var
    Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ConvertMailToHtml(fileName: WideString);
var
    mainName, htmlName, tempFolder: WideString;
    oTools: TTools;
begin
    // Remove .eml extension
    mainName := LeftStr( fileName, length(fileName)-4 );
    htmlName := mainName + '.htm';
    tempFolder := mainName;

    oTools := TTools.Create(Application);
    if not oTools.ExistFile(htmlName) then
    begin
        // We haven't generate the html for this email, generate it now.
        GenerateHtmlForEmail(htmlName, fileName, tempFolder );
    end;

end;

procedure TForm1.GenerateHtmlForEmail(htmlName: WideString;
emlFile: WideString; tempFolder: WideString);
var
    oMail: TMail;
    oTools: TTools;
    i, x, UBound, XBound: integer;
    att, tatt: IAttachment;
    addr: IMailAddress;
    addrs, atts, tatts: OleVariant;
    html, hdr, attname, tattname: WideString;
begin
    oTools := TTools.Create(Application);
    oMail := TMail.Create(Application);
    oMail.LicenseCode := 'TryIt';

    oMail.LoadFile( emlFile, false );

    try
        if oMail.IsEncrypted then
        oMail.Load(oMail.Decrypt(nil).Content);
    except
        on ep:Exception do
        ShowMessage( 'Decrypt Error: ' + ep.Message );
    end;

    try
        if oMail.IsSigned then
        oMail.VerifySignature();
    except
        on ep:Exception do
        ShowMessage( 'Verify Digital Signature Error: ' + ep.Message );
    end;

    // Decode winmail.dat (TNEF) and RTF body automatically
    // also convert RTF body to HTML automatically.
    oMail.DecodeTNEF();

    html := oMail.HtmlBody;
    hdr := hdr + '<font face="Courier New,Arial" size="2">';
    hdr := hdr + '<b>From:</b> ' + oMail.From.Name + '&lt;' +
        oMail.From.Address + '&gt;' + '<br>';

    addrs := oMail.ToAddr;
    UBound := VarArrayHighBound( addrs, 1 );
    if( UBound >= 0) then
    begin
        hdr := hdr + '<b>To:</b>';
        for i:= 0 to UBound do
        begin
        addr := IDispatch(VarArrayGet(addrs, i)) as IMailAddress;
        hdr := hdr + addr.Name + '&lt;' + addr.Address + '&gt';
        if( i < UBound ) then
            hdr := hdr + ';';
        end;
        hdr := hdr + '<br>' + #13#10;
    end;

    addrs := oMail.Cc;
    UBound := VarArrayHighBound( addrs, 1 );
    if( UBound >= 0) then
    begin
        hdr := hdr + '<b>Cc:</b>';
        for i:= 0 to UBound do
        begin
        addr := IDispatch(VarArrayGet(addrs, i)) as IMailAddress;
        hdr := hdr + addr.Name + '&lt;' + addr.Address + '&gt';
        if( i < UBound ) then
            hdr := hdr + ';';
        end;
        hdr := hdr + '<br>' + #13#10;
    end;

    hdr := hdr + '<b>Subject:</b>' + oMail.Subject + '<br>' + #13#10;

    // Parse attachment
    atts := oMail.Attachments;
    UBound := VarArrayHighBound( atts, 1 );
    if( UBound >= 0 ) then
    begin
        // Create a temporal folder to store attachments.
        if not oTools.ExistFile(tempFolder) then
        oTools.CreateFolder(tempFolder);

        hdr := hdr + '<b>Attachments:</b>';
        for i:= 0 to UBound do
        begin
            att := IDispatch(VarArrayGet(atts, i)) as IAttachment;

            attname := tempFolder + '\' + att.Name;
            att.SaveAs(attname, true);
            hdr := hdr + '<a href="' + attname + '" target="_blank">'
                + att.Name + '</a> ';
            // show embedded images
            if att.ContentID <> '' then
            begin
                // StringReplace doesn't support some non-ascii characters very well.
                html := StringReplace( html, 'cid:' + att.ContentID, attname,
                    [rfReplaceAll, rfIgnoreCase]);
            end
            else if Pos('image/', att.ContentType ) = 1 then
            begin
                html := html + '<hr><img src="' + attname + '">';
            end;
        end;
    end;

    hdr := '<meta http-equiv="Content-Type" content="text-html; charset=utf-8">' + hdr;
    html := hdr + '<hr>' + html;
    oTools.WriteTextFile( htmlName, html, 65001 );

end;

procedure TForm1.Button1Click(Sender: TObject);
var
    oTools: TTools;
    files: OleVariant;
    fileName: WideString;
    i, UBound: integer;
    mailFolder: WideString;
begin
    try
        oTools := TTools.Create(Application);

        // Create a folder named "inbox" under
        // current directory to store the email files
        mailFolder := GetCurrentDir() + '\inbox';
        oTools.CreateFolder(mailFolder);

        // Get all *.eml files in specified folder and parse it one by one
        files := oTools.GetFiles(mailFolder + '\*.eml');
        UBound := VarArrayHighBound( files, 1 );
        for i := 0 to UBound do
        begin
            fileName := VarArrayGet(files, i);
            ConvertMailToHtml(fileName);
        end;

    except
        on ep:Exception do
        ShowMessage( 'Error: ' + ep.Message );
    end;

end;

end.

In EAGetMail installer, there are many samples demonstrate how to use Web browser control to display the email, I suggest that you download it and have a try

pop3, imap4 samples

Next Section

At next section I will introduce how to parse Non-delivery report.

Appendix

Comments

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