Back to script library
Entra / Microsoft 365 · Exchange Online

Remove utility messages from mailboxes

Example of how to use the Microsoft Graph PowerShell SDK cmdlets to remove "utility" messages from user mailboxes.

Connect & set up

Run these once per session. All scopes are read-only unless the script makes changes.

Connect-MgGraph -NoWelcome -ClientId $AppId -TenantId $TenantId -CertificateThumbprint $AppThumbprint

Run it

The main script. Copy it, or download the .ps1 and run it from your console.

param(
[string] $TenantId = "",
[string] $AppId = "",
[int] $LookbackDays = 1825,
[string] $StartDate = (Get-Date).AddDays(-$LookbackDays),
[string] $EndDate = (Get-Date)
)
$AppThumbprint = "F79286DB88C21491110109A0222348FACF694CBD"
# The app needs the following application permissions:
# User.Read.All: Read user account details
# Mail.ReadWrite: Read and write mail in all mailboxes
# Mail.Send: Send mail as a user
Connect-MgGraph -NoWelcome -ClientId $AppId -TenantId $TenantId -CertificateThumbprint $AppThumbprint
# List the email addresses of the notification messages to search for and remove
$UM0 = "notifications@communityhub.microsoft.com"
$UM1 = "messages-noreply@linkedin.com"
$UM2 = "noreply@microsoft.com"
$UM3 = "notifications-noreply@linkedin.com"
$UM4 = "noreply@yammer.com"
$UM5 = "microsoft@powerapps.com"
$UM6 = "o365mc@microsoft.com"
$UM7 = "jobs-listings@linkedin.com"
$UM8 = "notifications@yammer.com"
$UM9 = "noreply@amazon.com"
$UM10 = "notify@mstechcommunity.microsoft.com"
$UM11 = "notifications@owler.com"
# Set the start and end dates for the search - starting five years ago and ending 30 days ago
[datetime]$StartDate = (Get-Date).AddDays(-$LookbackDays)
[string]$StartDate = Get-Date $StartDate -Format "yyyy-MM-ddTHH:mm:ssZ"
[datetime]$EndDate = (Get-Date).AddDays(-$LookbackDays)
[string]$EndDate = Get-Date $EndDate -Format "yyyy-MM-ddTHH:mm:ssZ"
# Define the service plan IDs for Exchange Online (Plan 1) and Exchange Online (Plan 2)
$ExoServicePlan1 = "9aaf7827-d63c-4b61-89c3-182f06f82e5c"
$ExoServicePlan2 = "efb87545-963c-4e0d-99df-69c6916d9eb0"
# Find users assigned a license that includes the Exchange Online (Plan 1) or Exchange Online (Plan 2) service plans.
# The check also looks for users with the Exchange Online service plan enabled.
Write-Host "Finding mailboxes..." -ForegroundColor Cyan
[array]$Users = Get-MgUser -Filter "assignedPlans/any(c:c/servicePlanId eq $ExoServicePlan1 and capabilityStatus eq 'Enabled') `
or assignedPlans/any(c:c/servicePlanId eq $ExoServicePlan2 and capabilityStatus eq 'Enabled')" `
-ConsistencyLevel eventual -CountVariable Test -All -PageSize 999 -Sort ('displayname') `
-Property Id, displayName, userprincipalName, assignedLicenses, assignedPlans, department, country, CreatedDateTime
If ($Users) {
Write-Output ("{0} users licensed for Exchange Online found" -f $Users.Count)
} Else {
Write-Output "No mailboxes found"
Break
}
$Report = [System.Collections.Generic.List[Object]]::new()
ForEach ($User in $Users) {
Write-Host ("Processing mailbox {0}" -f $User.DisplayName) -ForegroundColor Yellow
[int]$i = 0
[array]$Messages = Get-MgUserMailFolderMessage -UserId $User.Id -MailFolderId 'Inbox' `
-Filter "(ReceivedDateTime ge $StartDate and ReceivedDateTime le $EndDate) `
and (sender/emailAddress/address eq '$UM0' or sender/emailAddress/address eq '$UM1' or sender/emailAddress/address eq '$UM2' `
or sender/emailAddress/address eq '$UM3' or sender/emailAddress/address eq '$UM4' or sender/emailAddress/address eq '$UM5' `
or sender/emailAddress/address eq '$UM6' or sender/emailAddress/address eq '$UM7' or sender/emailAddress/address eq '$UM8' `
or sender/emailAddress/address eq '$UM9' or sender/emailAddress/address eq '$UM10' or sender/emailAddress/address eq '$UM11')" `
-Property Id, Subject, Sender, SentDateTime -All -PageSize 999
If ($Messages) {
# If messages are found, delete them!
ForEach ($Message in $Messages) {
Try {
Remove-MgUserMessage -UserId $User.Id -MessageId $Message.Id -ErrorAction Continue
$i++
$ReportLine = [PSCustomObject][Ordered]@{
Timestamp = (Get-Date -format s)
Action = 'Message Deleted'
Mailbox = $User.DisplayName
SMTPAddress = $User.UserPrincipalName
Subject = $Message.Subject
SenderEmail = $Message.Sender.EmailAddress.Address
SenderName = $Message.Sender.EmailAddress.Name
Sent = $Message.SentDateTime
}
} Catch {
Write-Host ("Failed to remove message {0} from mailbox {1} with error {2}" -f $Message.Id, $User.DisplayName, $_.Exception.Message) -ForegroundColor Red
$ReportLine = [PSCustomObject][Ordered]@{
Timestamp = (Get-Date -format s)
Action = 'Message Deletion Failed'
Mailbox = $User.DisplayName
SMTPAddress = $User.UserPrincipalName
Subject = $Message.Subject
SenderEmail = $Message.Sender.EmailAddress.Address
SenderName = $Message.Sender.EmailAddress.Name
Sent = $Message.SentDateTime
}
}
$Report.Add($ReportLine)
}
} Else {
Write-Host ("No notification messages found in mailbox {0}" -f $User.DisplayName) -ForegroundColor Green
}
If ($i -gt 0) {
Write-Host ("{0} notification messages removed from mailbox {1}" -f $i, $User.DisplayName) -ForegroundColor Green
}
}
$Report | Out-GridView -Title "Utility Messages Removed from Mailboxes"
# Send email to the mailbox owners
[array]$IndividualMailboxes = $Report | Sort-Object SMTPAddress -Unique | Select-Object -ExpandProperty SMTPAddress
$MsgSubject = "Notification Messages Removed from Your Mailbox"
$MsgFrom = 'Azure.Management.Account@office365itpros.com'
$HTMLHeader = "<body><h1>Messages removed by the ever-loyal Utility Message Removal Service</h1>
<p><strong>Generated:</strong> $(Get-Date -Format g)</p>
<h2><u>Messages removed from your Inbox</u></h2></p>
<p>The background agent removes messages from selected senders from your mailbox to avoid a build-up of messages with little value.</p>
<p>If necessary, you can recover these messages by going to the Deleted Items folder and using the <i>Recover items recently removed from this folder</i> option.</p>"
$HTMLFooter =
"<p>------------------------------------------------------------------------------</p>" +
"<p>This email was sent by the Utility Message Removal service" +
"<p>------------------------------------------------------------------------------</p></body>"
ForEach ($Address in $IndividualMailboxes) {
# Create a HTML fragment containing details of the messages removed from the mailbox
$HTMLReport = $Report | Where-Object {$_.SMTPAddress -eq $Address -and $_.Action -eq 'Message Deleted'} | `
Select-Object Action, Subject, SenderEmail, SenderName, Sent | Sort-Object {$_.Sent -as [datetime]} -Descending
Write-Host ("Sending notification about {0} removed messages to {1}" -f $HTMLReport.count, $Address)
$HTMLReport = $HTMLReport | ConvertTo-Html -Fragment
# Assemble the pieces into a complete HTML message
$HTMLBody = $HTMLHeader + $HTMLReport + $HTMLFooter
# Add the recipient using the mailbox's primary SMTP address
$EmailAddress = @{address = $Address}
$EmailRecipient = @{EmailAddress = $EmailAddress}
# Construct the message body
$MessageBody = @{
content = "$($HtmlBody)"
ContentType = 'html'
}
# Create a draft message in the sending mailbox
$NewMessage = New-MgUserMessage -UserId $MsgFrom -Body $MessageBody -ToRecipients $EmailRecipient -Subject $MsgSubject
# Send the message
Send-MgUserMessage -UserId $MsgFrom -MessageId $NewMessage.Id
}
Write-Host ("Utility message cleanup complete. Details of {0} notification messages sent to {1} users" -f $Report.Count, $IndividualMailboxes.Count) -ForegroundColor Cyan
# Generate the report in either Excel worksheet or CSV format, depending on if the ImportExcel module is available
If (Get-Module ImportExcel -ListAvailable) {
Import-Module ImportExcel -ErrorAction SilentlyContinue
$ExcelOutputFile = ((New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path) + "\Removed Notification Messages Report.xlsx"
$Report | Export-Excel -Path $ExcelOutputFile -WorksheetName "Deleted Notification Messages" -Title ("Removed Notification Messages {0}" -f (Get-Date -format 'dd-MMM-yyyy')) -TitleBold -TableName "Microsoft365LicensingReport"
Write-Host ("Report saved to {0}" -f $ExcelOutputFile) -ForegroundColor Green
} Else {
$CSVOutputFile = ((New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path) + "\Removed Notification Messages Report.CSV"
$Report | Export-Csv -Path $CSVOutputFile -NoTypeInformation -Encoding Utf8
Write-Host ("Report saved to {0}" -f $CSVOutputFile) -ForegroundColor Green
}

Parameters

ParameterDefaultNotes
-TenantId""Microsoft Entra tenant ID for app-only Graph authentication.
-AppId""Application (client) ID for the app registration used to connect.
-LookbackDays1825Maximum age in days of utility messages to remove from mailboxes (default is about five years).
-StartDate(Get-Date).AddDays(-10)Start of the reporting window.
-EndDate(Get-Date)End of the reporting window.
Attribution