One of the new features in Exchange 2010 is the ability to manage Out-Of-Office settings for mailboxes from EMS. This is made possible by the Get-MailboxAutoReplyConfiguration and Set-MailboxAutoReplyConfiguration cmdlets. Unfortunately, these cmdlets are only available in Exchange 2010. With Exchange 2007 SP2 or higher, using the Exchange EWS Managed API and PowerShell v2, you can write your own advanced functions that emulate the functionality of the auto reply cmdlets included with 2010. In this post, I'll share a couple of functions that you can use from within EMS that will allow you to do that.
Mailbox Permissions
Before we look at the code, a quick note about permissions. Ideally, we'd like to use Exchange impersonation to access and modify the OOF settings for a user. Unfortunately, EWS impersonation doesn't work with the GetUserOofSettings and SetUserOofSetting methods (see this post for details). So, you'll need to use the Add-MailboxPermission cmdlet to assign your account full access to the mailboxes you want to manage. For more details on Exchange Impersonation vs. Delegate Access, also check out this post.
The Get Function
This code assumes the EWS Managed API assembly is located in c:\bin; update the path as needed for your machine. If you have not yet downloaded the EWS Managed API, you can grab it here. This function is designed to return information similar to the Get-MailboxAutoReplyConfiguration cmdlet in Exchange 2010, here is the code:
function Get-EWSOofSettings { [CmdletBinding()] param( [Parameter(Position=0, ValueFromPipelineByPropertyName=$true, Mandatory=$true)] [System.String] [Alias("Identity")] $PrimarySmtpAddress, [Parameter(Position=1, Mandatory=$false)] [System.String] $ver = "Exchange2007_SP1" ) begin { Add-Type -Path "C:\bin\Microsoft.Exchange.WebServices.dll" $sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value $user = [ADSI]"LDAP://<SID=$sid>" } process { $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -Arg $ver $service.AutodiscoverUrl($user.Properties.mail) if($PrimarySmtpAddress -notmatch "@") { $PrimarySmtpAddress = (Get-Recipient $PrimarySmtpAddress).PrimarySMTPAddress.ToString() } $oof = $service.GetUserOofSettings($PrimarySmtpAddress) New-Object PSObject -Property @{ State = $oof.State ExternalAudience = $oof.ExternalAudience StartTime = $oof.Duration.StartTime EndTime = $oof.Duration.EndTime InternalReply = $oof.InternalReply ExternalReply = $oof.ExternalReply AllowExternalOof = $oof.AllowExternalOof Identity = (Get-Recipient $PrimarySmtpAddress).Identity } } }
Once you have the mailbox permissions worked out and have added the function to your PowerShell session, you can test out the code. The following example shows how you would run the function:

The above information is returned for a user with the alias of abarlow. If you've worked with the Get-MailboxAutoReplyConfiguration cmdlet in Exchange 2010, you'll notice that all of the same information is returned.
Finding Users in the Organization with Out-Of-Office Enabled
The Get-EWSOofSettings function is designed to accept pipeline input from the Get-Mailbox cmdet. This means that you could find the settings for multiple users in a single command. For instance, it may be useful to find all users who currently have OOF enabled:

