Coming soon - Get a detailed view of why an account is flagged as spam!
view details

This post has been de-listed

It is no longer included in search results and normal feeds (front page, hot posts, subreddit posts, etc). It remains visible only via the author's post history.

3
Gathering DMARC reports from an O365 Mailbox
Post Flair (click to view more posts with a particular flair)
Post Body

I know there are a lot of options out there for DMARC report gathering, but as a project to get used to MSGraph API I wanted to write a script to send a csv report of our DMARC mailbox. It gives a csv that looks like this

#Requires -modules microsoft.graph.mail

## Function to extract GZIP files
Function DeGZip-File{
    Param(
        $infile,
        $outfile = ($infile -replace '\.gz$','')
        )
    $inputfile = New-Object System.IO.FileStream $inFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read)
    $output = New-Object System.IO.FileStream $outFile, ([IO.FileMode]::Create), ([IO.FileAccess]::Write), ([IO.FileShare]::None)
    $gzipStream = New-Object System.IO.Compression.GzipStream $inputfile, ([IO.Compression.CompressionMode]::Decompress)
    $buffer = New-Object byte[](1024)
    while($true){
        $read = $gzipstream.Read($buffer, 0, 1024)
        if ($read -le 0){break}
        $output.Write($buffer, 0, $read)
        }
    $gzipStream.Close()
    $output.Close()
    $inputfile.Close()
}
 ## Function to convert records to a psobject
Function ConvertRecord($Record, $report){
    $unixtime = get-date 1/1/1970
    $Begin = $unixtime.AddSeconds($report.report_metadata.date_range.begin)
    $End = $unixtime.AddSeconds($report.report_metadata.date_range.end)
    $O = New-Object psobject -Property ([ordered]@{
        SourceIp = $Record.row.source_ip
        Count = [int]::Parse($Record.row.count)
        Disposition = $Record.row.policy_evaluated.disposition
        DkimDomain = $null;
        DkimResult = $Record.row.policy_evaluated.dkim
        SpfDomain = $Record.auth_results.spf.domain
        SpfResult = $Record.row.policy_evaluated.spf
        BeginDate = $begin
        EndDate = $end
        HeaderFrom = $Record.identifiers.header_from
        ReportFrom = $report.report_metadata.org_name
        OriginatingDomain = $report.policy_published.domain
    })

    if ($null -ne $Record.auth_results.dkim.domain) {
        if ($Record.auth_results.dkim.domain.GetType().Name -eq "Object[]"){
            $O.DkimDomain = $Record.auth_results.dkim.domain -join "|"
        } else {
            $O.DkimDomain = $Record.auth_results.dkim.domain
        }
    }

    return $O
}

import-module microsoft.graph.mail

$dst = "C:\DMARC\REPORT\LOCATION\"
$csvexport = $dst   "DMARC_Failed_Records.csv"
$mailbox = "[email protected]"

$ClientIDURL = 'https://pwdserver/clientid/url/'
$ClientID = Invoke-Restmethod -Method GET -Uri $ClientIDURL -UseDefaultCredentials
$tenantID = "TENANT-ID"
$certThumbprintURL = 'https://pwdserver/thumbprint/url/'
$certThumbprint = Invoke-Restmethod -Method GET -Uri $certThumbprintURL -UseDefaultCredentials
Connect-MgGraph -ClientID $ClientID.password -TenantId $tenantID -CertificateThumbprint $certThumbprint.password

## Get all messages
$messages = get-mgusermessage -UserId $mailbox -All

foreach ($m in $messages){
    ## Get Message attachement
    $attachment = Get-MgUserMessageAttachment -MessageId $m.Id -UserId $mailbox

    ## If attachment is an archive, grab and extract the report
    ## Mainly needed becuase Google sends DMARC reports as an eml with the archive attached rather than just sending the archive
    if ($attachment.ContentType -notlike "message*"){
        $filename = $dst   $attachment.name

        $Base64B = $attachment.AdditionalProperties.contentBytes
        $Bytes = [Convert]::FromBase64String($Base64B)
        [IO.File]::WriteAllBytes($Filename, $Bytes)

        switch ($attachment.name.Split(".")[-1]) {
            "zip" {
                expand-archive -Path $filename -DestinationPath $dst     
            }
            "gzip" {
                DeGZip-File  $Filename
            }
            "gz" {
                DeGZip-File  $Filename
            }
        }

        remove-item $filename -Confirm:$false
        Remove-MgUserMessage -MessageId $m.Id -UserId $mailbox
    }
    ## If the attachment is an eml, get the report archive that is attached to the eml file
    ## This was a PITA to figure out, but was super awesome feeling once I got it
    ## F-U Google for making this difficult, you are the ONLY one I have run across that does this
    Elseif ($attachment.ContentType -like "message*"){
        $uri = ("https://graph.microsoft.com/v1.0/users/"   $mailbox   "/messages/"   $m.id   "/attachments/"   $attachment.Id   '/?$expand=microsoft.graph.itemattachment/item' ) 

        $attachment = (Invoke-MgGraphRequest -Method get -Uri $uri).item.attachments
        $filename = $dst   $attachment.name

        $Base64B = $attachment.contentBytes
        $Bytes = [Convert]::FromBase64String($Base64B)
        [IO.File]::WriteAllBytes($Filename, $Bytes)

        switch ($attachment.name.Split(".")[-1]) {
            "zip" {
                expand-archive -Path $filename -DestinationPath $dst     
            }
            "gzip" {
                DeGZip-File  $Filename
            }
            "gz" {
                DeGZip-File  $Filename
            }
        }

        remove-item $filename -Confirm:$false
        Remove-MgUserMessage -MessageId $m.Id -UserId $mailbox

    }
}

## Gather all of the exported reports and convert to a csv
$files = Get-ChildItem -Path $dst -Filter *.xml
Foreach ($f in $files){
    $report = ([xml](get-content $f.fullname)).feedback
    $records = $report.record

    foreach ($record in $records){
        ConvertRecord $record $report | where-object {$_.dkimresult -ne "pass" -or $_.spfresult -ne "pass"} | export-csv $csvexport -Append -NoTypeInformation
    }
    Remove-Item $f.FullName -Confirm:$false
}

if (Test-path $csvexport){
    $mailsplat = @{
    SMTPServer = "mailserver";
    To = "[email protected]";
    From = "[email protected]";
    Subject = "Failed DMARC Report";
    Attachments = $csvexport
    }

    Send-MailMessage @mailsplat

    Remove-item $csvexport

}

Author
Account Strength
100%
Account Age
6 years
Verified Email
Yes
Verified Flair
No
Total Karma
62,781
Link Karma
1,004
Comment Karma
61,443
Profile updated: 3 days ago
Posts updated: 8 months ago

Subreddit

Post Details

We try to extract some basic information from the post title. This is not always successful or accurate, please use your best judgement and compare these values to the post title and body for confirmation.
Posted
1 year ago