Key Takeaways
- Choose the correct management plane across Exchange Online, Exchange Server, Purview, and hybrid environments.
- Manage recipients, mailboxes, permissions, mail flow, security, compliance, migration, and public folders safely.
- Build operational reports and troubleshooting workflows around evidence rather than guesswork.
- Preserve before-state, verification, and rollback evidence for production changes.
Practical Exchange Administration with PowerShell
Exchange administration usually starts with a simple request: give someone access to a mailbox, investigate a delivery problem, change a transport rule, prepare a migration, or find out why a setting is not behaving as expected.
The difficult part is rarely the first command.
The difficult part is knowing where the object is managed, what its current state is, how wide the change should be, and how you will prove that the result is correct.
This article brings those decisions together into one practical operating model. You will move from everyday recipient and mailbox administration into mail flow, security, compliance, hybrid operations, migration, public folders, monitoring, and troubleshooting.
1. Start with the management plane
Exchange administration becomes complicated when a property is visible in one place but authoritative somewhere else.
Exchange Online, Exchange Server, Microsoft Purview, and hybrid Exchange expose different command families and different boundaries. A syntactically correct command can still be the wrong operational choice if it is run against the wrong system.
| Management plane | Connection | Primary purpose | Operational rule |
|---|---|---|---|
| Exchange Online | `ExchangeOnlineManagement` / `Connect-ExchangeOnline` | Cloud recipients, mailboxes, mail flow, Exchange Online configuration, and many EOP tasks | Use modern authentication and current EXO behavior; prefer EXO-prefixed retrieval cmdlets for scale-sensitive reporting. |
| Exchange Server | Exchange Management Shell / supported remote PowerShell | Servers, databases, DAGs, transport, virtual directories, certificates, and on-premises recipients | Write current on-premises examples Subscription Edition-first. |
| Microsoft Purview / Security & Compliance | `Connect-IPPSSession` | Compliance search, eDiscovery, retention, audit, DLP, labels, and related compliance operations | Do not assume every compliance cmdlet exists in an Exchange Online session. |
| Hybrid Exchange | EXO PowerShell + Exchange Server EMS / management tools | Remote mailbox lifecycle, synchronized attributes, mail flow, OAuth, federation, migrations, and source-of-authority decisions | Determine where the relevant identity or Exchange attribute is authoritative before changing it. |
Before we start changing recipients and mailboxes, keep one idea in mind: good Exchange administration is a sequence of decisions, not a race to the first working cmdlet.
Exchange administration field guide
The operating model
Use the same evidence-driven sequence for a single recipient change or a larger production operation: know where to act, establish the current state, control the change, and prove the result.
Management Plane
Choose the correct management plane before touching the object or configuration.
What to do
- Identify whether the task belongs to Exchange Online, Exchange Server, Microsoft Purview, or a hybrid boundary.
- Determine the source of authority for the object or property.
- Confirm the session, tenant, forest, and applicable permissions.
Discover State
Inspect the actual object, identity, dependencies, and current values before deciding what to change.
What to do
- Confirm object type and stable identity.
- Inspect the properties relevant to the requested change.
- Check dependencies, synchronization state, and applicable policies.
Export Baseline
Preserve enough information to compare the result and support rollback if the change needs to be reversed.
What to do
- Export the relevant current configuration or object state.
- Record a change or run identifier and timestamp.
- Keep the baseline with the rest of the operational evidence.
Scope Target
Reduce the target set to the smallest group that satisfies the request and validate the count before writing.
What to do
- Use stable identities and deliberate filters.
- Count and inspect the target set before execution.
- Separate discovery or reporting logic from write operations.
Preview / Pilot
Use WhatIf where supported or validate the operation against a low-risk pilot before broad execution.
What to do
- Preview the intended operation when the cmdlet supports it.
- Pilot on a representative object or limited scope when practical.
- Review expected impact before proceeding.
Apply Change
Execute the smallest necessary change with appropriate permissions, error handling, and logging.
What to do
- Use the minimum required permissions for the task.
- Handle errors explicitly and capture useful output.
- Batch or throttle operations when scale requires it.
Verify Outcome
Do not treat command completion as proof of success. Validate the resulting Exchange behavior.
What to do
- Re-read the changed state with an appropriate Get/Test command.
- Validate service behavior from the relevant operational or end-user perspective.
- Check for side effects and unexpected differences from the baseline.
Preserve Evidence
Retain the evidence needed for support, audit, troubleshooting, and future comparison.
What to do
- Save command output, verification results, errors, and timestamps.
- Record what changed, when, by whom, and why.
- Keep the evidence associated with the change or incident record.
Rollback if Required
If the result is not acceptable, use the preserved baseline and documented rollback path rather than improvising.
What to do
- Compare the verified result with the intended state and baseline.
- Restore the documented previous values when rollback is required.
- Verify the restored service behavior and preserve the rollback evidence.
2. Recipient administration: identify before you modify
Most Exchange requests begin with a recipient, mailbox, group, contact, or resource. Identify the actual recipient class before changing it.
$Identity = 'alex@contoso.com'
Get-EXORecipient -Identity $Identity |
Select-Object DisplayName,
PrimarySmtpAddress,
RecipientType,
RecipientTypeDetails,
ExternalDirectoryObjectId,
Guid
Get-EXOMailbox -Identity $Identity `
-Properties ArchiveStatus,RetentionPolicy,CustomAttribute1 |
Select-Object DisplayName,
PrimarySmtpAddress,
RecipientTypeDetails,
ArchiveStatus,
RetentionPolicy,
CustomAttribute1
On Exchange Server:
Get-Recipient -Identity 'alex@contoso.com' |
Format-List Name,
PrimarySmtpAddress,
RecipientType,
RecipientTypeDetails,
Guid
| Recipient type | Typical management plane | Representative cmdlets | Operational consideration |
|---|---|---|---|
| User mailbox | EXO or Exchange Server, depending on mailbox location | `Get-EXOMailbox`, `Get-Mailbox`, `Set-Mailbox` | Confirm mailbox location, provisioning state, and synchronization status. |
| Shared mailbox | EXO or Exchange Server | `New-Mailbox -Shared`, `Set-Mailbox -Type Shared`, `Add-MailboxPermission` | Review permissions, storage, archive, and licensing requirements before changes. |
| Room / equipment mailbox | EXO or Exchange Server | `New-Mailbox -Room`, `New-Mailbox -Equipment`, `Set-CalendarProcessing` | Booking behavior is primarily calendar-processing configuration. |
| Mail user / contact | EXO or Exchange Server | `New-MailUser`, `New-MailContact`, `Set-MailUser`, `Set-MailContact` | These represent external mail targets; do not casually change recipient semantics. |
| Remote mailbox | Hybrid / on-premises management plane | `New-RemoteMailbox`, `Enable-RemoteMailbox`, `Set-RemoteMailbox` | The on-premises object represents a cloud mailbox in classic hybrid management. |
| Distribution group | EXO or Exchange Server | `New-DistributionGroup`, `Add-DistributionGroupMember` | Membership is explicitly managed rather than calculated. |
| Dynamic distribution group | EXO or Exchange Server | `New-DynamicDistributionGroup`, `Set-DynamicDistributionGroup` | Membership is calculated from a recipient filter; validate the filter before relying on it for delivery. |
Establish a baseline
For recurring administration, make discovery produce evidence rather than disappearing into the terminal.
$RunId = Get-Date -Format 'yyyyMMdd-HHmmss'
$Out = ".\RecipientBaseline-$RunId.csv"
Get-EXORecipient -ResultSize Unlimited |
Select-Object DisplayName,
PrimarySmtpAddress,
RecipientTypeDetails,
Guid,
ExternalDirectoryObjectId |
Sort-Object RecipientTypeDetails,DisplayName |
Export-Csv $Out -NoTypeInformation
Write-Host "Baseline exported to $Out"
3. Mailbox administration is service administration
Common mailbox changes include archives, forwarding, quotas, mailbox features, automatic replies, client access, regional settings, and resource booking.
| Area | Cmdlets | What to inspect | Operational caution |
|---|---|---|---|
| Inventory | `Get-EXOMailbox`, `Get-Mailbox`, `Get-EXOMailboxStatistics`, `Get-MailboxStatistics` | `Identity`, `ResultSize`, properties, property sets | Use optimized EXO retrieval for scale-sensitive reporting. |
| Mailbox features | `Set-Mailbox`, `Set-CASMailbox`, `Set-MailboxRegionalConfiguration` | Mailbox type, address visibility, retention, addresses, regional settings | Be deliberate with multivalued properties. |
| Archive | `Enable-Mailbox -Archive`, `Disable-Mailbox -Archive`, `Set-Mailbox` | Archive state and quota properties | Check licensing, mailbox plan, and tenant policy. |
| Automatic replies | `Get-MailboxAutoReplyConfiguration`, `Set-MailboxAutoReplyConfiguration` | State, messages, start/end times | Capture existing configuration before administrator-driven changes. |
| Resources | `Get-CalendarProcessing`, `Set-CalendarProcessing` | Booking policy, window, in-policy behavior, delegates | Calendar behavior is not explained by mailbox properties alone. |
| Client access | `Get-CASMailbox`, `Set-CASMailbox`, `Get-EXOCASMailbox` | OWA, MAPI, ActiveSync, POP, IMAP state | Validate the affected client population before broad protocol changes. |
Controlled forwarding
Forwarding deserves additional scrutiny because it can be both a legitimate business requirement and a security signal.
$Identity = 'alex@contoso.com'
$RunId = Get-Date -Format 'yyyyMMdd-HHmmss'
$Before = Get-EXOMailbox -Identity $Identity `
-Properties ForwardingAddress,
ForwardingSmtpAddress,
DeliverToMailboxAndForward
$Before |
Select-Object DisplayName,
PrimarySmtpAddress,
ForwardingAddress,
ForwardingSmtpAddress,
DeliverToMailboxAndForward |
Export-Csv ".\Forwarding-Before-$RunId.csv" -NoTypeInformation
Set-Mailbox -Identity $Identity `
-ForwardingSmtpAddress 'smtp:destination@contoso.com' `
-DeliverToMailboxAndForward $true
Get-EXOMailbox -Identity $Identity `
-Properties ForwardingAddress,
ForwardingSmtpAddress,
DeliverToMailboxAndForward |
Select-Object DisplayName,
PrimarySmtpAddress,
ForwardingAddress,
ForwardingSmtpAddress,
DeliverToMailboxAndForward
Bulk changes
CSV-driven work should separate input validation, target resolution, execution, and result reporting.
# CSV columns: Identity, Office, CustomAttribute1
$InputPath = '.\MailboxUpdates.csv'
$RunId = Get-Date -Format 'yyyyMMdd-HHmmss'
$LogPath = ".\MailboxUpdateLog-$RunId.csv"
$Rows = Import-Csv $InputPath
$Results = foreach ($Row in $Rows) {
$Result = [ordered]@{
Identity = $Row.Identity
Office = $Row.Office
CustomAttribute1 = $Row.CustomAttribute1
Status = 'NotStarted'
Error = $null
}
try {
if ([string]::IsNullOrWhiteSpace($Row.Identity)) {
throw 'Identity is blank.'
}
$Mailbox = Get-EXOMailbox -Identity $Row.Identity -ErrorAction Stop
$Params = @{
Identity = $Mailbox.PrimarySmtpAddress
Office = $Row.Office
CustomAttribute1 = $Row.CustomAttribute1
ErrorAction = 'Stop'
}
Set-Mailbox @Params
$Result.Status = 'Updated'
}
catch {
$Result.Status = 'Failed'
$Result.Error = $_.Exception.Message
}
[pscustomobject]$Result
}
$Results | Export-Csv $LogPath -NoTypeInformation
$Results | Group-Object Status | Select-Object Name,Count
Common failures include using display names as identities, confusing configuration with mailbox statistics, replacing an entire multivalued address collection when only one value should change, assuming shared mailboxes never require licensing, and changing client-access protocols without understanding the affected population.
4. Delegation: configure the exact right
Treat each delegation permission as a separate capability.
| Permission | Purpose | Representative cmdlets | Important distinction |
|---|---|---|---|
| Full Access | Open mailbox contents | `Add-MailboxPermission`, `Get-EXOMailboxPermission` | Does not grant Send As; automapping should be intentional. |
| Send As | Send as the mailbox or recipient | `Add-RecipientPermission`, `Get-EXORecipientPermission` | The mailbox appears as the sender; treat as a high-impact permission. |
| Send on Behalf | Send on behalf of the mailbox | `Set-Mailbox -GrantSendOnBehalfTo` | Use multivalue add/remove syntax to avoid overwriting existing delegates. |
| Folder permission | Access to a specific mailbox folder | `Add-MailboxFolderPermission`, `Set-MailboxFolderPermission` | Calendar and folder identities include the folder path. |
$Mailbox = 'shared-helpdesk@contoso.com'
$Delegate = 'alex@contoso.com'
Add-MailboxPermission -Identity $Mailbox -User $Delegate `
-AccessRights FullAccess `
-InheritanceType All `
-AutoMapping $false
Add-RecipientPermission -Identity $Mailbox -Trustee $Delegate `
-AccessRights SendAs `
-Confirm:$false
Set-Mailbox -Identity $Mailbox `
-GrantSendOnBehalfTo @{Add=$Delegate}
Add-MailboxFolderPermission -Identity "$Mailbox`:\Calendar" `
-User $Delegate `
-AccessRights Reviewer
Verify each right with the matching retrieval command:
Get-EXOMailboxPermission -Identity $Mailbox |
Where-Object {
$_.User -like '*alex*' -and
$_.AccessRights -contains 'FullAccess'
}
Get-EXORecipientPermission -Identity $Mailbox -Trustee $Delegate
Get-Mailbox -Identity $Mailbox |
Format-List GrantSendOnBehalfTo
Get-MailboxFolderPermission -Identity "$Mailbox`:\Calendar"
5. Mail flow rules: broad power requires narrow changes
Transport rules operate at organization scale. Evaluate five interacting dimensions:
conditions → exceptions → actions → priority → mode
StopRuleProcessing adds another important control because it determines whether lower-priority rules continue to evaluate the message.
Baseline the existing configuration first.
$RunId = Get-Date -Format 'yyyyMMdd-HHmmss'
Get-TransportRule |
Select-Object Name,
State,
Mode,
Priority,
Comments,
Description |
Export-Csv ".\TransportRules-Before-$RunId.csv" -NoTypeInformation
For a new change, prefer a narrow test or audit mode where the workload supports it.
New-TransportRule -Name 'Mark External Project Aurora Mail' `
-FromScope NotInOrganization `
-SubjectOrBodyContainsWords 'Project Aurora' `
-PrependSubject '[EXTERNAL-PROJECT] ' `
-Mode Audit `
-Comments 'Change CHG000000; owner Messaging Operations'
Get-TransportRule -Identity 'Mark External Project Aurora Mail' |
Format-List Name,
State,
Mode,
Priority,
Comments,
Description
Use message-trace evidence to prove Exchange Online behavior rather than relying only on the rule object’s configuration.
6. Connectors, domains, and routing
Start connector administration with the routing question: What path should the message take, and why? Exchange Online uses inbound/outbound connectors; Exchange Server uses Send/Receive connectors.
| Object | Representative cmdlets | Key properties | Operational concern |
|---|---|---|---|
| EXO inbound connector | `Get/New/Set/Remove-InboundConnector` | `SenderDomains`, `SenderIPAddresses`, `RequireTls` | Defines trusted or partner mail entering Exchange Online. |
| EXO outbound connector | `Get/New/Set/Remove-OutboundConnector`, `Validate-OutboundConnector` | `RecipientDomains`, `SmartHosts`, `TLSSettings` | Defines routes from Exchange Online to partners, smart hosts, or on-premises systems. |
| Exchange Server Send connector | `Get/New/Set/Remove-SendConnector` | `AddressSpaces`, `SmartHosts`, `DNSRoutingEnabled` | Defines outbound routing from on-premises transport. |
| Exchange Server Receive connector | `Get/New/Set/Remove-ReceiveConnector` | `Bindings`, `RemoteIPRanges`, `PermissionGroups`, `AuthMechanism` | Controls SMTP submission; open-relay exposure must be explicitly avoided. |
| Accepted / remote domains | `Get/Set-AcceptedDomain`, `Get/Set-RemoteDomain` | `DomainName`, `DomainType`, `TargetDeliveryDomain` | Domain classification and remote behavior often explain routing symptoms. |
# Exchange Online
Get-InboundConnector |
Select-Object Name,Enabled,ConnectorType,SenderDomains,
SenderIPAddresses,RequireTls
Get-OutboundConnector |
Select-Object Name,Enabled,ConnectorType,RecipientDomains,
SmartHosts,TLSSettings
Get-AcceptedDomain |
Select-Object Name,DomainName,DomainType,Default
Get-RemoteDomain |
Select-Object DomainName,AutoReplyEnabled,
AllowedOOFType,AutoForwardEnabled
# Exchange Server
Get-SendConnector |
Select-Object Name,Enabled,AddressSpaces,
SmartHosts,DNSRoutingEnabled,SourceTransportServers
Get-ReceiveConnector |
Select-Object Identity,Enabled,Bindings,
RemoteIPRanges,PermissionGroups,AuthMechanism
7. Message trace: diagnose the path, not just the symptom
Use the evidence source appropriate to the transport boundary: Exchange Online message trace; Exchange Server message tracking and queues.
| Scenario | Primary evidence | Useful inputs | What it tells you |
|---|---|---|---|
| Missing or delayed cloud message | `Get-MessageTraceV2` | Sender, recipient, time range, Message-ID when available | What Exchange Online observed: received, delivered, deferred, failed, quarantined, or expanded. |
| Detailed cloud event history | `Get-MessageTraceDetailV2` | MessageTraceId, recipient, MessageId | Pipeline events such as RECEIVE, SEND, DELIVER, DEFER, FAIL, EXPAND, and TRANSFER. |
| Deep cloud transport evidence | `Start-HistoricalSearch` | Report title, time range, MessageId, notification address | Extended Message Trace output for deeper analysis. |
| On-premises queue growth | `Get-Queue`, `Get-Message`, `Get-QueueDigest` | Server, queue identity, filters | Queue state, next hop, retry state, and affected messages. |
| On-premises delivery path | `Get-MessageTrackingLog` | Sender, recipients, MessageId, start/end, EventId | Events recorded by Exchange Server transport. |
$Start = (Get-Date).AddHours(-4)
$End = Get-Date
$Trace = Get-MessageTraceV2 `
-SenderAddress sender@contoso.com `
-RecipientAddress recipient@fabrikam.com `
-StartDate $Start `
-EndDate $End `
-ResultSize 5000
$Trace |
Select-Object Received,
SenderAddress,
RecipientAddress,
Subject,
Status,
MessageTraceId |
Export-Csv '.\MessageTraceV2.csv' -NoTypeInformation
$Trace |
Get-MessageTraceDetailV2 |
Export-Csv '.\MessageTraceDetailV2.csv' -NoTypeInformation
On Exchange Server:
Get-MessageTrackingLog `
-Sender sender@contoso.com `
-Recipients recipient@fabrikam.com `
-Start (Get-Date).AddHours(-4) `
-End (Get-Date) |
Select-Object Timestamp,
EventId,
Source,
Sender,
Recipients,
MessageSubject,
RecipientStatus
Get-Queue |
Format-Table Identity,Status,MessageCount,NextHopDomain
Get-QueueDigest
8. Security and protection policies
Protection administration follows a policy-and-rule model: the policy defines behavior; the rule controls scope, priority, and state.
| Area | Representative cmdlets | Check | Operational guidance |
|---|---|---|---|
| Anti-spam / hosted content filter | `Get/Set/New-HostedContentFilterPolicy`, `Get/Set/New-HostedContentFilterRule` | Policy settings plus rule scope and priority | Baseline policy/rule pairs before introducing custom behavior. |
| Anti-malware | `Get/Set/New-MalwareFilterPolicy`, `Get/Set/New-MalwareFilterRule` | Settings, recipients, exceptions | Policy and rule are separate objects. |
| Anti-phishing / Safe Links / Safe Attachments | Corresponding policy and rule families | Recipient scope, action settings, priority | Prefer standard or strict preset security policies before unnecessary custom sprawl. |
| Quarantine | `Get-QuarantineMessage`, `Release-QuarantineMessage`, `Delete-QuarantineMessage` | Message identity, recipient, received time | Preserve evidence before release or delete actions. |
| DKIM | `Get-DkimSigningConfig`, `New-DkimSigningConfig`, `Set-DkimSigningConfig` | Domain, enabled state, selectors | Coordinate DNS and service verification. |
| Message encryption | IRM and OME cmdlet families | Configuration, transport rules, message identity | Combine configuration, trace, headers, and client evidence during troubleshooting. |
Get-HostedContentFilterPolicy |
Select-Object Name,IsDefault,
SpamAction,HighConfidenceSpamAction
Get-HostedContentFilterRule |
Select-Object Name,State,Priority,
HostedContentFilterPolicy,RecipientDomainIs
Get-MalwareFilterPolicy |
Select-Object Name,IsDefault,Action,EnableFileFilter
Get-MalwareFilterRule |
Select-Object Name,State,Priority,
MalwareFilterPolicy,SentTo
Get-DkimSigningConfig |
Select-Object Domain,Enabled,Status,
Selector1CNAME,Selector2CNAME
9. Retention, compliance, eDiscovery, and audit
Compliance work requires precise terminology. Exchange MRM and Microsoft Purview retention are related but not interchangeable: MRM remains relevant to mailbox/archive lifecycle, while Purview provides the broader Microsoft 365 governance model.
| Area | Cmdlet family | Use case | Operational boundary |
|---|---|---|---|
| Exchange MRM | Retention policy/tag cmdlets, `Set-Mailbox`, `Start-ManagedFolderAssistant` | Mailbox retention tags, archive movement, deleted-item behavior | Exchange mailbox/archive lifecycle; do not present it as the only Microsoft 365 retention model. |
| Purview retention | `RetentionCompliancePolicy` / `RetentionComplianceRule` families | Multi-workload retention and deletion governance | Requires appropriate Purview permissions and licensing. |
| Compliance Search | `New-ComplianceSearch`, `Start-ComplianceSearch`, `Get-ComplianceSearch`, `New-ComplianceSearchAction` | Search locations and content | Use Security & Compliance PowerShell and verify current session requirements. |
| Unified audit | `Search-UnifiedAuditLog` | Microsoft 365 audit investigations | Export and preserve investigation evidence. |
| Exchange admin audit | `Get-AdminAuditLogConfig`, `Search-AdminAuditLog` | Administrative operation review | Useful for Exchange cmdlet and parameter activity. |
For compliance-search scenarios that require it, establish the Purview session explicitly.
Connect-IPPSSession -EnableSearchOnlySession
New-ComplianceSearch -Name 'Incident-Project-Aurora' `
-ExchangeLocation alex@contoso.com `
-ContentMatchQuery 'subject:"Project Aurora"'
Start-ComplianceSearch -Identity 'Incident-Project-Aurora'
Get-ComplianceSearch -Identity 'Incident-Project-Aurora'
For an audit investigation:
$Start = (Get-Date).AddDays(-7)
$End = Get-Date
Search-UnifiedAuditLog `
-StartDate $Start `
-EndDate $End `
-Operations SoftDelete,HardDelete,MoveToDeletedItems `
-UserIds alex@contoso.com `
-ResultSize 5000 |
Export-Csv '.\Audit-MailDeletion.csv' -NoTypeInformation
10. Hybrid administration: determine the source of authority
Hybrid Exchange is where administrative syntax meets architecture. A recipient can exist across directory, cloud, and on-premises systems without those systems sharing authority over every property.
Before changing a hybrid recipient, answer five questions:
- Is the object directory-synchronized?
- Where is identity authoritative?
- Where are Exchange attributes authoritative?
- Is cloud-managed Exchange attribute management enabled for this object or tenant?
- Is the task recipient management, service configuration, mail flow, or migration?
Get-HybridConfiguration | Format-List *
Get-OnPremisesOrganization |
Format-List Name,OrganizationGuid,HybridDomains,OutboundConnector
Get-IntraOrganizationConnector |
Format-List Name,DiscoveryEndpoint,TargetAddressDomains,Enabled
Get-OrganizationRelationship |
Format-List Name,DomainNames,
FreeBusyAccessEnabled,
TargetAutodiscoverEpr
Get-RemoteMailbox -Identity 'alex@contoso.com' |
Format-List Name,
PrimarySmtpAddress,
RemoteRoutingAddress,
RemoteRecipientType,
ExchangeGuid,
ArchiveGuid
| Task | Likely management plane | Representative cmdlets | Risk |
|---|---|---|---|
| Remote mailbox properties | Usually Exchange Server EMS / management tools unless supported cloud-managed attributes are enabled | `Get/Set-RemoteMailbox` | Wrong-plane edits can be overwritten by synchronization. |
| Cloud mailbox service settings | Exchange Online | `Set-Mailbox`, `Set-CASMailbox`, `Get-EXOMailbox` | Cloud-only service features belong in EXO. |
| Hybrid connectors / configuration | HCW plus EXO and EMS validation | `Get-HybridConfiguration`, connector cmdlets | Prefer HCW-owned configuration unless a documented change requires manual edits. |
| Free/busy and OAuth | Both sides | `Get-IntraOrganizationConnector`, `Test-OAuthConnectivity`, `Get-OrganizationRelationship` | Certificates, endpoints, and version dependencies matter. |
| Cloud-managed Exchange attributes | Exchange Online for supported attributes after enablement | Supported `Set-Mailbox` cloud-management controls | Do not treat cloud management as a blanket replacement for on-premises identity authority. |
11. Migration: make every phase observable
Mailbox migration depends on endpoint readiness, authentication, directory and mailbox state, throttling, data consistency, cutover timing, and post-move validation.
| Stage | Representative cmdlets | Operational focus |
|---|---|---|
| Endpoint discovery | `Get-MigrationEndpoint`, `Test-MigrationServerAvailability` | Confirm endpoint type, authentication, remote server, MRSProxy readiness, and credentials. |
| Batch creation | `New-MigrationBatch` | Use CSV input, endpoint, target delivery domain, and start/completion behavior intentionally. |
| Batch control | `Start-MigrationBatch`, `Stop-MigrationBatch`, `Complete-MigrationBatch`, `Remove-MigrationBatch` | Separate synchronization from completion when cutover timing matters. |
| User status | `Get-MigrationUser`, `Get-MigrationUserStatistics` | Review status, skipped items, consistency, errors, and reports. |
| Move requests | `New/Get/Suspend/Resume/Remove-MoveRequest`, `Get-MoveRequestStatistics` | Use for lower-level mailbox moves and troubleshooting. |
$Endpoint = Get-MigrationEndpoint |
Where-Object { $_.Identity -like '*Hybrid*' } |
Select-Object -First 1
$Batch = New-MigrationBatch -Name 'Wave-01' `
-SourceEndpoint $Endpoint.Identity `
-TargetDeliveryDomain 'contoso.mail.onmicrosoft.com' `
-CSVData ([System.IO.File]::ReadAllBytes('.\Wave-01.csv'))
Start-MigrationBatch -Identity $Batch.Identity
Get-MigrationBatch -Identity 'Wave-01'
Get-MigrationUser -BatchId 'Wave-01' |
Get-MigrationUserStatistics |
Select-Object Identity,
Status,
PercentComplete,
DataConsistencyScore,
SkippedItemCount
12. Public folders: treat them as an architecture
Public-folder administration combines hierarchy, content, permissions, mail enablement, mailboxes, capacity, migration, and client behavior, so treat it as a structured project rather than isolated commands.
Get-PublicFolder -Recurse -ResultSize Unlimited |
Select-Object Identity,
Name,
ParentPath,
MailEnabled |
Export-Csv '.\PublicFolder-Hierarchy.csv' -NoTypeInformation
Get-PublicFolderStatistics -ResultSize Unlimited |
Select-Object Name,
FolderPath,
ItemCount,
TotalItemSize,
LastModificationTime |
Export-Csv '.\PublicFolder-Statistics.csv' -NoTypeInformation
Get-MailPublicFolder -ResultSize Unlimited |
Select-Object Name,
PrimarySmtpAddress,
EmailAddresses |
Export-Csv '.\MailEnabledPublicFolders.csv' -NoTypeInformation
| Area | Representative cmdlets | What to preserve |
|---|---|---|
| Hierarchy | `Get/New/Set/Remove-PublicFolder` | Path and parent-child relationships; export before restructuring. |
| Statistics | `Get-PublicFolderStatistics` | Item count, size, and modification data. |
| Permissions | `Get/Add/Remove-PublicFolderClientPermission` | Explicit and inherited access before changes. |
| Mail enablement | `Get/Enable/Disable/Set-MailPublicFolder` | SMTP addresses and mail-flow expectations. |
| Public-folder mailboxes | `Get-Mailbox -PublicFolder`, `New-Mailbox -PublicFolder` | Placement and capacity considerations. |
| Migration | Migration batch and public-folder migration families | Pre/post snapshots, validation, lock-down/finalization steps, and one controlled migration plan. |
13. Monitoring and operational reporting
A useful operational report identifies the affected scope, fault domain, severity, and evidence. Exchange Server adds database, DAG, queue, and server-health data to the cloud-side configuration and trace data used in Exchange Online.
Exchange Server health snapshot
Get-ServerHealth -Identity EX01 |
Where-Object AlertValue -ne 'Healthy' |
Select-Object Server,
HealthSet,
Name,
AlertValue,
TargetResource
Get-MailboxDatabaseCopyStatus * |
Select-Object Name,
Status,
CopyQueueLength,
ReplayQueueLength,
ContentIndexState
Test-ReplicationHealth -Identity EX01
Get-QueueDigest
Exchange Online operational reports
$RunId = Get-Date -Format 'yyyyMMdd-HHmmss'
Get-EXOMailbox -ResultSize Unlimited `
-Properties ArchiveStatus,RetentionPolicy |
Select-Object DisplayName,
PrimarySmtpAddress,
RecipientTypeDetails,
ArchiveStatus,
RetentionPolicy |
Export-Csv ".\EXO-MailboxInventory-$RunId.csv" -NoTypeInformation
Get-EXOMailbox -ResultSize Unlimited `
-Properties ForwardingSmtpAddress,
ForwardingAddress,
DeliverToMailboxAndForward |
Where-Object {
$_.ForwardingSmtpAddress -or
$_.ForwardingAddress
} |
Select-Object DisplayName,
PrimarySmtpAddress,
ForwardingSmtpAddress,
ForwardingAddress,
DeliverToMailboxAndForward |
Export-Csv ".\EXO-ForwardingInventory-$RunId.csv" -NoTypeInformation
| Monitoring area | Representative cmdlets | Environment | Operational use |
|---|---|---|---|
| Server health | `Get-ServerHealth`, `Get-HealthReport`, monitoring probes | Exchange Server | Locate component-level health faults. |
| Database availability | `Get-MailboxDatabaseCopyStatus`, `Test-ReplicationHealth` | Exchange Server | Assess database-copy and replication health. |
| Queues and transport | `Get-Queue`, `Get-QueueDigest` | Exchange Server | Investigate delivery backlogs and routing incidents. |
| Message trace | `Get-MessageTraceV2`, `Get-MessageTraceDetailV2`, `Start-HistoricalSearch` | Exchange Online | Establish cloud-side transport evidence. |
| Mailbox reporting | `Get-EXOMailbox`, `Get-EXOMailboxStatistics` | Exchange Online | Inventory mailbox configuration and service data. |
| Audit / compliance | `Search-UnifiedAuditLog`, compliance cmdlets | Purview / Security & Compliance | Preserve investigation and governance evidence. |
14. Troubleshooting: collect evidence before changing things
Troubleshooting should be hypothesis-driven: collect evidence, isolate the fault domain, remediate deliberately, and verify the outcome.
| Symptom | Evidence to collect | Representative commands |
|---|---|---|
| Recipient cannot receive mail | Recipient type, accepted domain, address, moderation, rules, connectors, trace/tracking, quarantine | `Get-Recipient`, `Get-EXORecipient`, `Get-AcceptedDomain`, `Get-TransportRule`, Message Trace V2 or message tracking |
| Shared mailbox inaccessible | Full Access, automapping, mailbox type/state, licensing, Outlook/client state, hybrid ACL behavior | `Get-EXOMailboxPermission`, `Get-MailboxPermission`, `Get-Recipient` and client checks |
| External mail delayed | Trace status, connector, TLS, queue, remote response, DNS, smart host | Message Trace V2, `Start-HistoricalSearch`, `Get-Queue`, Send/Outbound connector cmdlets |
| Transport rule behaves unexpectedly | Priority, mode, conditions, exceptions, `StopRuleProcessing`, trace events | `Get-TransportRule`, `Get-MessageTraceDetailV2`, Extended Message Trace |
| Compliance search returns unexpected results | Session, permissions, location, query, indexing, time zone, scope | `Connect-IPPSSession`, `Get-ComplianceSearch`, audit cmdlets where relevant |
| Hybrid migration fails | Endpoint, authentication, MRSProxy, mailbox/archive state, skipped items, version, certificate, network | `Test-MigrationServerAvailability`, `Get-MigrationUserStatistics`, `Get-MoveRequestStatistics` |
A useful troubleshooting sequence is:
Confirm scope → choose management plane → collect evidence → test the hypothesis → isolate the fault domain → remediate → verify → preserve evidence
Reusable evidence folder
$CaseId = 'INC000000'
$RunId = Get-Date -Format 'yyyyMMdd-HHmmss'
$Path = ".\$CaseId-$RunId"
New-Item -ItemType Directory -Path $Path | Out-Null
Start-Transcript -Path "$Path\Transcript.txt"
Get-TransportRule |
Export-Clixml "$Path\TransportRules.xml"
Get-AcceptedDomain |
Export-Clixml "$Path\AcceptedDomains.xml"
Get-RemoteDomain |
Export-Clixml "$Path\RemoteDomains.xml"
Stop-Transcript
15. A production runbook pattern
For repeatable administration, make the operational stages explicit.
param(
[Parameter(Mandatory)]
[string]$ChangeId,
[Parameter(Mandatory)]
[string]$InputCsv,
[switch]$WhatIf
)
$RunId = Get-Date -Format 'yyyyMMdd-HHmmss'
$Root = ".\$ChangeId-$RunId"
New-Item -ItemType Directory -Path $Root -Force | Out-Null
Start-Transcript -Path "$Root\Transcript.txt"
try {
$Rows = Import-Csv $InputCsv
$Rows | Export-Csv "$Root\InputSnapshot.csv" -NoTypeInformation
# 1. Validate input
# 2. Discover and export before-state
# 3. Apply scoped change with ShouldProcess or -WhatIf
# 4. Verify and export after-state
# 5. Emit structured result objects
}
catch {
$_ | Out-File "$Root\FatalError.txt"
throw
}
finally {
Stop-Transcript
}
16. The production checklist
Use the following as the final muscle memory for Exchange PowerShell changes.
| # | Checkpoint | What good looks like |
|---|---|---|
| 1 | Choose management plane | EXO, Exchange Server, Purview, or a hybrid boundary is explicitly identified. |
| 2 | Verify RBAC | The operator has the cmdlets and parameters required. |
| 3 | Discover current state | Object type, identity, source of authority, and current values are confirmed. |
| 4 | Export baseline | Before-state is preserved with a run ID or change ID. |
| 5 | Scope narrowly | Targets are filtered and counted before a write. |
| 6 | Preview or pilot | Use `-WhatIf` where supported or test against a low-risk pilot object. |
| 7 | Execute defensively | Use `ErrorAction Stop`, structured handling, logging, and batching where appropriate. |
| 8 | Verify service behavior | Use matching Get/Test/trace/statistics commands rather than relying on command completion. |
| 9 | Preserve evidence | Transcript, output, errors, and verification results are retained. |
| 10 | Prepare rollback | Original values and an explicit rollback path are available. |
Conclusion
Practical Exchange administration is less about memorizing commands and more about learning to ask the right questions before you run them.
Where is this object actually managed? What is its current state? Who will be affected? What evidence will show that the change worked? What will let you recover if it did not?
Once those questions become part of your normal workflow, PowerShell becomes much more than a collection of Exchange commands. It becomes a dependable way to investigate, change, verify, and support the service.
References
- Exchange PowerShell documentation
Microsoft Learn documentation for Exchange Online PowerShell, Exchange Server PowerShell, Security & Compliance PowerShell, cmdlet syntax, permissions, and connection methods.
- Connect to Exchange Online PowerShell
Microsoft guidance for connecting to Exchange Online PowerShell with modern authentication.
- Get-EXOMailbox
Microsoft reference for optimized Exchange Online mailbox retrieval and property selection.
- Find the permissions required to run any Exchange cmdlet
Microsoft guidance for identifying management roles, role groups, parameters, and scopes.
- Connect to Security & Compliance PowerShell
Microsoft guidance for Security & Compliance PowerShell sessions.
- Message trace in Exchange Online
Microsoft reference for the current Exchange Online Message Trace V2 cmdlet.