7
votes

I am using PowerShell to loop through designated folders in Outlook and saving the attachments in a tree like structure. This works wonders, but now management has requested the email itself be saved as a PDF as well. I found the PrintOut method in object, but that prompts for a file name. I haven't been able to figure out what to pass to it to have it automatically save to a specific filename. I looked on the MSDN page and it was a bit to high for my current level.

I am using the com object of outlook.application.

Short of saving all of the emails to a temp file and using a third party method is there parameters I can pass to PrintOut? Or another way to accomplish this?

Here is the base of the code to get the emails. I loop through $Emails

$Outlook = New-Object -comobject outlook.application
$Connection = $Outlook.GetNamespace("MAPI")
#Prompt which folder to process
$Folder = $Connection.PickFolder()
$Outlook_Folder_Path = ($Folder.FullFolderPath).Split("\",4)[3]
$BaseFolder += $Outlook_Folder_Path + "\"
$Emails = $Folder.Items
2
I'am quite sure that you can save mails to .msg files with COM object. Then, you can batch PDF convertion with MSG2PDFConverter.exe (an Office tool)JPBlanc
@JPBlanc I believe that is possible but I was trying to avoid download/convert as that adds more then just a single PS1 file for users to run.Unfundednut
Technically you can print to PDF, from Outlook COMObject as well, but I expect the print driver would require the destination filename, and that one isn't easy to send, and it depends on the PDF printer driver installed in the system. I'd say go with external batch converter. You can also use -AsJob flag to start the batch converter if it only accepts one item at once.Vesper
How would you deal with attachments in those mails? Can you count on all machines have a pdf printer on them like CutePDF or Adobe's PDF printer? I found the PrintOut method in object, but that prompts for a file name. Can we see that code snippet perhaps? I would love to help but I don't want to recreate an entire solution just to get to this point to test.Matt
PrintOut does not give you much to work with it seems.Matt

2 Answers

5
votes

Looks like there are no built-in methods, but if you're willing to use third-party binary, wkhtmltopdf can be used.

  1. Get precompiled binary (use MinGW 32-bit for maximum compatibility).
  2. Install or extract installer with 7Zip and copy wkhtmltopdf.exe to your script directory. It has no external dependencies and can be redistributed with your script, so you don't have to install PDF printer on all PCs.
  3. Use HTMLBody property of MailItem object in your script for PDF conversion.

Here is an example:

# Get path to wkhtmltopdf.exe
$ExePath = Join-Path -Path (
    Split-Path -Path $Script:MyInvocation.MyCommand.Path
) -ChildPath 'wkhtmltopdf.exe'

# Set PDF path
$OutFile = Join-Path -Path 'c:\path\to\emails' -ChildPath ($Email.Subject + '.pdf')

# Convert HTML string to PDF file
$ret = $Email.HTMLBody | & $ExePath @('--quiet', '-', $OutFile) 2>&1

# Check for errors
if ($LASTEXITCODE) {
    Write-Error $ret
}

Please note, that I've no experience with Outlook and used MSDN to get relevant properties for object, so the code might need some tweaking.

1
votes

Had this same issue. This is what I did to fix it if anybody else is trying to do something similar.

You could start by taking your msg file and converting it to doc then converting the doc file to pdf.

$outlook = New-Object -ComObject Outlook.Application
$word = New-Object -ComObject Word.Application

Get-ChildItem -Path $folderPath -Filter *.msg? | ForEach-Object {

    $msgFullName = $_.FullName
    $docFullName = $msgFullName -replace '\.msg$', '.doc'
    $pdfFullName = $msgFullName -replace '\.msg$', '.pdf'

    $msg = $outlook.CreateItemFromTemplate($msgFullName)
    $msg.SaveAs($docFullName, 4)

    $doc = $word.Documents.Open($docFullName)
    $doc.SaveAs([ref] $pdfFullName, [ref] 17)

    $doc.Close()
 }

Then, just clean up the unwanted files after