
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.
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.
Automate New-User Onboarding in Active Directory
This guide builds a PowerShell script that onboards one new employee in four steps: it creates an Active Directory user account , adds them to security groups , provisions an on-premises Exchange mailbox , and creates their home folder on a file server and sets NTFS permissions . The purpose is to replace the error-prone click-through in Active Directory Users and Computers with one repeatable, reviewable run.
Automate DHCP Lease Reporting on Windows Server
This guide builds a read-only PowerShell script that enumerates your DHCP scopes, pulls the current IPv4 leases from each, writes them to a timestamped CSV, and (optionally) emails the file. It does not change any DHCP configuration — no scopes, reservations, options, or leases are created, modified, or deleted. The worst it can do is fill a disk with CSVs if you never prune them.




