InternalGetLegacyUserSettings<TSettings extends ConfigurationSettingsBase> method
Future<TSettings>
InternalGetLegacyUserSettings<
TSettings extends ConfigurationSettingsBase>( - TSettings newSettings,
- String emailAddress,
- List<String> redirectionEmailAddresses,
- 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");
}
}
}