Skip to content

Repository files navigation

EWS-App-Identifier

A PowerShell module that identifies the applications hitting Exchange Web Services (EWS) against your tenant, using Microsoft's EWS Usage report as input.

Microsoft is retiring EWS in Exchange Online in two phases. On October 1, 2026, tenants that haven't explicitly configured EWSEnabled will be switched to blocked by default - Microsoft's phased, admin-controllable disablement plan described in Exchange Online EWS, Your Time is Almost Up. Full, permanent shutdown follows on April 1, 2027. In between, Microsoft is rolling out EWSAllowedAppIDs - an allow list letting admins keep specific applications working past the October cutoff.

Building that allow list means knowing exactly which App IDs are still calling EWS and what they are - which is exactly what this module does. The EWS Usage report shows you which App IDs are calling EWS and how often, but it only gives you GUIDs. This module resolves those GUIDs to actual application names so you know what to migrate, decommission, add to your allow list, or leave alone.

Why this exists

Cross-referencing a list of App IDs against "is this Microsoft, a known ISV, or something in my own tenant" is a task every IT pro doing EWS remediation runs into. Instead of everyone solving it from scratch, this module bundles:

  • A curated, versioned database of known App IDs (first-party Microsoft apps, common ISVs like backup/CRM/migration tools) that works completely offline
  • An optional live Entra ID lookup for anything not in the database, resolved against your tenant's own app registrations
  • Aggregate reporting (total calls, top operations, first/last seen) instead of raw per-row CSV data
  • Risk flagging so high-volume unidentified apps bubble to the top of your list
  • A privacy-safe export that strips your TenantID before you share a report or open a GitHub issue asking "what's App ID X?"

Getting the EWS Usage report

  1. In the Microsoft 365 admin center, go to Health > Service health, or check the Exchange admin center's reporting section for the EWS usage report.
  2. Alternatively, Microsoft has been rolling this out via Entra ID Recommendations and direct download links referenced in Message Center posts about EWS retirement.
  3. The file downloads as EWSWeeklyUsage_<date>.csv with columns: TenantID, AppID, SoapAction, CallVolume, Date.

(If your tenant doesn't show this report yet, search the Microsoft 365 admin center for "EWS" or check Message Center — it's been staged out gradually.)

Installation

git clone https://github.com/peterschmidtdk/EWS-App-Identifier.git
Import-Module ./EWS-App-Identifier/EWSAppIdentifier.psd1

Or download the latest release as a zip, extract it, and Import-Module the .psd1 the same way.

Logging

Every function in this module writes to a log file by default - logs/EWSAppIdentifier_yyyyMMdd.log, rotating daily. Each entry records a timestamp, level, the function that wrote it, and what happened - report runs, exports, database updates, Graph lookups, and any errors along the way.

# Check current logging status and file path
Get-EWSLogPath

# View the last 25 entries
Get-EWSLogPath -Tail 25

# Turn logging off, or point it somewhere else
Set-EWSLogging -Enabled $false
Set-EWSLogging -Path 'C:\IT\Logs\EWSAppIdentifier'

In the interactive menu, option [9] shows recent log entries and [L] toggles logging on/off. The log directory is excluded from git via .gitignore - it's local activity data, not something to commit.

Logging failures (e.g. an unwritable log directory) never break the actual tool - they print a one-time warning and silently disable logging for the rest of the session rather than throwing.

Turning logging off (or redirecting it to a different path) only affects future entries - existing log files are never deleted, truncated, or modified. Logs are kept indefinitely for audit/compliance purposes; retention/cleanup is a deliberate decision for whoever operates this tool, not something the module does on its own.

Quick start

Option A: cmdlets directly (scripting/automation)

# Don't have the path handy? Just run it - you'll get a file picker (GUI on Windows,
# or a console prompt that lists CSVs in the current folder anywhere else)
Get-EWSAppReport

# Offline mode - resolves against the bundled known-app database only, no auth needed
Get-EWSAppReport -Path .\EWSWeeklyUsage_7_30_2026.csv | Format-Table -AutoSize

