I have got a case recently: “Can we check an email status (read/unread) regardless of whether the Read Receipt is being enabled or disabled in Outlook, or if a user checked the read receipt?” In this article, we’ll talk about how to track email read status in on-premises Exchange Server and a few words about this feature in Exchange Online (Microsoft 365).
Why may you need to get the email read status?
- If an email is crucial and you want to make sure that each employee has read it;
- Many companies use newsletter mailings (like news/birthdays/documents) and you want to get statistics on how effective such mailings are.
Can you have an email read status in an Exchange mailbox regardless of whether a sender requested a read receipt?
Tracking Read Status of an Email Message in Exchange Server
Let’s see how to get an email message read status in an on-prem Exchange Server mailbox. First of all, make sure that email read tracking is enabled in your Exchange organization:
Get-OrganizationConfig | Select ReadTrackingEnabled
True
— enabled, false
— disabled.
Enable the email read tracking using the command:
Set-OrganizationConfig -ReadTrackingEnabled $true
Only after running the command, read tracking data appear in the Exchange Server logs.
You can disable read status tracking for specific mailboxes (like, service or shared) using the command below:
Set-Mailbox [email protected] -MessageTrackingReadStatusEnabled $false
Then you need to get a message ID using the Get-MessageTrackingLog cmdlet:
Get-MessageTrackingLog -Sender [email protected] -MessageSubject "youremail subject" -Start (Get-Date).AddHours(-48) -EventId RECEIVE | Select MessageID
In our example, an email from this sender with a specific subject was sent several times for the last 48 hours. You can apply different filters to get an exact MessageID.
However, you can make it easier: open the email in Outlook, click File — Properties, and find the Message-ID in the Internet Headers section.
Then open the Exchange Management Shell and run the Get-MessageReadStatusReport.ps1 (the script code is shown below). Specify a mailbox name and a MessageID.
Thus, you get a CSV file with read statuses for the message in all user mailboxes. After an email has been delivered to the mailbox, two statuses are possible:
- Read –
The message is marked as Read in the user’s mailbox
- Unread –
The message is marked as Unread in the user’s mailbox
Here is Get-MessageReadStatusReport.ps1 script:
[CmdletBinding()]
param (
[Parameter( Mandatory=$true)]
[string]$Mailbox,
[Parameter( Mandatory=$true)]
[string]$MessageId
)
$output = @()
#Checking Exchange organization read tracking state
if (!(Get-OrganizationConfig).ReadTrackingEnabled) {
throw "Email tracking status is disabled"
}
#Getting an email ID
$msg = Search-MessageTrackingReport -Identity $Mailbox -BypassDelegateChecking -MessageId $MessageId
#There should be one message
if ($msg.count -ne 1) {
throw "$($msg).count emails found with this ID"
}
#Getting a report
$report = Get-MessageTrackingReport -Identity $msg.MessageTrackingReportId -BypassDelegateChecking
#Getting events
$recipienttrackingevents = @($report | Select -ExpandProperty RecipientTrackingEvents)
#Generating a list of recipients
$recipients = $recipienttrackingevents | select recipientaddress
#Getting an email status for each recipient
foreach ($recipient in $recipients) {
$events = Get-MessageTrackingReport -Identity $msg.MessageTrackingReportId -BypassDelegateChecking `
-RecipientPathFilter $recipient.RecipientAddress -ReportTemplate RecipientPath
$outputline = $events.RecipientTrackingEvents[-1] | Select RecipientAddress,Status,EventDescription
$output += $outputline
}
$output
$directory = "C:\PS\ExchangeReports"
$filename = 'ReadStatusReport'
$file = "$filename.csv"
#Exporting the report to CSV
$output | Export-Csv -NoTypeInformation -Append -Path "$directory\$file"
How to Check if a User Has Read an Email in Exchange Online (Microsoft 365)?
I tried to slightly modify this PowerShell script to get message read status in Exchange Online user mailboxes.
After connecting to my Microsoft 365 tenant using the Exchange Online PowerShell module, I checked to see if email read status tracking was enabled in Exchange Online. By default, messageTrackingReadStatusEnabled was enabled for all mailboxes in the tenant.
Get-EXOMailbox -Properties messageTrackingReadStatusEnabled|select UserPrincipalName,messageTrackingReadStatusEnabled
I edited the script, since the Get-MessageTrace
and Get-MessageTraceDetail
cmdlets are used for message tracking in Exchange Online instead of Get-MessageTrackingLog and Search-MessageTrackingReport. Unfortunately, Get-MessageTraceDetail in Exchange Online didn’t allow me to get a message status. Microsoft may improve the features of Get-MessageTraceDetail cmdlet to the ones of on-prem Search-MessageTrackingReport in the future, but now it does not work.
So the only way to view the message read status in an Exchange Online mailbox is Microsoft Graph API. You need to check the isRead property of the email (https://docs.microsoft.com/en-us/graph/api/message-get?view=graph-rest-1.0&tabs=http).