Trying to fetch mail info using Microsoft Graph
# Replace these with your app registration details
$tenantId = “”
$clientSecret = “”
$clientId = “”
# OAuth 2.0 token endpoint for your tenant
$tokenUrl = “https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token“
# Microsoft Graph API base URL
$graphApiUrl = “https://graph.microsoft.com/v1.0“
# The resource scope we are requesting (Mail.Read, MailboxSettings.Read, User.ReadBasic.All)
$scope = “https://graph.microsoft.com/.default“
# Request an OAuth 2.0 token from Azure AD using the client credentials flow
$tokenResponse = Invoke-RestMethod -Method Post -Uri $tokenUrl -ContentType “application/x-www-form-urlencoded” -Body @{
client_id = $clientId
client_secret = $clientSecret
scope = $scope
grant_type = “client_credentials”
}
# Extract the access token from the response
$accessToken = $tokenResponse.access_token
# Headers for authenticated requests to Microsoft Graph
$headers = @{
Authorization = “Bearer $accessToken”
}
# Function to fetch paginated results from Microsoft Graph API
function Get-PaginatedData {
param (
[Parameter(Mandatory = $true)]
[string]$initialUrl
)
$results = @()
$nextLink = $initialUrl
while ($nextLink) {
try {
$response = Invoke-RestMethod -Uri $nextLink -Headers $headers
$results += $response.value
# Check if there is more data to fetch
if ($response.’@odata.nextLink’) {
$nextLink = $response.’@odata.nextLink’
} else {
$nextLink = $null
}
} catch {
# Capture and display detailed error information
Write-Host “Error fetching data:”
if ($_.Exception.Response -is [System.Net.HttpWebResponse]) {
$httpResponse = $_.Exception.Response
Write-Host “StatusCode: $($httpResponse.StatusCode)”
Write-Host “StatusDescription: $($httpResponse.StatusDescription)”
# Read the response stream for detailed error
$streamReader = New-Object System.IO.StreamReader($httpResponse.GetResponseStream())
$responseBody = $streamReader.ReadToEnd()
Write-Host “Response Body: $responseBody”
} else {
Write-Host “An unknown error occurred.”
}
break
}
}
return $results
}
# Function to get all emails for a user
function Get-EmailsForUser {
param (
[Parameter(Mandatory = $true)]
[string]$userPrincipalName
)
$mailApiUrl = “$graphApiUrl/users/$userPrincipalName/messages”
return Get-PaginatedData -initialUrl $mailApiUrl
}
# Function to get attachment details for a specific email
function Get-AttachmentsForEmail {
param (
[Parameter(Mandatory = $true)]
[string]$userPrincipalName,
[Parameter(Mandatory = $true)]
[string]$emailId
)
$attachmentApiUrl = “$graphApiUrl/users/$userPrincipalName/messages/$emailId/attachments”
return Get-PaginatedData -initialUrl $attachmentApiUrl
}
# Function to get mailbox settings for a user (including last access time)
function Get-MailboxSettings {
param (
[Parameter(Mandatory = $true)]
[string]$userPrincipalName
)
$mailboxSettingsApiUrl = “$graphApiUrl/users/$userPrincipalName/mailboxSettings”
$mailboxSettings = Invoke-RestMethod -Uri $mailboxSettingsApiUrl -Headers $headers
return $mailboxSettings
}
# Step 1: Fetch only user mailboxes by filtering on userType eq ‘Member’
$usersApiUrl = “$graphApiUrl/users?`$filter=userType eq ‘Member'”
Write-Host “Fetching user mailboxes…”
$users = Get-PaginatedData -initialUrl $usersApiUrl
if ($users.Count -eq 0) {
Write-Host “No user mailboxes found. Aborting script.”
exit
}
# Initialize result collection
$mailboxDataCollection = @()
# Step 2: Loop through each user and gather mailbox data
foreach ($user in $users) {
$userPrincipalName = $user.userPrincipalName
Write-Host “Processing mailbox for $userPrincipalName…”
# Initialize user data
$mailData = @{
User = $userPrincipalName
TotalEmails = 0
TotalAttachments = 0
AttachmentsTypeCount = @{ ‘PDF’ = 0; ‘Word’ = 0; ‘Excel’ = 0; ‘PPT’ = 0; ‘Image’ = 0; ‘Other’ = 0 }
LastEmailReceived = $null
LastAccessTime = $null
}
# Get emails for this user
$emails = Get-EmailsForUser -userPrincipalName $userPrincipalName
foreach ($email in $emails) {
$mailData.TotalEmails++
# Track the last email received time
if (-not $mailData.LastEmailReceived -or $mailData.LastEmailReceived -lt $email.receivedDateTime) {
$mailData.LastEmailReceived = $email.receivedDateTime
}
# Check for attachments
if ($email.hasAttachments) {
$attachments = Get-AttachmentsForEmail -userPrincipalName $userPrincipalName -emailId $email.id
foreach ($attachment in $attachments) {
$mailData.TotalAttachments++
# Determine the type of attachment by file extension
if ($attachment.name -match ‘.pdf$’) { $mailData.AttachmentsTypeCount[‘PDF’]++ }
elseif ($attachment.name -match ‘.docx?$’) { $mailData.AttachmentsTypeCount[‘Word’]++ }
elseif ($attachment.name -match ‘.xlsx?$’) { $mailData.AttachmentsTypeCount[‘Excel’]++ }
elseif ($attachment.name -match ‘.pptx?$’) { $mailData.AttachmentsTypeCount[‘PPT’]++ }
elseif ($attachment.contentType -match ‘image/’) { $mailData.AttachmentsTypeCount[‘Image’]++ }
else { $mailData.AttachmentsTypeCount[‘Other’]++ }
}
}
}
# Get mailbox settings (last access time)
$mailboxSettings = Get-MailboxSettings -userPrincipalName $userPrincipalName
$mailData.LastAccessTime = $mailboxSettings.lastSignInDateTime
# Add user data to the results
$mailboxDataCollection += $mailData
}
# Step 3: Output results
$mailboxDataCollection | Format-Table -AutoSize
# Optionally, export the results to CSV
$mailboxDataCollection | Export-Csv -Path “MailboxDataReport.csv” -NoTypeInformation
My goal is to achieve:
Total Numbers of email by each mailboxTotal Attachments per email by each mailboxType of attachments (PDF, Word, Excel, PPT, Image, Etc..)Last access
Can someone help me in guiding where i am going wrong i have created azure app with proper permissions but my script is not giving me output as expected.
# Replace these with your app registration details$tenantId = “”$clientSecret = “”$clientId = “”# OAuth 2.0 token endpoint for your tenant$tokenUrl = “https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token”# Microsoft Graph API base URL$graphApiUrl = “https://graph.microsoft.com/v1.0″# The resource scope we are requesting (Mail.Read, MailboxSettings.Read, User.ReadBasic.All)$scope = “https://graph.microsoft.com/.default”# Request an OAuth 2.0 token from Azure AD using the client credentials flow$tokenResponse = Invoke-RestMethod -Method Post -Uri $tokenUrl -ContentType “application/x-www-form-urlencoded” -Body @{client_id = $clientIdclient_secret = $clientSecretscope = $scopegrant_type = “client_credentials”}# Extract the access token from the response$accessToken = $tokenResponse.access_token# Headers for authenticated requests to Microsoft Graph$headers = @{Authorization = “Bearer $accessToken”}# Function to fetch paginated results from Microsoft Graph APIfunction Get-PaginatedData {param ([Parameter(Mandatory = $true)][string]$initialUrl)$results = @()$nextLink = $initialUrlwhile ($nextLink) {try {$response = Invoke-RestMethod -Uri $nextLink -Headers $headers$results += $response.value# Check if there is more data to fetchif ($response.’@odata.nextLink’) {$nextLink = $response.’@odata.nextLink’} else {$nextLink = $null}} catch {# Capture and display detailed error informationWrite-Host “Error fetching data:”if ($_.Exception.Response -is [System.Net.HttpWebResponse]) {$httpResponse = $_.Exception.ResponseWrite-Host “StatusCode: $($httpResponse.StatusCode)”Write-Host “StatusDescription: $($httpResponse.StatusDescription)”# Read the response stream for detailed error$streamReader = New-Object System.IO.StreamReader($httpResponse.GetResponseStream())$responseBody = $streamReader.ReadToEnd()Write-Host “Response Body: $responseBody”} else {Write-Host “An unknown error occurred.”}break}}return $results}# Function to get all emails for a userfunction Get-EmailsForUser {param ([Parameter(Mandatory = $true)][string]$userPrincipalName)$mailApiUrl = “$graphApiUrl/users/$userPrincipalName/messages”return Get-PaginatedData -initialUrl $mailApiUrl}# Function to get attachment details for a specific emailfunction Get-AttachmentsForEmail {param ([Parameter(Mandatory = $true)][string]$userPrincipalName,[Parameter(Mandatory = $true)][string]$emailId)$attachmentApiUrl = “$graphApiUrl/users/$userPrincipalName/messages/$emailId/attachments”return Get-PaginatedData -initialUrl $attachmentApiUrl}# Function to get mailbox settings for a user (including last access time)function Get-MailboxSettings {param ([Parameter(Mandatory = $true)][string]$userPrincipalName)$mailboxSettingsApiUrl = “$graphApiUrl/users/$userPrincipalName/mailboxSettings”$mailboxSettings = Invoke-RestMethod -Uri $mailboxSettingsApiUrl -Headers $headersreturn $mailboxSettings}# Step 1: Fetch only user mailboxes by filtering on userType eq ‘Member’$usersApiUrl = “$graphApiUrl/users?`$filter=userType eq ‘Member'”Write-Host “Fetching user mailboxes…”$users = Get-PaginatedData -initialUrl $usersApiUrlif ($users.Count -eq 0) {Write-Host “No user mailboxes found. Aborting script.”exit}# Initialize result collection$mailboxDataCollection = @()# Step 2: Loop through each user and gather mailbox dataforeach ($user in $users) {$userPrincipalName = $user.userPrincipalNameWrite-Host “Processing mailbox for $userPrincipalName…”# Initialize user data$mailData = @{User = $userPrincipalNameTotalEmails = 0TotalAttachments = 0AttachmentsTypeCount = @{ ‘PDF’ = 0; ‘Word’ = 0; ‘Excel’ = 0; ‘PPT’ = 0; ‘Image’ = 0; ‘Other’ = 0 }LastEmailReceived = $nullLastAccessTime = $null}# Get emails for this user$emails = Get-EmailsForUser -userPrincipalName $userPrincipalNameforeach ($email in $emails) {$mailData.TotalEmails++# Track the last email received timeif (-not $mailData.LastEmailReceived -or $mailData.LastEmailReceived -lt $email.receivedDateTime) {$mailData.LastEmailReceived = $email.receivedDateTime}# Check for attachmentsif ($email.hasAttachments) {$attachments = Get-AttachmentsForEmail -userPrincipalName $userPrincipalName -emailId $email.idforeach ($attachment in $attachments) {$mailData.TotalAttachments++# Determine the type of attachment by file extensionif ($attachment.name -match ‘.pdf$’) { $mailData.AttachmentsTypeCount[‘PDF’]++ }elseif ($attachment.name -match ‘.docx?$’) { $mailData.AttachmentsTypeCount[‘Word’]++ }elseif ($attachment.name -match ‘.xlsx?$’) { $mailData.AttachmentsTypeCount[‘Excel’]++ }elseif ($attachment.name -match ‘.pptx?$’) { $mailData.AttachmentsTypeCount[‘PPT’]++ }elseif ($attachment.contentType -match ‘image/’) { $mailData.AttachmentsTypeCount[‘Image’]++ }else { $mailData.AttachmentsTypeCount[‘Other’]++ }}}}# Get mailbox settings (last access time)$mailboxSettings = Get-MailboxSettings -userPrincipalName $userPrincipalName$mailData.LastAccessTime = $mailboxSettings.lastSignInDateTime# Add user data to the results$mailboxDataCollection += $mailData}# Step 3: Output results$mailboxDataCollection | Format-Table -AutoSize# Optionally, export the results to CSV$mailboxDataCollection | Export-Csv -Path “MailboxDataReport.csv” -NoTypeInformationMy goal is to achieve:Total Numbers of email by each mailboxTotal Attachments per email by each mailboxType of attachments (PDF, Word, Excel, PPT, Image, Etc..)Last accessCan someone help me in guiding where i am going wrong i have created azure app with proper permissions but my script is not giving me output as expected. Read More