Automated M365 Employee Offboarding Script (Exchange, OneDrive & License Reclamation)

1. Enterprise Scenario & Objectives

Manual employee offboarding in enterprise Microsoft 365 environments introduces critical security gaps and operational overhead. When an organization parts ways with an employee, administrators must rapidly revoke access, secure company data, reallocate mailbox permissions to managers, and reclaim expensive enterprise licenses.

This production-ready script automates the full lifecycle in a single execution:

  • Disabling account sign-in immediately.
  • Revoking all active refresh tokens and user sessions.
  • Converting the primary mailbox to a Shared Mailbox and hiding it from the GAL.
  • Delegating FullAccess and SendAs permissions to the designated manager.
  • Configuring an automated Out-of-Office (OOF) notification response.
  • Reclaiming assigned M365 product licenses while preserving mailbox data.

2. Prerequisites & Required Modules

Run the following commands in PowerShell to install the necessary Graph and Exchange management modules:

Install-Module -Name Microsoft.Graph -Scope CurrentUser -Force
Install-Module -Name ExchangeOnlineManagement -Scope CurrentUser -Force

3. Authentication & Required Permissions

Ensure your administrative account or Azure Managed Identity has the following scopes assigned:

  • Graph API Scopes: User.ReadWrite.All, Directory.ReadWrite.All, UserAuthenticationMethod.ReadWrite.All
  • Exchange Role: Exchange Administrator

4. The Complete Production Script

<#
.SYNOPSIS
    Automated M365 Employee Offboarding Script
.DESCRIPTION
    Blocks sign-in, revokes tokens, converts mailbox to shared, delegates manager access,
    configures OOO reply, hides from GAL, and reclaims licenses.
.AUTHOR
    Innovation Guru (https://dsinnovationguru.com)
#>

param (
    [Parameter(Mandatory = $true)]
    [string]$UserPrincipalName,

    [Parameter(Mandatory = $true)]
    [string]$ManagerUPN,

    [Parameter(Mandatory = $false)]
    [string]$AutoReplyMessage = "This employee has left the organization. Please contact their manager for assistance."
)

$ErrorActionPreference = "Stop"
$LogPath = "C:\Logs\M365_Offboarding.log"

function Write-Log ($Message) {
    $TimeStamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    Add-Content -Path $LogPath -Value "[$TimeStamp] $Message"
    Write-Host "[$TimeStamp] $Message" -ForegroundColor Green
}

try {
    Write-Log "Starting offboarding workflow for user: $UserPrincipalName"

    # Step 1: Block Sign-In
    Update-MgUser -UserId $UserPrincipalName -AccountEnabled:$false
    Write-Log "Account sign-in disabled."

    # Step 2: Revoke Active Sessions & Refresh Tokens
    Revoke-MgUserSignInSession -UserId $UserPrincipalName | Out-Null
    Write-Log "Active user refresh tokens revoked."

    # Step 3: Convert Mailbox to Shared & Hide from GAL
    Set-Mailbox -Identity $UserPrincipalName -Type Shared -HiddenFromAddressListsEnabled $true
    Write-Log "Mailbox converted to Shared Mailbox and hidden from GAL."

    # Step 4: Delegate Full Access and Send As Permissions to Manager
    Add-MailboxPermission -Identity $UserPrincipalName -User $ManagerUPN -AccessRights FullAccess -AutoMapping $true
    Add-RecipientPermission -Identity $UserPrincipalName -Trustee $ManagerUPN -AccessRights SendAs -Confirm:$false
    Write-Log "FullAccess and SendAs permissions assigned to manager: $ManagerUPN"

    # Step 5: Set Out of Office (OOF) Auto-Reply
    Set-MailboxAutoReplyConfiguration -Identity $UserPrincipalName -AutoReplyState Enabled `
        -InternalMessage $AutoReplyMessage -ExternalMessage $AutoReplyMessage
    Write-Log "Out of Office auto-reply enabled."

    # Step 6: Reclaim Licenses (Preserving Data)
    $UserLicenses = (Get-MgUser -UserId $UserPrincipalName -Property AssignedLicenses).AssignedLicenses
    if ($UserLicenses) {
        foreach ($License in $UserLicenses) {
            Set-MgUserLicense -UserId $UserPrincipalName -RemoveLicenses @($License.SkuId) -AddLicenses @{}
        }
        Write-Log "All assigned M365 licenses revoked."
    } else {
        Write-Log "No active licenses found on account."
    }

    Write-Log "Offboarding successfully completed for $UserPrincipalName"
}
catch {
    Write-Log "ERROR: $_"
}

Save the script as Invoke-M365Offboarding.ps1 and execute it in an elevated PowerShell terminal. Use your Code Block Pro block below for the script content.

5. Execution & Enterprise Automation

Run the script locally via PowerShell:

.\Invoke-M365Offboarding.ps1 -UserPrincipalName "john.doe@dsinnovationguru.com" -ManagerUPN "jane.smith@dsinnovationguru.com"

Enterprise Automation: Import this script into an Azure Automation Account using a System-Assigned Managed Identity. You can trigger this runbook automatically via Webhooks integrated with your HR/IT Service Desk platform (ServiceNow, Jira, or Freshservice).

Leave a Comment

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

Scroll to Top