InternalGetLegacyUserSettings<TSettings extends ConfigurationSettingsBase> method

Future<TSettings> InternalGetLegacyUserSettings<TSettings extends ConfigurationSettingsBase>(
  1. TSettings newSettings,
  2. String emailAddress,
  3. List<String> redirectionEmailAddresses,
  4. OutParam<int> currentHopOutParam,
)
Calls the legacy Autodiscover service to retrieve configuration settings. The email address to retrieve configuration settings for. List of previous email addresses. Current number of redirection urls/addresses attempted so far.

Implementation

/* private */
Future<TSettings> InternalGetLegacyUserSettings<
        TSettings extends ConfigurationSettingsBase>(
    TSettings newSettings,
    String emailAddress,
    List<String> redirectionEmailAddresses,
    OutParam<int> currentHopOutParam) async {
  String domainName = EwsUtilities.DomainFromEmailAddress(emailAddress);

  OutParam<int> scpUrlCountOutParam = OutParam();
  scpUrlCountOutParam.param = 0;
  List<Uri?> urls =
      this.GetAutodiscoverServiceUrls(domainName, scpUrlCountOutParam);

  if (urls.length == 0) {
    throw new ServiceValidationException(
        "Strings.AutodiscoverServiceRequestRequiresDomainOrUrl");
  }

  // Assume caller is not inside the Intranet, regardless of whether SCP Urls
  // were returned or not. SCP Urls are only relevant if one of them returns
  // valid Autodiscover settings.
  this._isExternal = true;

  int currentUrlIndex = 0;

  // Used to save exception for later reporting.
  Exception? delayedException = null;
  OutParam<TSettings> settingsOutParam = OutParam();

  do {
    Uri? autodiscoverUrl = urls[currentUrlIndex];
    bool isScpUrl = currentUrlIndex < scpUrlCountOutParam.param!;

    try {
      settingsOutParam.param = this._GetLegacyUserSettingsAtUrl<TSettings>(
          newSettings, emailAddress, autodiscoverUrl);

      switch (settingsOutParam.param!.ResponseType) {
        case AutodiscoverResponseType.Success:
          // Not external if Autodiscover endpoint found via SCP returned the settings.
          if (isScpUrl) {
            this.IsExternal = false;
          }
          this.Url = autodiscoverUrl;
          return settingsOutParam.param!;
        case AutodiscoverResponseType.RedirectUrl:
          if (currentHopOutParam.param! < AutodiscoverMaxRedirections) {
            currentHopOutParam.param = currentHopOutParam.param! + 1;
            this.TraceMessage(enumerations.TraceFlags.AutodiscoverResponse,
                "Autodiscover service returned redirection URL '${settingsOutParam.param!.RedirectTarget}'.");

            urls[currentUrlIndex] =
                Uri.parse(settingsOutParam.param!.RedirectTarget!);
          } else {
            throw new AutodiscoverLocalException(
                "Strings.MaximumRedirectionHopsExceeded");
          }
          break;
        case AutodiscoverResponseType.RedirectAddress:
          if (currentHopOutParam.param! < AutodiscoverMaxRedirections) {
            currentHopOutParam.param = currentHopOutParam.param! + 1;
            this.TraceMessage(enumerations.TraceFlags.AutodiscoverResponse,
                "Autodiscover service returned redirection email address '${settingsOutParam.param!.RedirectTarget}'.");

            // If this email address was already tried, we may have a loop
            // in SCP lookups. Disable consideration of SCP records.
            this._DisableScpLookupIfDuplicateRedirection(
                settingsOutParam.param!.RedirectTarget!,
                redirectionEmailAddresses);

            return this.InternalGetLegacyUserSettings<TSettings>(
                newSettings,
                settingsOutParam.param!.RedirectTarget!,
                redirectionEmailAddresses,
                currentHopOutParam);
          } else {
            throw new AutodiscoverLocalException(
                "Strings.MaximumRedirectionHopsExceeded");
          }
        case AutodiscoverResponseType.Error:
          // Don't treat errors from an SCP-based Autodiscover service to be conclusive.
          // We'll try the next one and record the error for later.
          if (isScpUrl) {
            this.TraceMessage(
                enumerations.TraceFlags.AutodiscoverConfiguration,
                "Error returned by Autodiscover service found via SCP, treating as inconclusive.");

            delayedException = new AutodiscoverRemoteException(
                "Strings.AutodiscoverError", settingsOutParam.param!.Error);
            currentUrlIndex++;
          } else {
            throw new AutodiscoverRemoteException(
                "Strings.AutodiscoverError", settingsOutParam.param!.Error);
          }
          break;
        default:
          EwsUtilities.Assert(false, "Autodiscover.GetConfigurationSettings",
              "An unexpected error has occurred. This code path should never be reached.");
          break;
      }
    } on WebException catch (ex) {
      if (ex.Response != null) {
        IEwsHttpWebResponse response =
            this.HttpWebRequestFactory.CreateExceptionResponse(ex);
        OutParam<Uri> redirectUrlOutParam = OutParam();
        if (this._TryGetRedirectionResponse(response, redirectUrlOutParam)) {
          this.TraceMessage(enumerations.TraceFlags.AutodiscoverConfiguration,
              "Host returned a redirection to url ${redirectUrlOutParam.param}");

          currentHopOutParam.param = currentHopOutParam.param! + 1;
          urls[currentUrlIndex] = redirectUrlOutParam.param;
        } else {
          this.ProcessHttpErrorResponse(response, ex);

          this.TraceMessage(enumerations.TraceFlags.AutodiscoverConfiguration,
              "$_url failed: ${ex.runtimeType} (${ex.message})");

          // The url did not work, let's try the next.
          currentUrlIndex++;
        }
      } else {
        this.TraceMessage(enumerations.TraceFlags.AutodiscoverConfiguration,
            "$_url failed: ${ex.runtimeType} (${ex.message})");

        // The url did not work, let's try the next.
        currentUrlIndex++;
      }
    } on XmlException catch (ex) {
      this.TraceMessage(enumerations.TraceFlags.AutodiscoverConfiguration,
          "$_url failed: XML parsing error: $ex");

      // The content at the URL wasn't a valid response, let's try the next.
      currentUrlIndex++;
    } on IOException catch (ex) {
      this.TraceMessage(enumerations.TraceFlags.AutodiscoverConfiguration,
          "$_url failed: I/O error: $ex");

      // The content at the URL wasn't a valid response, let's try the next.
      currentUrlIndex++;
    }
  } while (currentUrlIndex < urls.length);

  // If we got this far it's because none of the URLs we tried have worked. As a next-to-last chance, use GetRedirectUrl to

  // redirection URL to get the configuration settings for this email address. (This will be a common scenario for
  // DataCenter deployments).
  Uri? redirectionUrl = await this._GetRedirectUrl(domainName);
  if ((redirectionUrl != null) &&
      await this.TryLastChanceHostRedirection<TSettings>(
          newSettings, emailAddress, redirectionUrl, settingsOutParam)) {
    return settingsOutParam.param!;
  } else {
    // Getting a redirection URL from an HTTP GET failed too. As a last chance, try to get an appropriate SRV Record

    throw UnimplementedError("GetRedirectionUrlFromDnsSrvRecord");
//                redirectionUrl = this.GetRedirectionUrlFromDnsSrvRecord(domainName);
    if ((redirectionUrl != null) &&
        await this.TryLastChanceHostRedirection<TSettings>(
            newSettings, emailAddress, redirectionUrl, settingsOutParam)) {
      return settingsOutParam.param!;
    }

    // If there was an earlier exception, throw it.
    else if (delayedException != null) {
      throw delayedException;
    } else {
      throw new AutodiscoverLocalException(
          "Strings.AutodiscoverCouldNotBeLocated");
    }
  }
}