Operations guide
Exchange ServerOperations manual
How to use this guide
This guide turns the official Microsoft documentation for Exchange Server (Subscription Edition, 2019 and 2016) into operational procedures you can use straight away. It does not replace the documentation: it makes it usable by someone who has just joined the team and has to work without breaking things.
Every section is marked with the minimum level of autonomy it requires. The level does not say how good you are, it says how much a mistake costs on that task.
| Level | Who | What they can do alone | What they must escalate |
|---|---|---|---|
| L1 | Helpdesk / first line | Reversible operations on single objects: creating mailboxes, groups, permissions, quotas, resetting client access, reading logs and queues. | Any change to servers, databases, connectors, certificates, DAG. |
| L2 | Junior sysadmin / second line | Mail flow diagnosis, queue management, receive connectors, ActiveSync policies, mailbox moves, planned routine maintenance. | AD schema changes, CU updates, unplanned switchovers, restores from backup. |
| L3 | Senior / point of reference | Everything else: updates, DAG, disaster recovery, certificates, architecture. | To Microsoft Support or the vendor. |
At the start of every procedure you will find the level label. If you are reading a procedure above your level, read it anyway: it helps you understand what happens when you escalate. But do not run it.
#Typographic conventions
- Text in
carattere monospaziatois a command, a cmdlet name, a path or a value to be typed exactly as shown. - Grey blocks with a side bar are PowerShell commands to paste into the Exchange Management Shell.
- Placeholders are written between angle brackets:
<UserName>,<ServerName>. They must be replaced, brackets included. - Coloured boxes flag notes, warnings and prohibitions. Red warnings mean operations with potential data loss.
The ten golden rules
If you remember only one page of this guide, remember this one.
1. Read before you write
Every Get- cmdlet is safe and changes nothing. Every Set-, New-, Remove-, Enable-, Disable-, Move- cmdlet changes something. Before running a command that changes anything, run the matching Get- on the same object and look at how it is now.
2. Use -WhatIf
Almost every cmdlet that changes something accepts -WhatIf: it shows what it would do without doing it. On commands that hit more than one object (filters, pipes, loops) -WhatIf is not an option, it is a requirement.
Set-Mailbox -Identity m.rossi -ProhibitSendQuota 5GB -WhatIf3. Distrust the pipe
Get-Mailbox | Set-Mailbox ... without a filter touches every mailbox in the organisation. It is the fastest way to cause an incident on this platform. Always filter, check the count, then run.
# 1) how many mailboxes would I hit?
(Get-Mailbox -ResultSize Unlimited -Filter "Department -eq 'Sales'").Count
# 2) simulation
Get-Mailbox -ResultSize Unlimited -Filter "Department -eq 'Sales'" | Set-Mailbox -IssueWarningQuota 4GB -WhatIf4. One operation, one ticket
No change in production without a ticket that justifies it. Record in the ticket the exact command you ran, not a description in words. It is for you in three months, when somebody asks why that mailbox has that permission.
5. Disabling is not deleting
In Exchange the two words have precise and different technical meanings. Disabling detaches the mailbox from the AD user and keeps it for the retention period. Deleting removes both user and mailbox. If you are asked to "delete the mailbox of someone who has left", in 99% of cases the correct answer is to disable it or convert it to shared.
6. Quotas are not opinions
Before raising a user's quota, check the free space on the database volume. A database that fills the disk takes every mailbox it contains offline, not just the one belonging to the user who asked for more room.
7. Do not touch connectors to fix a single message
Receive and send connectors are shared infrastructure. A problem affecting one sender or one domain is almost always solved at the rule, recipient or reputation level, not by changing a connector.
8. Before any maintenance on a DAG member, maintenance mode
Restarting an Exchange server hosting active databases without putting it into maintenance mode means interrupting users and risking "lossy" activations. The procedure has its own page in this guide and consists of commands to be run in the order given.
9. Watch disk space and transaction logs
The number one cause of serious incidents on Exchange is not an attack: it is a volume full of transaction logs because the backup has stopped running. Check the space every day.
10. If you don't know, escalate. Immediately.
Escalating within ten minutes costs an hour of a colleague's time. Guessing for two hours on a database can cost the whole company a day's work. There is no shame in the first and no excuse for the second.
Part 1 — Fundamentals
#1.1 What Exchange Server actually is
Exchange Server is the system that receives, sorts, stores and delivers company mail, along with calendars, contacts and tasks. Three components to keep in mind:
- The mailbox database: a file on disk (extension
.edb) that physically holds users' mail, accompanied by the transaction logs. A server usually hosts more than one. - Transport: the part that accepts messages, evaluates them, routes them and delivers them. When "mail isn't arriving", the problem is almost always here.
- Client access services: the front door for Outlook, phones and browsers. When "Outlook won't connect" but mail is flowing, the problem is almost always here.
From 2016 onwards these components live together in the same role, called Mailbox server. There is a second, optional role, the Edge Transport, installed in the DMZ without domain membership, acting as a perimeter filter towards the Internet.
#1.2 The tools you work with
| Tool | How you open it | What it is for | Limitation |
|---|---|---|---|
| EAC — Exchange admin center | Browser, address https://<server>/ecp | 90% of daily work on recipients, permissions, queues, certificates. | Does not expose every parameter; some operations exist only in PowerShell. |
| EMS — Exchange Management Shell | Start menu, on the server or on a workstation with the management tools | Everything. It is PowerShell with the Exchange cmdlets preloaded. | No safety net: what you type gets executed. |
| Exchange Toolbox | Start menu on the server | Contains the Queue Viewer and the mail flow tools. | On the server only. |
| Queue Viewer | From the Toolbox | See and unblock transport queues through a graphical interface. | Shows one server at a time. |
#1.3 Anatomy of a command
Exchange cmdlets always follow the Verb-Noun structure, followed by parameters. Once you know the structure, the rest follows.
Set-Mailbox -Identity m.rossi -ProhibitSendQuota 5GB
^ ^ ^ ^
| | | valore
| | parametro obbligatorio: quale oggetto
| su che tipo di oggetto agisco
cosa faccio| Verb | Meaning | Danger |
|---|---|---|
Get- | Reads and shows | None. Use it freely. |
Set- | Changes an existing object | Medium. Overwrites the previous value. |
New- | Creates an object | Low, but creates a mess if you get it wrong. |
Enable- / Disable- | Enables or disables a feature | Medium. |
Add- / Remove- | Adds or removes an item from a set | Medium to high depending on the object. |
Remove- | Deletes an object | High. Often irreversible. |
Move- | Moves (mailboxes, active databases) | High: it affects users while it runs. |
Test- | Runs a diagnostic | None. |
The three switches you have to know
-WhatIf— simulates, does not run. Always use it the first time.-Confirm:$false— suppresses the confirmation prompt. Do not use it until you are certain of the command: the prompt is there on purpose.-ResultSize Unlimited— removes the default 1,000-result limit on reads. Without it, aGet-Mailboxon a large organisation shows you only part of the picture and you don't notice.
Making the output readable
# only the properties you need, as a table
Get-Mailbox m.rossi | Format-Table Name,PrimarySmtpAddress,Database -Auto
# every property of an object, as a vertical list
Get-Mailbox m.rossi | Format-List *
# export it to attach to the ticket
Get-Mailbox -ResultSize Unlimited | Export-Csv C:\Temp\mailboxes.csv -NoTypeInformation -Encoding UTF8#1.4 The read-only commands to know by heart
These can be run at any time, even in the middle of an emergency, without asking anyone's permission.
| Command | Answers the question |
|---|---|
Get-Mailbox <user> | fl | Does this mailbox exist? Where is it? How is it configured? |
Get-MailboxStatistics <user> | How big is it? When did someone last connect to it? |
Get-CasMailbox <user> | Which client protocols are enabled on this mailbox? |
Get-MailboxPermission <user> | Who can open this mailbox? |
Get-ADPermission <user> | Who can send as this mailbox? |
Get-Queue | Are there messages stuck on this server? |
Get-QueueDigest -Dag <DAG> | Are there messages stuck on any server? |
Get-MessageTrackingLog | What happened to this message? |
Get-ExchangeServer | Which servers are there, what version, what roles? |
Get-MailboxDatabaseCopyStatus * | Are the database copies healthy? |
Get-ServerHealth <server> | Does the server consider itself healthy? |
Test-ServiceHealth | Are all the required Exchange services running? |
Part 2 — Mailboxes, groups and permissions
#2.1 Recipient types
Before you create anything, pick the right type. Changing it later is possible but laborious, and by then users have already arranged themselves around the wrong object.
| Type | When to use it | Does it have an active AD account? |
|---|---|---|
| User mailbox | A person. | Yes, with a licence and a password. |
| Shared mailbox | A functional address used by several people: info@, support@, amministrazione@. | The account exists but is disabled: access is by delegation. |
| Room mailbox | A meeting room that can be booked from the calendar. | Disabled account. |
| Equipment mailbox | A bookable resource that is not a room: projector, company car. | Disabled account. |
| Distribution group | An address that forwards to a list of recipients. | No, it is a group. |
| Mail-enabled security group | As above, but it also grants permissions. | No, it is a group. |
| Dynamic distribution group | The member list is computed on the fly from a query (e.g. everyone in a department). | No. |
| Mail contact | An external person who must appear in the address book. | No. |
| Mail user | A person with an internal account but an external mailbox (consultant, contractor). | Yes, but without a local mailbox. |
#2.2 Creating a user mailbox
From EAC
- Recipients > Mailboxes > New user mailbox.
- Choose whether to create a new AD user or to enable an existing one. In most companies the AD user is created first by the onboarding process: in that case choose existing user.
- Fill in the alias and primary address according to the company naming standard. If you don't know it by heart, ask: renaming later leaves loose ends.
- Save and verify.
From EMS
# enable the mailbox on an AD user that already exists (most common case)
Enable-Mailbox -Identity "m.rossi" -Database "DB01"
# create AD user + mailbox in one go
New-Mailbox -Name "Mario Rossi" -Alias m.rossi -UserPrincipalName [email protected] `
-FirstName Mario -LastName Rossi -Database "DB01" `
-Password (ConvertTo-SecureString -String "<InitialPassword>" -AsPlainText -Force) `
-ResetPasswordOnNextLogon $trueCheck
Get-Mailbox m.rossi | Format-List Name,Alias,PrimarySmtpAddress,EmailAddresses,Database,RecipientTypeDetails#2.3 Addresses and aliases
A mailbox has one primary address (the one that appears as the sender) and any number of secondary addresses, all of which receive. In EmailAddresses the primary is written with an uppercase SMTP:, the secondaries with a lowercase smtp:.
# add an alias without touching the other addresses
Set-Mailbox m.rossi -EmailAddresses @{Add="[email protected]"}
# remove an alias
Set-Mailbox m.rossi -EmailAddresses @{Remove="[email protected]"}
# change the primary address, keeping the old one as secondary
Set-Mailbox m.rossi -EmailAddresses @{Add="[email protected]"}
Set-Mailbox m.rossi -PrimarySmtpAddress "[email protected]" -EmailAddressPolicyEnabled $false#2.4 Storage quotas
Quotas have three progressive thresholds.
| Threshold | Parameter | Effect on the user |
|---|---|---|
| Warning | IssueWarningQuota | Gets a notification. Carries on working normally. |
| Send blocked | ProhibitSendQuota | Can no longer send. Still receives. |
| Fully blocked | ProhibitSendReceiveQuota | Can neither send nor receive. Senders get an NDR. |
Quotas can be inherited from the database or set per mailbox. To set them per mailbox you have to disable inheritance explicitly.
# read the current state
Get-MailboxStatistics m.rossi | Format-List DisplayName,TotalItemSize,ItemCount,LastLogonTime
Get-Mailbox m.rossi | Format-List UseDatabaseQuotaDefaults,IssueWarningQuota,ProhibitSendQuota,ProhibitSendReceiveQuota
# set custom quotas
Set-Mailbox -Identity m.rossi -UseDatabaseQuotaDefaults $false `
-IssueWarningQuota 9GB -ProhibitSendQuota 9.5GB -ProhibitSendReceiveQuota 10GB
# go back to the database values
Set-Mailbox -Identity m.rossi -UseDatabaseQuotaDefaults $true#2.5 Mail forwarding
Typical case: someone is away or has left the company and their mail has to go to a colleague.
# forward to an internal recipient, without keeping a copy
Set-Mailbox m.rossi -ForwardingAddress g.bianchi -DeliverToMailboxAndForward $false
# forward while keeping a copy in the original mailbox
Set-Mailbox m.rossi -ForwardingAddress g.bianchi -DeliverToMailboxAndForward $true
# forward to an external address (needs a contact or SmtpAddress)
Set-Mailbox m.rossi -ForwardingSmtpAddress "[email protected]" -DeliverToMailboxAndForward $true
# remove the forward
Set-Mailbox m.rossi -ForwardingAddress $null -ForwardingSmtpAddress $null#2.6 Delivery restrictions and size limits
# accept mail only from authenticated internal senders
Set-Mailbox communications -RequireSenderAuthenticationEnabled $true
# restrict who can write to a mailbox or a group
Set-DistributionGroup "All staff" -AcceptMessagesOnlyFromSendersOrMembers "Management"
# size limits per mailbox
Set-Mailbox m.rossi -MaxSendSize 35MB -MaxReceiveSize 35MB#2.7 Permissions: the three delegations
There are three distinct permissions and they get confused constantly, including by the people asking for them. Always clarify what is needed before granting them.
| Permission | What it allows | What it does NOT allow |
|---|---|---|
| Full Access | Opening the mailbox, reading, creating, moving and deleting items. | Sending messages from the mailbox. |
| Send As | Sending messages that appear to come from the mailbox. The recipient sees no trace of the delegate. | Reading the contents of the mailbox. |
| Send on Behalf | Sending messages with the sender shown as "Delegate on behalf of Mailbox". Replies go back to the mailbox. | Reading the contents of the mailbox. |
Full Access
Add-MailboxPermission -Identity "Assistenza Clienti" -User m.rossi `
-AccessRights FullAccess -InheritanceType All
# without opening the mailbox automatically in the delegate's Outlook profile
Add-MailboxPermission -Identity "Assistenza Clienti" -User m.rossi `
-AccessRights FullAccess -InheritanceType All -AutoMapping $false
# remove
Remove-MailboxPermission -Identity "Assistenza Clienti" -User m.rossi `
-AccessRights FullAccess -InheritanceType All
# check
Get-MailboxPermission "Assistenza Clienti" | Where {$_.AccessRights -like "Full*"} |
Format-Table -Auto User,Deny,IsInherited,AccessRightsSend As
Add-ADPermission -Identity "Assistenza Clienti" -User m.rossi -ExtendedRights "Send As"
# remove
Remove-ADPermission -Identity "Assistenza Clienti" -User m.rossi -ExtendedRights "Send As"
# check
Get-ADPermission -Identity "Assistenza Clienti" | Where {$_.ExtendedRights -like "Send*"} |
Format-Table -Auto User,Deny,ExtendedRightsSend on Behalf
# replaces the list of delegates
Set-Mailbox "Assistenza Clienti" -GrantSendOnBehalfTo m.rossi
# adds without touching the others
Set-Mailbox "Assistenza Clienti" -GrantSendOnBehalfTo @{Add="[email protected]"}
# removes just one
Set-Mailbox "Assistenza Clienti" -GrantSendOnBehalfTo @{Remove="[email protected]"}
# works on groups too
Set-DistributionGroup "Ufficio Stampa" -GrantSendOnBehalfTo s.verdi#2.8 Shared mailboxes
# create
New-Mailbox -Shared -Name "Assistenza Clienti" -Alias support `
-PrimarySmtpAddress [email protected]
# give access to a group
Add-MailboxPermission -Identity support -User "GRP-Assistenza" `
-AccessRights FullAccess -InheritanceType All
Add-ADPermission -Identity "Assistenza Clienti" -User "GRP-Assistenza" -ExtendedRights "Send As"
# convert a user mailbox to shared (typical for someone leaving)
Set-Mailbox m.rossi -Type Shared#2.9 Rooms and equipment
New-Mailbox -Room -Name "Sala Consiglio" -Alias sala.consiglio
New-Mailbox -Equipment -Name "Proiettore 1" -Alias proiettore1
# automatic booking with no human approval
Set-CalendarProcessing "Sala Consiglio" -AutomateProcessing AutoAccept `
-AllowConflicts $false -BookingWindowInDays 180 -MaximumDurationInMinutes 480 `
-AddOrganizerToSubject $true -DeleteComments $false
# booking with approval by a delegate
Set-CalendarProcessing "Sala Consiglio" -AutomateProcessing AutoAccept `
-AllBookInPolicy $false -AllRequestInPolicy $true -ResourceDelegates "s.verdi"
# capacity and location, useful in Outlook's room finder
Set-Mailbox "Sala Consiglio" -ResourceCapacity 12
Set-Place "Sala Consiglio" -Building "Sede centrale" -Floor 2 -Capacity 12#2.10 Groups
# plain distribution group
New-DistributionGroup -Name "Ufficio Acquisti" -Alias acquisti `
-PrimarySmtpAddress [email protected] -Type Distribution `
-OrganizationalUnit "contoso.it/Gruppi"
# mail-enabled security group (also used for permissions)
New-DistributionGroup -Name "GRP-Assistenza" -Type Security -Alias grp-support
# managing members
Add-DistributionGroupMember -Identity acquisti -Member m.rossi
Remove-DistributionGroupMember -Identity acquisti -Member g.bianchi
Get-DistributionGroupMember acquisti | Format-Table Name,PrimarySmtpAddress -Auto
# hide from the address book
Set-DistributionGroup acquisti -HiddenFromAddressListsEnabled $true
# allow only authenticated internal senders to write
Set-DistributionGroup "All staff" -RequireSenderAuthenticationEnabled $trueDynamic groups
Members are not listed: they are computed at every send from a query on attributes. Useful for lists that follow the org chart, dangerous if the AD attributes are not kept clean.
New-DynamicDistributionGroup -Name "All - Rome office" -Alias all.rome `
-RecipientFilter "(RecipientTypeDetails -eq 'UserMailbox') -and (Office -eq 'Roma')"
# ALWAYS CHECK who ends up in it, before announcing it
$g = Get-DynamicDistributionGroup "All - Rome office"
Get-Recipient -RecipientPreviewFilter $g.RecipientFilter | Format-Table Name,Office -Auto#2.11 Recovery: deleted items and disconnected mailboxes
The user deleted a message and also emptied Deleted Items
It is not lost. It goes into the Recoverable Items folder, invisible to the user but accessible for the configured retention period (default: 14 days, often raised to 30).
- First solution, with no admin involved: in Outlook, Deleted Items folder, "Recover deleted items from server". In 90% of cases that is enough and no ticket is needed.
- If that is not enough, check the retention window:
Get-Mailbox m.rossi | fl RetainDeletedItemsFor,SingleItemRecoveryEnabled - If a targeted recovery is needed, escalate to L2: searching and restoring from Recoverable Items requires discovery permissions and has to be logged.
# extend the retention window (usually done at database level)
Set-Mailbox m.rossi -RetainDeletedItemsFor 30.00:00:00
# protect against permanent purges
Set-Mailbox m.rossi -SingleItemRecoveryEnabled $trueDisconnected mailboxes
When a mailbox is disabled or deleted, it stays in the database in a disconnected state for the retention period (default 30 days). Within that window it can be recovered.
# find the disconnected mailboxes on a database
Get-MailboxStatistics -Database DB01 | Where {$_.DisconnectReason -ne $null} |
Format-Table DisplayName,DisconnectReason,DisconnectDate,MailboxGuid -Auto
# reconnect to an AD user
Connect-Mailbox -Identity "<MailboxGuid>" -Database DB01 -User "contoso\m.rossi"#2.12 Disable, delete, convert
| Operation | Command | What happens | Reversible? |
|---|---|---|---|
| Convert to shared | Set-Mailbox <x> -Type Shared | The mail stays, access passes to the delegates. | Yes. |
| Disable | Disable-Mailbox <x> | The mailbox detaches from the AD user and becomes disconnected. The AD user remains. | Yes, within the retention period. |
| Delete | Remove-Mailbox <x> | Removes both mailbox and AD account. | Only within the retention period, and with difficulty. |
| Permanently delete | Remove-Mailbox <x> -Permanent $true | Destroys the data immediately. | No. Never. |
#2.13 Moving a mailbox between databases
# start the move
New-MoveRequest -Identity m.rossi -TargetDatabase DB02 -BadItemLimit 10
# monitor it
Get-MoveRequest | Get-MoveRequestStatistics |
Format-Table DisplayName,Status,PercentComplete,BytesTransferred -Auto
# clear completed requests (mandatory: they stay there forever)
Get-MoveRequest -MoveStatus Completed | Remove-MoveRequest#2.14 PST import and export
The import/export cmdlets are not available by default even to organisation administrators: the role has to be assigned explicitly, for a specific reason. Anyone who can export mailboxes to PST can export anybody's mail.
# assign the role (L3 operation, one-off)
New-ManagementRoleAssignment -Role "Mailbox Import Export" -User "<administrator>"
# export
New-MailboxExportRequest -Mailbox m.rossi -FilePath "\\SRV-FILE\PSTExport\m.rossi.pst"
# export only a date range
New-MailboxExportRequest -Mailbox m.rossi `
-ContentFilter {(Received -ge "01/01/2025") -and (Received -lt "01/01/2026")} `
-FilePath "\\SRV-FILE\PSTExport\m.rossi-2025.pst"
# import
New-MailboxImportRequest -Mailbox m.rossi -FilePath "\\SRV-FILE\PSTImport\archivio.pst" `
-TargetRootFolder "Archivio importato"
# monitor it e ripulire
Get-MailboxExportRequest | Get-MailboxExportRequestStatistics | ft DisplayName,Status,PercentComplete
Get-MailboxExportRequest -Status Completed | Remove-MailboxExportRequestPart 3 — Clients, mobile devices, OWA
#3.1 How a client connects, briefly
Understanding this sequence on its own solves half the "Outlook won't connect" tickets.
- Outlook looks for its configuration through Autodiscover: it queries the user's SMTP domain, looking for known records and URLs.
- Autodiscover replies with the service URLs: mailbox, availability, offline address book, and so on.
- Outlook connects through MAPI over HTTP, the default protocol in recent versions (it used to be Outlook Anywhere / RPC over HTTP).
- Authentication happens according to what is configured on the virtual directories (Integrated Windows, Basic, or modern authentication through ADFS in SE).
So: if Outlook won't connect but OWA works, the problem is almost always in Autodiscover, in the certificate or in the local profile. If OWA doesn't work either, the problem is further upstream: services, virtual directories, database or network.
#3.2 Enabling and disabling protocols per mailbox
All client protocols are governed by the same cmdlet, Set-CasMailbox.
# snapshot of the situation
Get-CasMailbox m.rossi | Format-List Name,OWAEnabled,ActiveSyncEnabled,MAPIEnabled,PopEnabled,ImapEnabled,EwsEnabled
# disable
Set-CasMailbox m.rossi -ActiveSyncEnabled $false
Set-CasMailbox m.rossi -OWAEnabled $false
Set-CasMailbox m.rossi -PopEnabled $false -ImapEnabled $false
# re-enable
Set-CasMailbox m.rossi -ActiveSyncEnabled $true
# who still has POP/IMAP enabled (useful in a security review)
Get-CasMailbox -ResultSize Unlimited | Where {$_.PopEnabled -or $_.ImapEnabled} |
Format-Table Name,PopEnabled,ImapEnabled -Auto#3.3 Outlook on the web (OWA)
# state of the OWA virtual directories
Get-OwaVirtualDirectory | Format-List Server,Name,InternalUrl,ExternalUrl,*Authentication*
# OWA mailbox policies: what the user can do from a browser
Get-OwaMailboxPolicy | Format-List Name,*Enabled | Out-Host -Paging
# assign a policy to a mailbox
Set-CasMailbox m.rossi -OwaMailboxPolicy "Default"#3.4 Mobile devices and ActiveSync
Seeing what a user is carrying
Get-MobileDevice -Mailbox m.rossi | Format-Table FriendlyName,DeviceModel,DeviceOS,DeviceId,FirstSyncTime -Auto
Get-MobileDeviceStatistics -Mailbox m.rossi |
Format-Table DeviceFriendlyName,DeviceModel,LastSuccessSync,Status,DevicePolicyApplied -AutoMobile device mailbox policies
They impose security requirements on the device: PIN, encryption, automatic lock, remote wipe capability.
Get-MobileDeviceMailboxPolicy | Format-List Name,PasswordEnabled,MinPasswordLength,MaxInactivityTimeLock,AllowSimplePassword,RequireDeviceEncryption
Set-CasMailbox m.rossi -ActiveSyncMailboxPolicy "Aziendale"Device access rules
They decide whether a model or a device family is allowed, blocked, or quarantined pending approval.
Get-ActiveSyncDeviceAccessRule | Format-Table Characteristic,QueryString,AccessLevel -Auto
# explicitly allow a device family
New-ActiveSyncDeviceAccessRule -Characteristic DeviceModel -QueryString "iPhone" -AccessLevel Allow
# default behaviour for unclassified devices
Get-ActiveSyncOrganizationSettings | Format-List DefaultAccessLevel,AdminMailRecipientsRemote wipe
# 1) identify the device precisely
Get-MobileDevice -Mailbox m.rossi | Format-Table FriendlyName,DeviceModel,DeviceId,DeviceOS -Auto
# 2) wipe company data only (always the preferred option)
Clear-MobileDevice -Identity "<device Identity>" -AccountOnly `
-NotificationEmailAddresses "[email protected]"
# 3) full device wipe (company-owned devices only)
Clear-MobileDevice -Identity "<device Identity>" `
-NotificationEmailAddresses "[email protected]"
# remove the partnership after the wipe
Remove-MobileDevice -Identity "<device Identity>"#3.5 POP3 and IMAP4
Legacy protocols, still used by multifunction printers, business applications and appliances that have to read or send mail. They are also an attack surface: they almost always use basic authentication, which means credentials in the clear on the wire if TLS is not enforced.
# service state (they are disabled by default)
Get-Service MSExchangePOP3,MSExchangePOP3BE,MSExchangeIMAP4,MSExchangeIMAP4BE
# configuration
Get-PopSettings | Format-List Server,LoginType,UnencryptedOrTLSBindings,SSLBindings,X509CertificateName
Get-ImapSettings | Format-List Server,LoginType,UnencryptedOrTLSBindings,SSLBindings,X509CertificateName
# enforce TLS
Set-ImapSettings -LoginType SecureLogin
Set-PopSettings -LoginType SecureLogin#3.6 Diagnostic tree: "the client isn't working"
| Question | If YES | If NO |
|---|---|---|
| Does the problem affect a single user? | Go to step 2. | Jump to step 6: it is a service problem, not a user problem. Escalate. |
2. Does OWA work for that user (https://<server>/owa)? | The backend is healthy: it is a client or profile problem. Step 3. | The mailbox or the service has a problem. Step 5. |
| 3. Does it work from another PC, or in Outlook safe mode? | Local problem: profile, OST cache, add-in. Recreate the profile. | Step 4. |
4. Does Get-CasMailbox <user> show the protocol as enabled? | Check Autodiscover and the certificate: Test-OutlookWebServices -Identity <user> | Re-enable the protocol and try again. |
5. Does the mailbox respond? (Test-MapiConnectivity -Identity <user>) | Check quotas and mailbox state. | The database may be dismounted or failing over. Escalate to L2/L3. |
6. Are the services up? (Test-ServiceHealth) | Check queues, certificates and virtual directories. Escalate. | Start the missing services if you are authorised, otherwise escalate immediately. |
# the three diagnostic tests to keep handy
Test-ServiceHealth
Test-MapiConnectivity -Identity m.rossi
Test-OutlookWebServices -Identity m.rossi | Format-List Source,ServiceEndpoint,Scenario,Result,ErrorPart 4 — Mail flow and troubleshooting
#4.1 The transport pipeline in one page
Every message always goes through the same stages. Knowing which stage it stopped at is the diagnosis.
- Ingress. The message arrives through a receive connector (from the Internet, from an authenticated client, from an internal appliance) or is deposited by a local mailbox.
- Submission. It lands in the Submission queue, where the categorizer picks up the work.
- Recipient resolution. Exchange turns addresses into real recipients: it expands groups, applies forwards, resolves aliases.
- Routing. It decides where the message goes: local mailbox, another server in the organisation, send connector out to the Internet.
- Agents and rules. Mail flow rules (transport rules), journaling, DLP, antispam and antimalware are applied.
- Delivery. The message is deposited in the destination mailbox or queued towards the next hop.
#4.2 Message tracking: the number one tool
Get-MessageTrackingLog answers the question you will be asked most often: "what happened to this email?". It requires the Microsoft Exchange Transport Log Search service to be running.
# latest entries on the local server
Get-MessageTrackingLog -ResultSize 100
# everything a sender sent within a time window
Get-MessageTrackingLog -ResultSize Unlimited `
-Start "28/07/2026 08:00" -End "28/07/2026 18:00" `
-Sender "[email protected]" |
Format-Table Timestamp,EventId,Source,Recipients,MessageSubject -Auto
# failures only
Get-MessageTrackingLog -ResultSize Unlimited -Start "28/07/2026 00:00" -EventId FAIL |
Format-Table Timestamp,Sender,Recipients,RecipientStatus -Auto
# search by subject
Get-MessageTrackingLog -ResultSize Unlimited -MessageSubject "Fattura 2026" | ft Timestamp,EventId,Sender,RecipientsThe EventIds that matter
| EventId | Meaning | How to read it |
|---|---|---|
RECEIVE | The message came in. | The Source field says where from: SMTP (network), STOREDRIVER (local mailbox), AGENT. |
SEND | It was forwarded to the next hop. | Outbound to another server or to the Internet. |
DELIVER | It was delivered to a local mailbox. | If this event is there, the message arrived. The problem is in the client. |
FAIL | Delivery failed. | Read RecipientStatus: it contains the SMTP code and the reason. |
DEFER | Delivery deferred, it will retry. | Normal if occasional. If it persists, look at the queues. |
DROP | Dropped without an NDR. | Almost always a transport rule or the antispam. |
RESOLVE | Recipient resolved to a different address. | Alias, group or forward. |
EXPAND | Distribution group expanded. | From here on there is more than one recipient. |
TRANSFER | Split by bifurcation (content, different destinations). | Normal. |
POISONMESSAGE | Message deemed harmful to the service, isolated. | Anomaly: escalate. |
#4.3 Queues
Looking
# non-empty queues on the local server
Get-Queue -Exclude Empty | Format-Table Identity,DeliveryType,Status,MessageCount,NextHopDomain -Auto
# aggregated view across all servers (the first command to run in an incident)
Get-QueueDigest -Dag <DAGName>
Get-QueueDigest -Forest
# queues above a given threshold
Get-Queue -Filter "MessageCount -gt 100" | Format-List
# what's inside a queue
Get-Message -Queue "<queue Identity>" | Format-Table Identity,FromAddress,Subject,Status,SCL,Size -AutoQueue states
| State | Meaning | What to do |
|---|---|---|
Active | It is delivering right now. | Nothing. This is normal operation. |
Ready | Ready, waiting for resources. | Nothing. |
Retry | The connection to the next hop failed, it will retry at intervals. | Check DNS, connectivity and the state of the destination. Then Retry-Queue. |
Suspended | Suspended manually. No delivery. | If you didn't suspend it, ask who did and why before resuming it. |
Acting
# force a retry now (instead of waiting for the timer)
Retry-Queue -Identity "<queue Identity>"
Retry-Queue -Filter "Status -eq 'Retry'"
# resubmit messages to the categorizer (after routing or DNS changes)
Retry-Queue -Identity "<queue Identity>" -Resubmit $true
# suspend and resume
Suspend-Queue -Identity "<queue Identity>"
Resume-Queue -Identity "<queue Identity>"
# move a server's queues to another one (before maintenance)
Redirect-Message -Server SRV-EX01 -Target SRV-EX02.contoso.itActing on single messages
# suspend one specific message
Suspend-Message -Identity "<message Identity>"
# export a message to file for analysis (before removing it!)
$m = Export-Message -Identity "<message Identity>"
$m | AssembleMessage -Path "C:\Temp\message.eml"
# remove a message WITHOUT notifying the sender
Remove-Message -Identity "<message Identity>" -WithNDR $false
# remove all of a sender's messages from a queue (e.g. compromised account)
Get-Message -Queue "<queue Identity>" -Filter "FromAddress -eq '[email protected]'" |
Remove-Message -WithNDR $false -Confirm:$false#4.4 Connectors and accepted domains
# domains the organisation accepts as its own
Get-AcceptedDomain | Format-Table Name,DomainName,DomainType,Default -Auto
# receive connectors (who can deliver mail to us, and how)
Get-ReceiveConnector | Format-Table Server,Identity,Bindings,RemoteIPRanges,PermissionGroups -Auto
# send connectors (where we send outbound mail)
Get-SendConnector | Format-Table Name,AddressSpaces,SmartHosts,SourceTransportServers,Enabled -Auto#4.5 NDR: reading the error message
NDRs (Non-Delivery Reports) carry a three-level code. The first number says whether the problem is temporary or permanent.
| Code | Meaning | Who fixes it |
|---|---|---|
4.x.x | Temporary error. The server will retry. | Nobody, if it clears. If it persists for hours: L2. |
5.x.x | Permanent error. The message will not go. | Depends on the code. |
5.1.1 | Recipient does not exist. | The user got the address wrong. Check with Get-Recipient. |
5.1.10 | Recipient not found in the directory. | As above, often with an alias deleted recently. |
5.2.2 | Recipient's mailbox full. | The recipient, or L1 if internal (quota). |
5.2.3 | Message too large. | L1: check mailbox, connector and organisation limits. |
5.4.1 | No route to the recipient. | L2: routing, connectors, DNS. |
5.7.1 | Rejected for authorisation or policy reasons. | L2: relay permissions, delivery restrictions, rules. |
5.7.606 | IP blocked by the recipient (often Microsoft 365). | L3: delisting, IP reputation, SPF/DKIM/DMARC. |
#4.6 Manual SMTP test
Useful when you need to check whether a server answers and what it answers, without depending on a client or an application.
telnet mail.contoso.it 25
EHLO test.contoso.it
MAIL FROM:<[email protected]>
RCPT TO:<[email protected]>
DATA
Subject: test connettivita
message body
.
QUIT#4.7 Operational playbooks
Playbook A — "A user isn't receiving one specific email"
- Get the sender, the approximate time and the subject. Without at least two of the three, the search is impractical.
- Search the logs:
Get-MessageTrackingLog -Start "<now-1h>" -End "<now+1h>" -Recipients "<user>" | ft Timestamp,EventId,Sender,MessageSubject - If you find
DELIVER: the message is in the mailbox. Check Outlook rules, the Junk folder and the Archive folder. The problem is not Exchange. - If you find
FAIL: readRecipientStatus, you already have the cause. - If you find
DROP: check transport rules and antispam.Get-TransportRule | ft Name,State,Priority - If you find nothing: the message never reached the organisation. Have the sender check their own NDR. Then check the perimeter server's queues and any upstream filters.
Playbook B — "Nobody is receiving mail from outside"
- Immediate overview:
Get-QueueDigest -Forest - Services:
Test-ServiceHealthon every server. - Databases mounted:
Get-MailboxDatabaseCopyStatus * | ft Name,Status,ContentIndexState - Check that the public MX records point where they should and that port 25 is reachable from outside.
- Check the disk space on the volumes hosting queues and databases. A queue that won't drain because the disk is full is a recurring scenario.
- If the queues are growing but the services are up and the disk has room: escalate to L3. Do not restart services at random.
Playbook C — "An internal account is sending spam"
- Confirm:
Get-Queue -Filter "MessageCount -gt 500"andGet-Message -Queue <queue> | group FromAddress | sort Count -Desc | select -First 5 - Stop the sending immediately:
Set-Mailbox <user> -MaxSendSize 1KBor disable the account in AD according to the internal incident response procedure. - Cut the mobile channels:
Set-CasMailbox <user> -ActiveSyncEnabled $false -OWAEnabled $false - Drain that user's outbound queue, exporting a sample first as evidence.
- Check whether a forward or a hidden mail rule has been set:
Get-Mailbox <user> | fl Forwarding*andGet-InboxRule -Mailbox <user> - Password change, session revocation, escalation to the security owner. Document times and actions.
Playbook D — "Mail to one specific domain won't go out"
- Look at the queue towards that domain:
Get-Queue | Where {$_.NextHopDomain -like "*dominio.it*"} | fl - Read
LastError: it holds the remote server's text response, which often explains everything. - Check DNS resolution of the MX records from the server:
Resolve-DnsName dominio.it -Type MX - Try a manual telnet connection to their MX on port 25.
- If the remote answer mentions reputation or a blacklist, escalate: requesting delisting is L3 work and has to be coordinated with whoever runs the public DNS.
#4.8 Antispam: the SCL scale
Every message gets an SCL (Spam Confidence Level) score from 0 to 9. The thresholds decide what happens.
| Threshold | Parameter | Typical behaviour |
|---|---|---|
| Junk folder | SCLJunkThreshold | Delivered but moved to Junk Email. |
| Quarantine | SCLQuarantineThreshold | Diverted to the quarantine mailbox, for review. |
| Reject | SCLRejectThreshold | Rejected with an NDR to the sender. |
| Delete | SCLDeleteThreshold | Discarded silently. Nobody gets anything. |
Get-ContentFilterConfig | Format-List SCL*Threshold,SCL*Enabled
# senders and domains always allowed / always blocked
Get-ContentFilterConfig | Format-List BypassedSenders,BypassedSenderDomains
Set-ContentFilterConfig -BypassedSenderDomains @{Add="fornitore-fidato.it"}
# per-mailbox antispam preferences
Get-MailboxJunkEmailConfiguration m.rossi | fl Enabled,TrustedSendersAndDomains,BlockedSendersAndDomainsPart 5 — Maintenance, high availability and updates
#5.1 Routine checks
Every day (10 minutes, L1)
| Check | Command | Alarm threshold |
|---|---|---|
| Exchange services started | Test-ServiceHealth | A single required service not started. |
| Queues | Get-QueueDigest -Forest | Queues above a few hundred messages, or in Retry for hours. |
| Database copies | Get-MailboxDatabaseCopyStatus * | Any state other than Mounted / Healthy. |
| Search index | same output, ContentIndexState column | Anything other than Healthy. |
| Disk space | Get-Volume on the DB and log volumes | Below 20% free: plan. Below 10%: act today. |
| Backup completed | Backup product console | A single failed backup. The logs are not truncated and the disk fills up. |
# daily check, all in one go
Test-ServiceHealth | Format-Table Role,RequiredServicesRunning,ServicesNotRunning -Auto
Get-QueueDigest -Forest
Get-MailboxDatabaseCopyStatus * | Format-Table Name,Status,CopyQueueLength,ReplayQueueLength,ContentIndexState -Auto
Get-Volume | Where {$_.DriveLetter} | Format-Table DriveLetter,FileSystemLabel,
@{n="LiberoGB";e={[math]::Round($_.SizeRemaining/1GB,1)}},
@{n="Libero%";e={[math]::Round($_.SizeRemaining/$_.Size*100,0)}} -AutoEvery week (L2)
- Overall health check:
Get-ExchangeServer | Get-HealthReport -RollupGroup - DAG replication check:
Test-ReplicationHealth - Certificate expiry check:
Get-ExchangeCertificate | ft Thumbprint,Services,NotAfter,Subject -Auto - Review of active external forwards and of suspicious new Inbox rules.
- Review of the administrator audit logs, if enabled.
Every month (L2/L3)
- Check whether the latest cumulative and security update is available.
- Restore test: a restore that has never been tested is not a backup, it is a hope.
- Review of quotas and database growth.
- Check of inactive mailboxes and of leavers not yet processed.
#5.2 Managed availability: reading health state
Exchange monitors itself: probes collect data, monitors evaluate the state, responders attempt automatic corrective actions (restarting a service, recycling an application pool, and as a last resort restarting the server). Knowing how to read this system stops you intervening where the server is already fixing itself.
# overview per server
Get-HealthReport -Identity <ServerName>
# unhealthy health sets only
Get-HealthReport -Identity <ServerName> | Where {$_.AlertValue -ne "Healthy"} |
Format-Table HealthSetName,AlertValue,ServerComponent -Auto
# detail of the monitors in a specific set
Get-ServerHealth -Identity <ServerName> -HealthSet <SetName> |
Format-Table Name,AlertValue,HealthSetName -Auto
# aggregated view across the organisation or a DAG
Get-ExchangeServer | Get-HealthReport -RollupGroup
(Get-DatabaseAvailabilityGroup <DAGName>).Servers | Get-HealthReport -RollupGroup#5.3 Databases and copies
# list of databases and where they are active right now
Get-MailboxDatabase -Status | Format-Table Name,Server,Mounted,DatabaseSize,AvailableNewMailboxSpace -Auto
# state of every copy: the most important command in this section
Get-MailboxDatabaseCopyStatus * |
Format-Table Name,Status,CopyQueueLength,ReplayQueueLength,ContentIndexState,ActivationPreference -Auto| Column | What it means | Healthy value |
|---|---|---|
Status | Role and health of the copy. | Mounted on the active, Healthy on the passives. |
CopyQueueLength | Logs generated on the active and not yet copied to the passive. | Close to 0. High numbers = network or disk problem. |
ReplayQueueLength | Logs copied but not yet applied to the database. | Close to 0, except for deliberately lagged copies. |
ContentIndexState | State of the search index. | Healthy. If Failed, user searches do not work. |
ActivationPreference | Preference order for activation. | 1 = preferred copy. |
DAG replication check
Test-ReplicationHealth -Identity <ServerName>
# across all members
(Get-DatabaseAvailabilityGroup <DAGName>).Servers | ForEach-Object { Test-ReplicationHealth -Identity $_.Name }The test checks a series of components: replication service, Active Manager role, listener, member reachability, cluster networks, quorum group, file share witness, database redundancy and availability, presence of suspended, failed or seeding copies. Any outcome other than Passed has to be read item by item, not dismissed as a whole.
#5.4 Switchover: moving active databases
A switchover is the planned move of activity from one server to another. A failover is the same move, but unplanned: the system decides it when something breaks.
# move all of a server's active databases, letting the system choose
Move-ActiveMailboxDatabase -Server SRV-EX01
# move to a specific server
Move-ActiveMailboxDatabase -Server SRV-EX01 -ActivateOnServer SRV-EX02
# move a single database
Move-ActiveMailboxDatabase DB01 -ActivateOnServer SRV-EX02
# simulate first
Move-ActiveMailboxDatabase -Server SRV-EX01 -WhatIf#5.5 Maintenance mode on a DAG member
This is the procedure to learn by heart before touching any clustered Exchange server: updates, restarts, hardware work, Windows patches. It takes the server out of production in an orderly way, without interrupting users and without losing messages in transit.
Phase 1 — Entering maintenance
# 1. drain the transport queues
Set-ServerComponentState <ServerName> -Component HubTransport -State Draining -Requester Maintenance
# 2. apply the drain
Restart-Service MSExchangeTransport
# 3. (Exchange 2016 with unified messaging only)
Set-ServerComponentState <ServerName> -Component UMCallRouter -State Draining -Requester Maintenance
# 4. go to the Exchange scripts folder
CD $ExScripts
# 5. move active databases and critical roles elsewhere, and pause the cluster node
.\StartDagServerMaintenance.ps1 -ServerName <ServerName> -MoveComment Maintenance -PauseClusterNode
# 6. redirect the messages still queued to another server
Redirect-Message -Server <ServerName> -Target <FQDN other server>
# 7. take the server fully offline as far as the services are concerned
Set-ServerComponentState <ServerName> -Component ServerWideOffline -State Inactive -Requester MaintenancePhase 2 — Verifying it really is in maintenance
# only Monitoring and RecoveryActionsEnabled should read Active
Get-ServerComponentState <ServerName> | Format-Table Component,State -Autosize
# no active database can be activated here
Get-MailboxServer <ServerName> | Format-List DatabaseCopyAutoActivationPolicy # atteso: Blocked
# cluster node paused
Get-ClusterNode <ServerName> | Format-List
# queues empty
Get-QueueOnly when all four checks give the expected result can you proceed with the work: update, restart, hardware replacement.
Phase 3 — Returning to production
# 1. bring the server back online
Set-ServerComponentState <ServerName> -Component ServerWideOffline -State Active -Requester Maintenance
# 2. (Exchange 2016 with unified messaging only)
Set-ServerComponentState <ServerName> -Component UMCallRouter -State Active -Requester Maintenance
# 3.
CD $ExScripts
# 4. resume the cluster node, unblock activation, resume the copies
.\StopDagServerMaintenance.ps1 -ServerName <ServerName>
# 5. re-enable transport
Set-ServerComponentState <ServerName> -Component HubTransport -State Active -Requester Maintenance
Restart-Service MSExchangeTransport
# 6. final check
Get-ServerComponentState <ServerName> | Format-Table Component,State -Autosize
Get-MailboxDatabaseCopyStatus * | ft Name,Status,CopyQueueLength,ContentIndexState -Auto
# 7. optional: rebalance the active copies according to preference
.\RedistributeActiveDatabases.ps1 -DagName <DAGName> -BalanceDbsByActivationPreference -Confirm:$falseSet-ServerComponentState <ServerName> -Component ServerWideOffline -State Active -Requester Functional
Set-ServerComponentState <ServerName> -Component Monitoring -State Active -Requester Functional
Set-ServerComponentState <ServerName> -Component RecoveryActionsEnabled -State Active -Requester Functional#5.6 Cumulative and security updates
Every cumulative update (CU) is a full installation of the product: you do not need to install the previous CUs in sequence. Security updates (SU), on the other hand, apply to one specific CU.
Preparation, in order
- Read the release notes for that specific CU. Every CU has its own surprises.
- Check system requirements and prerequisites: they may have changed since the CU you have installed.
- Check whether the CU requires Active Directory schema updates or domain preparation. If it does, you need elevated permissions and a dedicated window.
- Run and verify a working backup of Active Directory and of Exchange.
- Save every customisation separately:
web.configandEdgeTransport.exe.configfiles, TLS settings and operating system cryptography. They get overwritten. - Test in a non-production environment, if you have one.
- Restart the server before you start, to clear any pending reboots.
- Temporarily disable the antivirus for the duration of the installation.
- If the server is a DAG member, put it into maintenance mode (§5.5).
- Run the setup program from an elevated prompt.
Indicative time stated by the documentation for a CU update: about three hours per server. Plan the window accordingly, and across multiple servers work in sequence, never in parallel.
# check the installed version and build
Get-ExchangeServer | Format-Table Name,Edition,AdminDisplayVersion,ServerRole -Auto
# more precise build check
Get-Command ExSetup.exe | ForEach {$_.FileVersionInfo}#5.7 Certificates
# list of certificates with expiry and assigned services
Get-ExchangeCertificate | Format-Table Thumbprint,Services,NotAfter,Subject,CertificateDomains -Auto
# which ones expire in the next 60 days
Get-ExchangeCertificate | Where {$_.NotAfter -lt (Get-Date).AddDays(60)} |
Format-Table Thumbprint,Subject,NotAfter,Services -AutoIn the Services column the letters show which services the certificate is assigned to: IMAP, POP, UM, IIS (web), SMTP. An expired certificate assigned to IIS blocks OWA, ECP, ActiveSync and Outlook connectivity for everyone, all at once.
#5.8 Backup and restore
Exchange supports backup through VSS. A successful full backup truncates the transaction logs: that is the mechanism that stops the volumes filling up. A backup that fails silently for days is the prelude to a full disk and dismounted databases.
- Full backup: copies databases and logs, then truncates the logs. This is the one you need.
- Incremental backup: copies only the logs since the last backup and truncates them.
- Copy backup: copies without truncating. Useful for occasional extractions, useless for log hygiene.
Recovery database
A recovery database lets you mount a restored copy of a database alongside production, to extract data without touching the live mailboxes. It is the correct mechanism for answering "we need that mailbox's mail as it was last month".
New-MailboxDatabase -Recovery -Name RDB01 -Server <ServerName> `
-EdbFilePath "E:\RDB01\DB01.edb" -LogFolderPath "E:\RDB01\Logs"
Mount-Database RDB01
# extract the contents into a folder of the destination mailbox
New-MailboxRestoreRequest -SourceDatabase RDB01 -SourceStoreMailbox "Mario Rossi" `
-TargetMailbox m.rossi -TargetRootFolder "Ripristino 2026-07"
Get-MailboxRestoreRequest | Get-MailboxRestoreRequestStatistics | ft Name,Status,PercentComplete#5.9 Disk space and transaction logs
Every change to a mailbox is written to a transaction log first and applied to the database afterwards. The logs pile up until a full backup truncates them. The usual causes of abnormal growth:
- The backup is not running, or runs but fails, or is configured as a copy backup.
- A bulk mailbox move or a large PST import in progress.
- A runaway synchronisation loop from a client or an application.
- A suspended or failed database copy preventing truncation in the DAG.
# how much each database takes up and how much white space it holds
Get-MailboxDatabase -Status | Format-Table Name,DatabaseSize,AvailableNewMailboxSpace,Mounted -Auto
# the 20 largest mailboxes: useful for seeing where growth is
Get-MailboxStatistics -Database DB01 | Sort-Object TotalItemSize -Descending |
Select-Object -First 20 DisplayName,TotalItemSize,ItemCount,LastLogonTimePart 6 — Quick reference
#6.1 Cheat sheet: from task to command
| I need to... | Command | Lvl |
|---|---|---|
| See a mailbox's configuration | Get-Mailbox <user> | fl | L1 |
| See how big a mailbox is | Get-MailboxStatistics <user> | L1 |
| Create a mailbox on an existing AD user | Enable-Mailbox -Identity <user> -Database <DB> | L1 |
| Create a shared mailbox | New-Mailbox -Shared -Name "<Name>" -Alias <alias> | L1 |
| Add an alias | Set-Mailbox <user> -EmailAddresses @{Add="<address>"} | L1 |
| Grant Full Access | Add-MailboxPermission -Identity <mailbox> -User <user> -AccessRights FullAccess -InheritanceType All | L1 |
| Grant Send As | Add-ADPermission -Identity <mailbox> -User <user> -ExtendedRights "Send As" | L1 |
| Grant Send on Behalf | Set-Mailbox <mailbox> -GrantSendOnBehalfTo @{Add="<user>"} | L1 |
| Set quotas | Set-Mailbox <user> -UseDatabaseQuotaDefaults $false -IssueWarningQuota ... -ProhibitSendQuota ... | L1 |
| Set up forwarding | Set-Mailbox <user> -ForwardingAddress <recipient> -DeliverToMailboxAndForward $true | L1 |
| Hide from the address book | Set-Mailbox <user> -HiddenFromAddressListsEnabled $true | L1 |
| Convert to shared | Set-Mailbox <user> -Type Shared | L1 |
| Add to a group | Add-DistributionGroupMember -Identity <group> -Member <user> | L1 |
| See a group's members | Get-DistributionGroupMember <group> | L1 |
| Disable ActiveSync for a user | Set-CasMailbox <user> -ActiveSyncEnabled $false | L1 |
| See a user's phones | Get-MobileDeviceStatistics -Mailbox <user> | L1 |
| Wipe company data from a phone | Clear-MobileDevice -Identity <id> -AccountOnly | L1* |
| Search for a message | Get-MessageTrackingLog -Sender <sender> -Start <time> -End <time> | L1 |
| See the queues, all servers | Get-QueueDigest -Forest | L1 |
| Force a delivery retry | Retry-Queue -Filter "Status -eq 'Retry'" | L2 |
| Remove messages from a queue | Get-Message -Queue <queue> -Filter ... | Remove-Message -WithNDR $false | L2 |
| Move a mailbox between databases | New-MoveRequest -Identity <user> -TargetDatabase <DB> | L2 |
| Export a mailbox to PST | New-MailboxExportRequest -Mailbox <user> -FilePath <UNC> | L2 |
| Check the services | Test-ServiceHealth | L1 |
| Check the database copies | Get-MailboxDatabaseCopyStatus * | L1 |
| Check DAG replication | Test-ReplicationHealth | L2 |
| Move a server's active databases | Move-ActiveMailboxDatabase -Server <server> | L3 |
| Put a server into maintenance | see §5.5, full procedure | L3 |
| Check the certificates | Get-ExchangeCertificate | ft Thumbprint,Services,NotAfter | L1 |
#6.2 Ports to know
| Port | Protocol | Used by |
|---|---|---|
| 25 | SMTP | Mail between servers and from the Internet. Receive connectors. |
| 587 | Authenticated SMTP | Sending from authenticated clients and applications. |
| 465 | SMTPS | Implicit TLS submission, used by some appliances. |
| 443 | HTTPS | OWA, ECP, EWS, ActiveSync, MAPI over HTTP, Autodiscover, OAB. The port. |
| 80 | HTTP | Only for redirection to HTTPS. |
| 110 / 995 | POP3 / POP3S | POP clients. |
| 143 / 993 | IMAP4 / IMAP4S | IMAP clients. |
| 2525 | Internal SMTP | Receiving between internal transport services on the same server. |
| 50636 | Secure LDAP (AD LDS) | EdgeSync synchronisation towards Edge Transport servers. |
| 64327 | SMTP | Redundant transport between Mailbox servers. |
#6.3 Critical services
| Service | If it is stopped... |
|---|---|
MSExchangeIS (Information Store) | Nobody can get to their mail. The single most critical service. |
MSExchangeTransport | Mail neither enters nor leaves the server. |
MSExchangeFrontEndTransport | The server does not accept SMTP connections from outside. |
MSExchangeRepl (Replication) | DAG replication stops. The copy queues grow. |
MSExchangeADTopology | Practically everything stops working: it is the base dependency. |
MSExchangeMailboxAssistant | Room booking, retention policies and the various assistants stop. |
MSExchangeTransportLogSearch | Message tracking logs can no longer be searched. |
W3SVC (IIS) | OWA, ECP, ActiveSync, Outlook: everything down. |
# quick check, by role
Test-ServiceHealth | Format-Table Role,RequiredServicesRunning,ServicesNotRunning -Auto#6.4 Escalation matrix
| Situation | Who handles it | Escalate within |
|---|---|---|
| A user is not receiving an email | L1 | If the playbooks in §4.7 give you no cause: 30 min. |
| A user cannot get to their mail | L1 | If OWA does not work: straight to L2. |
| Request for permissions, aliases, quotas, groups | L1 | Not escalated, just done. |
| Request to wipe a device | L1 with authorisation | If the authorisation is not clear: do not run it, escalate. |
| A queue growing on a server | L2 | If it passes a few thousand messages or lasts over 1h: L3. |
| Internal account sending spam | L1 blocks, L2 investigates | At the same time as the block: immediately to L2 and security. |
Database copy Failed or index Failed | L2 | Straight to L3 if it concerns the only healthy copy. |
| Certificate about to expire | L2 | At 60 days: plan with L3. At 7 days: emergency. |
| Dismounted database | L3 | Immediate. Do not attempt Mount-Database on your own. |
| Full disk on a DB or log volume | L3 | Immediate. |
| General service outage | L3 | Immediate, in parallel with collecting the state. |
#6.5 Ticket annotation template
TICKET #......... DATA/ORA: ..................
RICHIEDENTE: .................. AUTHORISED BY: ..................
RICHIESTA (una riga):
..................................................................
OBJECTS INVOLVED (mailboxes, groups, servers):
..................................................................
CHECK BEFORE (command + brief output):
..................................................................
COMMAND RUN (verbatim, copy-paste):
..................................................................
CHECK AFTER (command + output):
..................................................................
REVERSIBLE? [ ] Yes, how: .................. [ ] No
OUTCOME: [ ] Resolved [ ] Escalated to: ..................#6.6 Glossary
| Term | Meaning |
|---|---|
| Alias | Short internal name of a recipient, distinct from the email address. |
| Autodiscover | Service that automatically hands clients the mailbox configuration. |
| CAS | Client Access Services: the client access services, built into the Mailbox role. |
| CU | Cumulative Update: a full installation of the product. |
| DAG | Database Availability Group: a set of servers hosting replicated copies of the same databases. |
| DSN / NDR | Status or non-delivery notification generated by the transport system. |
| EAC | Exchange Admin Center: the web administration console (/ecp). |
| EMS | Exchange Management Shell: PowerShell with the Exchange cmdlets. |
| EWS | Exchange Web Services: the interface used by many third-party applications. |
| Failover | Unplanned activation of a database copy on another server. |
| MAPI over HTTP | Outlook's default connection protocol in recent versions. |
| OAB | Offline Address Book: the local copy of the address book used by Outlook. |
| PAM | Primary Active Manager: the DAG node that decides database activations. |
| SCL | Spam Confidence Level: antispam score from 0 to 9. |
| SE | Subscription Edition: the subscription edition of Exchange Server. |
| Shadow redundancy | Mechanism that keeps a spare copy of messages in transit. |
| Safety Net | Store of already-delivered messages, used to resubmit after a failover. |
| Switchover | Planned move of activity from one server to another. |
| Edge Transport | Perimeter role, in the DMZ, not joined to the domain. |
#6.7 Where to look when this guide isn't enough
- The official Microsoft Learn documentation for Exchange Server is the source of this guide and is updated more often than any internal manual. Search by cmdlet name: the reference page has the full syntax, every parameter and examples.
- Inside EMS the help is already installed:
Get-Help Set-Mailbox -FullandGet-Help Set-Mailbox -Examplesanswer without leaving the terminal. - To find out which permissions a task needs:
Get-ManagementRoleAssignment -RoleAssignee <user>shows what an administrator can do. - Setup logs live in
C:\ExchangeSetupLogs\ExchangeSetup.log. Transport, protocol and connectivity logs live in the logging folders of the Exchange installation.
#A closing note for beginners
Exchange is a platform that forgives little and warns late. The difference between a junior technician who grows quickly and one who accumulates incidents is not how many commands they know by heart: it is the habit of looking before touching, simulating before running, and writing down what they did.
The first few times you will be slow. That is perfectly fine. Speed arrives on its own after a few months; the habit of caution, if you don't build it now, never arrives at all.
No results. Try a cmdlet name (Set-Mailbox), an error code (5.7.1) or a task (quota).