Use PowerShell to set Exchange Out of Office status from any PC

I’m sure this has also happened already several times to you. You finish up your work to start into your well deserved holidays and only after you arrive at home do you realize that you forgot about to set your “Out of Office” status (considering that you actually do that). Usually, this would mean that you need to use your company device in order to connect back to work and set it up. If your company is running Exchange mail servers there is actually another option available which enables you to do the same from any PC that is connected to the Internet. The EWS Managed API is the technology that enables this.
I’ve written a module that uses the API in order to set an Out of Office message. The function has the following features:

  • Check whether the EWS Managed API is installed and offer an option to download and install in case it is not
  • Option to provide credentials (-ProvideCredentials switch) or use the current
  • A pop-up calendar to select the duration of the absence.
  • Automatic calculation of the return date based on the next business day after the duration end date
  • A custom OOTO message including start and return date (based on next business day after duration end date) and your Outlook signature (the signature is copied from your work PC ($env:APPDATE\Microsoft\Outlook\Signatures\) if available or should be within the same location as the module)
  • The function also creates an appointment in your Outlook based on the provided start and end date


Import-Module Set-OOTO
Set-OOTO '' -ExchangeVersion Exchange2007_SP1 -ProvideCredential

I’ve added my email and Exchange server version as default parameters to the function (if you are using Exchange 2007SP3 you can also need to use Exchange2007_SP1 as the value for the ExchangeVersion parameter (this took me quite a while to figure out)). Other than that you can of course modify the function with your own custom message and additional features (please share).
I’m posting the code below including helper functions to set the appointment and the calendar window. The code can also be downloaded from my GitHub repo:

function Get-DateRange {
Add-Type AssemblyName System.Windows.Forms
$form = new-object Windows.Forms.Form
$form.text = "Calendar"
$form.Size = new-object Drawing.Size @(656,639)
# Make "Hidden" SelectButton to handle Enter Key
$btnSelect = new-object System.Windows.Forms.Button
$btnSelect.Size = "1,1"
$form.Controls.Add($btnSelect )
$form.AcceptButton = $btnSelect
$cal = new-object System.Windows.Forms.MonthCalendar
$cal.ShowWeekNumbers = $true
$cal.MaxSelectionCount = 356
$cal.Dock = 'Fill'
return $cal.SelectionRange
function Set-CalendarAppointment($startDate,$endDate,$subject,$location){
$appointment = New-Object Microsoft.Exchange.WebServices.Data.Appointment($service)
$appointment.Subject = $subject
$appointment.Start = $startDate
$appointment.End = $endDate
$appointment.Location = $location
function Set-OOTO($Email='', [Microsoft.Exchange.WebServices.Data.ExchangeVersion]$ExchangeVersion=[Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1, [switch]$ProvideCredentials,[switch]$Off){
#EWS managed API 2.1
$apiPath = 'C:\Program Files (x86)\Microsoft\Exchange\Web Services\2.1\Microsoft.Exchange.WebServices.dll'
if (-not (Test-Path $apiPath)){
$a = new-object comobject
$answer = $a.popup("The function requires the EWS Mangaged API to be installed on your machine do you want to do download and install it now?", `
If ($answer -eq 6) {
$webclient = New-Object Net.WebClient
$url = ''
$path = "$env:TEMP\EwsManagedApi.MSI"
$webclient.DownloadFile($url, $path)
$argument = '/quiet'
Start-Process $path $argument Wait
} else {
Write-Warning "Please visit to download the EWS managed API manually"
Add-Type Path $apiPath
$script:service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)
if ($provideCredentials){
$credentials = Get-Credential
$service.Credentials = $credentials.GetNetworkCredential()
$oofSetting = $service.GetUserOofSettings($email)
if (!$off){
$dateRange = Get-DateRange
$startDt = [DateTime]::Parse(($dateRange.Start.ToLongDateString() + " 12:00 AM"))
#get next business day
$returnDt = $dateRange.End.AddDays(1)
while ($returnDt.DayOfWeek -eq "Saturday" -or $returnDt.DayOfWeek -eq "Sunday") { $returnDt = $returnDt.AddDays(1) }
$endDt = [DateTime]::Parse(($dateRange.End.AddDays(1).ToLongDateString() + " 12:00 AM"))
$msg="<span style='font-size:10.0pt;font-family:" + '"Arial","sans-serif"' + "'>"
<br><br>Thank you for your email.
<br>Please note I will be out of the office  from $($startDt.ToLongDateString()), returning $($returnDt.ToLongDateString()). During this time I will have no access to emails.
$msg += $text + "</span>"
#if on company pc get the signature otherwise go with the local copy
$remoteSigPath ="$env:APPDATA\Microsoft\Signatures\PLTeam.htm"
$localSigPath = ".\Signature.htm"
if (Test-Path $remoteSigPath){
copy $remoteSigPath $localSigPath
$msg += Get-Content $localSigPath | Out-String
$msg = $msg.ToString()
$msg = New-Object Microsoft.Exchange.WebServices.Data.OofReply($msg)
$oofSetting.InternalReply = $msg
$oofSetting.ExternalReply = $msg
$duration = New-Object Microsoft.Exchange.WebServices.Data.TimeWindow($startDt,$endDt)
$oofSetting.Duration = $duration
$oofSetting.State = [Microsoft.Exchange.WebServices.Data.OofState]::Enabled
$service.SetUserOofSettings($email, $oofSetting)
Set-CalendarAppointment $startDt $endDt "Out of Office" "Away"
Write-Host "Set OOTO from $($startDt.ToShortDateString()) to $($endDt.AddDays(-1).ToShortDateString())"
$oofSetting.State = [Microsoft.Exchange.WebServices.Data.OofState]::Disabled
$service.SetUserOofSettings($email, $oofSetting)
Export-ModuleMember Function @('Set-OOTO')

view raw


hosted with ❤ by GitHub


Photo Credit: nousku via Compfight cc

I'd love to hear what you think

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s