Have you ever used that "Test E-mail AutoConfiguration" utility in Outlook? It's a useful tool that will query the autodiscover service, showing you exactly what CAS URLs are being handed to a particular user, and what the MAPI/HTTP endpoint is for their Exchange mailbox. You can run this tool by pressing the Ctrl button, right clicking on the Outlook 2007/2010 tray icon, and selecting "Test E-mail AutoConfiguration". This is nice, but there are times when I want to be able to determine this information for a user without having to fire up Outlook, or when Outlook isn't installed where ever I happen to be at the moment. My solution for this is a PowerShell function that will retrieve this information using the EWS Managed API. Here's the code:
function Test-Autodiscover { [CmdletBinding()] param( [Parameter(Position=1, Mandatory=$true)] [String] $EmailAddress, [ValidateSet("Internal", "External")] [Parameter(Position=2, Mandatory=$false)] [String] $Location = "External", [Parameter(Position=3, Mandatory=$false)] [System.Management.Automation.PSCredential] $Credential, [Parameter(Position=4, Mandatory=$false)] [switch] $TraceEnabled, [Parameter(Position=5, Mandatory=$false)] [bool] $IgnoreSsl = $true, [Parameter(Position=6, Mandatory=$false)] [String] $Url ) begin{ Add-Type -Path 'C:\Program Files\Microsoft\Exchange\Web Services\1.1\Microsoft.Exchange.WebServices.dll' } process { $autod = New-Object Microsoft.Exchange.WebServices.Autodiscover.AutodiscoverService $autod.RedirectionUrlValidationCallback = {$true} $autod.TraceEnabled = $TraceEnabled if($IgnoreSsl) { [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} } if($Credential){ $autod.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials -ArgumentList $Credential.UserName, $Credential.GetNetworkCredential().Password } if($Url) { $autod.Url = $Url } switch($Location) { "Internal" { $autod.EnableScpLookup = $true $response = $autod.GetUserSettings( $EmailAddress, [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::InternalRpcClientServer, [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::InternalEcpUrl, [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::InternalEwsUrl, [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::InternalOABUrl, [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::InternalUMUrl, [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::InternalWebClientUrls ) New-Object PSObject -Property @{ RpcClientServer = $response.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::InternalRpcClientServer] InternalOwaUrl = $response.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::InternalWebClientUrls].urls[0].url InternalEcpUrl = $response.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::InternalEcpUrl] InternalEwsUrl = $response.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::InternalEwsUrl] InternalOABUrl = $response.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::InternalOABUrl] InternalUMUrl = $response.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::InternalUMUrl] } } "External" { $autod.EnableScpLookup = $false $response = $autod.GetUserSettings( $EmailAddress, [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalMailboxServer, [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalEcpUrl, [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalEwsUrl, [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalOABUrl, [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalUMUrl, [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalWebClientUrls ) New-Object PSObject -Property @{ HttpServer = $response.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalMailboxServer] ExternalOwaUrl = $response.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalWebClientUrls].urls[0].url ExternalEcpUrl = $response.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalEcpUrl] ExternalEwsUrl = $response.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalEwsUrl] ExternalOABUrl = $response.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalOABUrl] ExternalUMUrl = $response.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalUMUrl] } } } } <# .SYNOPSIS This function uses the EWS Managed API to test the Exchange Autodiscover service. .DESCRIPTION This function will retreive the Client Access Server URLs for a specified email address by querying the autodiscover service of the Exchange server. .PARAMETER EmailAddress Specifies the email address for the mailbox that should be tested. .PARAMETER Location Set to External by default, but can also be set to Internal. This parameter controls whether the internal or external URLs are returned. .PARAMETER Credential Specifies a user account that has permission to perform this action. Type a user name, such as "User01" or "Domain01\User01", or enter a PSCredential object, such as one from the Get-Credential cmdlet. .PARAMETER TraceEnabled Use this switch parameter to enable tracing. This is used for debugging the XML response from the server. .PARAMETER IgnoreSsl Set to $true by default. If you do not want to ignore SSL warnings or errors, set this parameter to $false. .PARAMETER Url You can use this parameter to manually specifiy the autodiscover url. .EXAMPLE PS C:\> Test-Autodiscover -EmailAddress administrator@uclabs.ms -Location internal This example shows how to retrieve the internal autodiscover settings for a user. .EXAMPLE PS C:\> Test-Autodiscover -EmailAddress administrator@uclabs.ms -Credential $cred This example shows how to retrieve the external autodiscover settings for a user. You can provide credentials if you do not want to use the Windows credentials of the user calling the function. .LINK http://msdn.microsoft.com/en-us/library/dd633699%28v=EXCHG.80%29.aspx #> }
There are a few ways to use this Test-Autodiscover function. First, lets say that you are logged on to a domain workstation. Running the function with the following parameters will use your logged on credentials to perform an SCP look up and return the internal settings for the specified e-mail address:
Test-Autodiscover -EmailAddress administrator@uclabs.ms -Location internal

You can omit the -Location parameter, which by default is set to "External", and the function will use DNS to locate autodiscover and retrieve the external settings:
Test-Autodiscover -EmailAddress administrator@uclabs.ms

Finally, you might be testing this from the a machine outside your domain. Just create a PSCredential object using the Get-Credential cmdlet and assign it to the -Credential parameter of the function. For example, here's the result from testing autodiscover for an Exchange Online mailbox hosted through Office 365:
Test-Autodiscover -EmailAddress admin@uclabs.onmicrosoft.com -Credential $cred

In order to use this function you'll need a few things. First, if you haven't already, go download the EWS Managed API. You'll also need the .NET Framework 3.5.1 and PowerShell v2 installed. At that point, all you need to do is add the Test-Autodiscover function to your shell session and you're good to go.





{ 12 comments… read them below or add one }
Thanks you Mike, nice article and also very nice tools that can help many administrator !
Thanks Hakim
Great article and tool..I finally got it to work but i am getting this:
Exception calling “GetUserSettings” with “2″ argument(s): “The Autodiscover service couldn’t be located.”
At C:\test-autodiscover.psm1:75 char:47
+ $response = $autod.GetUserSettings <<<< (
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Cannot index into a null array.
At C:\test-autodiscover.psm1:86 char:47
+ HttpServer = $response.Settings[ <<<< [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::Ex
ternalMailboxServer]
+ CategoryInfo : InvalidOperation: (ExternalMailboxServer:UserSettingName) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
I assume this is not configured on the server, yes?
Thanks!!
I just ran the test autoconfigu via outlook and no errors….I am thinking I did something wrong running the powershell..
Did you supply credentials?
Test-Autodiscover -EmailAddress admin@uclabs.onmicrosoft.com -Credential $cred
Great Job, Mike ( MVP) . Im running the script against a hosted exchange mailbox. First , was getting this error :
“Cannot find path ‘C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll’ because it does not exist.
Was able to modify the script using the loadfile function
” $dllpath = “C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll”
[void][Reflection.Assembly]::LoadFile($dllpath) ”
Now i couldnt get past this :
=======================
Exception calling “GetUserSettings” with “2″ argument(s): “The request failed. The remote server returned an error: (40
1) Unauthorized.”
At C:\Users\v-9saram\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1:56 char:47
+ $response = $autod.GetUserSettings <<<< (
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Cannot index into a null array.
At C:\Users\v-9saram\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1:67 char:47
+ HttpServer = $response.Settings[ <<<< [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::Ex
ternalMailboxServer]
+ CategoryInfo : InvalidOperation: (ExternalMailboxServer:UserSettingName) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
Any inputs would be really appreaciated..
Looks like an authentication issue. Did you provide creds when running the function? For example:
Test-Autodiscover -EmailAddress admin@uclabs.onmicrosoft.com -Credential $cred
Great article and tool Mike. I tried running it a few different way as you described using the -Location and -Credential parameter but I seem to be getting the same error no matter how I run it.
For example: I first open powershell and execute the following command to feed credentials for the script.
1. $cred=Get-Credential
2. I enter my credentials. In this case its my Office 365 credentials.
3. I dot source the script so that I can execute the function Test-Autodiscover
4. I execute the following command :
Test-Autodiscover -EmailAddress user@myfederatedo365domain.com -Credential $cred
I get this error:
Exception calling “GetUserSettings” with “2″ argument(s): “The Autodiscover service could not be located.”
At C:\Users\mike\Desktop\Test-Autodiscover.ps1:75 char:47
+ $response = $autod.GetUserSettings <<<< (
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Cannot index into a null array.
At C:\Users\mike\Desktop\Test-Autodiscover.ps1:86 char:47
+ HttpServer = $response.Settings[ <<<< [Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::Ex
ternalMailboxServer]
+ CategoryInfo : InvalidOperation: (ExternalMailboxServer:UserSettingName) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
This happens no matter if I run it with -Location internal, -Location External. Same error. Can you provide some guideance. I appreciate it. Thanks.
Since you’re using a vanity domain, make sure you have an autodiscover record in DNS for that domain. Without it, you’ll get that exact error.
Hi,
whats the fastest way to check that supplied URL is correct? I want to use hard coded URL for connection, but I need to have some check. And if that check fails the script use autodiscovery for getting correct URL
So in trying to get this to work, I am seeing an error not previously mentioned.
Function is dot sourced and I am providing the correct credentials.
Test-Autodiscover -EmailAddress admin@O365domain.onmicrosoft.com -Credential (Get-Credential)
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Cannot index into a null array.
At line:85 char:13
+ New-Object PSObject -Property @{
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
Any idea’s? Thanks!
Hi Brent,
Just tried a couple of things…it looks like you’ll get that when $autod.GetUserSettings() fails thanks to my lack of error handling
Try running it with tracing turned on
Test-Autodiscover -EmailAddress user@domain.com -Credential (Get-Credential) -TraceEnabled
I noticed that when I entered invalid creds and caused the code to fail that I would get the same “Cannot index into a null array.” With tracing enabled, you should see a 401 unauthorized if indeed the creds are no good. Otherwise, you should get something that will hopefully explain why it fails.