Table of Contents
Intro
A common task an exchange admin performs is tracking emails and seeing how the mail flow goes on a certain message. It is done by using Get-MessageTrackLog. let’s assume the following:
We have User1, User2, and User3. These users are members of a group named Group1 group1@mycompany.com. Group1 is a MailEndabled Exchange Group, and all the users have permission to SendOnBehalf of Group1.
An email was sent from Group1@mycompany.com to externaluser@intenret.com with the subject of “test1” to the internet, and we need to know which user sent this email.
Prerequisites
This script supports Exchange 2016 / Exchange Server 2019 on-prem
Investigating the SendOnBehalf permission
Users with sending on behalf permission use outlook to compose a new email. The user selects the group name they are delegated to send on behalf of, and they send the email. But sometimes, the user sends the wrong email, and you need to investigate which user sends the email on behalf of the group the email.
let’s start by trying the following command
Get-MessageTrackingLog -Sender group1@mycompany.com -Recipients externaluser@internet.com -Start (Get-Date).AddDays(-1)
The return result contains the regular data related to the message processing.
Not enough information to show which user sent on behalf of the distribution Group1. Even after expanding the properties of each entry with the | Format-list
, the returned information won’t contain much useful information, related to which user exactly sends the message. The output for ExternalSend EventID is similar to this
RunspaceId : bcbc32d1-2aad-43bb-92ae-853322f11422
Timestamp : 30-Aug-20 10:13:34 AM
ClientIp : 192.168.0.1
ClientHostname : Server1
ServerIp : 192.168.0.10
ServerHostname : 192.168.0.10
SourceContext : ;250 2.0.0 07U6DNXv028102-07U6DXNx028102 Message accepted for delivery;ClientSubmitTime:
ConnectorId : SendConnector
Source : SMTP
EventId : SENDEXTERNAL
Recipients : {externaluser@intenret.com}
RecipientStatus : {250 2.1.5 externaluser@intenret.com… Recipient ok}
TotalBytes : 6983
RecipientCount : 1
RelatedRecipientAddress :
MessageSubject : test1
Sender : group1@mycompany.com
ReturnPath : group1@mycompany.com
Directionality : Originating
MessageLatencyType : EndToEnd
EventData : {[E2ELatency, 1.406], [ExternalSendLatency, 1.125], [ToEntity, Internet], [FromEntity, Hosted], [MsgRecipCount, 1], [IncludeInSla, True], [Microsoft.Exchange.Transport.MailRecipient.RequiredTlsAuthLevel,
Opportunistic], [Microsoft.Exchange.Transport.MailRecipient.EffectiveTlsAuthLevel, EncryptionOnly], [IsSmtpResponseFromExternalServer, True], [DeliveryPriority, Normal], [AccountForest, mycompany.com]}
TransportTrafficType : Email
SchemaVersion : 15.01.1847.009
As shown from the colored bolded text, the sender is the group itself, and no information related to who sent the email.
The solution to Find the user SendOnBehalf of Group1
I will start by showing the actual user who sent on behalf of the distribution group (user1@mycompany.com), and how the result will look like in the Get-MessageTrackLog
. So let’s make the first change and execute the following command:
Get-MessageTrackingLog -Sender user1@mycompany.com -Recipients externaluser@internet.com | fl Recipients,Sender,EventData
Recipients : {externaluser@internet.com}
Sender : user1@mycompany.com
EventData : {[MailboxDatabaseGuid, d519b839-03b2-44cc-8bf8-ee2a9f6d01fa], [ItemEntryId,
00-00-00-00-9C-B8-92-3C-06-AE-F1-4A-AA-3F-A5-FA-A9-22-43-D6-07-00-B5-C7-9D-B9-59-48-E3-43-B9-8B-77-93-11-F0-8C-63-00-00-00-FB-71-FB-00-00-F3-29-04-BC-DF-0A-01-44-92-4D-09-A5-B5-D8-42-76-00-03-E3-59-0A-C2-00-00],
[DeliveryPriority, Normal], [AccountForest, adcci.gov.ae], [PurportedSender, mygroup1@company.com]}
Recipients : {externaluser@internet.com}
Sender : user1@mycompany.com
EventData : {[ItemEntryId,
00-00-00-00-9C-B8-92-3C-06-AE-F1-4A-AA-3F-A5-FA-A9-22-43-D6-07-00-B5-C7-9D-B9-59-48-E3-43-B9-8B-77-93-11-F0-8C-63-00-00-00-FB-71-FB-00-00-F3-29-04-BC-DF-0A-01-44-92-4D-09-A5-B5-D8-42-76-00-03-E3-59-0A-C2-00-00],
[DeliveryPriority, Normal], [PurportedSender, group1@mycompany.com]}
Notice the Sender property which holds the individual user email address and the PurportedSender which holds the group email address, this actually is telling that this user user1@mycompany.com SendOnBehalf group1@mycompany.com emails to the internet. So the key we need to use in our search is Sender and PurportedSender.
But in the case of a group with a lot of members in it, we won’t go through all of them manually, so with a small script we can achieve this:
Get-MessageTrackingLog -Recipients externaluser@internet.com | where {($_.EventData -contains "[PurportedSender, mygroup1@mycompany.com]")}| fl EventData,Sender
SendOnBehalf Finder PowerShell Script
But to avoid duplicated results, I made a Powershell script that includes everything. The filter is based on the EventID=Submit.
The Supported parameters are:
- [String, Required]RecipientsEmail: its the Recipient Email
- [String, Required]SourceGroupName: The name of the Exchange group which the email sent using this group email “MyGroup1@mycompany.com”
- [Int, NotRequired]PeriodinHour: The default value is 24 hour, and it’s the search time base, so it searches for all emails before 24 hours. No need to add the minus “-” sign. You just need to mention the range to search
- [String, Not Required]ServerToSearch: Default Localhost. this is the Exchange server you want to search through. You can add multiple servers, for example “Server1″,”Server2”
- [String, Required]MgmtPSFullUri: The URI to connect to MGMT Powershell URI to initial the session, usually its https://Exchange_Name_Space_URL/powershell ,or maybe http://servername_FQDN/Powershell
The script will establish the connection to the exchange server and do the filter and query needed to get the result.
Anyway, read the comment to understand how this script work, easy 1 liner execution. 🙂
<#
.SYNOPSIS
This script will tell you which user use the SendOnBehalf permission to send email to the internet on behalf of a group.
.DESCRIPTION
If you multiple users and they are granted the SendOnBehalf permission on a group, this script will tell
which user send which email
.PARAMETER FirstParameter
$RecipientsEmail: Required, and its the Recient Email
.PARAMETER SecondParameter
$SourceGroupName: Required, the name of the Exchange group which the email sent using this group email "MyGroup1@mycompany.com"
.PARAMETER ThirdParameter
$PeriodinHour: NotRequired, Default value is 24 hour and its the search time base, so it will search for all emails before 24 hour.
No need to add the minus sign, its by default there, you just need to mention the range to search
.PARAMETER ForthParameter
$ServerToSearch: NotRequired, Default Localhost. this is the Exchange server you want to search, you can add multiple servers for example "Server1","Server2"
.PARAMETER Sixthparameter
$MgmtPSFullUri: Required, The URI to connect to MGMT Powershell URI to initial the session, usually its https://Exchange_Name_Space_URL/powershell ,or maybe http://servername_FQDN/Powershell
You can find the URI through the following powershell command
(Get-PowerShellVirtualDirectory -Server MyServerName).InternalUrl.AbsoluteUri
.OUTPUTS
The Sender: User1@Mycompany.com
The Group: Mygroup@mycompany.com
The Subject: EmailMessageSubject
The Server: Server1
--------------------------
.EXAMPLE
.\WhoSendWhat.ps1 -RecipientsEmail externaluser@ontheinternet.com -SourceGroupName mygroup@mycompany.com -PeriodinHour 24 -ServerToSearch "myserver"
or for multiple servers
.\WhoSendWhat.ps1 -RecipientsEmail externaluser@ontheinternet.com -SourceGroupName mygroup@mycompany.com -PeriodinHour 24 -ServerToSearch "Server1","Server2"
.NOTES
Feel free and let me know if you got any comment by sending me an email to farisnt@gmail.com
Make sure that the server you prefer to use to establish the Powershell session is the first one
#>
[cmdletbinding()]
param(
[parameter(Mandatory)]$RecipientsEmail,
[parameter(Mandatory)]$SourceGroupName,
[parameter(Mandatory)]$ServerToSearch,
[parameter(Mandatory)]$MgmtPSFullUri,
[parameter(Mandatory=$false)]$PeriodinHour=24
)
Try{
if (!(Get-PSSession | where {($_.ConfigurationName -like "microsoft.exchange") -and ($_.State -like "Opened")})){
$ExchangeSession=New-PSSession -ConnectionUri $MgmtPSFullUri -ConfigurationName microsoft.exchange -ErrorAction Stop
Import-PSSession $ExchangeSession
Write-Host "Connection is established and will start getting the result.. please wait"
}
}
catch{
Write-Host $Error[0] -ForegroundColor Red
Write-Host "Ops, some issue occure and cannot continue..."
break
}
try{
foreach ($SingleServer in $ServerToSearch){
$Emails=Get-MessageTrackingLog -Recipients $RecipientsEmail -Start (Get-Date).AddHours(-$PeriodinHour) -Server $SingleServer -ErrorAction stop | where {($_.EventData -contains "[PurportedSender, $SourceGroupName]") -and ($_.EventId -like "SUBMIT")}
if ($Emails.count -gt 0){
foreach ($item in $Emails){
$Eventdatainfo = (($item.EventData | where {$_ -like "*PurportedSender*"}).substring(18)).split("]")[0]
Write-Host "The Sender: " $item.Sender
Write-Host "The Group: " $Eventdatainfo
Write-Host "The Subject: " $item.MessageSubject
Write-Host "The Server: " $SingleServer
Write-Host " --------------------------"
Write-Host ""
}
}
Else{
Write-Host "No result found"
}
}
}
catch {
Write-Host $Error[0] -ForegroundColor Red
}
If you like this post, then check on Redistribute Mailboxes from Large Exchange Database Smaller DB
Also, you can take a look at my Github and find more PowerShell Scripts.