For license details, see Plans and pricing.
From October 2026, Exchange Online blocks all EWS traffic when EWS is enabled and the tenant's EwsAllowedAppIDs list is empty. To keep Cloud Platform access to EWS, add the Cloud Platform App IDs to this list and turn on EWS for your tenant.
This article covers two ways to do this:
Manually: Follow Option 1: Configure EWS manually, then confirm the result with the Verification checklist.
With a script: Run the PowerShell script in Option 2: Configure EWS using the script. It does the same steps automatically and verifies the result.
It also covers how to roll back the change and troubleshoot common EWS errors.
Overview
Cloud Platform uses Exchange Web Services (EWS) to access resources which are not available through Graph. Two organization-level settings control this:
Configuration | Purpose | Required |
Global EWS enablement ( | Turns EWS on for the Exchange Online tenant. | Required |
Allowed application IDs ( | When | Required (from October 2026, an empty list blocks all EWS traffic) |
Both options do the following, in order:
Retrieves the tenant's current
EwsAllowedAppIDslist.Finds Cloud Platform's App IDs in the tenant's Enterprise Applications.
Adds any missing Cloud Platform App IDs without removing the App IDs that are already configured.
Sets
EwsEnabledto True.
How the allow list behaves
EwsAllowedAppIDsis enforced only whenEwsEnabledis True. WhenEwsEnabledis blank ($null), the list is ignored. WhenEwsEnabledis False, all EWS traffic is blocked whatever the list contains.When
EwsEnabledisTrue, only the applications in the list can use EWS. From October 2026, if the list is empty, all EWS traffic is blocked.If the list is empty today, this guide adds the Cloud Platform App IDs to it. Any other application that needs EWS must also have its App ID in the list.
Changes to
EwsAllowedAppIDscan take up to 24 hours to take effect because of caching. Changes toEwsEnabledusually take effect within 1 hour, but can take up to 4 hours.
Prerequisites
Requirement | Details |
Shell | Azure Cloud Shell (PowerShell) or PowerShell 7+ |
Exchange Online PowerShell |
|
Azure CLI |
|
Roles | Exchange Administrator (or Organization Management) to change the organization config, plus at least Directory Readers to list Enterprise Applications |
Before you start, sign in to Exchange Online PowerShell (for Steps 1, 3 and 4) and to Azure CLI (for Step 2).
Option 1: Configure EWS manually
Run Steps 1 to 4 in order, then run the Verification checklist.
Step 1: Retrieve the current EwsAllowedAppIDs list
EwsAllowedAppIDs is returned only when you add the -RetrieveEwsOperationAccessPolicy switch.
Get-OrganizationConfig -RetrieveEwsOperationAccessPolicy | Format-List EwsAllowedAppIDs
Example output:
EwsAllowedAppIDs : aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee,11111111-2222-3333-4444-555555555555
Save this value. You need it in Step 3, and it is your rollback point.
To show one App ID per line, which is easier to compare:
(Get-OrganizationConfig -RetrieveEwsOperationAccessPolicy).EwsAllowedAppIDs -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ }
📝NOTE:
The value is a single comma-separated string, not a list.
The list may already contain App IDs that your administrators added, or that Microsoft added automatically based on your tenant's recent EWS usage. Keep all of them; Step 3 only adds to the list.
A blank result means no App IDs are allowed. While EwsEnabled is True, that blocks all EWS traffic.
Step 2: Get Cloud Platform's App IDs from the tenant's Enterprise Applications
2.1 List the Cloud Platform service principals
az ad sp list --all ` --query "[?starts_with(displayName, 'Druva inSync Exchange') || starts_with(displayName, 'Druva M365')].{Name:displayName,AppId:appId}" ` -o table
Example output:
Name AppId ---------------------------- ------------------------------------ Druva Exchange <...> <druva-app-id-1> ...
2.2 Write down the Cloud Platform App IDs
Use the AppId column (not ObjectId). Example:
<druva-app-id-1>
<druva-app-id-2>
Step 3: Add the missing Cloud Platform App IDs without removing existing ones
Set-OrganizationConfig -EwsAllowedAppIDs does not support adding or removing individual App IDs. Every call replaces the whole list. To add App IDs, Microsoft's method is to read the current list, add the new App IDs to it, and write the full list back. That is what this step does.
3.1 Compare the two lists
Using the outputs of Step 1 and Step 2, find the Cloud Platform App IDs that are not in the current list. GUID comparison is not case-sensitive.
If all Cloud Platform App IDs are already present, no change is needed. Go to Step 4.
If any Cloud Platform App ID is missing, continue to 3.2.
If the current list is empty, all Cloud Platform App IDs are missing. Continue to 3.2; the new list will contain only the Cloud Platform App IDs.
3.2 Option A: Set the merged value by hand
Build one comma-separated string: all existing App IDs from Step 1, followed by the missing Cloud Platform App IDs.
Set-OrganizationConfig -EwsAllowedAppIDs "<Existing-App-ID-1>,<Existing-App-ID-2>,<Druva-App-ID-1>,<Druva-App-ID-2>"
❗IMPORTANT: Copy every existing App ID exactly. Any App ID you leave out is removed from the allow list, and that application is blocked from EWS.
3.3 Option B: Merge with PowerShell (recommended)
This reads the live value, adds only the missing Cloud Platform App IDs, and writes the combined list back. It also handles an empty list and skips App IDs that are already present. Replace the placeholders with the App IDs from Step 2.2.
# Druva App IDs from Step 2.2 $druvaAppIds = @( '<druva-app-id-1>', '<druva-app-id-2>' ) # Current list (Step 1) $currentValue = (Get-OrganizationConfig -RetrieveEwsOperationAccessPolicy).EwsAllowedAppIDs $existing = @($currentValue -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ }) Write-Host "Current list (save for rollback): $currentValue" # Druva App IDs not in the current list (-notcontains is case-insensitive) $missing = @($druvaAppIds | Where-Object { $existing -notcontains $_ }) if ($missing.Count -eq 0) { Write-Host "All Druva App IDs are already present. No change needed." } else { $merged = ($existing + $missing) -join ',' Write-Host "Adding: $($missing -join ', ')" Write-Host "New list: $merged" Set-OrganizationConfig -EwsAllowedAppIDs $merged }
3.4 Confirm the list before you continue
Get-OrganizationConfig -RetrieveEwsOperationAccessPolicy | Format-List EwsAllowedAppIDs
Confirm that every Cloud Platform App ID from Step 2.2 and every App ID from Step 1 is in the list. Do not continue to Step 4 until it is.
3.5 Rollback
If the list was not blank in Step 1, restore the value you saved:
Set-OrganizationConfig -EwsAllowedAppIDs "<value saved in Step 1>"
If the list was blank in Step 1, do not clear it once EWS is enabled. While EwsEnabled is True, an empty list blocks all EWS traffic, including Cloud Platform's.
Step 4: Verify and enable EWS globally
The organization-wide setting determines whether EWS is available at all. Enabling it also turns on enforcement of the list you prepared in Step 3.
4.1 Check the current configuration
Get-OrganizationConfig | Select-Object EwsEnabled
Possible output:
EwsEnabled : True
or
EwsEnabled :
If the value is already True, no change is needed. Go to the verification checklist.
Changes to EwsAllowedAppIDs can take up to 24 hours to reach every Exchange Online server. If EwsEnabled is currently blank and EWS is working, you can wait up to 24 hours after Step 3 before you run 4.2. This makes it less likely that EWS access is briefly interrupted for applications in the list.
4.2 Enable EWS (if False or blank)
Set-OrganizationConfig -EwsEnabled $true
4.3 Verify
Get-OrganizationConfig | Select-Object EwsEnabled
Expected:
EwsEnabled : True
Verification checklist
Check 1: EWS is enabled
Get-OrganizationConfig | Select-Object EwsEnabled
✅ EwsEnabled is True.
Check 2: All Cloud Platform App IDs are in EwsAllowedAppIDs
Get-OrganizationConfig -RetrieveEwsOperationAccessPolicy | Format-List EwsAllowedAppIDs
Or check each Cloud Platform App ID automatically. This uses $druvaAppIds from Step 3.3, so run it in the same PowerShell session.
$allowed = @((Get-OrganizationConfig -RetrieveEwsOperationAccessPolicy).EwsAllowedAppIDs -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ }) $druvaAppIds | ForEach-Object { [pscustomobject]@{ AppId = $_; Present = ($allowed -contains $_) } } | Format-Table✅ Every Cloud Platform App ID shows Present = True.
✅ Every App ID that was in the list in Step 1 is still there.
Troubleshooting
Symptom | Likely cause |
Cloud Platform still cannot reach EWS right after the change |
|
HTTP 403 with header |
|
HTTP 403 with header | The Cloud Platform App ID is not in |
Other EWS applications stopped working after the change | They are not in |
| Add - |
Option 2: Configure EWS using the script
The script runs Steps 1 to 4 of this guide, in the same order, and then runs the verification checklist. It saves the current EwsAllowedAppIDs list to a backup file before it makes any change.
Run these steps with a script
The script runs Steps 1 to 4 of this guide, in the same order, and then runs the verification checklist. It saves the current EwsAllowedAppIDs list to a backup file before it makes any change.
Run the script
The commands below assume you saved the Full script as ews_druva_allowed_appids.ps1.
Open Azure Cloud Shell (PowerShell) or PowerShell 7+.
Preview the changes. The script writes nothing.
./ews_druva_allowed_appids.ps1 -WhatIf -v
Run all steps. The script asks you to confirm each change.
./ews_druva_allowed_appids.ps1 -vCheck the verification output at the end of the run. A successful run ends with [OK] Verification passed. If a check fails, the script shows a [FAIL] line and exits with code 1.
To skip the confirmation prompts, add -Confirm:$false.
To follow the 24-hour wait in 4.1, decline the prompt to set EwsEnabled, then run the script again after the wait. The first run reports [FAIL] EwsEnabled = '', which is expected. The second run makes no list change and turns on EWS.
Parameters
Parameter | Description |
| Display-name prefixes used to find the Cloud Platform applications. Matching is case-sensitive. Default: |
| Optional. Tenant ID to sign in to with Azure CLI, and to check the Exchange Online session against. |
| Uses device-code sign-in for Exchange Online and Azure CLI (for machines without a browser). |
| Folder for the backup of the current list. Default: $HOME |
| Shows detailed output. |
| Shows what would change. Writes nothing. |
| Runs all steps without prompting. |
| Shows help and exits. |
Script behavior
Stage | What the script does |
Sign-in | Reuses existing Exchange Online and Azure CLI sessions, and signs in only when none exists. In Azure Cloud Shell, Azure CLI is already signed in, and Exchange Online falls back to device code. Outside Cloud Shell, it uses browser sign-in, or device code with |
Tenant check | Stops if Exchange Online and Azure CLI are signed in to different tenants. Otherwise, App IDs from one tenant would be written into another tenant's allow list. |
Step 1 | Saves the current list to |
Step 2 | Skips Microsoft first-party applications. Prefixes such as |
Step 3 | Uses Option B (3.3). |
Before Step 4 | Reads the list again. If any App ID is missing, stops and does not change |
Step 4 | Makes no change if |
Verification | Runs Check 1 and Check 2, and checks that no existing App ID was removed. |
End of run | If the list changed and was not empty, shows the rollback command: |
Script troubleshooting
Script message | Action |
Azure CLI (az) not found. | Use Azure Cloud Shell or install Azure CLI. |
Azure CLI sign-in failed. | Sign in again, or use |
Exchange Online (...) and Azure CLI (...) are signed in to different tenants. | Sign in to the same tenant and re-run. |
Exchange Online is signed in to tenant ..., not ... | Sign in to the tenant passed in - |
Set-OrganizationConfig is not available. | Sign in with an Exchange Administrator account. |
Set-OrganizationConfig does not accept -EwsAllowedAppIDs in this tenant yet. | Microsoft's rollout has not reached the tenant; try again later. |
az ad sp list failed. | Check that you have Directory Readers or higher. |
No Druva applications found for prefixes: ... | Check the names (matching is case-sensitive). Set them with |
Druva App IDs are not in the list: ... EwsEnabled was not changed. | Repeat Check 2. EWS was not turned on. |
Script
<# .SYNOPSIS Adds Druva's App IDs to EwsAllowedAppIDs without removing existing entries, then turns on EWS for the tenant. .DESCRIPTION Automates docs/EWS_Druva_AllowedAppIds_Guide.md, in the same order: 1. Reads the current EwsAllowedAppIDs list and saves it to a backup file. 2. Finds Druva's App IDs in the tenant's Enterprise Applications (az ad sp list, name-prefix filter), excluding Microsoft first-party applications. 3. Adds the missing Druva App IDs. Set-OrganizationConfig -EwsAllowedAppIDs replaces the whole list, so the script reads the current list, appends the missing IDs, and writes the full value back. If the list is empty, it is populated with the Druva App IDs. 4. Sets EwsEnabled to $true, only after the list is confirmed to contain every Druva App ID. 5. Verifies EwsEnabled is True, every Druva App ID is in the list, and no existing App ID was removed. The list is updated before EWS is turned on because EwsAllowedAppIDs is enforced only once EwsEnabled is True. Turning on EWS first with an empty list would block all EWS traffic, including Druva's. Changes to EwsAllowedAppIDs can take up to 24 hours to take effect; changes to EwsEnabled up to 4 hours. Sign-in: - Reuses existing Exchange Online and Azure CLI sessions; signs in only when there is none. - In Azure Cloud Shell, Azure CLI is already signed in. Exchange Online falls back to device code. - Outside Cloud Shell, uses browser sign-in, or device code with -UseDeviceCode. - Stops if Exchange Online and Azure CLI are signed in to different tenants. - Disconnects Exchange Online at the end only if this script opened the session. Requirements: - Azure Cloud Shell (PowerShell) or PowerShell 7+ - ExchangeOnlineManagement module (installed automatically if missing) - Azure CLI (az) - Exchange Administrator (to change the org config) and Directory Readers or higher (to list Enterprise Applications) .PARAMETER NamePrefixes Display-name prefixes used to find Druva applications. Matching is case-sensitive. Default: 'Druva Exchange', 'Office 365' .PARAMETER TenantId Optional. Tenant ID to sign in to with Azure CLI, and to check the Exchange Online session against. .PARAMETER UseDeviceCode Use device-code sign-in for Exchange Online and Azure CLI (for machines without a browser). .PARAMETER BackupFolder Folder for the backup of the current list. Default: $HOME .PARAMETER v Verbose output. .PARAMETER Help Show help and exit. .EXAMPLE ./ews_druva_allowed_appids.ps1 -WhatIf -v Show what would change. Nothing is written. .EXAMPLE ./ews_druva_allowed_appids.ps1 -v Run all steps. Prompts before each change. .EXAMPLE ./ews_druva_allowed_appids.ps1 -Confirm:$false Run all steps without prompting. .EXAMPLE ./ews_druva_allowed_appids.ps1 -UseDeviceCode -TenantId 00000000-0000-0000-0000-000000000000 Sign in with device code to a specific tenant. .NOTES Source: https://techcommunity.microsoft.com/blog/exchange/introducing-ewsallowedappids-preparing-for-the-final-phase-of-ews-retirement/4529471 #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param( [string[]]$NamePrefixes = @('Druva inSync Exchange', 'Druva M365'), [string]$TenantId = "", [switch]$UseDeviceCode, [string]$BackupFolder = "$HOME", [switch]$v, [switch]$Help ) if ($Help) { Get-Help $MyInvocation.MyCommand.Path -Detailed exit 0 } $ErrorActionPreference = 'Stop' # Owner tenants of Microsoft first-party applications. Prefixes such as 'Office 365' also match these. $MicrosoftTenantIds = @('f8cdef31-a31e-4b4a-93e4-5f571e91255a', '72f988bf-86f1-41af-91ab-2d7cd011db47') $IsCloudShell = ($env:AZUREPS_HOST_ENVIRONMENT -like 'cloud-shell*') -or [bool]$env:ACC_CLOUD function Write-Info($msg) { if ($v) { Write-Host "[INFO] $msg" -ForegroundColor Cyan } } function Write-Ok($msg) { Write-Host "[OK] $msg" -ForegroundColor Green } function Write-Warn($msg) { Write-Host "[WARN] $msg" -ForegroundColor Yellow } function Write-Fail($msg) { Write-Host "[FAIL] $msg" -ForegroundColor Red } function Get-AllowedAppIds { # EwsAllowedAppIDs is only returned with -RetrieveEwsOperationAccessPolicy. $raw = (Get-OrganizationConfig -RetrieveEwsOperationAccessPolicy).EwsAllowedAppIDs @($raw -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ }) } # ----- 0. Prerequisites --------------------------------------------------- if (-not (Get-Command az -ErrorAction SilentlyContinue)) { throw "Azure CLI (az) not found. Use Azure Cloud Shell or install Azure CLI." } if (-not (Get-Module -ListAvailable ExchangeOnlineManagement)) { Write-Info "Installing ExchangeOnlineManagement module..." Install-Module ExchangeOnlineManagement -Scope CurrentUser -Force } Import-Module ExchangeOnlineManagement -ErrorAction Stop Write-Info "Environment: $(if ($IsCloudShell) { 'Azure Cloud Shell' } else { 'Local PowerShell' })" # ----- Sign in: Azure CLI ------------------------------------------------- Write-Info "Checking Azure CLI sign-in..." $azAccount = az account show -o json 2>$null if ($LASTEXITCODE -ne 0 -or ($TenantId -and (($azAccount -join "`n") | ConvertFrom-Json).tenantId -ne $TenantId)) { Write-Info "Signing in to Azure CLI..." $azArgs = @('login', '--allow-no-subscriptions', '-o', 'none') if ($TenantId) { $azArgs += @('--tenant', $TenantId) } if ($UseDeviceCode -or $IsCloudShell) { $azArgs += '--use-device-code' } az @azArgs if ($LASTEXITCODE -ne 0) { throw "Azure CLI sign-in failed." } $azAccount = az account show -o json } $azTenantId = (($azAccount -join "`n") | ConvertFrom-Json).tenantId Write-Info "Azure CLI tenant: $azTenantId" # ----- Sign in: Exchange Online ------------------------------------------- Write-Info "Checking Exchange Online sign-in..." $exoOpenedByScript = $false $exoConnection = $null try { $exoConnection = Get-ConnectionInformation -ErrorAction SilentlyContinue | Where-Object { $_.State -eq 'Connected' } | Select-Object -First 1 } catch { } if (-not $exoConnection) { Write-Info "Signing in to Exchange Online..." if ($UseDeviceCode) { Connect-ExchangeOnline -Device -ShowBanner:$false -ErrorAction Stop } else { try { Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop } catch { Write-Warn "Sign-in failed, trying device code." Connect-ExchangeOnline -Device -ShowBanner:$false -ErrorAction Stop } } $exoOpenedByScript = $true $exoConnection = Get-ConnectionInformation | Where-Object { $_.State -eq 'Connected' } | Select-Object -First 1 } else { Write-Info "Using existing Exchange Online session ($($exoConnection.UserPrincipalName))." } try { # Both sessions must point at the same tenant, otherwise App IDs from one tenant # would be written into another tenant's allow list. $exoTenantId = "$($exoConnection.TenantID)" Write-Info "Exchange Online tenant: $exoTenantId" if ($exoTenantId -and $exoTenantId -ne $azTenantId) { throw "Exchange Online ($exoTenantId) and Azure CLI ($azTenantId) are signed in to different tenants. Sign in to the same tenant and re-run." } if ($TenantId -and $exoTenantId -and $exoTenantId -ne $TenantId) { throw "Exchange Online is signed in to tenant $exoTenantId, not $TenantId." } # Missing cmdlet or parameter means the account lacks the role, or Microsoft's rollout has not reached the tenant. $setCmd = Get-Command Set-OrganizationConfig -ErrorAction SilentlyContinue if (-not $setCmd) { throw "Set-OrganizationConfig is not available. Sign in with an Exchange Administrator account." } if (-not $setCmd.Parameters.ContainsKey('EwsAllowedAppIDs')) { throw "Set-OrganizationConfig does not accept -EwsAllowedAppIDs in this tenant yet. Microsoft's rollout has not reached it; try again later." } # ----- Step 1: current list ------------------------------------------- Write-Host "`n== Step 1: Current EwsAllowedAppIDs ==" -ForegroundColor Cyan $existing = Get-AllowedAppIds if ($existing.Count -eq 0) { Write-Host " (empty)" } else { $existing | ForEach-Object { Write-Host " $_" } } $backupPath = Join-Path $BackupFolder ("EwsAllowedAppIDs-backup-{0}.txt" -f (Get-Date -Format 'yyyyMMdd-HHmmss')) ($existing -join ',') | Out-File -FilePath $backupPath -Encoding ASCII Write-Host "Current list saved to $backupPath" # ----- Step 2: Druva App IDs ------------------------------------------ Write-Host "`n== Step 2: Druva App IDs from Enterprise Applications ==" -ForegroundColor Cyan $conditions = ($NamePrefixes | ForEach-Object { "starts_with(displayName, '$($_ -replace "'", "''")')" }) -join ' || ' $query = "[?$conditions].{Name:displayName,AppId:appId,Owner:appOwnerOrganizationId}" Write-Info "Listing Enterprise Applications (can take a few minutes in large tenants)..." $json = az ad sp list --all --query $query -o json if ($LASTEXITCODE -ne 0) { throw "az ad sp list failed. Check that you have Directory Readers or higher." } $found = @(($json -join "`n") | ConvertFrom-Json) foreach ($s in @($found | Where-Object { $MicrosoftTenantIds -contains $_.Owner })) { Write-Info "Skipping Microsoft first-party app: $($s.Name) ($($s.AppId))" } $found = @($found | Where-Object { $MicrosoftTenantIds -notcontains $_.Owner }) if ($found.Count -eq 0) { throw "No Druva applications found for prefixes: $($NamePrefixes -join ', '). Check the names (matching is case-sensitive)." } $found | Format-Table Name, AppId -AutoSize | Out-String | Write-Host $druvaAppIds = @($found.AppId | Where-Object { $_ } | Sort-Object -Unique) # ----- Step 3: add missing, keep existing ----------------------------- Write-Host "`n== Step 3: Add missing Druva App IDs ==" -ForegroundColor Cyan $missing = @($druvaAppIds | Where-Object { $existing -notcontains $_ }) $listUpdated = $false if ($missing.Count -eq 0) { Write-Ok "All Druva App IDs are already in EwsAllowedAppIDs. No change needed." } else { Write-Host "Missing: $($missing -join ', ')" if ($existing.Count -eq 0) { Write-Warn "The list is empty. Once EWS is on, only the applications in the list can use EWS." } $merged = ($existing + $missing) -join ',' Write-Host "New list: $merged" if ($PSCmdlet.ShouldProcess('EwsAllowedAppIDs', "Write $($existing.Count + $missing.Count) App IDs (adds $($missing.Count))")) { Set-OrganizationConfig -EwsAllowedAppIDs $merged $listUpdated = $true Write-Ok "EwsAllowedAppIDs updated." } } if ($WhatIfPreference) { Write-Host "`n== Step 4: Turn on EWS ==" -ForegroundColor Cyan Write-Host "What if: EwsEnabled would be set to True if it is not already." Write-Warn "-WhatIf: nothing was changed, so verification is skipped." return } # Do not turn on EWS unless the list holds every Druva App ID. $allowedNow = Get-AllowedAppIds $stillMissing = @($druvaAppIds | Where-Object { $allowedNow -notcontains $_ }) if ($stillMissing.Count -gt 0) { throw "Druva App IDs are not in the list: $($stillMissing -join ', '). EwsEnabled was not changed." } # ----- Step 4: EwsEnabled --------------------------------------------- Write-Host "`n== Step 4: Turn on EWS ==" -ForegroundColor Cyan $ewsEnabled = (Get-OrganizationConfig).EwsEnabled Write-Host "Current EwsEnabled: '$ewsEnabled'" if ($ewsEnabled -eq $true) { Write-Ok "EwsEnabled is already True." } elseif ($PSCmdlet.ShouldProcess('Organization config', 'Set EwsEnabled to $true')) { Set-OrganizationConfig -EwsEnabled $true Write-Ok "EwsEnabled set to True." } # ----- Verification --------------------------------------------------- Write-Host "`n== Verification ==" -ForegroundColor Cyan $failed = $false $ewsNow = (Get-OrganizationConfig).EwsEnabled if ($ewsNow -eq $true) { Write-Ok "EwsEnabled = True" } else { Write-Fail "EwsEnabled = '$ewsNow'"; $failed = $true } $allowedNow = Get-AllowedAppIds foreach ($id in $druvaAppIds) { if ($allowedNow -contains $id) { Write-Ok "Druva App ID present: $id" } else { Write-Fail "Druva App ID missing: $id"; $failed = $true } } foreach ($id in $existing) { if ($allowedNow -notcontains $id) { Write-Fail "Existing App ID was removed: $id"; $failed = $true } } if ($listUpdated) { if ($existing.Count -gt 0) { Write-Host "To undo the list change: Set-OrganizationConfig -EwsAllowedAppIDs (Get-Content '$backupPath')" } else { Write-Host "The list was empty before. Do not clear it: once EWS is on, an empty list blocks all EWS traffic." } } Write-Warn "Changes to EwsAllowedAppIDs can take up to 24 hours to take effect, and EwsEnabled up to 4 hours." if ($failed) { exit 1 } Write-Ok "Verification passed." } finally { if ($exoOpenedByScript) { Write-Info "Disconnecting the Exchange Online session opened by this script..." Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue } }