Photo by Anthony Shkraba on


This article will help to fetch Office 365 service status programmatically and send an email if there is a service degradation because of an incident. You can schedule this to run every few minutes.

Create Application in Azure

  • Login to with Global Admin credentials.
  • Navigate to Azure Active Directory > App registrations and click on New registration.
  • You can refer below screenshots for application config and permission required.
  • Creating App :
  • API Permission
  • You will need Client ID, Tenant ID and Client Secret as shown below for the script on respective options :

Folder Structure & Script

  • Create a folder on this path : C:\Script\O365_Outage
  • Save below text as Outage.ps1
  • This script is only looking for outages related to “Exchange Online” and “Microsoft 365 suite“. If you want to include more services, refer output of $ServiceStatus.Value and modify $outage variable.
  • Credits goes to : for the basics of this script.
#API Page
#Force TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Update these based on your App.
$TenantID = 'TypeTenantID' #The Directory ID from Azure AD
$ClientID = 'TypeAppID' #The Application ID of the registered app
$ClientSecret = 'TypeClientSecret' #The secret key of the registered app

$body = @{grant_type="client_credentials";resource="";client_id=$ClientID;client_secret=$ClientSecret }
$oauth = Invoke-RestMethod -Method Post -Uri "$($tenantID)/oauth2/token?api-version=1.0" -Body $body
#$oauth = Invoke-RestMethod -Uri$tenantId/oauth2/v2.0/token -body $body -Method POST
$token = @{'Authorization' = "$($oauth.token_type) $($oauth.access_token)" }

# Retrieve Office 365 Service Status
$ServiceStatus = Invoke-RestMethod -Uri "$($TenantID)/ServiceComms/Messages" -Headers $token -Method Get -Verbose
# filtering the status values and you can modify these combinations for your purpose.
$outage = $ServiceStatus.Value | Where-Object {(($_.Status -eq "Service degradation") -AND ($_.classification -eq "Incident") -AND (($_.WorkloadDisplayName -eq "Exchange Online") -OR ($_.WorkloadDisplayName -eq "Microsoft 365 suite")))} | Select ID,WorkloadDisplayName,Status,Classification, ImpactDescription

# construct file name for the html output
cd C:\Script\O365_Outage
$d = (Get-Date).ToString('yyyyMMddTHHmm')
$html = "C:\Script\O365_Outage\O365_Outage_" + $d + ".htm"
$html_head = "<style type='text/css'> 
table {font-family:verdana,arial,sans-serif;font-size:12px;color:#333333;border-width: 1px;border-color: #729ea5;border-collapse: collapse;} 
th {font-family:verdana,arial,sans-serif;font-size:12px;background-color:#acc8cc;border-width: 1px;padding: 8px;border-style: solid;border-color: #729ea5;text-align:left;} 
tr {font-family:verdana,arial,sans-serif;background-color:#d4e3e5;} 
td {font-family:verdana,arial,sans-serif;font-size:12px;border-width: 1px;padding: 8px;border-style: solid;border-color: #729ea5;} 

# exporting outage detail to HTML for futher email sending
$outage | ConvertTo-Html -head $html_head -Property ID,WorkloadDisplayName,Status,Classification,ImpactDescription  | out-file $html

Function send_mail([string]$message,[string]$subject) { 
    $emailFrom = "" 
    $emailTo = "" 
    $smtpServer = "" 
    $Subject = "Office 365 Outage Alert"
    $message = Get-Content $html | out-string
    Send-MailMessage -SmtpServer $smtpServer -To $emailTo -From $emailFrom -Subject $subject -Body $message -BodyAsHtml 
If ($outage -ne $null)
    send_mail $message $subject 
else { 

Thank you for reading !