How to Convert EML Files to HTML using PowerShell

You can use a PowerShell script to batch convert emails in EML format to HTML files.

There are a number of utilities, many of them quite pricey, that let you convert email messages stored in EML format to other file formats. But if you want a quick and easy (and free) way to convert EML files to HTML files, you can try the PowerShell cmdlet below.

Since there are a larger number of apps that deal with HTML files, once the emails are in HTML format, it is a relatively simple task to convert them to other file formats. For example, you could use Adobe Acrobat or other PDF software to convert the HTML files to PDFs.

function ConvertFrom-EmlToHtml
{
    [CmdletBinding()]

    Param
    (
        [Parameter(ParameterSetName="Path", Position=0, Mandatory=$True)]
        [String]$Path,

        [Parameter(ParameterSetName="LiteralPath", Mandatory=$True)]
        [String]$LiteralPath,

        [Parameter(ParameterSetName="FileInfo", Mandatory=$True, ValueFromPipeline=$True)]
        [System.IO.FileInfo]$Item
    )

    Process
    {
        switch ($PSCmdlet.ParameterSetName)
        {
            "Path"        { $files = Get-ChildItem -Path $Path }
            "LiteralPath" { $files = Get-ChildItem -LiteralPath $LiteralPath }
            "FileInfo"    { $files = $Item }
        }

        $files | % {
            # Work out file names
            $emlFn  = $_.FullName
            $htmlFn = $emlFn -replace '\.eml$', '.html'

            # Skip non-.msg files
            if ($emlFn -notlike "*.eml") {
                Write-Verbose "Skipping $_ (not an .eml file)..."
                return
            }

            # Do not try to overwrite existing files
            if (Test-Path -LiteralPath $htmlFn) {
                Write-Verbose "Skipping $_ (.html already exists)..."
                return
            }

            # Read EML
            Write-Verbose "Reading $_..."
            $adoDbStream = New-Object -ComObject ADODB.Stream
            $adoDbStream.Open()
            $adoDbStream.LoadFromFile($emlFn)
            $cdoMessage = New-Object -ComObject CDO.Message
            $cdoMessage.DataSource.OpenObject($adoDbStream, "_Stream")

            # Generate HTML
            Write-Verbose "Generating HTML..."
            $html = "<!DOCTYPE html>`r`n"
            $html += "<html>`r`n"
            $html += "<head>`r`n"
            $html += "<meta charset=`"utf-8`">`r`n"
            $html += "<title>" + $cdoMessage.Subject + "</title>`r`n"
            $html += "</head>`r`n"
            $html += "<body style=`"font-family: sans-serif; font-size: 11pt`">`r`n"
            $html += "<div style=`"margin-bottom: 1em;`">`r`n"
            $html += "<strong>From: </strong>" + $cdoMessage.From + "<br>`r`n"
            $html += "<strong>Sent: </strong>" + $cdoMessage.SentOn + "<br>`r`n"
            $html += "<strong>To: </strong>" + $cdoMessage.To + "<br>`r`n"
            if ($cdoMessage.CC -ne "") {
                $html += "<strong>Cc: </strong>" + $cdoMessage.CC + "<br>`r`n"
            }
            if ($cdoMessage.BCC -ne "") {
                $html += "<strong>Bcc: </strong>" + $cdoMessage.BCC + "<br>`r`n"
            }
            $html += "<strong>Subject: </strong>" + $cdoMessage.Subject + "<br>`r`n"
            $html += "</div>`r`n"
            if ($cdoMessage.HTMLBody -ne "") {
                $html += "<div>`r`n"
                $html += $cdoMessage.HTMLBody + "`r`n"
                $html += "</div>`r`n"
            } else {
                $html += "<div><pre>"
                $html += $cdoMessage.TextBody
                $html += "</pre></div>`r`n"
            }
            $html += "</body>`r`n"
            $html += "</html>`r`n"

            # Write HTML
            Write-Verbose "Saving HTML..."
            Add-Content -LiteralPath $htmlFn $html

            # Output to pipeline
            Get-ChildItem -LiteralPath $htmlFn
        }
    }

    End
    {
        Write-Verbose "Done."
    }
}

Installation

Save the code to a file called EmlUtility.psm1, and put it in its own folder called EmlUtility in your PowerShell modules folder.

On Windows Vista and newer, the PowerShell modules folder is typically found here:

C:\Users\__your_username__\Documents\WindowsPowerShell\Modules

On Windows XP, the PowerShell modules folder is typically found here:

C:\Documents and Settings\__your_username__\Documents\WindowsPowerShell\Modules

If the PowerShell modules folder doesn’t exist, create it.

Usage

To use the cmdlet to convert all the EML files in the current directory, simply import the new module and run the ConvertFrom-EmlToHtml as follows:

Import-Module EmlUtility
ConvertFrom-EmlToHtml *

And of course you can pipe input files or specify a single file or a wildcard pattern as you can with other PowerShell cmdlets:

ConvertFrom-EmlToHtml "Email from * to me dated *.eml"
Get-ChildItem -Recurse | ConvertFrom-EmlToHtml

Tags: EML, HTML, PowerShell