Export Outlook Mails als .msg
Guten Morgen Zusammen,
ich habe ein Problem mit einem Powershell Skript.
Aktuell sichert das Skript alle Mails im Ordner Posteingang nach Eingabe eines bestimmten Zeitraums in einen Ordner als .msg Datei. Das funktioniert auch. Allerdings werden die Unterordner im Posteingang scheinbar ignoriert. Auch wenn ich mit der Rekursiv Funktion suche, werden diese ignoriert. Hat jemand einen Tipp? Oder geht es gänzlich einfacher?
ich habe ein Problem mit einem Powershell Skript.
Aktuell sichert das Skript alle Mails im Ordner Posteingang nach Eingabe eines bestimmten Zeitraums in einen Ordner als .msg Datei. Das funktioniert auch. Allerdings werden die Unterordner im Posteingang scheinbar ignoriert. Auch wenn ich mit der Rekursiv Funktion suche, werden diese ignoriert. Hat jemand einen Tipp? Oder geht es gänzlich einfacher?
# Function: Validate-Properties
function Validate-Properties {
param (
[psobject]$InputObject,
[string[]]$RequiredProperties
)
$MissingProps = @()
foreach ($Prop in $RequiredProperties) {
if (-not $InputObject.PSObject.Properties[$Prop]) {
$MissingProps += $Prop
}
}
return $MissingProps
}
# Function: Create-FileName
function Create-FileName {
param (
[psobject]$InputObject,
[string]$FileNameFormat
)
$FileName = $FileNameFormat
$FileName = $FileName -replace '%SenderName%', $InputObject.SenderName
$FileName = $FileName -replace '%Subject%', $InputObject.Subject -replace '[<>:"/\\|?*]', '' # Remove invalid characters
$FileName = $FileName -replace '%ReceivedTime%', $InputObject.ReceivedTime.ToString('yyyyMMdd_HHmmss')
return $FileName
}
# Function: Get-ValidFileName
function Get-ValidFileName {
param (
[string]$FileName
)
# Replace invalid characters for Windows file names
$InvalidChars = [System.IO.Path]::GetInvalidFileNameChars()
foreach ($char in $InvalidChars) {
$FileName = $FileName -replace [regex]::Escape($char), ''
}
return $FileName
}
# Function: Add-Numbering
function Add-Numbering {
param (
[string]$FileName,
[string]$FileExtension
)
$Counter = 1
$BaseFileName = $FileName
while (Test-Path "$FileName.$FileExtension") {
$FileName = "$BaseFileName ($Counter)"
$Counter++
}
return "$FileName.$FileExtension"
}
# Function: Export-OutlookMessage
function Export-OutlookMessage {
[CmdletBinding()]
Param(
[parameter(Mandatory=$true,ValueFromPipeline=$true)] [ValidateNotNullOrEmpty()] [psobject[]]$Messages,
[parameter(Mandatory=$true,ValueFromPipeline=$false)] [string]$OutputFolder,
[parameter(Mandatory=$false,ValueFromPipeline=$false)] [string]$FileNameFormat='FROM= %SenderName% SUBJECT= %Subject%',
[parameter(Mandatory=$false,ValueFromPipeline=$false)] [ref]$SkippedMessages
)
BEGIN {
Write-Verbose -Message 'Export-OutlookMessage starting...'
$olSaveAsTypes = "Microsoft.Office.Interop.Outlook.olSaveAsType" -as [type]
# Convert format message to real file name, replace %...% with message attribute
$RegEx = '(\%)(.+?)(\%)'
$ReqProps = @('Subject','SaveAs','SenderName')
$ReqProps += ([regex]::Matches($FileNameFormat,$RegEx) ).Value -replace '%',''
# Initialize queue for skipped messages, if it is passed
if ($SkippedMessages) {
$SkippedMessages.Value = @()
}
}
PROCESS {
foreach ($Message in $Messages) {
# Check input object
$NotFoundProps = Validate-Properties -InputObject $Message -RequiredProperties $ReqProps # Validate-Properties is internal function
if ($NotFoundProps) {
$ErrorMessage = 'Message '
if ($Message.Subject) {
$ErrorMessage += $Message.Subject
} else {
$ErrorMessage += 'Unknown'
}
$ErrorMessage += ' is not a proper object. Missing: ' + ($NotFoundProps -join ',')
if ($SkippedMessages) {
$SkippedMessages.Value += $Message # adding skipped messages to referenced variable if passed
}
Write-Error -Message $ErrorMessage
Continue # next foreach
}
Write-Verbose -Message ('Processing '+($Message.Subject))
# Creating file name
$FileName = Create-FileName -InputObject $Message -FileNameFormat $FileNameFormat # Create-FileName is internal function
# Fix file name
$FileName = Get-ValidFileName -FileName $FileName
$FullFilePath = Add-Numbering -FileName (Join-Path -Path $OutputFolder -ChildPath $FileName) -FileExtension 'msg'
Write-Verbose -Message "Saving message to $FullFilePath"
# Save message to disk
try {
$Message.SaveAs($FullFilePath,$olSaveAsTypes::olMSGUnicode)
} catch {
if ($SkippedMessages) {
$SkippedMessages.Value += $Message # adding skipped messages to referenced variable if passed
}
Write-Error -Message ('Message save exception.'+$Error[0].Exception)
}
}
}
END {
Write-Verbose -Message 'Export-OutlookMessage completed.'
}
}
Add-Type -AssemblyName System.Windows.Forms
# Function to prompt for date input
function Get-DateRange {
$StartDateInput = Read-Host "Enter the start date (dd.MM.yyyy)"
$EndDateInput = Read-Host "Enter the end date (dd.MM.yyyy)"
try {
# Parse the input dates using the specified format
$StartDate = [datetime]::ParseExact($StartDateInput, "dd.MM.yyyy", $null)
$EndDate = [datetime]::ParseExact($EndDateInput, "dd.MM.yyyy", $null)
# Ensure the start date is before or equal to the end date
if ($StartDate -gt $EndDate) {
throw "Start date must be before or equal to end date."
}
} catch {
Write-Error "Invalid date format or range. Please use dd.MM.yyyy format."
exit 1
}
return @{ StartDate = $StartDate; EndDate = $EndDate }
}
# Function to prompt user for folder selection
function Get-OutputFolder {
$FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
$FolderBrowser.Description = "Select the folder where you want to save the exported emails"
# Show the dialog and get the result
$DialogResult = $FolderBrowser.ShowDialog()
if ($DialogResult -eq [System.Windows.Forms.DialogResult]::OK) {
$SelectedPath = $FolderBrowser.SelectedPath
if (-not (Test-Path -Path $SelectedPath)) {
New-Item -ItemType Directory -Path $SelectedPath | Out-Null
Write-Output "Created folder: $SelectedPath"
}
return $SelectedPath
} else {
Write-Error "No folder was selected. Exiting script."
exit 1
}
}
# Get date range from the user
$DateRange = Get-DateRange
$StartDate = $DateRange.StartDate
$EndDate = $DateRange.EndDate
# Get output folder from the user
$OutputFolder = Get-OutputFolder
# Initialize Outlook COM object
$Outlook = New-Object -ComObject Outlook.Application
$Namespace = $Outlook.GetNamespace("MAPI")
$Inbox = $Namespace.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox)
$InboxMessages = $Inbox.Items
# Initialize counters
$SuccessCount = 0
$FailureCount = 0
# Filter messages by date range
$FilteredMessages = @()
foreach ($Item in $InboxMessages) {
if ($Item -is [Microsoft.Office.Interop.Outlook.MailItem] -and $Item.ReceivedTime -ge $StartDate -and $Item.ReceivedTime -le $EndDate) {
$FilteredMessages += $Item
}
}
# Display total count for debugging
$TotalItems = $FilteredMessages.Count
Write-Output "Total items to process: $TotalItems"
# Loop through filtered messages
for ($i = 0; $i -lt $TotalItems; $i++) {
$Item = $FilteredMessages[$i]
try {
# Create a valid filename for the email with sender name included
$SenderName = $Item.SenderName -replace '[\\/:*?"<>|]', '' # Remove invalid characters
$FileName = "{0:yyyyMMdd_HHmm} - {1} - {2}.msg" -f $Item.ReceivedTime, $SenderName, $Item.Subject
$FileName = $FileName -replace '[\\/:*?"<>|]', '' # Remove invalid filename characters
# Define the full path for the file
$FilePath = Join-Path -Path $OutputFolder -ChildPath $FileName
# Save the mail item
$Item.SaveAs($FilePath, 3) # 3 corresponds to olMSGUnicode
Write-Output "Saved: $FilePath"
$SuccessCount++
}
catch {
Write-Warning "Failed to save an item. Subject: $($Item.Subject) - Error: $_"
$FailureCount++
}
# Display progress information
$PercentComplete = [math]::Round((($i + 1) / $TotalItems) * 100, 2)
Write-Output "Progress: $PercentComplete% Complete - Processing item $($i + 1) of $TotalItems"
}
# Summary of the operation
Write-Output "Successfully saved $SuccessCount items."
Write-Output "Failed to save $FailureCount items."
Please also mark the comments that contributed to the solution of the article
Content-Key: 12360602016
Url: https://administrator.de/contentid/12360602016
Printed on: August 20, 2024 at 05:08 o'clock
1 Comment
Moin.
Du musst dir eine rekursive Funktion in der Art und Weise bauen dann klappt das auch ...
Gruß
Auch wenn ich mit der Rekursiv Funktion suche, werden diese ignoriert.
Dann hast du die Funktion falsch aufgebaut.Du musst dir eine rekursive Funktion in der Art und Weise bauen dann klappt das auch ...
function RecurseIntoFolders {
param(
$parentfolder
)
# alle Mails des Ordners durchlaufen und exportieren
foreach($mail in $parentfolder.Items){
# .....
# $mail.SaveAs(.......)
}
# alle Unterordner des Ordners mit der Funktion rekursiv durchlaufen
foreach($folder in $parentfolder.Folders){
RecurseIntoFolders -parentfolder $folder
}
}
RecurseIntoFolders -parentfolder $inbox