Parse Email Body, Attachment and Convert Email to HTML page in C++/CLI/CLR

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 C++/CLI/CLR.

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 C++/CLI/CLR 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.

[C++/CLI/CLR 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.

#include "stdafx.h"

using namespace System;
using namespace System::Text;
using namespace System::Text::RegularExpressions;
using namespace System::Collections;
using namespace System::IO;
using namespace EAGetMail; //add EAGetMail namespace

String^ _FormatHtmlTag( String ^src )
{
    src = src->Replace( ">", ">" );
    src = src->Replace( "<", "&lt;" );
    return src;
}

// We generate a html + attachment folder for every email, once the html is create,
// next time we don't need to parse the email again.
void _GenerateHtmlForEmail( String ^htmlName, String ^emlFile, String ^tempFolder )
{
    Mail ^oMail = gcnew Mail("TryIt");
    oMail->Load( emlFile, false );

    if( oMail->IsEncrypted )
    {
        try
        {
            // This email is encrypted, we decrypt it by user default certificate.
            // you can also use specified certificate like this
            // Certificate ^oCert = gcnew Certificate();
            // oCert->Load("c:\\test.pfx", "pfxpassword",
            //      Certificate::CertificateKeyLocation::CRYPT_USER_KEYSET);
            // oMail = oMail->Decrypt( oCert );
            oMail = oMail->Decrypt( nullptr );
        }
        catch(Exception ^ep )
        {
            Console::WriteLine( ep->Message );
            oMail->Load( emlFile, false );
        }
    }

    if( oMail->IsSigned )
    {
        try
        {
            // This email is digital signed.
            EAGetMail::Certificate ^cert = oMail->VerifySignature();
            Console::WriteLine( "This email contains a valid digital signature.");

            // You can add the certificate to your certificate storage like this
            // cert->AddToStore(
            // Certificate::CertificateStoreLocation::CERT_SYSTEM_STORE_CURRENT_USER,
            //      "addressbook" );
            // then you can use send the encrypted email back to this sender.
        }
        catch(Exception ^ep )
        {
            Console::WriteLine( ep->Message );
        }
    }

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

    String ^html = oMail->HtmlBody;
    StringBuilder ^hdr = gcnew StringBuilder();

    hdr->Append( "<font face=\"Courier New,Arial\" size=2>" );
    hdr->Append( String::Format( "<b>From:</b> {0}<br>",
                _FormatHtmlTag(oMail->From->ToString())));
    array<MailAddress^>^  addrs = oMail->To;
    int count = addrs->Length;
    if( count > 0 )
    {
        hdr->Append( "<b>To:</b> ");
        for( int i = 0; i < count; i++ )
        {
            hdr->Append(  _FormatHtmlTag(addrs[i]->ToString()));
            if( i < count - 1 )
            {
                hdr->Append( ";" );
            }
        }
        hdr->Append( "<br>" );
    }

    addrs = oMail->Cc;

    count = addrs->Length;
    if( count > 0 )
    {
        hdr->Append( "<b>Cc:</b> ");
        for( int i = 0; i < count; i++ )
        {
            hdr->Append(  _FormatHtmlTag(addrs[i]->ToString()));
            if( i < count - 1 )
            {
                hdr->Append( ";" );
            }
        }
        hdr->Append( "<br>" );
    }

    hdr->Append( String::Format( "<b>Subject:</b>{0}<br>\r\n",
            _FormatHtmlTag(oMail->Subject)));

    array<Attachment^>^ atts = oMail->Attachments;
    count = atts->Length;
    if( count > 0 )
    {
        if( !Directory::Exists( tempFolder ))
            Directory::CreateDirectory( tempFolder );

        hdr->Append( "<b>Attachments:</b>" );
        for( int i = 0; i < count; i++ )
        {
            Attachment ^att = atts[i];

            String ^attname = String::Format( "{0}\\{1}", tempFolder, att->Name );
            att->SaveAs( attname , true );
            hdr->Append( String::Format( "<a href=\"{0}\" target=\"_blank\">{1}</a> ",
                attname, att->Name ));
            String^ simage = "image/";
            if( att->ContentID->Length > 0 )
            {
                // Show embedded image.
                html = html->Replace( String::Format( "cid:{0}", att->ContentID), attname );
            }
            else if( String::Compare( att->ContentType, 0,
                "image/", 0, simage->Length, true ) == 0 )
            {
                // show attached image.
                html = String::Concat( html,
                String::Format( "<hr><img src=\"{0}\">", attname ));
            }
        }
    }

    Regex ^reg = gcnew Regex( "(<meta[^>]*charset[ \t]*=[ \t\"]*)([^<> \r\n\"]*)",
        (RegexOptions)(RegexOptions::Multiline | RegexOptions::IgnoreCase));
    html = reg->Replace( html, "$1utf-8" );
    if( !reg->IsMatch( html ))
    {
        hdr->Insert( 0,
        "<meta HTTP-EQUIV=\"Content-Type\" Content=\"text-html; charset=utf-8\">" );
    }

    html = html->Insert( 0, "<hr>" );
    html = html->Insert( 0, hdr->ToString());

    FileStream ^fs = gcnew FileStream(htmlName,
        FileMode::Create,FileAccess::Write, FileShare::None );
    array<unsigned char>^ data = System::Text::UTF8Encoding::UTF8->GetBytes( html );
    fs->Write(data, 0, data->Length);
    fs->Close();
    oMail->Clear();
}

void ConvertMailToHtml(String ^fileName)
{
    try
    {
        int pos = fileName->LastIndexOf(".");
        String ^mainName = fileName->Substring(0, pos);
        String ^htmlName = mainName + ".htm";

        String ^tempFolder = mainName;
        if (!File::Exists(htmlName))
        {
            // We haven't generate the html for this email, generate it now.
            _GenerateHtmlForEmail(htmlName, fileName, tempFolder);
        }

        Console::WriteLine("Please open {0} to browse your email",
            htmlName);
    }
    catch (Exception ^ep)
    {
        Console::WriteLine(ep->Message);
    }
}

int main(array<System::String ^> ^args)
{
    // Create a folder named "inbox" under current directory
    // to save the email retrieved.
    String ^curpath = Directory::GetCurrentDirectory();
    String ^mailbox = String::Format("{0}\\inbox", curpath);

    // If the folder is not existed, create it.
    if (!Directory::Exists(mailbox))
    {
        Directory::CreateDirectory(mailbox);
    }

    // Get all *.eml files in specified folder and parse it one by one.
    array<String^> ^files = Directory::GetFiles(mailbox, "*.eml");
    for (int i = 0; i < files->Length; i++)
    {
        //convert specified email file to HTML
        ConvertMailToHtml(files[i]);
    }

    return 0;
}

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.