JH.Yang
JH.Yang

Reputation: 11

Need a way to find Exchange product version by using EWS web service (SOAP)

I am trying to get Exchange product version for different servers. The servers are hosted by Microsoft, Clients or third party service providers. I need a way to find the version - so I can use correct schema and version specified operations (like "Get Password Expiration" introduced in Exchange2010_SP2). The min product version supported is "Exchange2007". The soap request I send to server to retrieve the version is below.

<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2007_SP1" />
  </soap:Header>
  <soap:Body>
    <GetFolder xmlns="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
      <FolderShape>
        <t:BaseShape>Default</t:BaseShape>
      </FolderShape>
      <FolderIds>
        <t:DistinguishedFolderId Id="sentitems" />
      </FolderIds>
    </GetFolder>
  </soap:Body>
</soap:Envelope>

The problem for this request is the returned server versions are vary and not clearly shows the Exchange product version. The version values I got are something like 'V2_68', 'V2015_10_05'. I have failed to match these values to Exchange product version as the values are not stable.

I have tried to use AutoDiscover GetUserSettingsResponseMessage operation. For some servers this operation can return schemas in tag EwsSupportSchemas. But not all servers support AutoDiscover.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:a="http://schemas.microsoft.com/exchange/2010/Autodiscover"      
               xmlns:wsa="http://www.w3.org/2005/08/addressing" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      
               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <a:RequestedServerVersion>Exchange2010</a:RequestedServerVersion>
    <wsa:Action>http://schemas.microsoft.com/exchange/2010/Autodiscover/Autodiscover/GetUserSettings</wsa:Action>
    <wsa:To>https://myserver.contoso.com/autodiscover/autodiscover.svc</wsa:To>
  </soap:Header>
  <soap:Body>
    <a:GetUserSettingsRequestMessage xmlns:a="http://schemas.microsoft.com/exchange/2010/Autodiscover">
      <a:Request>
        <a:Users>
          <a:User>
            <a:Mailbox>[email protected]</a:Mailbox>
          </a:User>
        </a:Users>
        <a:RequestedSettings>
          <a:Setting>UserDisplayName</a:Setting>
          <a:Setting>UserDN</a:Setting>
          <a:Setting>UserDeploymentId</a:Setting>
          <a:Setting>InternalMailboxServer</a:Setting>
          <a:Setting>MailboxDN</a:Setting>
          <a:Setting>ActiveDirectoryServer</a:Setting>
          <a:Setting>CasVersion</a:Setting>
          <a:Setting>EwsSupportedSchemas</a:Setting>
        </a:RequestedSettings>
      </a:Request>
    </a:GetUserSettingsRequestMessage>
  </soap:Body>
</soap:Envelope>

Thank you so much.

Upvotes: 1

Views: 3207

Answers (3)

carlos357
carlos357

Reputation: 449

Exchange returns the server information in every response. You can do a dummy request and get the version from there. Using the EWS managed api library available here: https://github.com/OfficeDev/ews-managed-api

You can do the following:

   /// <summary>
        /// It returns the Exchange server version. It works for any Exchange version since 2007 SP1
        /// </summary>
        private ExchangeVersion GetExchangeVersion(Uri EWS_Url, ExchangeCredentials exchange_credentials=null)
        {

            // We pick the oldest version supported by the EWS library which is 2007 SP1
            // Newer exchange versions are backwards compatible
            ExchangeService exchange_service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
            exchange_service.Url = EWS_Url;

            if (exchange_credentials==null)
                exchange_service.UseDefaultCredentials = true;
            else
                exchange_service.Credentials = exchange_credentials;


            // We do a dummy call
            Folder exchange_folder;
            exchange_folder = Folder.Bind(exchange_service, WellKnownFolderName.Inbox);
            exchange_folder.Load();

            // Retrieve the server info returned in the last call
            ExchangeServerInfo server_info = exchange_service.ServerInfo;


            // This is based on the list from:
            // https://technet.microsoft.com/en-us/library/hh135098(v=exchg.150).aspx
            //
            if (server_info.MajorVersion == 8 && server_info.MinorVersion >= 1)
                return (ExchangeVersion.Exchange2007_SP1);
            else if (server_info.MajorVersion == 14 && server_info.MinorVersion == 0)
                return (ExchangeVersion.Exchange2010);
            else if (server_info.MajorVersion == 14 && server_info.MinorVersion == 1)
                return (ExchangeVersion.Exchange2010_SP1);
            else if (server_info.MajorVersion == 14 && server_info.MinorVersion >= 2)
                return (ExchangeVersion.Exchange2010_SP2);
            else if (server_info.MajorVersion == 15 && server_info.MinorVersion == 0)
                return (ExchangeVersion.Exchange2013);
            else if (server_info.MajorVersion >= 15)
                return (ExchangeVersion.Exchange2013_SP1);
            else
                throw (new Exception("Unknown Exchange version"));
        }

Upvotes: 2

Erik Cederstrand
Erik Cederstrand

Reputation: 10245

I have the same problem.

You can peek into /EWS/types.xsd and read the version attribute, but even that is not guaranteed to work, because Exchange admins can misconfigure Exchange servers in very creative ways. Additionally, Office365 seems to try really hard to only play well with Microsoft brand products.

After multiple attempts to behave nicely, I have resorted to trial-and-error. Before anything else, I send a dummy request that is supported in all EWS versions (ResolveNames service with UnresolvedEntry=DUMMY) and test if the server accepts the RequestServerVersion value. If not, rinse and repeat with a new RequestServerVersion value until the request is accepted. If the server responds with a sane ServerVersionInfo value (of the form ExchangeYYYY[_SPn]) I use that in the following requests, otherwise I use the RequestServerVersion value I sent. My eyes are bleeding over this hack, but it's the only way I've found to work reliably with the wide range of Exchange servers I'm communicating with.

FWIW, here's the RequestServerVersion values I test with as of Jan 2016:

  • Exchange2007
  • Exchange2007_SP1
  • Exchange2010
  • Exchange2010_SP1
  • Exchange2010_SP2
  • Exchange2013
  • Exchange2016

Upvotes: 0

Glen Scales
Glen Scales

Reputation: 22032

You need to differentiate between OnPrem where the request your trying will work okay (eg you will see and Exchange Schema Version) and Office365 which is the only time you will get schema versions like 'V2_68', 'V2015_10_05' (this is because the cloud and OnPrem versions have diverged) and you should expect that will change as the update cadences in the cloud vary. There are lots of ways to determine if your accessing a cloud Mailbox from the autodiscover to just looking at the EndPoint your request are going to (eg on Office365 everything will go to the Load Balanced endpoint).

Cheers Glen

Upvotes: 0

Related Questions