Turn automatic replies on, off or on a schedule for any user's mailbox
Build a workflow action that turns a user's automatic replies on, off, or on for a date range, so MSPs and IT teams can handle out-of-office requests for absent staff and leavers by asking SuperIT.
| Runs in | Cloud sandbox (PowerShell) |
| Uses | Microsoft Graph credential with an Exchange Online scope |
| Suggested approval | Require approval from superit:admins for every run |
| Category |
Test it with SuperIT before you rely on it
This is an example, not a ready-made action, and its script hasn't been tested end to end in a SuperIT tenant. The Exchange Online credential it depends on hasn't been tested with SuperIT either, so it may not work as written. Before you use it, work through it with SuperIT: ask SuperIT to review the script against your environment and requirements, adjust it together, then test it on a test account or device. Test in the action editor runs the script for real.
Why use an action instead of asking SuperIT
SuperIT reads Microsoft 365 through your Microsoft 365 connection, but that connection is read-only, and mailbox changes like this one need Exchange Online, which SuperIT can't call in a chat. Setting an automatic reply on someone else's mailbox needs an action with an Exchange Online credential. It's mainly for engineers setting a reply on a leaver's or absent colleague's mailbox; users can set their own in Outlook.
To check whether a user's out-of-office is on and what it says, just ask SuperIT in chat.
When to use it
- "Jane is off sick and can't get to her laptop, please put her out-of-office on."
- "Set an out-of-office on Tom's mailbox saying he's left and to contact [email protected]."
- "Schedule Priya's automatic reply from 1 to 14 August."
What the action does
- Checks the inputs. A scheduled reply needs both dates, and the end date must be after the start date.
- Connects to Exchange Online with the credential.
- Turns automatic replies on, off or scheduled for the mailbox, with the internal message and, if given, a message for external senders. External replies go only to senders in the mailbox's contacts.
- Prints the mailbox's new automatic-reply settings.
What it doesn't do: it doesn't forward mail, block sign-in or convert the mailbox to shared. It doesn't set different replies per sender.
This guide uses Exchange Online because Microsoft Graph's delegated permissions only let an account change its own mailbox settings, not another user's.
Before you begin
- A Microsoft Graph credential for Exchange Online actions, named
M365 Exchange, with the scopehttps://outlook.office365.com/Exchange.Manage, signed in with an account that holds Exchange Administrator. A credential for Microsoft Graph scopes doesn't work here. Link it only to Exchange Online actions. This credential setup hasn't been tested with SuperIT; if the credential won't register or the script can't connect, see Exchange Online tasks. - An authorization policy with one rule: Specific groups
superit:engineers,superit:admins→ Require approval fromsuperit:admins. Don't add an Anyone rule: the script doesn't receive the requester's identity, so an end user could change someone else's mailbox. - The Engineer or Admin role to build the action in Workflows → Actions. Only admins can create actions in chat.
Build it with SuperIT
Create a workflow action called "Set out-of-office reply".
Runtime: PowerShell in the cloud sandbox. Credential: M365 Exchange
(Exchange Online, connect with Connect-ExchangeOnline -AccessToken).
Inputs:
- mailbox (email, required)
- state (select, required, choices: on, off, scheduled)
- message (textarea, optional) - reply for internal senders, required unless state is off
- external_message (textarea, optional) - reply for external senders
- start_date (date, optional), end_date (date, optional) - required when scheduled
It should validate the dates, HTML-encode the messages, send external replies to
known contacts only, call Set-MailboxAutoReplyConfiguration, and print the result.
Authorization policy: engineers and admins, every run approved by superit:admins.
SuperIT repeats the brief back, drafts the script, checks it, and creates the action as a draft. Review the script in Workflows → Actions, test it, then publish it.
Or build it yourself
| Name | Type | Required | Example |
|---|---|---|---|
mailbox |
Yes | [email protected] |
|
state |
select (choices on, off, scheduled) |
Yes | scheduled |
message |
textarea | No | I'm out of the office until 14 August. |
external_message |
textarea | No | Thanks for your email. I'm away until 14 August. |
start_date |
date | No | 2026-08-01 |
end_date |
date | No | 2026-08-14 |
# Goal: set a mailbox's automatic replies on, off or scheduled in Exchange Online,
# then print the settings Exchange reports back.
$token = $env:CREDENTIAL_M365_EXCHANGE_TOKEN
function Invoke-OutOfOfficeUpdate {
param([string]$Mailbox, [string]$State, [string]$Message, [string]$ExternalMessage, [string]$StartDate, [string]$EndDate)
$Mailbox = $Mailbox.Trim()
$State = $State.Trim().ToLower()
Assert-Inputs -Mailbox $Mailbox -State $State -Message $Message -StartDate $StartDate -EndDate $EndDate
$window = if ($State -eq 'scheduled') { Get-ReplyWindow -StartDate $StartDate -EndDate $EndDate }
$settings = New-AutoReplySettings -Mailbox $Mailbox -State $State -Message $Message `
-ExternalMessage $ExternalMessage -Window $window
Connect-ExchangeWithToken
try {
Set-AutoReply -Settings $settings
Write-AutoReplySummary -Mailbox $Mailbox -Config (Get-MailboxAutoReplyConfiguration -Identity $Mailbox)
} finally {
Disconnect-ExchangeOnline -Confirm:$false
}
}
function Assert-Inputs {
param([string]$Mailbox, [string]$State, [string]$Message, [string]$StartDate, [string]$EndDate)
if (-not $token) { throw "Link the M365 Exchange credential to this action." }
if ($Mailbox -notmatch '^[^@\s]+@[^@\s]+$') { throw "mailbox must be an email address." }
if ($State -notin 'on', 'off', 'scheduled') { throw "state must be on, off or scheduled." }
if ($State -ne 'off' -and -not $Message) { throw "message is required unless state is off." }
if ($State -eq 'scheduled' -and (-not $StartDate -or -not $EndDate)) { throw "start_date and end_date are required when scheduled." }
}
function Get-ReplyWindow {
param([string]$StartDate, [string]$EndDate)
$start = [datetime]::ParseExact($StartDate, 'yyyy-MM-dd', $null)
# EndTime is exclusive, so stop at midnight after end_date to include that whole day.
$end = [datetime]::ParseExact($EndDate, 'yyyy-MM-dd', $null).AddDays(1)
if ($end -le $start) { throw "end_date must be on or after start_date." }
@{ Start = $start; End = $end }
}
function New-AutoReplySettings {
param([string]$Mailbox, [string]$State, [string]$Message, [string]$ExternalMessage, [hashtable]$Window)
$settings = @{ Identity = $Mailbox; AutoReplyState = @{ on = 'Enabled'; off = 'Disabled'; scheduled = 'Scheduled' }[$State] }
if ($State -ne 'off') {
if (-not $ExternalMessage) { $ExternalMessage = $Message }
$settings.InternalMessage = ConvertTo-ReplyHtml -Text $Message
$settings.ExternalMessage = ConvertTo-ReplyHtml -Text $ExternalMessage
# Known: only senders in the mailbox's contacts learn the person is away, not every outside sender.
$settings.ExternalAudience = 'Known'
}
if ($Window) {
$settings.StartTime = $Window.Start
$settings.EndTime = $Window.End
}
$settings
}
function ConvertTo-ReplyHtml {
param([string]$Text)
# Exchange stores the reply as HTML, so encode the text before turning line breaks into <br>.
[System.Net.WebUtility]::HtmlEncode($Text) -replace "`r?`n", '<br>'
}
function Connect-ExchangeWithToken {
$upn = Get-TokenUpn
Import-Module ExchangeOnlineManagement
try {
# A delegated token must be paired with the signed-in admin's UPN, read from the token itself.
Connect-ExchangeOnline -AccessToken $token -UserPrincipalName $upn -ShowBanner:$false
} catch {
Write-Error "Failed to connect to Exchange Online as '$upn': $_"
exit 1
}
}
function Get-TokenUpn {
$part = $token.Split('.')[1].Replace('-', '+').Replace('_', '/')
$part += '=' * ((4 - $part.Length % 4) % 4)
([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($part)) | ConvertFrom-Json).upn
}
function Set-AutoReply {
param([hashtable]$Settings)
try {
# -ErrorAction Stop: Exchange cmdlets run in their own module and ignore the script's $ErrorActionPreference.
Set-MailboxAutoReplyConfiguration @Settings -ErrorAction Stop
} catch {
Write-Error "Failed to set automatic replies for '$($Settings.Identity)': $_"
exit 1
}
}
function Write-AutoReplySummary {
param([string]$Mailbox, [object]$Config)
Write-Output "=== AUTOMATIC REPLIES ==="
Write-Output "Mailbox : $Mailbox"
Write-Output "State : $($Config.AutoReplyState)"
if ($Config.AutoReplyState -eq 'Scheduled') {
Write-Output "Start : $($Config.StartTime)"
Write-Output "End : $($Config.EndTime)"
}
# $script: so the runner's wrapper sees it; a plain assignment stays local to this function.
$script:result = @{ mailbox = $Mailbox; state = "$($Config.AutoReplyState)"; start = "$($Config.StartTime)"; end = "$($Config.EndTime)" }
}
Invoke-OutOfOfficeUpdate -Mailbox $ctx.inputs.mailbox -State $ctx.inputs.state -Message $ctx.inputs.message `
-ExternalMessage $ctx.inputs.external_message -StartDate $ctx.inputs.start_date -EndDate $ctx.inputs.end_date
The script asks for midnight at the start of start_date and midnight after end_date. The sandbox runs in UTC, and Exchange may apply those times in UTC or in the mailbox's time zone, so a scheduled reply can start or end a few hours from midnight local time. Check the start and end times in Stdout and in Outlook on the web, and test a scheduled reply before you rely on the timing.
Test it
Test runs for real
Test skips authorization and approval, uses the real M365 Exchange credential, and really changes the mailbox's automatic replies. Use a test mailbox.
The script is untested, so treat your first test runs as debugging, and don't publish the action until a test run does exactly what you expect.
- On the action, select Test. Enter a test mailbox,
onand a short message. - Read the This is not a dry run. warning, tick "I understand this is a real execution that may change real systems." and select Start test run.
- Check Stdout, then send the test mailbox an email and check the automatic reply.
- Test with
scheduledand two dates, and check the start and end times Outlook on the web shows. - Test again with
off.
Use it
Publish the action. Engineers ask SuperIT, for example "Put an out-of-office on Jane's mailbox until Friday saying to contact her manager", and the run waits for an admin to approve it. To check first, ask "Is Jane's out-of-office on?"; SuperIT reads that through the Microsoft 365 connection without running the action.
End users can set their own automatic replies in Outlook.
For MSPs, publish to managed teams from the Publish dialog; an engineer or admin in each team authorizes its own M365 Exchange credential.
Variations
- Use it as part of offboarding with a fixed leaver message. See Offboard a Microsoft 365 user.
- Set
ExternalAudiencetoAllif every outside sender should get the external reply. That also tells anyone who emails the mailbox that the person is away. - Forward mail as well. See Set up mail forwarding.