PowerShell – How to Fix a Corrupted Exchange Mailbox with One Click

As a system administrator, I’ve dealt with my share of corrupted Exchange mailboxes. The go-to fix is often a “rebuild,” a process that involves backing up the user’s entire mailbox to a PST file, disabling their mailbox, re-enabling it to create a fresh one, and finally importing the old data back. While effective, this process is painfully manual and time-consuming, involving hours of waiting for exports and imports to complete. If a database issue affects multiple users, this can turn into days of work.

This is a perfect scenario for PowerShell automation. The following script automates the entire backup, repair, and restore workflow. It turns a multi-hour, hands-on process into a single script that you can run and walk away from, freeing you up to handle other critical tasks.

The PowerShell Script for Mailbox Repair

This script defines a reusable function to monitor progress, then executes the full repair sequence: export, disable, enable, and import.

Note: As recommended by the source material, this script is best run directly on an Exchange Server or an admin station with the Exchange Management Shell installed until you are familiar with remote PowerShell sessions.

PowerShell

# It's good practice to define functions at the top of your script.
function Get-Status {
    param (
        [string]$User,
        [string]$Type # Type will be either "Export" or "Import"
    )

    $Status = ""
    # This loop will run until the status is "Completed" or "Failed"
    do {
        if ($Type -eq "Export") {
            $Request = Get-MailboxExportRequest -Mailbox $User | Select-Object -Last 1
        } else {
            $Request = Get-MailboxImportRequest -Mailbox $User | Select-Object -Last 1
        }
        
        $Status = $Request.Status
        Write-Host "Current $Type status for $User: $Status"
        Start-Sleep -Seconds 5
    }
    until ($Status -eq "Completed" -or $Status -eq "Failed")

    return $Status
}

# --- Main Script ---
# Get user information
$UserName = Read-Host "Enter the username of the mailbox to repair"
$PSTPath = "\\YOUR-SERVER\PST-Backups\$UserName.pst" # IMPORTANT: Change to your network share

# Step 1: Backup the user's mailbox
Write-Host "`nStarting mailbox export for $UserName..." -ForegroundColor Green
New-MailboxExportRequest -Mailbox $UserName -FilePath $PSTPath

# Step 2: Wait for the backup to complete
$ExportStatus = Get-Status -User $UserName -Type "Export"

# Step 3: Check status and proceed with repair
if ($ExportStatus -eq "Completed") {
    Write-Host "Export complete. Disabling and re-enabling mailbox..." -ForegroundColor Green
    
    # Disable and re-enable the mailbox to repair it
    Disable-Mailbox -Identity $UserName -Confirm:$false
    Enable-Mailbox -Identity $UserName
    
    # Step 4: Import the backup into the new mailbox
    Write-Host "`nStarting mailbox import for $UserName..." -ForegroundColor Green
    New-MailboxImportRequest -Mailbox $UserName -FilePath $PSTPath

    # Step 5: Wait for the import to complete and confirm
    $ImportStatus = Get-Status -User $UserName -Type "Import"
    if ($ImportStatus -eq "Completed") {
        Write-Host "Mailbox repair for $UserName is complete!" -ForegroundColor Green
    } else {
        Write-Host "Mailbox import failed. The backup is safe at $PSTPath for manual import." -ForegroundColor Red
    }
} else {
    Write-Host "Mailbox export failed. No changes were made to the mailbox." -ForegroundColor Red
}

How the Script Works: Understanding New Concepts

This script introduces two powerful programming concepts that are essential for advanced automation: functions and the Do-Until loop.

Creating Reusable Code with Functions

A function is a named block of code that performs a specific task and can be called multiple times throughout your script. In my experience, if you find yourself writing the same or similar code more than once, it’s time to create a function. This makes your script shorter, easier to read, and much simpler to maintain, as you only need to update the logic in one place. The concept is fundamental to most programming languages, including Python.

In our script, the Get-Status function is a perfect example. We need to monitor the progress of both an export and an import. Instead of writing the monitoring logic twice, we create a single, flexible function that can handle both tasks.

Waiting for a Condition with the Do-Until Loop

We’ve used ForEach loops before to perform an action on every item in a list. But what if we need a loop to run indefinitely until a specific condition is met? For that, we use a Do-Until loop.

A Do-Until loop works like this:

  1. Do: It runs the code inside the loop block.
  2. Until: It then checks the exit condition.
  3. If the condition is false, it repeats the loop; if it’s true, the loop stops.

This is perfect for checking the status of a long-running task. In our Get-Status function, the loop continuously checks the mailbox request status every 5 seconds. It only stops when the status is either “Completed” or “Failed”. The -or operator allows us to check for multiple exit conditions at once.

The Exchange Cmdlets Doing the Heavy Lifting

This script relies on a handful of powerful cmdlets from the Exchange Management Shell to interact with mailboxes.

  • New-MailboxExportRequest: This kicks off the process of backing up a user’s live mailbox to a .pst file on a network share.
  • Get-MailboxExportRequest: This cmdlet checks the status of the ongoing export (e.g., Queued, InProgress, Completed, Failed).
  • Disable-Mailbox: This disconnects the mailbox from the user account in Active Directory. The mailbox itself isn’t deleted immediately, but it’s no longer associated with the user.
  • Enable-Mailbox: This creates a new, empty mailbox in the Exchange database and links it to an existing user who doesn’t have one. This is the step that often fixes corruption issues.
  • New-MailboxImportRequest: This starts the process of importing the data from our backed-up .pst file into the user’s new mailbox.
  • Get-MailboxImportRequest: Just like its export counterpart, this checks the status of the import process.

Conclusion

What was once a tedious, multi-hour manual task can now be handled by a single script. By creating a reusable function and using a Do-Until loop to intelligently wait for tasks to complete, we’ve built a robust tool that saves an immense amount of time and prevents data loss by ensuring each step succeeds before moving to the next. This is the true power of PowerShell: turning complex administrative workflows into reliable, one-click solutions.

More Topics

Hello! I'm a gaming enthusiast, a history buff, a cinema lover, connected to the news, and I enjoy exploring different lifestyles. I'm Yaman Şener/trioner.com, a web content creator who brings all these interests together to offer readers in-depth analyses, informative content, and inspiring perspectives. I'm here to accompany you through the vast spectrum of the digital world.

Leave a Reply

Your email address will not be published. Required fields are marked *