In the early days of Office 365, back when FOPE was a thing, a nifty little feature existed that allowed customers to schedule some of the available reports. In time, FOPE got replaced by EOP and the feature was brought over to the Office 365 Admin Center, as part of the “Security & Compliance” reports (powered by the EOP backend). That didn’t last long either, and those reports were first moved to the SCC, then split between the standalone Compliance and Security portals. Nowadays, you can find most of them under the Defender portal, whereas the new and supposedly “improved” Purview portal does not feature a separate reports page anymore, so any existing reports are buried few clicks deep. The one remaining schedulable report can be found in the new EAC.
As an example of the type of report you can have delivered on a scheduled cadence, here is a screenshot of the good old Mail traffic report (sadly, no longer available) delivered directly in my mailbox. At a glance, you can get the visualization of mail traffic for the previous week, along with a breakdown of the numbers of messages received. The bottom section of the email gives you the list of top senders and recipients. All delivered directly in your mailbox, one per week.
The report schedule feature effectively allows you to deliver “snapshots” of certain reports via email, on a selected cadence. It resonates quite well with C-suites and RACI stakeholders that don’t usually have access to the UI bits, or cannot be bothered to login to multiple separate portals to access the data. It is still puzzling to me why Microsoft never expanded the feature to cover all available reports, and barely mentions it in the documentation. In contrast, many of the ISVs in the Microsoft 365 reporting space provide similar scheduling capabilities, and advertise them heavily. And, those “snapshots” can also be quite useful for historical overview purposes.
Despite my criticism above, I consider the report schedule feature one of the hidden gems of the Microsoft 365 suite, so I am grad it is still around. The feature has not received any updates in the past few years, but some of the supported reports have been deprecated, replaced or shuffled around since the last time I wrote about it (back in 2015), so it is due for another look. Moreover, it looks like Microsoft has scrapped most of the articles that detailed the feature and nowadays you can only find instructions on how to schedule the Email security reports. Documentation on the underlying Exchange Online PowerShell cmdlets is nowhere to be found either… all the more reason to publish an article around this!
So let’s dig right in. In a nutshell, report schedules are managed via a set of Exchange Online PowerShell cmdlets, as is the case for most “legacy” features. A schedule is basically a set of metadata telling the backend which report to execute on what cadence, and where to send the output. The good old admin.protection.outlook.com backend is still used for the feature, as well as its sibling Request report feature, which in turn explains the dependence on ExO PowerShell cmdlets. Speaking of cmdlets, those include:
- Get-ReportScheduleList, used to list all report schedules within the tenant.
- Get-ReportSchedule, which lists details for a particular scheduled report. As you can get the same set of details via the Get-ReportScheduleList cmdlet, without the need to provide an id value, you can pretty much ignore this cmdlet.
- New-ReportSchedule is used to create a new report schedule.
- Set-ReportSchedule can be used to modify the properties of a an existing schedule.
- Remove-ReportSchedule to remove a report schedule that is no longer needed.
- Get-ReportExecutionInstance can be used to list all instances where a scheduled report was executed over the past year. Yes, it goes back an year, which is pretty generous considered the limited window most other features within O365 cover.
Here is an example of a scheduled report’s properties, as obtained via the Get-ReportScheduleList cmdlet:
ScheduleId : 8999e40e-ab95-471e-a5cf-6ec78a91066d Identity : 8999e40e-ab95-471e-a5cf-6ec78a91066d OrganizationId : 923712ba-352a-4eda-bece-09d0684d0cfb ScheduleName : Weekly Mail Traffic Report ReportType : MailTraffic ReportFrequency : Weekly Direction : All ExpiryDate : 01/01/2025 00:00:00 Locale : en-US NotificationEmail : {user@domain.com} FileUrls : {} SenderAddress : RecipientAddress : DLPPolicy : TransportRule : ReportLastRunTime : 19/10/2022 18:26:16 ReportStatusDescription : Active StartDate : 14/05/2021 00:00:00 EncryptionType : All EncryptionTemplate : All
This gives us all the relevant properties, and thus the corresponding parameters to use with the PowerShell cmdlets. Here are some additional details on the most important ones, ordered by PowerShell parameter position value:
- Direction is a filter parameter and defines the directionality of the report you’re scheduling. Available values include: Inbound, Outbound and All, with All being the default value. The property is mandatory when creating most schedules.
- DlpRuleId signifies the DLP rule against which to run the report, and is applicable only to (some of) the DLP-related reports. Well, all of them are deprecated now. So you can ignore this parameter.
- EncryptionTemplate is another optional one, relevant only to the Email encryption report (IRME). The value you specify here must correspond to one of the IRM templates available within your tenant, or All.
- EncryptionType is also optional and relevant only to the Email encryption report (IRME). This property defines which types of encrypted messages to include in the report: those encrypted by policy (EncryptionPolicy) or those encrypted manually (EncryptionManual), or both (All).
- ExpiryDate defines the end date for the schedule, i.e. when to stop sending the reports. Required for the cmdlet, but optional when using the UI. If you do not provide a value the schedule will span over one year, starting from today’s date.
- FileUrls can be used to optionally filter (some of) the (now deprecated) ATP reports.
- Identity gives you the unique identifier for the report schedule.
- IncludeDLP is a switch parameter, relevant only to the (now deprecated) DLP reports.
- Locale is an optional property, which defines the localization of the email notifications sent upon execution of report schedules.
- NotificationEmail defines the recipient(s) of the email notifications sent upon report schedule execution. This is a mandatory property, with value defaulting to the address of the user who created the schedule (when using the UI). You can specify more than one address here, although the UI only allows you to select internal addresses.
- RecipientAddress can be used to optionally filter (some of) the reports.
- ReportFrequency is another mandatory property, defining the schedule of the report’s execution. Available values include: Once, Daily, Weekly, Monthly, with Weekly being the default one.
- ReportLastRunTime is an informational property, giving you the datetime of the last execution of the report schedule.
- ReportStatusDescription gives you the status of the report. We do not have a matching parameter to update the status, so a report schedule can either be Active, or removed.
- ReportType defines which report you are creating a schedule for, and thus is a mandatory property. Available values include: MailTraffic, DLP, DLPActions, Rule, TopMalware, TopRuleMatches, TopSenderRecipient, SpoofDetections, UnifiedPolicyDLP, UnifiedOverridesDLP, UnifiedDLPIncident, ETR, DLPETR, IRME, UserCompromiseReport, UrlReport, TPSEmailMalware, TPSEmailPhish, MailFlowStatus, TPSEmailSpam, Zap, MailFlowStatusMailFlowView.
- ScheduleId is another unique identifier, and seems to always match the Identity value.
- ScheduleName gives you the name of the scheduled report. The property is mandatory when creating new schedules. You can have reports with duplicate names, as the Identity property is used as unique identifier.
- SenderAddress can be used to optionally filter (some of) the reports.
- StartDate defines the start date for the schedule, i.e. from which date to start sending the reports. Required for the cmdlet, but optional when using the UI. If you do not provide a value, today’s date will be used.
- TransportRuleId is the last parameter, also an optional one. The corresponding property actually has the name of TransportRule, without the “id” part.
Based on the information presented above, we can now check out few examples of creating report schedules via PowerShell and the New-ReportSchedule cmdlet. We have few mandatory parameters to provide, most important of which is the type of report. Sadly, not all reports can be scheduled, but more on this later. For now, lets focus on some common scenarios, such as the Top senders and recipients report or the Mailflow status report. Both reports can be used to identify sudden spikes or drops in email activity, which in turn might indicate a compromised user or a more widespread issue with mail flow. You can use the following PowerShell cmdlets to create schedules for said reports:
#Create a schedule for the Top senders and recipients report New-ReportSchedule -ReportType TopSenderRecipient -Direction All -ReportFrequency Weekly -StartDate "01 Jan 2025" -ExpiryDate "01 Jan 2026" -NotificationEmail user@domain.com -ScheduleName "Mail flow status weekly report" #Create a schedule for the Mailflow status report New-ReportSchedule -ReportType MailFlowStatus -Direction All -ReportFrequency Weekly -StartDate "01 Jan 2025" -ExpiryDate "01 Jan 2026" -NotificationEmail user@domain.com -ScheduleName "Mail flow status weekly report"
By combining the two schedules, we can recreate the now deprecated Mail traffic report we saw on the screenshot above. In fact few other reports have been deprecated or replaced in the past years, so if you have existing scheduled, you might want to check on them. Of the newly introduced reports, security folks will likely find the Threat protection one most useful. In terms of creating a schedule for them however, the same set of parameters can be used, with just replacing the report type. Other reports, such as the UserCompromiseReport or the ZAP one require fewer parameters (i.e. –Direction is not needed). And some reports do require additional parameters, for example the Message encryption one:
#Create a schedule for the Message encryption report New-ReportSchedule -ReportType IRME -Direction All -ReportFrequency Weekly -StartDate "01 Jan 2025" -ExpiryDate "01 Jan 2026" -NotificationEmail user@domain.com -ScheduleName "Message encryption weekly" -EncryptionType All - EncryptionTemplate All
In addition, some reports can be scoped down by leveraging the set of filtering parameters, for example most of the mail flow related reports support filtering by sender (-SenderAddress) or recipient (-RecipientAddress). The –Direction parameter can be used to scope reports to just incoming our outgoing messages. And for the sake of completeness, let me add that working with the DLP reports requires the use of the –IncludeDLP switch (even though all the DLP reports are deprecated now):
#Create a report schedule for the DLP Actions report (deprecated now) New-ReportSchedule -Direction All -ReportType DLPActions -ReportFrequency Weekly -StartDate "01 Jan 2025" -ExpiryDate "01 Jan 2026" -NotificationEmail user@domain.com -ScheduleName "DLP Actions" -IncludeDLP #List all report schedules, including those related to DLP reports Get-ReportScheduleList -IncludeDLP
It is important to reiterate that not all values currently accepted by the –ReportType parameter are actually supported, some of the corresponding reports have been deprecated. For example, all of the DLP-related reports have been deprecated for few years now, but Microsoft is yet to reflect this in the cmdlet’s code. In the list below, I’ve marked any such values, whereas for reports that can currently be scheduled, I’ve provided a link to the corresponding page in the UI:
- MailTraffic – The now deprecated Mail traffic report. Replaced by the MailFlowStatus, MailFlowStatusMailFlowView and TopSenderRecipient reports
- DLP – Deprecated
- DLPActions – Deprecated
- DLPETR – Deprecated
- Rule – Deprecated
- TopMalware – The Top malware report
- TopRuleMatches – Deprecated
- TopSenderRecipient – The Top senders and recipients report
- SpoofDetections – The Spoof mail report
- UnifiedPolicyDLP – Deprecated
- UnifiedOverridesDLP – Deprecated
- UnifiedDLPIncident – Deprecated
- ETR – The Exchange Transport rule report
- IRME* – The Microsoft 365 Message encryption report
- UserCompromiseReport – The Compromised users report
- UrlReport – The URL Threat protection report
- TPSEmailMalware – The Email malware view of the Threat protection report
- TPSEmailPhish – The Email phish view of the Threat protection report
- TPSEmailSpam – The Email spam view of the Threat protection report
- MailFlowStatus – The Mailflow status report
- MailFlowStatusMailFlowView – The Mailflow view of the Mailflow status report
- Zap – The Post-delivery activities report (aka the ZAP report)
The values marked with asterisk (*) correspond to reports that are still available in the UI, but might not be supported for scheduling (even though both the UI and PowerShell allows you to create a schedule for them). Unfortunately, Microsoft hasn’t been keeping the cmdlet up to date, and with the constant moves between various portals, some of the UI bits can also be outdated.
In the above list, you might notice that there is a single (O-N-E) Exchange Online report. In other words almost none of the reports available in the Exchange Admin Center or via Exchange Online PowerShell cmdlets can be scheduled. A shame, as reports such as the Auto forwarded messages one are top matches for this feature! Other workloads have sadly followed the same pattern, with almost all of the Compliance reports gone now, and the Microsoft 365 usage reports never supporting the scheduling functionality to begin with. Only the Defender suite seems to keep this functionality alive, even though not all of the reports available therein support it.
Speaking of which, the Defender reports are the only one that have actual documentation mentioning the scheduling feature. For each of the supported reports, you can use the UI within the Defender portal to create a new schedule, whereas existing schedules can be viewed and managed via the Reports > Email & Collaboration > Manage schedules page. Microsoft has done a fairly good job of describing the process in their documentation, so I will not go into any details here. What they do not cover is the underlying PowerShell bits, which should be the tool of choice for any partner or ISV looking to schedule any of the supported reports across multiple customer tenants. So hopefully this article will help with that!
Now that we understand how to use the New-ReportSchedule cmdlet and know the set of properties supported, remaining cmdlets are very straightforward to use. The Get- cmdlet can be used to see the properties of existing schedules and schedule executions in the past year. Set-ReportSchedule can be used to update (some of) the properties of existing schedules, and if you want to remove an existing schedule, you can leverage the Remove-ReportSchedule cmdlet. Still, the lack of help and documentation on the cmdlets usage is dissapointing.
In summary, in this article we reviewed the Exchange Online PowerShell cmdlets behind the report scheduling feature. It is yet another example of a nice feature that has been systematically neglected by Microsoft, but the good news is that is it still around and can provide you with an easy way to deliver any of the supported reports directly in the mailbox of any interested party, with minimum effort. Granted, you can build a more robust solution based on the available APIs, and in fact many ISV products in the reporting/management space offer similar functionalities. Those however usually come at a cost. So use this feature while you still can!
UPDATE 20/01/2025: Microsoft just released Roadmap update #377680, enabling a “lookalike” scheduling functionality for Communication compliance policies. Keep in mind that you will not find this functionality under the Communication Compliance > Reports page. Instead, you have to select/open a policy then hit the Export the report button on the top right corner. While there are some similarities in the scheduling experience, this functionality is not based on the good old *-ReportSchedule cmdlets, so you cannot use them to manage it. Some additional details can be found in the official documentation on the feature.