Exchange
Table of Contents
Search Mailbox Audit Logs
- Make sure that mailbox auditing is enabled.
- Make sure that you have sufficient rights (PIM roles activated if necessary).
- ExchangeOnlineManagement module installed.
- Session to Exchange Online.
get-mailbox diningservices | select audit*
Output:
AuditEnabled : True
AuditLogAgeLimit : 90.00:00:00
AuditAdmin : {Update, MoveToDeletedItems, SoftDelete, HardDelete…}
AuditDelegate : {Update, MoveToDeletedItems, SoftDelete, HardDelete…}
AuditOwner : {Update, MoveToDeletedItems, SoftDelete, HardDelete…}
Execute the following PowerShell to get the audit logs. Adjust the dates as needed.
$Mailbox = "<Mailbox Name>"
$start = (Get-Date).AddDays(-90); $end = (Get-Date); $auditData = New-Object System.Collections.ArrayList;
$Params = @{
Identity = $Mailbox
StartDate = $Start
EndDate = $End
LogonTypes = "Owner", "Admin", "Delegate"
ResultSize = 50000
}
search-mailboxAuditLog @Params -ShowDetails -OutVariable +auditdata | out-null
Restore Recoverable Mail Items
Get a list of the recoverable items
Get-RecoverableItems $Mailbox -ResultSize unlimited
Restore all recoverable items
(Get-RecoverableItems $Mailbox -ResultSize unlimited) | Restore-RecoverableItems
Restore recoverable items that have been deleted from the Inbox folder.
(Get-RecoverableItems $Mailbox -ResultSize unlimited) | ? {$_.lastparentpath -eq "Inbox"} | Restore-RecoverableItems
Rename Mailbox
Renaming a shared mailbox and updating all associated attributes including aliases and proxy addresses.
function Rename-Mailbox
{
<#
.SYNOPSIS
Renames a shared mailbox and updates all associated attributes including aliases and proxy addresses.
.DESCRIPTION
This function renames a shared mailbox by updating all identity-related attributes including:
- Alias, Name, DisplayName
- PrimarySmtpAddress, WindowsEmailAddress, MicrosoftOnlineServicesID
- All proxy addresses to match the new naming convention
It handles both primary and secondary proxy addresses, maintains existing domain configurations,
and provides comprehensive error handling for complete mailbox identity consistency.
.PARAMETER Identity
The current identity of the shared mailbox (email address or alias).
.PARAMETER NewAlias
The new alias for the shared mailbox.
.PARAMETER NewDisplayName
The new display name for the shared mailbox. If not provided, it will be generated from the NewAlias.
.PARAMETER Domain
The domain to use for the primary email address. If not provided, uses the existing primary domain.
.PARAMETER UpdateAllProxyAddresses
Switch to update all proxy addresses with the new alias while maintaining the existing domains.
.PARAMETER WhatIf
Shows what would happen if the function runs without actually making changes.
.PARAMETER Confirm
Prompts for confirmation before making changes.
.EXAMPLE
Rename-SharedMailbox -Identity "old-mailbox@contoso.com" -NewAlias "new-mailbox"
Renames the shared mailbox to use "new-mailbox" as the alias.
.EXAMPLE
Rename-SharedMailbox -Identity "finance@contoso.com" -NewAlias "accounting" -NewDisplayName "Accounting Department" -UpdateAllProxyAddresses
Renames the mailbox and updates all proxy addresses with the new alias.
.NOTES
Author: Joseph Streeter
Requires: Exchange Online PowerShell Module (ExchangeOnlineManagement)
Prerequisites: Must be connected to Exchange Online using Connect-ExchangeOnline
Version: 1.1
#>
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')]
param
(
[Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
[ValidateNotNullOrEmpty()]
[string]$Identity,
[Parameter(Mandatory = $true, Position = 1)]
[ValidateNotNullOrEmpty()]
[ValidatePattern('^[a-zA-Z0-9._-]+$')]
[string]$NewAlias,
[Parameter(Mandatory = $false)]
[string]$NewDisplayName,
[Parameter(Mandatory = $false)]
[string]$Domain,
[Parameter(Mandatory = $false)]
[switch]$UpdateAllProxyAddresses
)
begin
{
Write-Verbose "Starting Rename-SharedMailbox function"
# Check if Exchange Online module is available and connected
try
{
# First check if the Exchange Online module commands are available
if (-not (Get-Command Get-Mailbox -ErrorAction SilentlyContinue))
{
Write-Error "Exchange Online PowerShell module is not loaded. Please install and import the ExchangeOnlineManagement module first."
return
}
# Test actual connection by trying to get connection info
$connectionInfo = Get-ConnectionInformation -ErrorAction SilentlyContinue
if (-not $connectionInfo -or $connectionInfo.Count -eq 0)
{
Write-Error "Not connected to Exchange Online. Please run 'Connect-ExchangeOnline' first."
return
}
# Verify we can actually query Exchange Online
$null = Get-OrganizationConfig -ErrorAction Stop
Write-Verbose "Successfully verified Exchange Online connection"
}
catch
{
Write-Error "Failed to verify Exchange Online connectivity: $($_.Exception.Message). Please ensure you are connected to Exchange Online."
return
}
}
process
{
try
{
Write-Verbose "Processing mailbox: $Identity"
# Get the current mailbox
$currentMailbox = Get-Mailbox -Identity $Identity -ErrorAction Stop
if ($currentMailbox.RecipientTypeDetails -ne 'SharedMailbox')
{
throw "The specified mailbox '$Identity' is not a shared mailbox. Current type: $($currentMailbox.RecipientTypeDetails)"
}
Write-Information "Found shared mailbox: $($currentMailbox.DisplayName) [$($currentMailbox.PrimarySmtpAddress)]"
# Set default values if not provided
if (-not $NewDisplayName)
{
$NewDisplayName = $NewAlias -replace '[._-]', ' ' |
ForEach-Object { (Get-Culture).TextInfo.ToTitleCase($_.ToLower()) }
}
if (-not $Domain)
{
$Domain = ($currentMailbox.PrimarySmtpAddress -split '@')[1]
}
# Build new proxy addresses
$newPrimaryEmail = "$NewAlias@$Domain"
$newProxyAddresses = @()
# Add the new primary SMTP address
$newProxyAddresses += "SMTP:$newPrimaryEmail"
if ($UpdateAllProxyAddresses)
{
# Update all existing proxy addresses with new alias while preserving domains
foreach ($proxyAddress in $currentMailbox.EmailAddresses)
{
if ($proxyAddress -like 'smtp:*')
{
$addressDomain = ($proxyAddress -split '@')[1]
if ($addressDomain -ne $Domain)
{
$newProxyAddresses += "smtp:$NewAlias@$addressDomain"
}
}
elseif ($proxyAddress -notlike 'SMTP:*')
{
# Preserve non-SMTP addresses (like X400)
$newProxyAddresses += $proxyAddress
}
}
}
else
{
# Keep existing proxy addresses except the old primary
foreach ($proxyAddress in $currentMailbox.EmailAddresses)
{
if ($proxyAddress -like 'smtp:*')
{
$newProxyAddresses += $proxyAddress
}
elseif ($proxyAddress -notlike 'SMTP:*')
{
$newProxyAddresses += $proxyAddress
}
}
}
# Remove duplicates
$newProxyAddresses = $newProxyAddresses | Select-Object -Unique
# Display what will be changed
Write-Information "Proposed changes:"
Write-Information " Current Alias: $($currentMailbox.Alias) -> New Alias: $NewAlias"
Write-Information " Current Name: $($currentMailbox.Name) -> New Name: $NewAlias"
Write-Information " Current Display Name: $($currentMailbox.DisplayName) -> New Display Name: $NewDisplayName"
Write-Information " Current Primary Email: $($currentMailbox.PrimarySmtpAddress) -> New Primary Email: $newPrimaryEmail"
Write-Information " Current Windows Email: $($currentMailbox.WindowsEmailAddress) -> New Windows Email: $newPrimaryEmail"
Write-Information " Current MicrosoftOnlineServicesID: $($currentMailbox.MicrosoftOnlineServicesID) -> New MicrosoftOnlineServicesID: $newPrimaryEmail"
Write-Information " New Proxy Addresses: $($newProxyAddresses -join ', ')"
# Apply changes if not in WhatIf mode
if ($PSCmdlet.ShouldProcess($Identity, "Rename shared mailbox to '$NewAlias'"))
{
# Update the mailbox properties
$setMailboxParams = @{
Identity = $Identity
Alias = $NewAlias
Name = $NewAlias
DisplayName = $NewDisplayName
MicrosoftOnlineServicesID = $newPrimaryEmail
EmailAddresses = $newProxyAddresses
ErrorAction = 'Stop'
}
Set-Mailbox @setMailboxParams
# Update the user properties (WindowsEmailAddress)
$setUserParams = @{
Identity = $NewAlias
WindowsEmailAddress = $newPrimaryEmail
ErrorAction = 'Stop'
}
Set-User @setUserParams
Write-Information "Successfully renamed shared mailbox '$Identity' to '$NewAlias'" -InformationAction Continue
# Return the updated mailbox object
return Get-Mailbox -Identity $NewAlias
}
}
catch
{
$errorMessage = "Failed to rename shared mailbox '$Identity': $($_.Exception.Message)"
Write-Error $errorMessage
throw $_
}
}
end
{
Write-Verbose "Completed Rename-SharedMailbox function"
}
}
# Example usage (commented out)
<#
# Connect to Exchange Online first
# Connect-ExchangeOnline
# Example 1: Basic rename
# Rename-SharedMailbox -Identity "oldname@contoso.com" -NewAlias "newname"
# Example 2: Full rename with proxy address updates
# Rename-SharedMailbox -Identity "finance@contoso.com" -NewAlias "accounting" -NewDisplayName "Accounting Department" -UpdateAllProxyAddresses -Verbose
# Example 3: What-if scenario
# Rename-SharedMailbox -Identity "test@contoso.com" -NewAlias "testing" -WhatIf
#>