Simplify user tasks like bulk creation, updates, password resets, deletions, license checks & more — all from one place.
🚀 Launch ToolkitInactive user accounts can pose a security risk or lead to unnecessary license consumption. Instead of manually tracking them, this Graph PowerShell script automatically detects inactive users and sends each of them a customized email reminder.
Perfect for IT admins looking to proactively manage user activity with automated communication.
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "User.Read.All", "Reports.Read.All", "Mail.Send"
# Define inactivity threshold (e.g., 90 days)
$thresholdDate = (Get-Date).AddDays(-90)
# Get all users including sign-in activity
$users = Get-MgUser -All -Property Id, DisplayName, UserPrincipalName, Mail, SignInActivity
# Filter inactive users
$inactiveUsers = $users | Where-Object {
$_.SignInActivity -and $_.SignInActivity.LastSignInDateTime -lt $thresholdDate -and
$_.Mail -ne $null
}
Write-Host "`nSending custom inactivity alerts to users..." -ForegroundColor Cyan
foreach ($user in $inactiveUsers) {
$lastSignIn = $user.SignInActivity.LastSignInDateTime.ToString("yyyy-MM-dd")
# Customize the email message
$body = @{
Message = @{
Subject = "We've noticed you're inactive in Microsoft 365"
Body = @{
ContentType = "HTML"
Content = @"
Hello $($user.DisplayName),
We noticed that you haven’t signed into your Microsoft 365 account since $lastSignIn.
If you still need access, please sign in soon to avoid potential deactivation.
Thank you,
IT Administrator
"@
}
ToRecipients = @(@{ EmailAddress = @{ Address = $user.Mail } })
}
SaveToSentItems = $true
}
try {
Send-MgUserMail -UserId "admin@yourdomain.com" -BodyParameter $body
Write-Host "Notification sent to $($user.UserPrincipalName)" -ForegroundColor Green
}
catch {
Write-Host "Failed to send email to $($user.UserPrincipalName): $($_.Exception.Message)" -ForegroundColor Red
}
}
The script authenticates using three key delegated permissions:
A threshold date is set (e.g., 90 days ago). Users with sign-ins before this date are considered inactive.
It checks each user's last sign-in and email address. If eligible, it sends a personalized HTML email using Send-MgUserMail.
You can take this automation further with the following ideas:
Keep a log of who was notified:
$inactiveUsers | Export-Csv "NotifiedUsers.csv" -NoTypeInformation
Use Get-MgUserManager -UserId
Use Task Scheduler or Azure Automation to run the script on a weekly or monthly basis.
Add a switch to simulate sending (dry run) without actually dispatching emails.
| Error | Cause | Solution |
|---|---|---|
| Send-MgUserMail: MailboxNotEnabled | Sender account has no mailbox | Ensure admin@yourdomain.com is a licensed user with Exchange mailbox |
| Access Denied or Authorization_RequestDenied | Missing Graph permissions | Use Connect-MgGraph -Scopes "User.Read.All", "Reports.Read.All", "Mail.Send" |
| NullReferenceException | Some users don't have SignInActivity or Mail | Filter for $_.SignInActivity -and $_.Mail -ne $null |
| Too many requests | Rate-limited by Graph API | Add delay (Start-Sleep -Seconds 2) between sends for large orgs |
This script automates user communication by detecting inactive users and sending customized email reminders. It's a clean, proactive way to reduce license waste, improve engagement, and keep user directories tidy.
💡 Automation isn't just about IT efficiency—it's about making users aware, engaged, and secure.
© m365corner.com. All Rights Reserved. Design by HTML Codex