functions/User/Get-OspreyUserEmailActivity.ps1

function Get-OspreyUserEmailActivity {
    <#
.DESCRIPTION
    Pulls email-related activity (Update, Delete, Send) for a user from the UAL. Does NOT pull MailItemsAccessed record.
.PARAMETER UserPrincipalName
    Single UPN of a user, comma separated list of UPNs, or array of objects that contain UPNs.
.OUTPUTS

    File: Exchange_UAL_Audit.csv
    Path: \<User>
    Description: All Exchange related audit events found in the Unified Audit Log.

    File: Exchange_Mailbox_Audit.csv
    Path: \<User>
    Description: All Exchange related audit events found in the Mailbox Audit Log.
    .EXAMPLE

    Get-OspreyUserMailboxAuditing -UserPrincipalName user@contoso.com

    Search for all Mailbox Audit logs from user@contoso.com
    .EXAMPLE

    Get-OspreyUserMailboxAuditing -UserPrincipalName (get-mailbox -Filter {Customattribute1 -eq "C-level"})

    Search for all Mailbox Audit logs for all users who have "C-Level" set in CustomAttribute1
#>


    param
    (
        [Parameter(Mandatory = $true)]
        [array]$UserPrincipalName
    )

    Test-EXOConnection
    $InformationPreference = "Continue"

    # Verify our UPN input
    [array]$UserArray = Test-UserObject -ToTest $UserPrincipalName

    foreach ($Object in $UserArray) {
        [string]$User = $Object.UserPrincipalName

        Out-LogFile ("Attempting to Gather Email Activity from the UAL for " + $User) -action

        ##Searching for Update records##
        #These records will show what emails a threat actor may have accessed

        Out-LogFile "Searching Unified Audit Log for Update events."
        $UALUpdateRecords = Get-AllUnifiedAuditLogEntry -UnifiedSearch ("Search-UnifiedAuditLog -UserIDs " + $User + " -RecordType ExchangeItem -operation update")
            
        if ($null -eq $UALUpdateRecords) {
            Out-LogFile "No Update activity found."
        }
        # If not null then we must have found some events so export them
        else {
            Out-LogFile ("Found " + $UALUpdateRecords.Count + " email Update records") 

            #build custom object out of UAL records to get the most important information
            $UpdateReport = Foreach ($record in $UALUpdateRecords) {
                $record1 = $record.auditdata | ConvertFrom-Json
                $subject = $record1.Item | Select-Object -ExpandProperty Subject -erroraction SilentlyContinue
                if ($null -eq $subject) {
                    $Subject = "Osprey: Subject Not Found"
                }
                [PSCustomObject]@{
                    CreationTime      = $record1.CreationTime
                    RecordId          = $record1.Id
                    Operation         = $record1.Operation
                    UserID            = $record1.UserID
                    ClientIP          = $record1.ClientIP
                    Subject           = $subject
                    ParentFolder      = $record1.Item | Select-Object -ExpandProperty ParentFolder  | Select-object -expandproperty Path
                    Attachments       = $record1.Item | Select-Object Attachments | Select-object -expandproperty Attachments
                    InternetMessageId = $record1.Item | Select-Object -ExpandProperty InternetMessageId
                    Id                = $record1.Item | Select-Object -ExpandProperty Id
                }
            }
            #output the object
            $UpdateReport | Out-MultipleFileType -FilePrefix "Email_Update_Records" -User $user -csv -json -xml
        }

        ##Searching for Delete records##
        Out-LogFile "Searching Unified Audit Log for Delete events."
        $UALDeleteRecords = Get-AllUnifiedAuditLogEntry -UnifiedSearch ("Search-UnifiedAuditLog -UserIDs " + $User + " -RecordType ExchangeItemGroup")

        if ($null -eq $UALDeleteRecords) {
            Out-LogFile "No Delete activity found."
        }
        else {
            Out-LogFile ("Found " + $UALDeleteRecords.Count + " email Delete records")

            #build custom object out of UAL records to get the most important information
            #this is a bit screwy right now due to the occasional multiple records returned in one record. will fix eventually.
            $DeleteReport = Foreach ($record in $UALDeleteRecords) {
                $record1 = $record.auditdata | ConvertFrom-Json
                $subject = $record1.AffectedItems | Select-object Subject | Select-object -expandproperty subject -erroraction SilentlyContinue
                if ($null -eq $subject) {
                    $Subject = "Osprey: Subject Not Found"
                }
                [PSCustomObject]@{
                    CreationTime = $record1.CreationTime
                    RecordId     = $record1.Id
                    Operation    = $record1.Operation
                    UserID       = $record1.UserID
                    ClientIP     = $record1.ClientIP
                    Subject      = $subject
                    Folder       = $record1.AffectedItems | Select-Object -ExpandProperty ParentFolder  | Select-object -expandproperty Path
                }
            }
            #output the object
            $DeleteReport | Out-MultipleFileType -FilePrefix "Email_Delete_Records" -User $user -csv -json -xml
        }

        ##Searching for Create records##
        Out-LogFile "Searching Unified Audit Log for Create events."
        $UALCreateRecords = Get-AllUnifiedAuditLogEntry -UnifiedSearch ("Search-UnifiedAuditLog -UserIDs " + $User + " -RecordType ExchangeItem -operation create")
            
        if ($null -eq $UALCreateRecords) {
            Out-LogFile "No Create activity found."
        }
        # If not null then we must have found some events so export them
        else {
            Out-LogFile ("Found " + $UALCreateRecords.Count + " email Create records") 

            #build custom object out of UAL records to get the most important information
            $CreateReport = Foreach ($record in $UALCreateRecords) {
                $record1 = $record.auditdata | ConvertFrom-Json
                $subject = $record1.Item | Select-Object -ExpandProperty Subject -erroraction SilentlyContinue
                if ($null -eq $subject) {
                    $Subject = "Osprey: Subject Not Found"
                }
                [PSCustomObject]@{
                    CreationTime      = $record1.CreationTime
                    RecordId          = $record1.Id
                    Operation         = $record1.Operation
                    UserID            = $record1.UserID
                    ClientIP          = $record1.ClientIP
                    Subject           = $subject
                    ParentFolder      = $record1.Item | Select-Object -ExpandProperty ParentFolder  | Select-object -expandproperty Path
                    InternetMessageId = $record1.Item | Select-Object -ExpandProperty InternetMessageId
                    Id                = $record1.Item | Select-Object -ExpandProperty Id
                }
            }
            #output the object
            $CreateReport | Out-MultipleFileType -FilePrefix "Email_Create_Records" -User $user -csv -json -xml
        }

    }
}