Email security & monitoring
Internal Email Volume Report
Reports the number of messages sent per internal user per day from Exchange Online message trace, exported to CSV. Note: Get-MessageTrace covers only the last 10 days and is being replaced by Get-MessageTraceV2.
Replace generic placeholder values (tenant, domain, secrets) for your own environment before running. Read it first and test safely.
<#
.SYNOPSIS
Reports internal email volume per user per day from Exchange Online.
.DESCRIPTION
Connects to Exchange Online and, over a configurable window (default 7 days),
counts messages sent by internal users (matched by your own email domain),
groups them by sender and day, and exports the result to CSV.
Requires:
- The ExchangeOnlineManagement PowerShell module (Install-Module ExchangeOnlineManagement)
- An account permitted to run message-trace / mail-traffic reports.
.NOTES
Set the values in the "Configure for your environment" block before running.
Generic placeholder values are used in place of real tenant/domain values.
#>
# ---------------------------------------------------------------------------
# Configure for your environment
# ---------------------------------------------------------------------------
$AdminUpn = '[email protected]' # your Exchange Online admin account
$InternalDomain = '@yourdomain.co.nz' # your organisation's primary email domain
$OutputPath = 'C:\temp\InternalEmailMetrics.csv' # where to write the report
$DaysBack = 7 # how many days back to report on
# Connect to Exchange Online (prompts for sign-in / MFA)
Connect-ExchangeOnline -UserPrincipalName $AdminUpn
# Define the reporting window
$StartDate = (Get-Date).AddDays(-$DaysBack)
$EndDate = Get-Date
# Pull message-trace data; fall back to the traffic summary report if empty
$MessageTraceData = Get-MessageTrace -StartDate $StartDate -EndDate $EndDate
if ($MessageTraceData.Count -eq 0) {
Write-Host "No data from Get-MessageTrace. Trying alternative method..." -ForegroundColor Yellow
$MessageTraceData = Get-MailTrafficSummaryReport -StartDate $StartDate -EndDate $EndDate
}
# Count messages sent by internal users, grouped by sender and day
if ($MessageTraceData.Count -gt 0) {
$EmailVolumePerDay = $MessageTraceData |
# Internal senders only (match your own domain), and only delivered items
Where-Object { $_.SenderAddress -like "*$InternalDomain" -and $_.Received -ne $null } |
# Group by "sender - yyyy-MM-dd"
Group-Object { "$($_.SenderAddress) - $($_.Received.ToString('yyyy-MM-dd'))" } |
Select-Object @{Name='Sender'; Expression={($_.Name -split ' - ')[0]}},
@{Name='Date'; Expression={($_.Name -split ' - ')[1]}},
@{Name='Count'; Expression={$_.Count}} |
Sort-Object Date, Sender
$EmailVolumePerDay | Export-Csv -Path $OutputPath -NoTypeInformation
Write-Host "Report exported to $OutputPath" -ForegroundColor Green
} else {
Write-Host "No email data found for the specified date range." -ForegroundColor Red
}