
Bulk-Set Out-of-Office Auto-Replies with Exchange PowerShell
Before you run this
This guide sets the Automatic Replies (out-of-office) configuration on multiple mailboxes at once, using Set-MailboxAutoReplyConfiguration in Exchange Online PowerShell. It turns auto-reply on (or schedules it), and writes the internal and external message text. It does not delete mail, move anything, or change mailbox permissions — but it does overwrite whatever auto-reply text and state each affected mailbox currently has, and there is no built-in "undo" that restores the previous message. If a user had their own carefully worded reply set, this replaces it. So capture the current state first (I show how below) and treat the change list as production data.
Privileges: you need an account with a Microsoft 365 admin role that can manage mailboxes — Exchange Administrator (or Global Administrator) is the normal one. You connect with the ExchangeOnlineManagement module. You do not need local admin on your workstation, but you do need to be able to install a PowerShell module for your user, and to get through your tenant's MFA / Conditional Access when connecting.
Test first: read the script before you run it. Run it against one test mailbox you own before you point it at a list of real people. Every command below that changes anything supports -WhatIf — use it on the first pass so you see exactly which mailboxes would be touched and nothing is written.
There is no firewall or network path here, so the console-connection and config-backup warnings don't apply — but the equivalent discipline does: export the existing auto-reply settings for your target mailboxes before you change them, so you can put them back.
What I'm assuming
- Exchange Online (Microsoft 365), not on-premises Exchange. The cmdlet name and parameters are the same on on-prem Exchange 2016/2019, but you'd connect through the Exchange Management Shell instead of
Connect-ExchangeOnline. - ExchangeOnlineManagement module v3 (the current REST-based module), on PowerShell 5.1 or 7.
- You already have a way to identify the target mailboxes: a CSV of email addresses, or a filter (a department, a group).
Install and connect
If you don't already have the module:
# Installs for the current user only; no elevation needed
Install-Module ExchangeOnlineManagement -Scope CurrentUser
Connect. This opens the sign-in / MFA prompt:
# Replace with the admin UPN you actually sign in as
Connect-ExchangeOnline -UserPrincipalName admin@example.com
Step 1: Capture the current state (your rollback)
Before changing anything, export what's there now. This is your only real path back to the previous message text.
# List of target addresses, one per line, header "UserPrincipalName"
$targets = Import-Csv .\targets.csv
$targets | ForEach-Object {
Get-MailboxAutoReplyConfiguration -Identity $_.UserPrincipalName |
Select-Object Identity, AutoReplyState, ExternalAudience,
StartTime, EndTime, InternalMessage, ExternalMessage
} | Export-Csv .\autoreply-backup.csv -NoTypeInformation
Keep autoreply-backup.csv. If you need to restore, you'll read it back and feed the old values into Set-MailboxAutoReplyConfiguration (shown at the end).
The targets.csv file is just:
UserPrincipalName
alice@example.com
bob@example.com
Substitute your own addresses. If you'd rather build the list from a filter instead of a CSV — say everyone in a department — get the identities like this and skip the import:
# Example filter; adjust the property/value to your directory
$targets = Get-Mailbox -ResultSize Unlimited -Filter "Department -eq 'Support'" |
Select-Object @{n='UserPrincipalName';e={$_.UserPrincipalName}}
Get-Mailbox -Filter uses OPATH filter syntax; check the Exchange Online docs for Get-Mailbox if you need a filter on a less common property, rather than guessing at the property name.
Step 2: Set the same auto-reply on everyone
The parameters that matter on Set-MailboxAutoReplyConfiguration:
-AutoReplyState—Enabled,Disabled, orScheduled.-InternalMessage— text sent to senders inside your organisation.-ExternalMessage— text sent to external senders.-ExternalAudience—None(no external replies),Known(only your contacts), orAll.-StartTime/-EndTime— only used when-AutoReplyStateisScheduled.
HTML is allowed in the message bodies. Here's the same message on every target, turned on immediately, with a -WhatIf first pass:
$internal = "I'm out of the office and will reply when I return. For anything urgent, contact the service desk."
$external = "Thanks for your email. Our office is currently closed; we'll respond on the next business day."
foreach ($u in $targets) {
Set-MailboxAutoReplyConfiguration -Identity $u.UserPrincipalName `
-AutoReplyState Enabled `
-ExternalAudience All `
-InternalMessage $internal `
-ExternalMessage $external `
-WhatIf # <-- shows what would change; remove to apply
}
Read the -WhatIf output. When it lists exactly the mailboxes you expect, remove the -WhatIf and run it again to apply.
Step 3 (alternative): Schedule a window instead
If this is for a known closure — a holiday, an office move — schedule it so it turns itself off. Use Scheduled and give both times. Build the DateTime values with Get-Date so there's no ambiguity about format:
$start = Get-Date "2025-12-24 17:00"
$end = Get-Date "2026-01-02 08:00"
foreach ($u in $targets) {
Set-MailboxAutoReplyConfiguration -Identity $u.UserPrincipalName `
-AutoReplyState Scheduled `
-StartTime $start `
-EndTime $end `
-ExternalAudience All `
-InternalMessage $internal `
-ExternalMessage $external `
-WhatIf
}
The times are interpreted per the mailbox's own time-zone setting, so if your users span time zones a single fixed clock time won't mean the same moment for all of them — worth knowing before you promise "off at 5pm everywhere".
Step 4: Per-user message from a CSV
If each person needs their own text, put it in the CSV and read the columns. Add InternalMessage and ExternalMessage columns to targets.csv:
Import-Csv .\targets.csv | ForEach-Object {
Set-MailboxAutoReplyConfiguration -Identity $_.UserPrincipalName `
-AutoReplyState Enabled `
-ExternalAudience All `
-InternalMessage $_.InternalMessage `
-ExternalMessage $_.ExternalMessage `
-WhatIf
}
Same rule: -WhatIf first, then remove it.
Verify it worked
Read the settings straight back for your targets and confirm the state and text:
$targets | ForEach-Object {
Get-MailboxAutoReplyConfiguration -Identity $_.UserPrincipalName |
Select-Object Identity, AutoReplyState, ExternalAudience, StartTime, EndTime
} | Format-Table -AutoSize
AutoReplyState should read Enabled (or Scheduled with the right window). You can also open one test account in Outlook on the web — Settings → Mail → Automatic replies — and see the same message. Setting can take a short while to propagate before an actual test email bounces back a reply, so don't panic if the first probe is quiet.
Undo / roll back
To simply turn it all off:
foreach ($u in $targets) {
Set-MailboxAutoReplyConfiguration -Identity $u.UserPrincipalName `
-AutoReplyState Disabled -WhatIf # remove -WhatIf to apply
}
To restore the previous messages you captured in Step 1, read the backup and write each row's old values back:
Import-Csv .\autoreply-backup.csv | ForEach-Object {
Set-MailboxAutoReplyConfiguration -Identity $_.Identity `
-AutoReplyState $_.AutoReplyState `
-ExternalAudience $_.ExternalAudience `
-InternalMessage $_.InternalMessage `
-ExternalMessage $_.ExternalMessage `
-WhatIf
}
If any restored mailbox was originally Scheduled, you'll also need to pass its StartTime/EndTime from the backup — they're in the CSV.
When you're finished, close the session cleanly:
Disconnect-ExchangeOnline -Confirm:$false
For the exact, current parameter list and any values I haven't shown, see Microsoft Learn for Set-MailboxAutoReplyConfiguration and Get-MailboxAutoReplyConfiguration — check there before scripting a parameter you're not sure about rather than guessing at syntax.
Runs enterprise networks and security for a living, and writes Shore Up to turn two decades of hands-on Linux, Windows and mail-server work into guides you can actually use.
More about the author →Was this article helpful?
Tap a star — no sign-in needed.
Be the first to rate this article.
Related guides
Bulk-Create Shared Mailboxes and Permissions in Exchange Online with PowerShell
This guide reads a CSV file and, for each row, creates a shared mailbox in Exchange Online and grants the people you list Full Access and Send As on it. The purpose is to onboard many shared mailboxes (team@, support@, invoices@) in one pass instead of clicking through the admin center dozens of times.
Remove Stale Exchange Mailbox Delegates and Restore Security
This guide finds and removes delegate access that a former or reassigned user still holds on other people's mailboxes in Exchange Online — the four kinds that actually let one account read or send as another: Full Access , Send As , Send on Behalf , and folder-level (calendar) delegate permissions. Its purpose is offboarding hygiene: when someone leaves or changes roles, their standing access to shared and personal mailboxes should go with them.
Bulk-Export Exchange Distribution List Membership for Compliance
An auditor asks the same question every year: who was in which distribution list on this date? Clicking through each group in the admin center does not scale past a handful of groups, and it produces nothing you can hand over. This guide scripts a clean, point-in-time CSV of every distribution group and its members.
Automate User Offboarding in Active Directory with PowerShell
This script offboards one leaving user in a single pass: it disables their AD account, records and removes their group memberships (except the primary group), and moves the account into a disabled-users OU. A separate, clearly marked step sets mail forwarding on their mailbox. The point is a consistent, logged procedure so nothing gets missed and you can reconstruct exactly what changed.




