Group Nesting Report for Exchange Online Distribution Lists

Back in 2011 I created a script that provided a group nesting report for on-premises AD groups using the Quest ActiveRoles cmdlets, you can find that here. However recently I needed to provide the same functionality with Exchange Online Distribution Groups, so I updated the code.

The script assumes you’ve made a connection to Exchange Online powershell, so be sure to add the appropriate commands to the top of the script to make a remote Psh connection to EXO or invoke the Exchange Online V2 module.

Running the command will produce a graphical tree-view of your groups and their nested groups. I plan to add additional functionality, for things like a CSV or XML output, as well as storing the group membership information so that group nesting could be re-created.

The bulk of the work is done with a Function, which performs the review of the group, it’s membership, and then creates the tree-view and iterates down thru multiple nested levels if necessary.

The code can be found below (and will be moving to PowerShell Gallery soon), and above that is an example of the script in action. You’ll notice it took approximately 17 minutes to complete, that’s because I have just over 10,000 distribution groups in my test tenant. I suspect it would take longer if there were more nested groups to locate and report on…

Write-Host "$(Get-Date)"

Function get-groupmembers($groupname, $iteration)
{
	$group = Get-DistributionGroup $groupname

		$members = $null
		$members = Get-DistributionGroupMember $group.name | Where { $_.RecipientType -Like "*group*" }
		
		if ($members)
		{
			if ($iteration -eq "0") { write-host -foregroundcolor yellow $group.name }
			++$iteration
			
			foreach ($member in $members)
			{
				for ($i = $iteration; $i -gt 0; $i--) { write-host "    " -nonewline }
				write-host "|"
				for ($i = $iteration; $i -gt 0; $i--) { write-host "    " -nonewline }
				write-host "+—-$member"
				get-groupmembers -groupname $member.name -iteration $iteration
			}
		}
}

#$groups = Get-DistributionGroup -ResultSize Unlimited
foreach ($group in $groups) { get-groupmembers -groupname $group.name -iteration 0 }

Write-Host "$(Get-Date)"