Simplify user tasks like bulk creation, updates, password resets, deletions, license checks & more — all from one place.
🚀 Launch ToolkitKnowing who is licensed in your tenant helps with cost control, access governance, and compliance reporting. This simple script pulls all licensed, enabled member accounts from Microsoft Entra ID (Azure AD) and emails the list (as a CSV attachment) to an administrator using Microsoft Graph PowerShell.
# ===== Simple Graph PowerShell Script =====
# Fetch all LICENSED users and email the list to admin
# Requires: Microsoft.Graph module
# Scopes: User.Read.All, Mail.Send
# --- Variables ---
$FromUser = "admin@contoso.com" # Sender (must have mailbox)
$To = "it-ops@contoso.com" # Recipient
$Subject = "Licensed users report"
$CsvOutDir = "$env:TEMP"
# --- Connect to Microsoft Graph ---
Import-Module Microsoft.Graph -ErrorAction Stop
Connect-MgGraph -Scopes "User.Read.All","Mail.Send"
# --- Build Filter: licensed members only, enabled accounts ---
# Note: Using $count in filter requires -ConsistencyLevel eventual (and often -CountVariable)
$filter = "assignedLicenses/`$count ne 0 and userType eq 'Member' and accountEnabled eq true"
# --- Fetch Users ---
$selectProps = "id","displayName","userPrincipalName","jobTitle","department","accountEnabled","createdDateTime"
$users = Get-MgUser -All -Filter $filter -ConsistencyLevel eventual -CountVariable total -Property $selectProps |
Select-Object $selectProps
# --- Export to CSV ---
if (-not (Test-Path -Path $CsvOutDir)) { New-Item -ItemType Directory -Path $CsvOutDir | Out-Null }
$ts = Get-Date -Format "yyyyMMdd_HHmmss"
$csvPath = Join-Path $CsvOutDir ("LicensedUsers_{0}.csv" -f $ts)
$users | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8
# --- Prepare HTML Body ---
$summaryHtml = @"
<html>
<body style='font-family:Segoe UI,Arial,sans-serif'>
<h3>Licensed Users Report</h3>
<p>Total licensed users: <b>$($users.Count)</b></p>
<p>The full list is attached as a CSV.</p>
</body>
</html>
"@
# --- Prepare Attachment ---
$fileBytes = [System.IO.File]::ReadAllBytes($csvPath)
$base64Content = [System.Convert]::ToBase64String($fileBytes)
$csvFileName = [System.IO.Path]::GetFileName($csvPath)
$attachment = @{
"@odata.type" = "#microsoft.graph.fileAttachment"
name = $csvFileName
contentBytes = $base64Content
contentType = "text/csv"
}
# --- Prepare Mail Object ---
$mail = @{
message = @{
subject = "${Subject}"
body = @{
contentType = "HTML"
content = $summaryHtml
}
toRecipients = @(@{ emailAddress = @{ address = $To } })
attachments = @($attachment)
}
saveToSentItems = $true
}
# --- Send Email ---
Send-MgUserMail -UserId $FromUser -BodyParameter $mail
Write-Host "Done. CSV saved at: $csvPath" -ForegroundColor Green
Define the sender/recipient addresses, email subject, and where to save the CSV.
Loads the unified Microsoft.Graph module and connects with delegated scopes:
Uses an OData filter that returns only licensed (assignedLicenses/$count ne 0), enabled (accountEnabled eq true) member accounts (userType eq 'Member'). Because $count is referenced in the filter, -ConsistencyLevel eventual (and commonly -CountVariable) is included.
Retrieves a concise set of user fields (DisplayName, UPN, JobTitle, Department, etc.) and shapes them with Select-Object.
Creates a timestamped CSV in the specified directory.
Builds a brief HTML summary, attaches the CSV as a file attachment, and sends via Send-MgUserMail, saving a copy to Sent Items.
Error | Cause | Solution |
---|---|---|
Authorization_RequestDenied | Missing delegated consents for User.Read.All or Mail.Send | Reconnect with required scopes; admin consent may be needed. |
Get-MgUser not recognized | Graph module not installed/loaded | Install-Module Microsoft.Graph -Scope CurrentUser then Import-Module Microsoft.Graph. |
Empty CSV | No users match the filter (e.g., all are unlicensed/disabled) | Test simpler filters; confirm license assignments in Entra admin center. |
Email not delivered | $FromUser isn’t mailbox-enabled or lacks permission | Use a mailbox-enabled account; verify it can send to $To. |
HTML appears plain | Client strips styles | Keep minimal inline CSS or switch to plain text body. |
This lightweight script gives you a reliable, repeatable way to discover licensed users and deliver the results directly to an administrator’s inbox. It’s easy to schedule, simple to extend (e.g., add license names), and perfect for ongoing compliance and cost-control workflows.
© m365corner.com. All Rights Reserved. Design by HTML Codex