🔧 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

Fetch Microsoft 365 Guest Users & Email Report with PowerShell

Guest accounts in Microsoft 365 are essential for collaboration with external partners, but keeping track of them is critical for security and compliance. This script automates the process of retrieving all guest accounts from Microsoft Entra ID (Azure AD) and emailing the list as a CSV file to an administrator.


i) Script

# ===== Simple Graph PowerShell Script =====
# Fetch all GUEST 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   = "Guest 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: guest accounts (all) ---
$filter = "userType eq 'Guest'"

# --- Fetch Users ---
$selectProps = "id","displayName","userPrincipalName","mail","accountEnabled","createdDateTime","externalUserState","externalUserStateChangeDateTime"
$users = Get-MgUser -All -Filter $filter -ConsistencyLevel eventual -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 ("GuestUsers_{0}.csv" -f $ts)
$users | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8

# --- Prepare HTML Body ---
$summaryHtml = @"
$summaryHtml = @"
<html>
  <body style='font-family:Segoe UI,Arial,sans-serif'>
    <h3>Guest Users Report</h3>
    <p>Total guest 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 (use ${Subject} to avoid colon parsing issues) ---
$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
                            


ii) How the Script Works

  1. Variable Setup
  2. Defines key parameters including the sender’s mailbox ($FromUser), recipient ($To), subject line, and output directory for saving the CSV file.

  3. Graph Connection
  4. Loads the Microsoft.Graph module and connects to Microsoft Graph with the delegated scopes:

    • User.Read.All — to read all user objects in the tenant.
    • Mail.Send — to send email from the sender’s mailbox.
  5. Filtering Guest Accounts
  6. Applies the OData filter userType eq 'Guest' to retrieve only guest accounts, regardless of their enabled/disabled status.

  7. Fetching User Data
  8. Get-MgUser retrieves the guest accounts and selects useful properties such as DisplayName, UPN, email, accountEnabled status, creation date, and invitation state.

  9. Export to CSV
  10. Writes the list to a timestamped CSV file in the defined output directory.

  11. Email Preparation
  12. Creates an HTML summary showing the total number of guest users and attaches the CSV file as a Base64-encoded fileAttachment.

  13. Sending the Email
  14. Uses Send-MgUserMail to send the message with the attachment from $FromUser to $To, saving it to Sent Items.


iii) Further Enhancements

  • Enabled Guests Only: Add and accountEnabled eq true to the $filter to limit results to active guests.
  • Pending Acceptance Filter: Filter by externalUserState eq 'PendingAcceptance' to find guests who have not yet accepted their invitations.
  • Schedule Reports: Use Task Scheduler or Azure Automation to send the guest list daily/weekly.
  • Multiple Recipients: Expand the toRecipients array to send to multiple admins at once.
  • CSV Preview in Email: Include the first few rows in the email body for quick review.

Possible Errors & Solutions

Error Cause Solution
Authorization_RequestDenied Missing Graph permissions Reconnect with Connect-MgGraph -Scopes "User.Read.All","Mail.Send" and grant consent.
Get-MgUser not recognized Microsoft.Graph module not installed Run Install-Module Microsoft.Graph -Scope CurrentUser and import the module.
CSV file is empty No guest accounts found Verify guests exist in Entra ID; remove or adjust filter to test retrieval.
Email not sent $FromUser is not mailbox-enabled or lacks permissions Use a mailbox-enabled account or assign proper send rights.
HTML email looks plain Client strips styles Keep minimal inline styling or opt for plain text content.

Conclusion

This script is a straightforward yet powerful way to maintain oversight of external collaboration in Microsoft 365. By automating the retrieval and delivery of the guest account list, you ensure that administrators stay informed and can act promptly if there are unexpected or inactive guest users. With small tweaks, this can become part of your regular security and compliance routine.


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