It's worth mentioning here that if a user has a duration set (start and end time) the state will show as "Scheduled". In that case, you would simply modify your where clause to ?{($_.state -eq "Enabled") -or ($_.state -eq "Scheduled")}
The Set Function
Again, this code assumes the EWS Managed API assembly is located in c:\bin, you'll need to update the path accordingly. This function is similar to the Set-MailboxAutoReplyConfiguration cmdlet in Exchange 2010.
function Set-EWSOofSettings { [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$true)] [System.String] $Identity, [Parameter(Position=1, Mandatory=$false)] [System.String] $State, [Parameter(Position=2, Mandatory=$false)] [System.String] $ExternalAudience, [Parameter(Position=3, Mandatory=$false)] [System.DateTime] $StartTime, [Parameter(Position=4, Mandatory=$false)] [System.DateTime] $EndTime, [Parameter(Position=5, Mandatory=$false)] [System.String] $InternalReply, [Parameter(Position=6, Mandatory=$false)] [System.String] $ExternalReply, [Parameter(Position=7, Mandatory=$false)] [System.String] $ver = "Exchange2007_SP1" ) begin { Add-Type -Path "C:\bin\Microsoft.Exchange.WebServices.dll" $sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value $user = [ADSI]"LDAP://<SID=$sid>" } process { $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -arg $ver $service.AutodiscoverUrl($user.Properties.mail) if($Identity -notmatch "@") { $Identity = (Get-Recipient $Identity).PrimarySMTPAddress.ToString() } $oof = $service.GetUserOofSettings($Identity) if($StartTime -and $EndTime) { $Duration = New-Object Microsoft.Exchange.WebServices.Data.TimeWindow ` -arg $StartTime,$EndTime $PSBoundParameters.Duration = $Duration $PSBoundParameters.State = "Scheduled" [Void]$PSBoundParameters.remove("StartTime") [Void]$PSBoundParameters.remove("EndTime") } foreach($p in $PSBoundParameters.GetEnumerator()) { if($p.key -ne "Identity") { $oof."$($p.key)" = $p.value } } $service.SetUserOofSettings($Identity,$oof) } }
Here is an example using the above function to enable out-of-office for a user:

Looking at the function parameters, you can see that several properties can be set including start and end time, internal and external reply, and also external audience.
Here is another example. This will schedule out of office using a start and end time, set the internal and external reply, and configure the external audience to "Known" so that external replies are only sent to recipients in the users contact list:
$end = Get-Date "7/15/2010"
Set-EWSOofSettings -Identity jknapp -StartTime $start -EndTime $end -InternalReply "I am out of the office" -ExternalReply "I am out of the office" -ExternalAudience Known

Note that when setting a start and end time, you do not need to provide a value for the state parameter, it will automatically be set to "Scheduled". And finally, to turn off OOF for a user, set the value for the state parameter to "disabled".





{ 4 trackbacks }
{ 35 comments… read them below or add one }
Very usefull tips for those running exchange 2007, thank you for sharing
Thanks for the feedback
This tip saved my day.
Greatly appreciated your sharing.
Awesome, thanks Marcos!
Thanks for the post… I’m trying to implement this but I get this error in PowerShell console when I try to run the first code …
Missing closing ‘)’ in expression.
At C:\Documents and Settings\besadmin\Desktop\Step1.ps1:5 char:9
+ [ <<<< System.String]
Any suggestions on what I'm doing incorrect?
Josh
Josh, are you running PowerShell v2? Also, have a look at this post
I’m using 1.0
Ok, that is the problem. As stated at the beginning of the post, these are advanced functions written for PowerShell v2. If you are running Exchange 2007 SP2 or higher, you can upgrade to PowerShell v2 and then you’ll be all set.
Great! Thanks I must have missed that line.
One more thing… I updated to 2.0 and ran the two listed above, but when I try to use EMS to get the in I get this [PS] C:\Documents and Settings\besadmin>Get-EWSOofSettings -Identity jbright
The term ‘Get-EWSOofSettings’ is not recognized as the name of a cmdlet, functi
on, script file, or operable program. Check the spelling of the name, or if a p
ath was included, verify that the path is correct and try again.
At line:1 char:19
+ Get-EWSOofSettings <<<< -Identity jbright
+ CategoryInfo : ObjectNotFound: (Get-EWSOofSettings:String) [],
CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Last Post I promise… If I can’t figure this out I go on Merry Way!
[PS] C:\Documents and Settings\frodo1>Get-Mailbox -ResultSize Unlimited -Identit
y jbright | ForEach-Object { Get-EWSOofSettings -Identity $_.alias }
Exception calling “AutodiscoverUrl” with “1″ argument(s): “A valid SMTP address
must be specified.”
At C:\Get-OOF.psm1:21 char:33
+ $service.AutodiscoverUrl <<<< ($user.Properties.mail)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Exception calling "GetUserOofSettings" with "1" argument(s): "The Url property
on the ExchangeService object must be set."
At C:\Get-OOF.psm1:27 char:43
+ $oof = $service.GetUserOofSettings <<<< ($PrimarySmtpAddress)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
The function uses autodiscover to determine the EWS url based on the identity of the person running the code. Does the user account you are running the function with have an Exchange mailbox, and is the mail attribute set on their AD account to a valid smtp address?
Wow. All I have to say is, “Thank you!”
Your very welcome Andrew!
Hi Mike,
I’m having the similar problem Josh had:
“[PS] C:\>Get-EWSOofSettings -identity UXX
Exception calling “AutodiscoverUrl” with “1″ argument(s): “The Autodiscover ser
vice couldn’t be located.”
At C:\Program Files\Microsoft\Exchange Server\bin\Get-EWSOofSettings.ps1:21 cha
r:33
+ $service.AutodiscoverUrl <<<< ($user.Properties.mail)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Exception calling "GetUserOofSettings" with "1" argument(s): "The Url property
on the ExchangeService object must be set."
At C:\Program Files\Microsoft\Exchange Server\bin\Get-EWSOofSettings.ps1:27 cha
r:43
+ $oof = $service.GetUserOofSettings <<<< ($PrimarySmtpAddress)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
StartTime :
State :
InternalReply :
ExternalReply :
Identity : XX-ad/XXX/XXX/Users/XX, User
ExternalAudience :
EndTime :
AllowExternalOof :"
I had a look on your other posts but can't get it to work. I'm running PowerShell 2 under Windows XP SP3 and the Exchange is 2007 SP3.
Really appreciate if you could help me since this Oof is a day-to-day process and we need to find a better way to do it!!
Rgrds,
Bruno
I have Windows 7 , 32 bit operating system with service pack 1.
I have installed exchange 2007 SP3 management tools on it with powershell version 2.0
I also installed the Exchange and Active Directory powerpacks from PowerGui.
I have created my profile with the get-ewsoofsettings function and my profile loads without any error.
When I run get-ewsoofsettings -identity user@domain.com I get the following error
———-
Exception calling “AutodiscoverUrl” with “1″ argument(s): “A valid SMTP address
must be specified.”
At C:\Users\xxx\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.p
s1:21 char:33
+ $service.AutodiscoverUrl <<<< ($user.Properties.mail)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Exception calling "GetUserOofSettings" with "1" argument(s): "The Url property
on the ExchangeService object must be set."
At C:\Users\xxx\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.p
s1:27 char:43
+ $oof = $service.GetUserOofSettings <<<< ($PrimarySmtpAddress)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
The function attempts to use the callers email address to determine the EWS endpoint using AutoDiscover. Are you running this with an account that has an Exchange mailbox? If not, that could be the cause of the error.
Is it possible to do this without the Autodiscover section in the code?
The first command complains about the Autodiscover not being able to be located, but it does return the OoO settings.
However, when I run the second, it pukes all over the place and will not make any adjustments.
Exception calling “AutodiscoverUrl” with “1″ argument(s): “The Autodiscover ser
vice couldn’t be located.”
At C:\utilities\Set-EwsOofSettings.psm1:38 char:33
+ $service.AutodiscoverUrl <<<< ($user.Properties.mail)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Exception calling "GetUserOofSettings" with "1" argument(s): "The Url property
on the ExchangeService object must be set."
At C:\utilities\Set-EwsOofSettings.psm1:44 char:43
+ $oof = $service.GetUserOofSettings <<<< ($Identity)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Property 'InternalReply' cannot be found on this object; make sure it exists an
d is settable.
At C:\utilities\Set-EwsOofSettings.psm1:57 char:22
+ $oof. <<<< "$($p.key)" = $p.value
+ CategoryInfo : InvalidOperation: (InternalReply:String) [], Run
timeException
+ FullyQualifiedErrorId : PropertyNotFound
Property 'ExternalReply' cannot be found on this object; make sure it exists an
d is settable.
At C:\utilities\Set-EwsOofSettings.psm1:57 char:22
+ $oof. <<<< "$($p.key)" = $p.value
+ CategoryInfo : InvalidOperation: (ExternalReply:String) [], Run
timeException
+ FullyQualifiedErrorId : PropertyNotFound
Property 'Duration' cannot be found on this object; make sure it exists and is
settable.
At C:\utilities\Set-EwsOofSettings.psm1:57 char:22
+ $oof. <<<< "$($p.key)" = $p.value
+ CategoryInfo : InvalidOperation: (Duration:String) [], RuntimeE
xception
+ FullyQualifiedErrorId : PropertyNotFound
Property 'State' cannot be found on this object; make sure it exists and is set
table.
At C:\utilities\Set-EwsOofSettings.psm1:57 char:22
+ $oof. <<<< "$($p.key)" = $p.value
+ CategoryInfo : InvalidOperation: (State:String) [], RuntimeExce
ption
+ FullyQualifiedErrorId : PropertyNotFound
Exception calling "SetUserOofSettings" with "2" argument(s): "Value cannot be n
ull.
Parameter name: oofSettings"
At C:\utilities\Set-EwsOofSettings.psm1:60 char:36
+ $service.SetUserOofSettings <<<< ($Identity,$oof)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Thanks for your help!
smooter
Yeah, you can set the URL manually. For example, replace $service.AutodiscoverUrl($user.Properties.mail) with:
$url = “https://ex1.contoso.com/EWS/Exchange.asmx”
$service.Url = New-Object System.Uri -ArgumentList $url
Another thing to check is that the machine you are running the code from trusts the certificates on your CAS server.
!!! VERY SIMPLE SOLUTION:
1. Give yourself full access permissions to the user’s mailbox
2. Goto your control panel, then Mail (32-bit)
3. Under Profiles, add a profile (no OST / Non-Cached Mode) with the user’s mail address (do not give credentials)
4. When asked for credentials just use your own ]
5. Open Outlook with newly created profile, and go to the OOO Assistant.
6. Voila!
That’s great…use whatever method works best for you. I am not saying my solution here is the best way to do anything. I’m just sharing some code I used to solve a problem.
Can this be used against an exchange 2007 sp1 environment but running it on my win7 desktop with PS v2?
thanks!
Yes, you can run it remotley from Win7…just make sure the EWS Managed API assembly is local so it can be imported.
Mike,
We are running into an issue while using GetUserOofSettings method of EWS. Every time we try using the current users’ credential it throws “The smtp address has no mailbox associated with” error. Though other api works… Do you have any suggestions ? I would greatly appreciate it
thanks
Sheetal
Hello,
Is there any way to do the same for Exchange 2007 SP1?
Any ideas?
Thanks!
Yes, you should be able to run it remotely from a machine with PowerShell v2…just make sure the EWS Managed API assembly is local so it can be imported.
Of course, 2007 SP1 is pretty old, so I’d consider upgrading to SP3 anyways. It’s been available since June of 2010. I know that’s not always an easy thing to do though
Hello Mike,
I’m running this function on a server Exchange 2007 SP3, PS 2.0 and receive this message error
Exception calling “GetUserOofSettings” with “1″ argument(s): “The request faile
d. The remote server returned an error: (403) Forbidden.”
At C:\function.ps1:29 char:43
+ $oof = $service.GetUserOofSettings <<< User is not mailbox owner. User = S-1-5-21-292766723
8-228183578-1654702620-7801, MailboxGuid = S-1-5-21-2605977091-1024320090-31298
82909-1281″
At C:\function.ps1:29 char:43
+ $oof = $service.GetUserOofSettings <<<< ($PrimarySmtpAddress)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Any ideas?
Regards
Ernesto.
Do you have full access rights to the mailbox?
Yes i have full access to the mailbox, also with the user i’m trying to run this function has a mailbox.
Sometimes i receive this error
[PS] C:\Documents and Settings\user1>Get-EWSOofSettings -Identity user2
Exception calling “GetUserOofSettings” with “1″ argument(s): “The request faile
d. The remote server returned an error: (403) Forbidden.”
At C:\function.ps1:29 char:43
+ $oof = $service.GetUserOofSettings <<< User is not mailbox owner. User = S-1-5-21-292766723
8-228183578-1654702620-7801, MailboxGuid = S-1-5-21-2605977091-1024320090-31298
82909-1281″
At C:\function.ps1:29 char:43
+ $oof = $service.GetUserOofSettings <<<< ($PrimarySmtpAddress)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Thanks in advance
Ernesto
Thanks a lot for this post, is working now, seem to be we had a replication problems.
Ernesto.
Mike Hi,
Can you post your script at Script Center?
http://technet.microsoft.com/en-US/scriptcenter/
Ty,
Sure, you’ll need to add the function to your PowerShell session, check out this post for details:
http://www.mikepfeiffer.net/2010/06/how-to-add-functions-to-your-powershell-session/
I got it working! What about if you have three different Mailbox servers? Example EX1 EX2 EX3 if the code is ran on EX1 it can Set OOF on all mailboxes within EX1 but not EX2 and EX3? Thanks again! I know I’m filling up your comments section…
Here’s an example. Let’s say that you want to disable OOF for every mailbox in the org:
Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox | ForEach-Object { Set-EWSOofSettings -Identity $_.alias -State Disabled }
So, you use Get-Mailbox to retrieve every mailbox in the organization, regardless of which database they are in and which server that database is mounted on. You then pipe the results to ForEach-Object, loop through each item in the collection and disable the setting for the mailbox.
Josh or Bruno,
How did you get it working? Experiencing the same problem – logged on as Enterprise Admin…