Back to script library
Entra / Microsoft 365 · Compliance & audit

New retention policy for shared mailboxes

A script to add shared mailboxes to a dedicated Microsoft 365 retention policy.

Connect & set up

Run these once per session. All scopes are read-only unless the script makes changes.

Connect-ExchangeOnline -showBanner:$false -UserPrincipalName (Get-MgContext).Account

Run it

The main script. Copy it, or download the .ps1 and run it from your console.

[array]$Modules = Get-Module | Select-Object -ExpandProperty Name
If ("ExchangeOnlineManagement" -Notin $Modules) {
Write-Host "Connecting to Exchange Online..." -ForegroundColor Yellow
Connect-ExchangeOnline -showBanner:$false -UserPrincipalName (Get-MgContext).Account
}
# Connect to the Security & Compliance Center PowerShell
Write-Host "Connecting to Security & Compliance Center PowerShell..." -ForegroundColor Yellow
Connect-IPPSSession -ShowBanner:$false -UserPrincipalName (Get-MgContext).Account
# Find shared mailboxes
Write-Host "Finding shared mailboxes..." -ForegroundColor Yellow
[array]$Mbx = Get-ExoMailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited
If ($Mbx) {
# Only take mailboxes with unlimited hold duration
Write-Host ("{0} Shared mailboxes found" -f $Mbx.Count) -ForegroundColor Green
} Else {
Write-Host "No shared mailboxes found" -ForegroundColor Green
Break
}
# Create file containing mailbox data for the holds
$MbxReport = [System.Collections.Generic.List[Object]]::new()
ForEach ($M in $Mbx) {
$ReportLine = [PSCustomObject][Ordered]@{
UserPrincipalName = $M.UserPrincipalName
DisplayName = $M.DisplayName
ObjectId = $M.ExternalDirectoryObjectId
}
$MbxReport.Add($ReportLine)
}
# Can't have more than 1,000 mailboxes as locations for a retention policy: https://learn.microsoft.com/en-us/microsoft-365/compliance/retention-limits?view=o365-worldwide#locations-for-retention-policies
If ($MbxReport.Count -gt 1000) {
Write-Host ("There are {0} shared mailboxes. Retention policy locations are limited to 1000 mailboxes. Please split the mailboxes into smaller groups and run the script again." -f $MailboxesToHold.Count) -ForegroundColor Red
Break
}
[array]$MailboxesToHold = $MbxReport.UserPrincipalName | Sort-Object -Unique
Write-Host "Creating Microsoft 365 retention policy for shared mailboxes..." -ForegroundColor Yellow
$NewPolicy = New-RetentionCompliancePolicy -Name "Shared Mailboxes Retention Policy" -ExchangeLocation $MailboxesToHold `
-Comment ("Retention policy for shared mailboxes created by New-RetentionPolicySharedMailboxes.PS1 script on {0}" -f (Get-Date).ToString("dd-MMM-yyyy"))
If ($NewPolicy) {
Write-Host ("Retention policy {0} created" -f $NewPolicy.Name) -ForegroundColor Green
$NewPolicyRule = New-RetentionComplianceRule -Name TwoYearSharedMailboxRetention -Policy "Shared Mailboxes Retention Policy" -RetentionDuration 730 `
-Comment "Created by New-RetentionPolicySharedMailboxes.PS1 script"
If ($NewPolicyRule) {
Write-Host ("Retention rule {0} created" -f $NewPolicyRule.Name) -ForegroundColor Green
} Else {
Write-Host "Failed to create retention rule" -ForegroundColor Red
Break
}
} Else {
Write-Host "Failed to create retention policy" -ForegroundColor Red
Break
}
Write-Host "Updating shared mailboxes to remove Exchange retention policies..." -ForegroundColor Yellow
ForEach ($M in $Mbx) {
$MbxIdentity = $M.ExternalDirectoryObjectId
Write-Host ("Removing retention policies from shared mailbox {0}" -f $M.DisplayName) -ForegroundColor Yellow
Set-Mailbox -Identity $MbxIdentity -RetentionPolicy $null
}
Write-Host ("{0} shared mailboxes updated to use the {1} Microsoft 365 retention policy" -f $Mbx.count, $NewPolicy.Name) -ForegroundColor Green
Attribution