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 -ForceInstall-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).
