Another quick post. This time we combine Advanced Hunting Kusto Query Language (KQL) queries and Microsoft PowerShell Graph SDK.
We will use the same Advanced Hunting Kusto Query Language (KQL) as before:
EmailEvents
| summarize Recipients= make_list(RecipientEmailAddress) by Subject,
NetworkMessageId
| project Subject, Recipients, NetworkMessageId
The PowerShell is also mostly the same with a few changes.
# Connect to the Graph using the App registration details
Connect-MgGraph `
-ClientId "05c53143-7c86-48b8-ac78" `
-TenantId "4510da24-0f43-48d3-837d" `
-CertificateThumbprint "3F813D3DAC8E3613199359D23AEBA"
However, we need to adjust the App registration API permissions to include the following:
- SecurityEvents.ReadWrite.All
- ThreatHunting.Read.All
Remember, these permissions will also need admin consent.

Now for the PowerShell:
# Define the Query
$query = "EmailEvents
| summarize Recipients = make_list(RecipientEmailAddress) by Subject,
NetworkMessageId
| project Subject, Recipients, NetworkMessageId"
# Create the JSON body
$body = @{
Query = $query
} | ConvertTo-Json
# Invoke the Microsoft Graph API to run the hunting query
$result = Invoke-MgGraphRequest `
-Method POST `
-Uri "https://graph.microsoft.com/v1.0/security/runHuntingQuery" `
-Body $body
# Process the results and create rows for each item with the specified columns
$table = $result.results | ForEach-Object {
[PSCustomObject]@{
Subject = $_.Subject
RecipientList = $_.Recipients
NetworkMessageId = $_.NetworkMessageId
}
}
# Display the table
$table | Format-Table
Here is the full code:
Connect-MgGraph `
-ClientId "<ClientId>" `
-TenantId "<TenantId>" CertificateThumbprint`
-CertificateThumbprint "<>"
$query = "EmailEvents
| summarize Recipients = make_list(RecipientEmailAddress) by Subject,
NetworkMessageId
| project Subject, Recipients, NetworkMessageId"
$body = @{
Query = $query
} | ConvertTo-Json
$result = Invoke-MgGraphRequest `
-Method POST `
-Uri "https://graph.microsoft.com/v1.0/security/runHuntingQuery" `
-Body $body
$table = $result.results | ForEach-Object {
[PSCustomObject]@{
Subject = $_.Subject
RecipientList = $_.Recipients
NetworkMessageId = $_.NetworkMessageId
}
}
$table | Format-Table
After executing this code will return the same values that the Kusto Query Language (KQL) returned within Advance Hunting. I hope this is helpful, happy hunting 🙂
You must log in to post a comment.