How to Report Microsoft 365 Groups Expiration Dates

Viva Engage Communities Now Covered by Groups Expiration Policy

Updated 22 November 2024

A reader question about the Microsoft 365 Groups expiration policy caused me to review some PowerShell code I wrote to report the next renewal dates for the set of groups within the scope of the expiration policy. The question was related to Yammer (now Viva Engage), to know if the Microsoft 365 Group expiration policy covers the groups by Viva Engage and will remove inactive groups when necessary. The answer is yes; Microsoft updated policy processing last year to accommodate the Microsoft 365 groups used by Viva Engage (Yammer) communities when networks run in Microsoft 365 native mode.

In 2020, Microsoft changed the way the Microsoft 365 Groups expiration policy works to introduce automatic renewal. Instead of bothering group owners with email to remind them to renew the group, a background job looks for evidence that the group is active. If the evidence exists, Microsoft 365 renews the group automatically. Unfortunately, a limited set of signals govern renewal:

  • SharePoint Online: View, edit, download, move, share, or upload files.
  • Outlook: Join group, read/write message in the group mailbox, or like a message (in OWA).
  • Teams: Visit a Teams channel.
  • Viva Engage: View a post within a Viva Engage community or an interactive email in Outlook.

It’s debatable if a group is active if just one group member visits a Teams channel or views a post in a Viva Engage community. The Microsoft Graph gathers a wide array of signals about user activity and there’s surely a more precise method to determine group activity than the actions cited above. The Groups and Teams activity report is an example of how to code your own assessment of group activity.

In any case, the answer remains that you can add the Microsoft 365 groups used by Viva Engage communities to the Groups expiration policy through the Microsoft Entra admin center (Figure 1).

Defining groups to include in the expiration policy
Figure 1: Defining groups to include in the expiration policy

You can also add groups to the policy with PowerShell.

Tenants can choose to apply the Groups expiration policy to selected groups or to all Microsoft 365 groups in the tenant. Users who are members of the groups covered by the policy must have Entra ID P1 licenses.

PowerShell Code to Report Group Expiration

To report group expiration dates, we need to fetch the information about groups under the control of the expiration policy and interpret the dates. We can do this with the Get-MgGroup cmdlet from the Microsoft Graph PowerShell SDK. Here’s the code, which uses a filter to find groups with an expiration date greater than the earliest possible date for a Microsoft 365 group (or Office 365 group as it was in 2014).

Write-Host "Looking for Microsoft 365 Groups with an expiration date set"
[array]$Groups = Get-MgGroup -Filter "groupTypes/any(c:c eq 'unified') and ExpirationDateTime ge 2014-01-01T00:00:00Z" -All -PageSize 500 -ConsistencyLevel Eventual -CountVariable Var -Property DisplayName, CreatedDateTime, RenewedDateTime, ExpirationDateTime
    
If (!($Groups)) {   
    Write-Host "No groups with expiration dates found"
    Break
}   Else {
    Write-Host ("Found {0} groups with expiration dates" -f $Var)
}
$Today = (Get-Date)
$Report = [System.Collections.Generic.List[Object]]::new()

ForEach ($G in $Groups) {
    $Days = (New-TimeSpan -Start $G.CreatedDateTime -End $Today).Days  # Age of group
    $DaysLeft = (New-TimeSpan -Start $Today -End $G.ExpirationDateTime).Days
    $ReportLine = [PSCustomObject]@{
       Group                   = $G.DisplayName
       Created                 = Get-Date($G.CreatedDateTime) -format 'dd-MMM-yyyy HH:mm'
      "Age in days"            = $Days
      "Last renewed"           = Get-Date($G.RenewedDateTime) -format 'dd-MMM-yyyy'
      "Next renewal"           = Get-Date($G.ExpirationDateTime) -format 'dd-MMM-yyyy'
      "Days before expiration" = $DaysLeft}
      $Report.Add($ReportLine)
} # End Foreach

$Report = $Report | Sort-Object "Days before expiration"

The output will look something like this:

Group                                       Created     Age in days Last renewed Next renewal Days before expiration
-----                                       -------     ----------- ------------ ------------ ----------------------
Microsoft Graph Gurus                       01-Aug-2022         843 16-Jul-2024  16-Jul-2026                     601
PowerShell Gurus                            01-Aug-2022         843 16-Jul-2024  16-Jul-2026                     601
Knocksinna Working Group                    01-Aug-2022         843 02-Jul-2024  02-Jul-2026                     587
Forza Roma 2019                             01-Mar-2019        2092 20-Feb-2023  19-Feb-2025                      89
Customer Case Studies                       01-Nov-2021        1116 27-Sep-2023  26-Sep-2025                     308
Customer Prospects                          01-Nov-2021        1116 15-Nov-2023  14-Nov-2025                     357
All R &A Users                              02-Jun-2018        2364 27-Mar-2024  27-Mar-2026                     490
Corporate Acquisition Planning 2020         03-Jun-2019        1998 14-May-2023  13-May-2025                     172
Mobile Application Policies (Team)          03-Jun-2019        1998 14-May-2023  13-May-2025                     172
Andy Ruth Leadership                        03-Oct-2017        2606 09-Jul-2023  08-Jul-2025                     228
Sales Department team                       04-Aug-2016        3031 24-Apr-2023  23-Apr-2025                     152
Tango (Caen)                                04-Jan-2019        2148 16-Dec-2022  15-Dec-2024                      23
Project Condor                              05-Nov-2018        2208 04-Sep-2024  04-Sep-2026                     651
Dynamic MVPs                                05-Oct-2017        2604 31-Jul-2023  30-Jul-2025                     250

The script is downloadable from GitHub.

Reporting the Groups Expiration Policy

I’ve written several scripts to report the Groups Expiration Policy. The original version used the Get-UnifiedGroup cmdlet. The next changed the Get-UnifiedGroup cmdlet (which is highly functional and returns lots of information at the expense of being slow) for Graph API requests. The current version uses the Microsoft Graph PowerShell SDK. Hopefully, this version will last a few years!


Learn how to exploit the data available to Microsoft 365 tenant administrators through the Office 365 for IT Pros eBook. We love figuring out how things work.

10 Replies to “How to Report Microsoft 365 Groups Expiration Dates”

  1. Hi ,

    I just want to know if the Autorenewal activity through Yammer that was introduced in Jan 2022 is applicable for a network that is non native. Yet the groups are M365 groups

  2. Hi Toni,
    it’s a bit trial and error, because there is no mentioning to which cloud services I should connect (Exchange, AzureAD, etc.)
    Thinking broadly about Graph, is there a possibility to create a report / query on Azure admin portal without PowerShell, e.g. a Workbook based on Kusto query, or similar?

  3. Thank you for your post… I am just wondering if A planner activity counts as an activity for the group expiration..

  4. Does this example require group expiration policy to be enabled on the tenant? Or can it be run as a ‘what-if’ prior to enabling group expiration? If group expiration needs to be on for this to work, is there an alternative method that could provide the expiration information based on an expiration timeframe I provide? For example, what is ‘days to expiration’ if I set group lifetime to 365 days?

    1. Expiration policies depend on groups being stamped with an expiration date and Graph signals. You can mimic the date check by using a custom attribute to store an expiration date but it’s hard to mimic the Graph signals.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.