Author Posts

November 26, 2014 at 5:52 pm

I found this script and it works great , but I would like to save the .msg files form certain dates . this script does not have that functionality

any suggestions on how I can add that tothe existing script or another solution?

 .\Save-Email.ps1 -DestinationPath 'C:\Saved Emails'

The following command will save only the unread emails in the Inbox to the C:\Saved Emails\ folder

PS C:\> .\Save-Email.ps1 -DestinationPath 'C:\Saved Emails' -UnreadOnly

The following command will save only the unread emails in the Inbox to the C:\Saved Emails\ folder and mark them as read

PS C:\> .\Save-Email.ps1 -DestinationPath 'C:\Saved Emails' -UnreadOnly -MarkRead

This example demonstrates using the pipeline to send a DirectoryInfo object to the script in the pipeline

PS C:\> Get-ChildItem 'C:\Users' -Recurse | Where-Object {$_.Name -eq "Saved Emails"} | .\Save-Email.ps1

If you do not enter a value for the DestinationPath parameter on the command line, you will be prompted to enter a value after pressing .  At this point, do not enclose the value with quotation marks even if the path includes spaces. 


#Binding for Common Parameters

        HelpMessage='Folder path to store emails. Do not use quotation marks even if the path has spaces.',
    [Alias("Destination", "Dest", "FullName")]


#Removes invalid Characters for file names from a string input and outputs the clean string
#Similar to VBA CleanString() Method
#Currently set to replace all illegal characters with a hyphen (-)
Function Remove-InvalidFileNameChars {

        [Parameter(Mandatory=$true, Position=0)]

    return [RegEx]::Replace($Name, "[{0}]" -f ([RegEx]::Escape([String][System.IO.Path]::GetInvalidFileNameChars())), '-')

#Test for destination folder nonexistence
if (!(Test-Path $DestinationPath)) {
    #Set values for prompt and menu
    $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
        "Confirmation Choice"
    $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
        "Negative Response"
    $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
    $title = "Invalid Destination"
    $message = "The folder you entered does not exist.  Would you like to create the folder?"

    #Prompt for folder creation and store answer
    $result = $host.UI.PromptForChoice($title, $message, $options, 0)

    #If yes, create.
    if ($result -eq 0) {
        New-Item $DestinationPath -ItemType Directory | Out-Null
        Write-Host "Directory created."
    #If no, exit
    else {exit}
#Add a trailing "\" to the destination path if it doesn't already
if ($DestinationPath[-1] -ne "\") {
    $DestinationPath += "\"

#Add Interop Assembly
Add-type -AssemblyName "Microsoft.Office.Interop.Outlook" | Out-Null

#Type declaration for Outlook Enumerations, Thank you Hey, Scripting Guy! blog for this demonstration
$olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$olSaveType = "Microsoft.Office.Interop.Outlook.OlSaveAsType" -as [type]
$olClass = "Microsoft.Office.Interop.Outlook.OlObjectClass" -as [type]

#Add Outlook Com Object, MAPI namespace, and set folder to the Inbox
$outlook = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNameSpace("MAPI")
#Future Functionality to Receive Email before saving - Still Needs Testing
#$outlook.Session | Out-Null
#$outlook.Session.SendAndReceive($false) | Out-Null
$folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)

#Iterate through each object in the chosen folder
foreach ($email in $folder.Items) {
    #Get email's subject and date
    [string]$subject = $email.Subject
    [string]$sentOn = $email.SentOn

    #Strip subject and date of illegal characters, add .msg extension, and combine
    $fileName = Remove-InvalidFileNameChars -Name ($sentOn + "-" + $subject + ".msg")

    #Combine destination path with stripped file name
    $dest = $DestinationPath + $fileName
    #Test if object is a MailItem
    if ($email.Class -eq $olClass::olMail) {
        #Test if UnreadOnly switch was used
        if ($UnreadOnly) {
            #Test if email is unread and save if true
            if ($email.Unread) {
                #Test if MarkRead switch was used and mark read
                if ($MarkRead) {
                    $email.Unread = $false
                $email.SaveAs($dest, $olSaveType::olMSG)
        #UnreadOnly switch not used, save all
        else {
            $email.SaveAs($dest, $olSaveType::olMSG)

#Quit Outlook and release the ComObject and references
#This does not seem to work correctly in a script versus the command line
#and does not shut the process down like expected after reading the 
#TechNet article here:
#Any help with this would be appreciated
Remove-Variable folder
Remove-Variable namespace
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($outlook) | Out-Null
Remove-Variable outlook

November 26, 2014 at 7:18 pm

I solved it with a simple if statement based on the $sentOn