Экспортировать почту Outlook как .msg

У меня проблема со скриптом 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 г.

1 Ответ

2
Фортунат
Ответ получен11 сентября 2024 г.

Ваш ответ

Загрузить файл.