Off-Boarding Automation : Manage Exchange Online Group access through PowerShell

Today, I’d like to share with you a PowerShell script that solves a recurring challenge in business : managing Exchange Online group memberships when an employee leaves.

The offboarding challenge :

In organizations using Microsoft 365, employees often accumulate dozens or even hundreds of memberships in different distribution groups and Microsoft 365 groups over time. When they leave, manually deleting these accesses is:

  • Time-consuming for IT teams
  • Prone to human error
  • Potential source of security breaches if accesses are forgotten

Real Example :

Let’s take a user as example :

To be able to see all groups membership for one user, you need to go to Exchange Admin Center then :

  1. Select “Recipeint” then “Mailboxes
  2. Select User Mailbox
  3. Select “Others” tab
  4. Select “Member of

As you can see here, this user have about 30 group membership (Sorry, I cant show you Group names), so when Off-Boarding this user we need to go and delete user membership one by one, this can take to much time, and can cause errors also.

The solution : PowerShell automation

The script I’ve developed enables :

  • Automatically identify all Exchange groups to which a user belongs
  • Remove all these memberships in a single operation
  • Generate a detailed report of actions carried out

Why is this crucial?

  • Security : Eliminate the risk of residual access to internal communications
  • Compliance : Accurately document access removals for audits
  • Efficiency : Reduce the offboarding process from hours to minutes
  • Reliability : Guarantee that no group is overlooked, even for very active users

Identity and access management is a fundamental element of modern cybersecurity. Tools like this help us maintain a secure environment, while freeing up time for our IT teams.

Here is the script :

You need to specify $UserEmailAddress parameters in the bottom of the script.

# Script to remove a user from all Exchange Online groups
# Make sure you have installed the ExchangeOnlineManagement module and are connected to Exchange Online

function Connect-ToExchangeOnline 
{
    # Check if the module is installed
    if (!(Get-Module -ListAvailable -Name ExchangeOnlineManagement)) 
    {
        Write-Host "The ExchangeOnlineManagement module is not installed. Installation in progress..." -ForegroundColor Yellow
        Install-Module -Name ExchangeOnlineManagement -Force -AllowClobber
    }
    # Import ExchangeOnlineManagement module
    Import-Module ExchangeOnlineManagement

    # Connect to Exchange online
    Connect-ExchangeOnline 
}

function Remove-UserFromAllGroups 
{
    param(
        [Parameter(Mandatory=$true)]
        [string]$UserEmail
    )
    
    # Check if the user exists
    try 
    {
        $user = Get-EXOMailbox -Identity $UserEmail -ErrorAction Stop
        Write-Host "User found : $($user.DisplayName)" -ForegroundColor Green
    }
    catch 
    {
        Write-Host "The user with the email address $UserEmail was not found." -ForegroundColor Red
        return
    }
    
    # Retrieve all distribution groups
    Write-Host "Search for distribution groups..." -ForegroundColor Yellow
    $distributionGroups = Get-DistributionGroup -ResultSize Unlimited 
    
    # Recover all Microsoft 365 groups
    Write-Host "Search for Microsoft 365 groups..." -ForegroundColor Yellow
    $m365Groups = Get-UnifiedGroup -ResultSize Unlimited
    
    $removedFromCount = 0
    $errorCount = 0
    $groupsList = @()

    # Check and remove user from distribution groups
    foreach ($group in $distributionGroups) 
    {
        try 
        {
            $groupMembers = Get-DistributionGroupMember -Identity $group.Identity -ResultSize Unlimited
            if ($groupMembers.PrimarySmtpAddress -contains $UserEmail) 
            {
                Write-Host "Remove user from distribution group : $($group.DisplayName)" -ForegroundColor Yellow
                Remove-DistributionGroupMember -Identity $group.Identity -Member $UserEmail -Confirm:$false
                $removedFromCount++
                $groupsList += "Distribution: $($group.DisplayName)"
            }
        }
        catch 
        {
            Write-Host "Error verifying/deleting user from group $($group.DisplayName): $_" -ForegroundColor Red
            $errorCount++
        }
    }
    
    # Check and remove user from Microsoft 365 groups
    foreach ($group in $m365Groups) 
    {
        try 
        {
            $groupMembers = Get-UnifiedGroupLinks -Identity $group.Identity -LinkType Members -ResultSize Unlimited
            if ($groupMembers.PrimarySmtpAddress -contains $UserEmail) 
            {
                Write-Host "Remove user from Microsoft 365 group : $($group.DisplayName)" -ForegroundColor Yellow
                Remove-UnifiedGroupLinks -Identity $group.Identity -LinkType Members -Links $UserEmail -Confirm:$false
                $removedFromCount++
                $groupsList += "Microsoft 365 : $($group.DisplayName)"
            }
        }
        catch 
        {
            Write-Host "Error verifying/deleting user from group $($group.DisplayName): $_" -ForegroundColor Red
            $errorCount++
        }
    }
    
    # Summary of operations
    Write-Host "`n--- Summary ---" -ForegroundColor Cyan
    Write-Host "User : $($user.DisplayName) ($UserEmail)" -ForegroundColor Cyan
    Write-Host "Deleted from $removedFromCount groups" -ForegroundColor Green
    Write-Host "Errors encountered : $errorCount" -ForegroundColor Cyan
    
    if ($groupsList.Count -gt 0) 
    {
        Write-Host "`nRemoved user groups :" -ForegroundColor Green
        $groupsList | ForEach-Object { Write-Host "- $_" -ForegroundColor Yellow }
    }
}

# Main

Connect-ToExchangeOnline
# You need to specify User Email Address parameter here
$UserEmailAddress = "user@domain.com"
Remove-UserFromAllGroups -UserEmail $UserEmailAddress
  • Execution Result :

Thanks

Aymen EL JAZIRI (Microsoft MVP)
Aymen EL JAZIRI (Microsoft MVP)

Hi, I’m Aymen El Jaziri , a passionate System Administrator and Microsoft MVP, with years of hands-on experience in managing and securing modern IT infrastructures.
This blog is where I share technical guides, automation scripts, product reviews, and real-world solutions that help IT professionals simplify their day-to-day work and stay ahead in a fast-evolving cloud ecosystem.
Whether you’re here to troubleshoot an issue, improve your automation game, or learn new best practices , welcome in my blog !
Let’s build a stronger, smarter IT community together.
Feel free to connect with me on LinkedIn for more content, discussions, or collaboration opportunities.

Thanks

Aymen

Articles: 154