Group Expiration Warning Emails
30 days before an Office 365 Group expires, email all owners with a renewal link and summary of group activity.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
This flow monitors Office 365 Groups for upcoming expiration dates and proactively notifies group owners before their groups are deleted. It runs daily, queries Microsoft Graph API for groups with expiration policies, identifies those expiring within a configurable warning threshold (default: 30 days), and sends personalized warning emails to each group's owners with renewal instructions. An admin summary report is also sent with a consolidated view of all warned groups.
Use Case
Organizations using Azure AD group expiration policies risk losing groups (and their associated Teams, SharePoint sites, and mailboxes) when owners fail to renew them in time. This flow ensures owners receive timely, actionable warnings with direct renewal links, and IT admins get a daily summary of groups approaching expiration for governance oversight.
Flow Architecture
Recurrence
RecurrenceDaily at 8:00 AM Eastern.
Initialize Variables
InitializeVariable (x7)Hydrates seven variables: varWarningDays (Integer, from env var flowlibs_GroupExpirationWarningDays, default 30), varGraphTenantId, varGraphClientId, varGraphClientSecret, varNotificationEmail (all String, from matching env vars), varReportBody (String, accumulates HTML rows for the admin summary), and varGroupsWarnedCount (Integer counter).
HTTP - Get Groups With Expiration
HTTPCalls Microsoft Graph: GET /groups?$filter=expirationDateTime ne null with ActiveDirectoryOAuth to retrieve all groups that have an expiration date set.
Parse JSON - Groups Response
ParseJsonParses the Graph response to surface id, displayName, expirationDateTime, mail, and description for each group.
Loop Through Groups
ForeachFor each group returned: calculates days remaining, checks the warning threshold, and (when matched) emails the owners and appends a row to the admin summary.
Compose - Calculate Days Until Expiry
ComposeExpression div(sub(ticks(expirationDateTime), ticks(utcNow())), 864000000000) yields the integer days remaining.
Check If Group Expiring Soon
If conditionBranches on days remaining <= varWarningDays AND days remaining > 0.
- HTTP - Get Group Owners — Calls Graph: GET /groups/{id}/owners?$select=displayName,mail.
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_NotificationEmail | String | <configure> | Admin email (or distribution list) that receives the consolidated summary report after each run. Set per tenant. |
| flowlibs_GroupExpirationWarningDays | String | 30 | Number of days before a group's expiration to trigger warning emails (e.g. 30 = warn 30 days out). Cast to int via int(parameters('flowlibs_GroupExpirationWarningDays')). |
| flowlibs_GraphTenantId | String | <your-tenant-id> | Azure AD tenant ID used for the ActiveDirectoryOAuth HTTP authentication against Microsoft Graph. |
| flowlibs_GraphClientId | String | <configure> | Application (client) ID of the Azure AD app registration used to call Microsoft Graph. |
| flowlibs_GraphClientSecret | String | <configure> | Client secret for the Azure AD app registration. Store in Key Vault or a secured env-var pipeline. |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| Office 365 Outlook | shared_office365 | SendEmailV2 (owner warning emails and admin summary email) |
| HTTP | http | HTTP - Get Groups With Expiration (GET https://graph.microsoft.com/v1.0/groups?$filter=expirationDateTime ne null) HTTP - Get Group Owners (GET https://graph.microsoft.com/v1.0/groups/{id}/owners?$select=displayName,mail) |
Note — All connections are referenced as solution connection references; the flow is portable between environments as long as a connection is mapped at import time.
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Adjust warning threshold
- Change the flowlibs_GroupExpirationWarningDays env-var value (e.g. 14 for two-week warnings, 60 for two-month warnings). No flow edit required.
- Add multiple warning tiers
- Duplicate the If-condition inside the loop with different thresholds (e.g. 7-day urgent vs 30-day standard) and send different email templates per tier.
- Target specific groups
- Modify the Graph $filter (e.g. append and startsWith(displayName, 'Project')) to only monitor groups whose display name matches a pattern.
- Add Teams notification
- Add a Teams PostMessageToConversation action after the owner email to also alert in a Teams channel.
- Track renewals
- Add a SharePoint list to log warned groups and track which ones get renewed vs. expired, then read it on the next run to suppress re-warnings.
- Graph API permissions
- The app registration needs Group.Read.All and GroupMember.Read.All as application permissions, admin-consented in the target tenant.
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01Days to expiry
Computes integer days remaining until the group's expirationDateTime. 864000000000 is the number of 100ns ticks in a day.
EXPR.02Null-safe description
Falls back to a literal 'No description' when the group has no description property.
EXPR.03Join owner emails
Joins the projected owner email array with semicolons so it can be used directly as the To field in Send an email.
EXPR.04Warning days from env var
Casts the String-typed env var to an integer for numeric comparison against the days-remaining value.
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.