We’ve gotten reports from the end-users in an environment that Office 365 ATP Safe Attachments scan is taking a long time to finish. This causes frustration among the end users.

We got in contact with Microsoft and requested a report on Safe Attachments scan times, which they could not supply. After some research it seemed that this was not offered by either Microsoft or any reliable third-party. So we did some additional research and came up with the following script.

To execute this script you need to have the appropriate permissions in your tenant, and be running Exchange Online PowerShell.

Connect-ExchangeOnline

$Outfile = "C:\temp\ATPscan-$(Get-Date -Format "yyMMdd").csv"

$MessageList = $null  
$CurrMessages = $null
$Page = 1

do  
{  
    Write-Host "Collecting Message Trace - Page $Page..."  
    $CurrMessages = Get-MessageTrace -StartDate ((Get-Date).AddDays(-1)) -EndDate (Get-Date) -PageSize 5000 -Page $Page -Status Delivered | Where {$_.Size -gt 1MB}
    $Page++  
    $MessageList += $CurrMessages  
}  
until ($CurrMessages -eq $null)

#If starting a new analysis start from here.
$Row = 0
$TotalRow = $MessageList.count

# If resuming an ongoing/crashed analysis, start from here.
Write-Host "Starting at row $Row out of $TotalRow"
$MessageList | Select-Object -Skip $Row | % {
    $ID = ($_.MessageTraceId).Guid
    $Sender = $_.SenderAddress
    $Recipient = $_.RecipientAddress
    $Size = $_.Size
    $MessageDetails = $_ | Get-MessageTraceDetail | where { $_.Event -eq "Advanced Threat Protection" -or $_.Event -eq "Deliver"} | sort Date
    $First = ($MessageDetails | select -First 1).Date
    $Last = ($MessageDetails | select -Last 1).Date

    # Only if ATP was used
    If ($First -ne $null -and $Last -ne $null) {

        If ($First -eq $Last) {$Delay = 0}
        Else { $Delay =  [math]::Round((New-TimeSpan –Start $First –End $Last).TotalSeconds,0) }
        $Item = New-Object System.Object;
        $Item | Add-Member -Type NoteProperty -Name "ID" -Value $ID;
        $Item | Add-Member -Type NoteProperty -Name "Sender" -Value $Sender;
        $Item | Add-Member -Type NoteProperty -Name "Recipient" -Value $Recipient;
        $Item | Add-Member -Type NoteProperty -Name "Size" -Value $Size;
        $Item | Add-Member -Type NoteProperty -Name "Start" -Value $First;
        $Item | Add-Member -Type NoteProperty -Name "End" -Value $Last;
        $Item | Add-Member -Type NoteProperty -Name "Delay" -Value $Delay;
        #$results += $Item
        $Item | Export-Csv $Outfile -Encoding UTF8 -Delimiter ";" -NoTypeInformation -Append
    }
    $Row++
    If ($Row -like "*00") { Write-Host "$(Get-Date -Format "HH:mm"): Processed row $Row out of $TotalRow" }
}
Once executed and all the data collected we imported the CSV file into Power BI to get the graphics.

Please note that the script can take a long time to execute. We have about 100K transactions in our tenant and the script could take several hours to run.