Reporting on Microsoft 365 Groups links (2023 updated version)

For today’s exercise in updating old scripts, we will take a look at a simple scenario – listing all “links” across Microsoft 365 Groups within your organization. Few different sets of links exist: owners, members, subscribers, aggregators, and eventSubscribers, with the latter two not currently supported. We can also derive a set of guest links based on the members list. As Microsoft Teams are also leveraging the membership of the underlying Microsoft 365 Group, it’s that more important to get the full set of “links”.

You can think of obtaining Microsoft 365 Group links as the analogue of listing all members for “traditional” groups. There are many different ways we can achieve such a fundamental task, though there are some caveats that predetermine our choice of method. Firstly, the Exchange Online Get-UnifiedGroupLinks cmdlet is still the only way to list Microsoft 365 Group “subscribers”, i.e. the set of users who have opted out to receive messages addressed to the Group directly within their Inbox. In addition to that, the Graph method and cmdlets still do not cover all possible recipient types that can be added to a Group, and even though such scenarios fall under the “unsupported” category, in some cases it’s good to have them covered.

Without further ado, let’s dive into the script. Firstly, we will of course need the set of Microsoft 365 Groups within the organization. Unfortunately, the Get-UnifiedGroup cmdlet is not exactly know to be the best performant one, so for the purposes of this script, I’ve chosen to obtain the set of groups by leveraging the Get-EXORecipient cmdlet instead. This has the added benefit of minimizing the set of properties returned, although if you are looking to include additional details about the Microsoft 365 Group object within the output, Get-EXORecipient is not the best choice. Anyway, here’s how to use the Get-EXORecipient cmdlet to obtain a list of Microsoft 365 Groups:

Get-EXORecipient -RecipientTypeDetails GroupMailbox -ResultSize Unlimited | Select-Object -Property Displayname,PrimarySMTPAddress,ExternalDirectoryObjectId

Once we have the set of Microsoft 365 Groups, we proceed to iterate over each group and fetch the various “links” by means of executing the Get-UnifiedGroupLinks cmdlet. At total three different executions of the Get-UnifiedGroupLinks cmdlet are needed for each group, so the process will take some time. For each “link”, we collect just two properties: RecipientTypeDetails, which helps us determine whether this is a Guest user, and WindowsLiveID, which serves as unique identifier for the object. We then rearrange the output and export to a CSV file, a sample of which is shown below:

Sample output of the Microsoft 365 Groups links report script

Speaking of output, the default format used is one line per each Link entry, which generates a CSV file easy to filter by either Group ID (via the DisplayName or PrimarySMTPAddress columns), User (via the Member column) or Link type (via the MemberType column). If you prefer a smaller output file, with one entry per Group object and a concatenated list of links, use the CondensedOutput parameter:

.\O365_Groups_links_reportV2.ps1 -CondensedOutput

On the other hand, if you want to play with the output before exporting it, you can omit the –CondensedOutput parameter, and then leverage the $varO365GroupMembers global variable, which stores the output. For example, you can use the following to filter out and export just the list of Owners:


$varO365GroupMembers | ? {$_.MemberType -eq "Owner"} | Sort Member -Descending | Export-Csv -NoTypeInformation "O365GroupLinks.csv"

A bit more complicated example shows the type of operations you can perform with the output. In the sample below, we filter the output to only feature Owners, then group it by the identity of the owner. As a result, we now have a hash-table to quickly check whether a given user is an owner of any Microsoft 365 Group and return the corresponding list of groups:


$owners = $varO365GroupMembers | ? {$_.MemberType -eq "Owner"} | group Member -AsString -AsHashTable


Before closing the article, few additional remarks. The script requires the use of the “V2” version of the ExchangeOnlineManagement PowerShell module, which by now all of you should be using. This is not only enforced by the #Requires statement, but the Check-Connectivity helper function, which is used to check for any existing session and/or establish a new one as needed. Since we’re using the V2 module, throttling concerns should be alleviated, so you might as well remove the simple anti-throttling control on line 79.

Finally, here’s a link to the script over at my GitHub repo:

1 thought on “Reporting on Microsoft 365 Groups links (2023 updated version)

Leave a Reply

Your email address will not be published. Required fields are marked *

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