What is read, and what is never read. The script runs only Get-* cmdlets and sends: mail flow rules (name, state, mode, priority, the outside addresses they redirect/BCC/copy to, and the names of their conditions and actions), mailboxes that forward or have send-on-behalf delegates (address, display name, type, where they forward, whether a copy is kept, the delegates), mailbox Full Access and Send As grants that were added on purpose, your outbound spam policies’ auto-forwarding setting and who they apply to, remote domains and accepted domains. It never reads mail, folders, calendars or contacts, never sends the words a rule matches on or rule comments, and never changes anything.
Inbox rules are covered separately. Rules people create in Outlook (forward my mail to…) come from the Microsoft 365 integration through Microsoft Graph, with no extra setup; the “Inbox rules forwarding mail outside the company” check reads them.
What you need
- A Microsoft 365 tenant with Exchange Online, and an Azure subscription in the same tenant to hold the Automation account (its cost for one short daily job is typically zero to a few cents a month).
- A person who is a Global Administrator or Privileged Role Administrator (to grant the managed identity its two permissions in Step 3), and Contributor on the Azure subscription or resource group (Steps 2, 4 and 5).
- A ConfigView admin (Step 1).
Step 1: Create a ConfigView API key for the upload
- In ConfigView, go to Admin > Integrations and open API keys (or avatar menu → API Keys). See REST API for more on keys.
- Create key, name it
Exchange export runbook. - Under the allowed scopes, select all seven
Push: Exchange Online …entries (mail flow rules, mailbox forwarding + send on behalf, mailbox permissions, Send As grants, outbound spam policies, remote domains, accepted domains). Select nothing else. - Copy the key (
cv_live_…). It is shown once.
Step 2: Create the Automation account
- In the Azure portal, Create a resource → Automation.
- Pick the subscription, a resource group and a region, and a name such as
configview-exchange-export. On the Advanced tab leave System assigned managed identity on (the default). - Open the new account → Runtime Environments → Create: name
ps72-exo, language PowerShell, runtime 7.2. Under Packages, add from the gallery ExchangeOnlineManagement (version 3.x).
Step 3: Give the managed identity read-only Exchange access
The identity needs two things: Microsoft’s Exchange.ManageAsApp permission (lets an app sign in to Exchange Online PowerShell) and the Global Reader role (what it may read). Global Reader can read everything in the tenant and change nothing. 3a. Exchange.ManageAsApp. There is no portal button for managed identities; run this once in Azure Cloud Shell (PowerShell) or any PowerShell with the Microsoft Graph module, signed in as a Global Administrator or Privileged Role Administrator:Step 4: Add three variables
In the Automation account → Shared Resources → Variables → Add a variable:
Optional:
ConfigViewMaxMinutes (default 150), the time the script may spend before it stops. Full Access grants are read one mailbox at a time, so very large tenants (tens of thousands of mailboxes) may need longer; if the budget runs out the script sends everything else and skips that section rather than sending half of it.
Step 5: Import the script and schedule it
-
Download the script from your own ConfigView server (it always matches your server’s version):
https://{companyname}.configview.com/api/v1/ingest/exchange/runbook.ps1 -
In the Automation account → Process Automation → Runbooks → Import a runbook: upload
Invoke-ConfigViewExchangeExport.ps1, type PowerShell, runtime environment ps72-exo (Step 2). Publish it. -
Start it once and open the job’s Output: it lists each section with its item count and ends with
ConfigView export run … complete. - Link to schedule → Create a new schedule: once a day, at a quiet hour.
Step 6: Check it in ConfigView
Open Admin > Integrations → Exchange Online. The health check reads what arrived:- No export has arrived yet: the runbook has not run, or its uploads are refused. The job output shows the HTTP error.
- Sections missing / latest run is partial: one cmdlet failed (usually a missing role) or the time budget ran out. The other checks keep using the last complete export.
- Freshness warning: nothing arrived for 48 hours. Check the schedule and that the managed identity still holds its role.
How the upload works
Each run sends seven sections toPOST /api/v1/ingest/exchange.<section> on your server, authenticated with the API key. A large section is split into parts of up to 1.5 MB, and every part carries the same run id, so ConfigView only uses a run once all of its parts have arrived; a re-sent part is ignored. ConfigView keeps 30 days of runs.