Microsoft Graph API - How to find out which user sent an email on behalf of a shared mailbox address with Send As permission?

Aaron Olson 6 Reputation points
2022-07-06T19:41:06.657+00:00

I have a shared mailbox. The shared mailbox has an address SHAREDBOX1@mycompany.com. A handful of users have access to send emails on behalf of that mailbox. Via the Microsoft Graph API, is it possible to see which user sent an individual email via the sharedbox1 address?

With this use case in mind, it makes sense this would only be something we would check on outgoing messages.

Looking at the docs https://learn.microsoft.com/en-us/graph/api/resources/message?view=graph-rest-1.0 , the message properties specifically, is there any way to find which user sent an email on behalf of a shared mailbox?

For example, this is a (fake, all ids have been faked and sanitized) example email sent from a shared mailbox by a user on behalf of the shared mailbox represented in the the MS Graph API to 3 other users

 {  
        "@odata.etag": "W/\"CQSJDKJGKJGROwCC\"",  
        "id": "AASDGSDGSDFMP4-RK_VSDFA1-bSDFSDFjB-JHUffy=",  
        "createdDateTime": "2022-07-06T16:50:55Z",  
        "lastModifiedDateTime": "2022-07-06T16:51:03Z",  
        "changeKey": "CSDFSDFSDGSFDSDFSFCC",  
        "categories": [],  
        "receivedDateTime": "2022-07-06T16:50:00Z",  
        "sentDateTime": "2022-07-06T16:50:45Z",  
        "hasAttachments": false,  
        "internetMessageId": "<PDSVSSVSVFGNFGHJ.something.prod.outlook.com>",  
        "subject": "RE: Work Stuff",  
        "importance": "normal",  
        "parentFolderId": "SDFFGAGSDFHSDFHDFNIUERGHSJHDNVUIAGNOIGAIU",  
        "conversationId": "JHFBVJHSBVJBVJHZVJ=",  
        "conversationIndex": "ETHYTJTJDGNRYJD",  
        "isDeliveryReceiptRequested": false,  
        "isReadReceiptRequested": false,  
        "isRead": true,  
        "isDraft": false,  
        "webLink": "https://outlook.office365.com/owa/?ItemID=SFBHWIUEwfADtegVAJBVSHFBVYUS&exvsurl=1&viewmodel=ReadMessageItem",  
        "inferenceClassification": "focused",  
        "sender": {  
            "emailAddress": {  
                "name": "SHAREDBOX1",  
                "address": "SHAREDBOX1@mycompany.com"  
            }  
        },  
        "from": {  
            "emailAddress": {  
                "name": "SHAREDBOX1",  
                "address": "SHAREDBOX1@mycompany.com"  
            }  
        },  
        "toRecipients": [  
            {  
                "emailAddress": {  
                    "name": "Thad",  
                    "address": "thad@mycompany.com"  
                }  
            }  
        ],  
        "ccRecipients": [  
            {  
                "emailAddress": {  
                    "name": "Chad",  
                    "address": "chad@mycustomer.com"  
                }  
            },  
            {  
                "emailAddress": {  
                    "name": "Vlad",  
                    "address": "vlad@mycustomer.com"  
                }  
            }  
        ],  
        "bccRecipients": [],  
        "replyTo": [],  
        "flag": {  
            "flagStatus": "notFlagged"  
        }  
    }  

The email is from SHAREDBOX1@mycompany.com, being sent to Chad, Vlad, and Thad.
Let's say the user who actually sent the email on behalf of SHAREDBOX1@mycompany.com is brad@mycompany.com

I was hoping that the "sender" field would have contained brad@mycompany.com, as according to these docs https://learn.microsoft.com/en-us/graph/outlook-send-mail-from-other-user#send-on-behalf but that appears to not be the case. Both "sender" and "from" are always populated as SHAREDBOX1@mycompany.com (so that would indicate that the permission on the shared box for the users is "Send As" instead of "Send on Behalf") https://learn.microsoft.com/en-us/graph/outlook-send-mail-from-other-user#send-as