# With live Entra lookup for anything not in the local database
Connect-MgGraph -Scopes "Application.Read.All"
Get-EWSAppReport -Path .\EWSWeeklyUsage_7_30_2026.csv -UseGraph |
    Sort-Object TotalCalls -Descending |
    Format-Table AppId, Name, Publisher, TotalCalls, RiskFlag -AutoSize

# Focus on what actually needs attention
Get-EWSAppReport -Path .\ews-usage.csv -UseGraph |
    Where-Object RiskFlag -ne 'OK'

# Export a shareable report with your TenantID stripped (default)
Get-EWSAppReport -Path .\ews-usage.csv |
    Export-EWSAppReport -Path .\findings.csv

Option B: interactive menu (no scripting required)

.\Start-EWSAppIdentifier.ps1

Shows a banner with your session state (Entra connection, database size, last report), then a menu to run a report, view/export it, look up a single App ID, refresh the known-app database, or connect to Entra ID - all without touching cmdlet syntax. Every menu action is just a thin wrapper over the module functions above, so you can move to direct cmdlet use any time.

Sample output

Illustrative only — App IDs, names, and publishers below are fictional (Contoso/Fabrikam), not entries from the bundled database:

AppId                                Name                      Publisher   TotalCalls  RiskFlag
-----                                ----                      ---------   ----------  --------
4f6e2a91-8c3d-4b7a-9e15-2d8f61a4c9b7 Unidentified              -           59988       INVESTIGATE - high volume, unidentified
8a2c5e14-6f39-4d82-b1a7-3c9e0f7d5a62 Contoso Backup Tool       Contoso     9984        Verify - third-party ISV
c1d4f8a3-7b2e-4916-9a5c-8e3f61d2b479 Fabrikam Sync Connector   Fabrikam    14620       OK

Functions

Function Purpose
Import-EWSUsageReport Loads and validates the raw CSV
Resolve-EWSAppId Resolves a single App ID (known-db → optional live Entra → unidentified)
Get-EWSAppReport Main entry point — aggregated, identified, risk-flagged report
Export-EWSAppReport CSV export with TenantID scrubbed/hashed by default
Update-KnownAppIdDatabase Pulls the latest community-contributed known-appids.json
Write-EWSLog Writes a timestamped entry to the module's log file
Set-EWSLogging Enable/disable logging, or change the log directory
Get-EWSLogPath Check logging status and view recent entries

Run Get-Help <function> -Full for complete parameter docs and examples.

Contributing an App ID

Found an App ID that shows up in your EWS report but isn't in data/known-appids.json? Once you've identified it — via Get-MgServicePrincipal, publisher documentation, or a support case — please open a PR adding it:

"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx": {
  "name": "Vendor Product Name",
  "publisher": "Vendor",
  "type": "third-party-isv",
  "notes": "Short description of what it does and why it calls EWS.",
  "source": "how you identified it (vendor docs, support case, etc.)"
}

Valid type values: first-party (Microsoft), third-party-isv, tenant-registered (only relevant for illustrative/example entries — real tenant-registered apps should never be committed here, since they're specific to one organization).

Please don't include tenant-specific App IDs, internal app names, or anything from a private Entra tenant — this file is meant to be universally useful, not a record of any specific organization's app inventory.

Privacy note

The EWS Usage report includes your TenantID on every row. Export-EWSAppReport strips it by default. If you're sharing a report snippet in a GitHub issue or forum post asking for help identifying an App ID, double-check you're using the scrubbed export — or just share the AppId column value, which is what people actually need to help you.

Requirements

  • PowerShell 5.1+ or PowerShell 7+
  • Microsoft.Graph.Applications module (only required for -UseGraph)
  • Application.Read.All Graph scope for live tenant lookups

Related reading

License

MIT — see LICENSE.

About

PowerShell module that identifies what's calling Exchange Web Services in your tenant, because the EWS Usage report gives you App IDs, not app names, and EWS itself is gone Oct 1, 2026.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages