У меня проблема со скриптом Powershell. В настоящее время скрипт сохраняет все письма в папке "Входящие" как файлы .msg после ввода определенного периода времени. Это тоже работает. Однако подпапки в папке "Входящие" кажутся игнорируемыми. Даже если я ищу с помощью рекурсивной функции, они игнорируются. Есть ли у кого-нибудь совет? Или есть более простой способ?
# 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."
Никандр
Вопрос задан19 мая 2024 г.