Assuming the permission is "Send As", is there somewhere else in the API where that information can be looked up?

Thank you!

PS, I also asked this question on SO https://stackoverflow.com/questions/72888977/microsoft-graph-api-how-to-find-out-which-user-sent-an-email-on-behalf-of-a-sh

Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
11,445 questions
0 comments No comments
{count} vote

3 answers

Sort by: Most helpful
  1. Dillon Silzer 56,681 Reputation points
    2022-07-06T21:07:48.093+00:00

    Have you tried using the script from https://o365reports.com/2022/05/11/find-who-sent-email-from-shared-mailbox-in-office-365-using-powershell/ ?

    Authenticate

    .\FindWhoSentEmailFromSharedMailbox.ps1

    "To audit all the emails sent from a shared mailbox using the SendAs permission, run the script with -SendAsOnly param."

    .\FindWhoSentEmailFromSharedMailbox.ps1 -SendAsOnly

    See the web page for further usage.

    <#  
    =============================================================================================  
    Name:           Find who sent email from shared mailbox  
    Description:    This script finds who sent emails from shared mailbox  
    Version:        1.0  
    Website:        o365reports.com  
    Script by:      O365Reports Team  
    For detailed script execution: https://o365reports.com/2022/05/11/find-who-sent-email-from-shared-mailbox-in-office-365-using-powershell  
    ============================================================================================  
    #>  
    Param  
    (  
        [Parameter(Mandatory = $false)]  
        [Nullable[DateTime]]$StartDate,  
        [Nullable[DateTime]]$EndDate,  
        [string]$SharedMBIdentity,  
        [switch]$SendAsOnly,  
        [Switch]$SendOnBehalfOnly,  
        [string]$UserName,  
        [string]$Password  
    )  
      
    Function Connect_Exo  
    {  
     #Check for EXO v2 module inatallation  
     $Module = Get-Module ExchangeOnlineManagement -ListAvailable  
     if($Module.count -eq 0)   
     {   
      Write-Host Exchange Online PowerShell V2 module is not available  -ForegroundColor yellow    
      $Confirm= Read-Host Are you sure you want to install module? [Y] Yes [N] No   
      if($Confirm -match "[yY]")   
      {   
       Write-host "Installing Exchange Online PowerShell module"  
       Install-Module ExchangeOnlineManagement -Repository PSGallery -AllowClobber -Force  
       Import-Module ExchangeOnlineManagement  
      }   
      else   
      {   
       Write-Host EXO V2 module is required to connect Exchange Online.Please install module using Install-Module ExchangeOnlineManagement cmdlet.   
       Exit  
      }  
     }   
     Write-Host Connecting to Exchange Online...  
     #Storing credential in script for scheduling purpose/ Passing credential as parameter - Authentication using non-MFA account  
     if(($UserName -ne "") -and ($Password -ne ""))  
     {  
      $SecuredPassword = ConvertTo-SecureString -AsPlainText $Password -Force  
      $Credential  = New-Object System.Management.Automation.PSCredential $UserName,$SecuredPassword  
      Connect-ExchangeOnline -Credential $Credential  
     }  
     else  
     {  
      Connect-ExchangeOnline  
     }  
    }  
      
    $MaxStartDate=((Get-Date).AddDays(-89)).Date  
      
    #Getting SendAs emails for past 90 days  
    if(($StartDate -eq $null) -and ($EndDate -eq $null))  
    {  
     $EndDate=(Get-Date).Date  
     $StartDate=$MaxStartDate  
    }  
    #Getting start date to audit sendas emails report  
    While($true)  
    {  
     if ($StartDate -eq $null)  
     {  
      $StartDate=Read-Host Enter start time for report generation '(Eg:04/28/2021)'  
     }  
     Try  
     {  
      $Date=[DateTime]$StartDate  
      if($Date -ge $MaxStartDate)  
      {   
       break  
      }  
      else  
      {  
       Write-Host `nAudit can be retrieved only for past 90 days. Please select a date after $MaxStartDate -ForegroundColor Red  
       return  
      }  
     }  
     Catch  
     {  
      Write-Host `nNot a valid date -ForegroundColor Red  
     }  
    }  
      
      
    #Getting end date to audit sendas emails report  
    While($true)  
    {  
     if ($EndDate -eq $null)  
     {  
      $EndDate=Read-Host Enter End time for report generation '(Eg: 04/28/2021)'  
     }  
     Try  
     {  
      $Date=[DateTime]$EndDate  
      if($EndDate -lt ($StartDate))  
      {  
       Write-Host End time should be later than start time -ForegroundColor Red  
       return  
      }  
      break  
     }  
     Catch  
     {  
      Write-Host `nNot a valid date -ForegroundColor Red  
     }  
    }  
      
    $OutputCSV=".\AuditWhoSentEmailsFromSharedMailbox_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm` tt).ToString()).csv"   
    $IntervalTimeInMinutes=1440    #$IntervalTimeInMinutes=Read-Host Enter interval time period '(in minutes)'  
    $CurrentStart=$StartDate  
    $CurrentEnd=$CurrentStart.AddMinutes($IntervalTimeInMinutes)  
      
    #Check whether CurrentEnd exceeds EndDate  
    if($CurrentEnd -gt $EndDate)  
    {  
     $CurrentEnd=$EndDate  
    }  
      
    if($CurrentStart -eq $CurrentEnd)  
    {  
     Write-Host Start and end time are same.Please enter different time range -ForegroundColor Red  
     Exit  
    }  
      
    Connect_EXO  
    $CurrentResultCount=0  
    $AggregateResultCount=0  
    Write-Host `nAuditing emails sent from shared mailboxes - $StartDate to $EndDate...  
    $ProcessedAuditCount=0  
    $OutputEvents=0  
    $ExportResult=""     
    $ExportResults=@()    
      
    #Check whether to retrieve for all the Shared mailboxes or a specific mailbox  
    if($SharedMBIdentity -eq "")  
    {  
     $SMBs=(Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails SharedMailbox).PrimarySMTPAddress  
    }  
    else  
    {  
     #Checking whether the user is available  
     if((Get-Mailbox -Identity $SharedMBIdentity -RecipientTypeDetails Sharedmailbox) -eq $null)  
     {  
      Write-Host Given Shared Mailbox does not exist. Please check the name. -ForegroundColor Red  
      exit  
     }  
    }  
      
    #Check for SendAs and SendOnBehalf filter  
    if($SendAsOnly.IsPresent)  
    {  
     $Operations="SendAs"  
    }  
    elseif($SendOnBehalfOnly.IsPresent)  
    {  
     $Operations="SendOnBehalf"  
    }  
    else  
    {  
     $Operations="SendAs,SendOnBehalf"  
    }  
      
    while($true)  
    {  
     #Getting audit data for the given time range  
     Search-UnifiedAuditLog -StartDate $CurrentStart -EndDate $CurrentEnd -Operations $Operations -SessionId s -SessionCommand ReturnLargeSet -ResultSize 5000 | ForEach-Object {  
      $ResultCount++  
      $ProcessedAuditCount++  
      Write-Progress -Activity "`n     Retrieving email sent activities from $CurrentStart to $CurrentEnd.."`n" Processed audit record count: $ProcessedAuditCount"  
      $MoreInfo=$_.auditdata  
      $Operation=$_.Operations  
      $SentBy=$_.UserIds  
      if($SentBy -eq "S-1-5-18")  
      {  
       $SentBy="Service account"  
      }  
      $AuditData=$_.auditdata | ConvertFrom-Json  
      If($Operation -eq "SendAs")  
      {  
       $SentFrom=$AuditData.SendAsUserSMTP  
      }  
      else  
      {  
       $SentFrom=$AuditData.SendOnBehalfOfUsersmtp  
      }  
      
      if($SharedMBIdentity -eq "")  
      {  
       if($SMBs -notcontains $SentFrom)  
       {  
        return  
       }  
      }  
      elseif($SentFrom -ne $SharedMBIdentity)  
      {  
       return  
      }  
         
      $Subject=$AuditData.Item.Subject  
      $Result=$AuditData.ResultStatus  
      $PrintFlag="True"  
      $SentTime=(Get-Date($AuditData.CreationTime)).ToLocalTime()  #Get-Date($AuditData.CreationTime) Uncomment to view the Activity Time in UTC  
       #Export result to csv  
       $OutputEvents++  
         #Export result to csv  
      $ExportResult=@{'Sent Time'=$SentTime;'Sent By'=$SentBy;'Sent From'=$SentFrom; 'Subject'=$Subject; 'Operation'=$Operation;'Result'=$Result;'More Info'=$MoreInfo}  
      $ExportResults= New-Object PSObject -Property $ExportResult    
      $ExportResults | Select-Object 'Sent Time','Sent By','Sent From','Subject','Operation','Result','More Info' | Export-Csv -Path $OutputCSV -Notype -Append   
        
     }  
     $currentResultCount=$currentResultCount+$ResultCount  
       
     if($CurrentResultCount -ge 50000)  
     {  
      Write-Host Retrieved max record for current range.Proceeding further may cause data loss or rerun the script with reduced time interval. -ForegroundColor Red  
      $Confirm=Read-Host `nAre you sure you want to continue? [Y] Yes [N] No  
      if($Confirm -match "[Y]")  
      {  
       Write-Host Proceeding audit log collection with data loss  
       [DateTime]$CurrentStart=$CurrentEnd  
       [DateTime]$CurrentEnd=$CurrentStart.AddMinutes($IntervalTimeInMinutes)  
       $CurrentResultCount=0  
       if($CurrentEnd -gt $EndDate)  
       {  
        $CurrentEnd=$EndDate  
       }  
      }  
      else  
      {  
       Write-Host Please rerun the script with reduced time interval -ForegroundColor Red  
       Exit  
      }  
     }  
      
       
     if($ResultCount -lt 5000)  
     {   
      if($CurrentEnd -eq $EndDate)  
      {  
       break  
      }  
      $CurrentStart=$CurrentEnd   
      if($CurrentStart -gt (Get-Date))  
      {  
       break  
      }  
      $CurrentEnd=$CurrentStart.AddMinutes($IntervalTimeInMinutes)  
      $CurrentResultCount=0  
      if($CurrentEnd -gt $EndDate)  
      {  
       $CurrentEnd=$EndDate  
      }  
     }                                                                                               
     $ResultCount=0  
    }  
      
    #Open output file after execution  
    If($OutputEvents -eq 0)  
    {  
     Write-Host No records found  
    }  
    else  
    {  
     Write-Host `nThe output file contains $OutputEvents audit records  
     if((Test-Path -Path $OutputCSV) -eq "True")   
     {  
      Write-Host `nThe Output file availble in $OutputCSV -ForegroundColor Green  
      $Prompt = New-Object -ComObject wscript.shell     
      $UserInput = $Prompt.popup("Do you want to open output file?",`     
     0,"Open Output File",4)     
      If ($UserInput -eq 6)     
      {     
       Invoke-Item "$OutputCSV"     
      }   
     }  
    }  
      
    #Disconnect Exchange Online session  
    Disconnect-ExchangeOnline -Confirm:$false -InformationAction Ignore -ErrorAction SilentlyContinue  
    

  2. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.


    Comments have been turned off. Learn more

  3. Piyush Chugh 5 Reputation points
    2023-03-13T08:13:35.86+00:00

    OP is specifically asking about a way to achieve this using Microsoft Graph API, which till date does not seem possible to me. The only actionable right now seems to be upvoting this feature request in Graph API -

    https://techcommunity.microsoft.com/t5/microsoft-365-developer-platform/determine-user-who-sent-a-shared-mailbox-message/idc-p/3766156#M1653

    0 comments No comments