This scripts helps to suspend all messages in an Exchange transport queue and to export all suspended messages to a given target folder.

The script uses the AssembleMessage cmdlet to properly export queued messages as .eml files.

Optionally, all exported messages can be removed from the transport queue.

 

Examples

PowerShell
Edit|Remove
# EXAMPLE 1 
# Export messages from queue MCMEP01\45534 to D:\ExportedMessages and do not delete messages after export 
.\Export-MessageQueue -Queue MCMEP01\45534 -Path D:\ExportedMessages 
 
# EXAMPLE 2 
# Export messages from queue MCMEP01\45534 to D:\ExportedMessages and delete messages after export 
.\Export-MessageQueue -Queue MCMEP01\45534 -Path D:\ExportedMessages -DeleteAfterExport
 
Find the corresponding blog post for comments here: https://www.granikos.eu/en/justcantgetenough/PostId/282/export-messages-from-message-queue
Enhance the PowerShell script at Github here: https://github.com/Apoc70/Export-MessageQueue

PowerShell Script

PowerShell
Edit|Remove
<# 
    .SYNOPSIS 
    Export messages from a transport queue to file system for manual replay  
    
    Thomas Stensitzki 
     
    THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE  
    RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. 
     
    Version 1.12017-01-05 
 
    Ideas, comments and suggestions to support@granikos.eu  
  
    .LINK   
    More information can be found at http://scripts.granikos.eu 
     
    .DESCRIPTION 
     
    This script suspends a transport queue, exports the messages to the local file system. After successful export the messages are optionally deleted from the queue. 
     
    .NOTES  
    Requirements  
    - Exchange Server 2013+ 
    - Windows Server 2012 R2   
    - Utilizes global functions library 
 
    Revision History  
    --------------------------------------------------------------------------------  
    1.0     Initial community release  
    1.1     Some PowerShell hygiene 
     
    .PARAMETER Queue 
    Full name of the transport queue, e.g. SERVER\354 
    Use Get-Queue -Server SERVERNAME to identify message queue 
 
    .PARAMETER Path 
    Path to folder for exprted messages 
 
    .PARAMETER DeleteAfterExport 
    Switch to delete per Exchange Server subfolders and creating new folders 
 
    .EXAMPLE 
    Export messages from queue MCMEP01\45534 to D:\ExportedMessages and do not delete messages after export 
 
    .\Export-MessageQueue -Queue MCMEP01\45534 -Path D:\ExportedMessages 
 
    .EXAMPLE 
    Export messages from queue MCMEP01\45534 to D:\ExportedMessages and delete messages after export 
 
    .\Export-MessageQueue -Queue MCMEP01\45534 -Path D:\ExportedMessages -DeleteAfterExport 
 
#> 
param( 
  [parameter(Mandatory=$true,HelpMessage='Transport queue holding messages to be exported (e.g. SERVER\354)')] 
    [string] $Queue, 
  [parameter(Mandatory=$true,HelpMessage='File path to local folder for exprted messages (e.g. E:\Export)')] 
    [string] $Path, 
    [switch] $DeleteAfterExport 
) 
 
# Set-StrictMode -Version Latest 
 
# Implementation of global module 
Import-Module GlobalFunctions 
$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path 
$ScriptName = $MyInvocation.MyCommand.Name 
$logger = New-Logger -ScriptRoot $ScriptDir -ScriptName $ScriptName -LogFileRetention 14 
$logger.Write('Script started') 
$logger.Write("Working on message queue $($Queue), Export folder: $($Path), DeleteAfterExport: $($DeleteAfterExport)") 
 
### FUNCTIONS ----------------------------- 
 
function Request-Choice { 
    param([string]$Caption) 
    $choices =  [System.Management.Automation.Host.ChoiceDescription[]]@("&Yes","&No") 
    [int]$defaultChoice = 1 
 
    $choiceReturn = $Host.UI.PromptForChoice($Caption, "", $choices, $defaultChoice) 
 
    return $choiceReturn    
} 
 
function Check-Folders { 
    # Check, if export folder exists 
    if(!(Test-Path $Path)) { 
        # Folder does not exist, lets create a new root folder 
        New-Item -Path $Path -ItemType Directory | Out-Null 
         
        $logger.Write("Folder $($Path) created") 
    } 
} 
 
 
function Check-Queue { 
    # Check message queue 
    $messageCount = -1 
    try { 
        $messageQueue = Get-Queue $Queue 
        $messageCount = $messageQueue.MessageCount 
         
        $logger.Write("$($messageCount) message(s) found in queue $($Queue)") 
    } 
    catch { 
        $logger.Write("Queue $($Queue) cannot be accessed") 
    } 
    $messageCount 
} 
 
function Export-Messages { 
    # Export suspended messages 
    try { 
        # Suspend messages in queue 
        $logger.Write("Suspending queue $($Queue)") 
        Get-Queue $Queue | Get-Message -ResultSize Unlimited | Suspend-Message -Confirm:$false 
 
        # Fetch suspended messages 
        $logger.Write("Fetching suspended messages from queue $($Queue)") 
         
        $messages = @(Get-Message $Queue -ResultSite Unlimited | Where-Object{$_.Status -eq "Suspened"} ) 
 
        $logger.Write("$($messages.Count) suspended messages fetched from queue $($Queue)") 
 
        # Export fetched messages 
        $messages | ForEach-Object {$m++;Export-Message $_.Identity | AssembleMessage -Path (Join-Path "$($m).eml" -Path $Path)} 
    } 
    catch {} 
} 
 
function Delete-Messages { 
    # Delete suspended messages from queue 
     
    $logger.Write("Delete  suspended messages from queue $($Queue)") 
     
    Get-Message -Queue $Queue -ResultSize Unlimited | Where-Object{$_.Status -eq "Suspened"} | Remove-Message -WithNDR $false -Confirm:$false  
} 
 
 
# MAIN #################################################### 
 
# 1. Check export folder 
Check-Folders 
 
# 2. Check queue 
if((Check-Queue -gt 0)) { 
    if((Request-Choice -Caption "Do you want to suspend and export all messages in queue $($Queue)?") -eq 0{ 
        # Yes, we want to suspend and delete messages 
        Export-Messages 
    } 
    else { 
        # No, we do not want to delete message 
        $logger.Write("User choice: Do not suspend and export messages") 
    } 
    if($DeleteAfterExport) { 
        if((Request-Choice -Caption "Do you want to DELETE all suspended messages from queue $($Queue)?") -eq 0{ 
            $logger.Write("User choice: DELETE suspended") 
            Write-Output "Suspended messages will be deleted WITHOUT sending a NDR!" 
            Delete-Messages  
        }  
        else { 
            $logger.Write("User choice: DO NOT DELETE suspended") 
            Write-Output "Exported messages have NOT been deleted from queue!" 
            Write-Output "Remove messages manually and be sure, if you want to send a NDR!" 
        } 
    } 
} 
else { 
    Write-Output "Queue $($Queue) does not contain any messages" 
    $logger.Write("Queue $($Queue) does not contain any messages"} 
 
$logger.Write("Script finished") 
Write-Host "Script finished"