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'

.EXAMPLE
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

.EXAMPLE
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

.EXAMPLE
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

.NOTES
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. 

.LINK
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.application.aspx
http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/26/use-powershell-to-data-mine-your-outlook-inbox.aspx
#>

#Binding for Common Parameters
[CmdletBinding(DefaultParameterSetName="All")]

Param(
    [Parameter(Mandatory=$true,
        Position=0,
        HelpMessage='Folder path to store emails. Do not use quotation marks even if the path has spaces.',
        ValueFromPipelineByPropertyName=$true
    )]
    [Alias("Destination", "Dest", "FullName")]
    [String]$DestinationPath,
    
    [Parameter(ParameterSetName="All")]
    [Parameter(Mandatory=$true,ParameterSetName="Unread")]
    [Switch]$UnreadOnly,

    [Parameter(ParameterSetName="Unread")]
    [Switch]$MarkRead
)

#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 {

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

    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:  http://technet.microsoft.com/en-us/library/ff730962.aspx
#Any help with this would be appreciated
$outlook.Quit()
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