đź”§ New: User Management Graph PowerShell Toolkit

Simplify user tasks like bulk creation, updates, password resets, deletions, license checks & more — all from one place.

🚀 Launch Toolkit

Email Tenant Users by Job Title Using Graph PowerShell

In large organizations, HR or IT departments often need quick access to user lists based on specific job roles — for instance, all Analysts, Developers, or Managers. Rather than manually exporting data from Microsoft Entra ID, you can automate this task using Microsoft Graph PowerShell. This script fetches all users matching a given job title, generates a detailed CSV report, and emails it to administrators or stakeholders automatically.


The Script


Import-Module Microsoft.Graph -ErrorAction Stop
Connect-MgGraph -Scopes "User.Read.All","Directory.Read.All","Mail.Send"

$FromUser   = "admin@contoso.com"
$ToList     = "it-ops@contoso.com;hr@contoso.com"
$Subject    = 'Tenant Users Report: Job Title - Analyst'
$JobTitle   = "Analyst"
$CsvOutDir  = "$env:TEMP"

$users = Get-MgUser -All -Property "id,displayName,userPrincipalName,mail,department,jobTitle,usageLocation,accountEnabled,createdDateTime,businessPhones,mobilePhone" |
Where-Object { $_.JobTitle -match $JobTitle }

$rows = $users | ForEach-Object {
  $primaryPhone = $null
  if ($_.BusinessPhones -and $_.BusinessPhones.Count -gt 0) { $primaryPhone = $_.BusinessPhones[0] }
  elseif ($_.MobilePhone) { $primaryPhone = $_.MobilePhone }

  [PSCustomObject]@{
    DisplayName       = $_.DisplayName
    UserPrincipalName = $_.UserPrincipalName
    Mail              = $_.Mail
    Department        = $_.Department
    JobTitle          = $_.JobTitle
    UsageLocation     = $_.UsageLocation
    AccountEnabled    = $_.AccountEnabled
    Phone             = $primaryPhone
    CreatedDate       = $_.CreatedDateTime
  }
}

if (-not (Test-Path -Path $CsvOutDir)) { New-Item -ItemType Directory -Path $CsvOutDir | Out-Null }
$ts = Get-Date -Format "yyyyMMdd_HHmmss"
$csvPath = Join-Path $CsvOutDir ("Tenant_Users_ByJobTitle_{0}.csv" -f $ts)
$rows | Sort-Object DisplayName | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8

$totalUsers = ($rows | Measure-Object).Count
$summaryHtml = @"
<html>
  <body style='font-family:Segoe UI,Arial,sans-serif'>
    <h3>Tenant Users Report - Job Title: $JobTitle</h3>
    <p>Total users found: <b>$totalUsers</b></p>
    <p>The attached CSV includes: DisplayName, UPN, Mail, Department, JobTitle, UsageLocation, AccountEnabled, Phone, and CreatedDate.</p>
  </body>
</html>
"@

$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"
}

$recipients = @()
$ToList.Split(@(';', ','), [System.StringSplitOptions]::RemoveEmptyEntries) | ForEach-Object {
  $addr = $_.Trim()
  if ($addr) { $recipients += @{ emailAddress = @{ address = $addr } } }
}

$mail = @{
  message = @{
    subject = "$Subject"
    body    = @{
      contentType = "HTML"
      content     = $summaryHtml
    }
    toRecipients = $recipients
    attachments  = @($attachment)
  }
  saveToSentItems = $true
}

Send-MgUserMail -UserId $FromUser -BodyParameter $mail
Write-Host "Done. Report saved at: $csvPath" -ForegroundColor Green

                            

ii) How the Script Works

  1. Connects to Microsoft Graph using the required scopes (User.Read.All, Directory.Read.All, Mail.Send).
  2. Defines the job title filter (e.g., “Analyst”) and fetches all matching users from the tenant using Get-MgUser.
  3. Builds a dataset including display name, UPN, mail, department, job title, usage location, and account status.
  4. Exports the results into a timestamped CSV file in the temporary directory.
  5. Composes an HTML email summarizing total users found.
  6. Attaches and sends the CSV to the administrators automatically.

iii) Further Enhancements

  • Add multiple job title filters (e.g., “Engineer”, “Consultant”, “Analyst”).
  • Include additional user properties like manager or assigned licenses.
  • Automate the script execution using Windows Task Scheduler or Azure Automation.
  • Export results to a shared OneDrive or SharePoint folder instead of email.
  • Combine with department-based filtering for more refined reporting.

iv) Possible Errors and Solutions

Error Cause Solution
Authorization_RequestDenied Missing Graph permissions Reconnect with User.Read.All, Directory.Read.All, and Mail.Send.
Get-MgUser not recognized Graph module missing/outdated Install or update Microsoft.Graph using Install-Module Microsoft.Graph.
Empty CSV file No users match the given job title Verify job title value or check for case sensitivity.
Email not sent Sender lacks mailbox permissions Ensure $FromUser is a licensed mailbox account.
Split error on recipients Improper email delimiter Use ; or , to separate addresses.

v) Conclusion

This Graph PowerShell script provides a quick and automated way to fetch users by job title, generate a detailed CSV report, and deliver it to administrators via email. It eliminates the need for manual exports, ensures timely data delivery, and helps maintain better visibility into your organization’s workforce. When scheduled regularly, it becomes a powerful reporting utility for both IT and HR teams.


Graph PowerShell Explorer Widget

20 Graph PowerShell cmdlets with easily accessible "working" examples.


Permission Required

Example:


                


                


                

© m365corner.com. All Rights Reserved. Design by HTML Codex