Created
June 1, 2021 18:08
-
-
Save yosida95/f72ea12d95dbd4f7c56e73a8ebda2873 to your computer and use it in GitHub Desktop.
DMARC report parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"encoding/xml" | |
"flag" | |
"log" | |
"net" | |
"os" | |
"time" | |
) | |
var reportName string | |
func init() { | |
flag.StringVar(&reportName, "report", "", "") | |
} | |
type DmarcReport struct { | |
XMLName xml.Name `xml:"feedback"` | |
Metadata DmarcReportMetadata `xml:"report_metadata"` | |
PolicyPublished DmarcReportPolicyPublished `xml:"policy_published"` | |
Records []DmarcRecord `xml:"record"` | |
} | |
type DmarcReportMetadata struct { | |
OrgName string `xml:"org_name"` | |
Email string `xml:"email"` | |
ReportId string `xml:"report_id"` | |
DateRange struct { | |
Begin int64 `xml:"begin"` | |
End int64 `xml:"end"` | |
} `xml:"date_range"` | |
XMLName xml.Name `xml:"report_metadata"` | |
} | |
type DmarcReportPolicyPublished struct { | |
Domain string `xml:"domain"` | |
Adkim string `xml:"adkim"` | |
Aspf string `xml:"aspf"` | |
P string `xml:"p"` | |
SP string `xml:"sp"` | |
Pct int `xml:"pct"` | |
XMLName xml.Name `xml:"policy_published"` | |
} | |
type DmarcRecord struct { | |
Row DmarcRecordRow `xml:"row"` | |
Identifiers DmarcRecordIdentifiers `xml:"identifiers"` | |
AuthResults DmarcRecordAuthResult `xml:"auth_results"` | |
XMLName xml.Name `xml:"record"` | |
} | |
type DmarcRecordRow struct { | |
SourceIP string `xml:"source_ip"` | |
Count int64 `xml:"count"` | |
PolicyEvaluated struct { | |
Dispotision string `xml:"disposition"` | |
DKIM string `xml:"dkim"` | |
SPF string `xml:"spf"` | |
Reason struct { | |
Type string `xml:"type"` | |
Comment string `xml:"comment"` | |
} `xml:"reason"` | |
} `xml:"policy_evaluated"` | |
XMLName xml.Name `xml:"row"` | |
} | |
type DmarcRecordIdentifiers struct { | |
HeaderFrom string `xml:"header_from"` | |
XMLName xml.Name `xml:"identifiers"` | |
} | |
type DmarcRecordAuthResult struct { | |
DKIM struct { | |
Domain string `xml:"domain"` | |
Result string `xml:"result"` | |
Selector string `xml:"selector"` | |
} `xml:"dkim"` | |
SPF struct { | |
Domain string `xml:"domain"` | |
Result string `xml:"result"` | |
} `xml:"spf"` | |
XMLName xml.Name `xml:"auth_results"` | |
} | |
func main() { | |
flag.Parse() | |
fh, err := os.Open(reportName) | |
if err != nil { | |
log.Printf("Failed to open report: %v", err) | |
return | |
} | |
var report DmarcReport | |
err = xml.NewDecoder(fh).Decode(&report) | |
fh.Close() | |
if err != nil { | |
log.Printf("Failed to parse report: %v", err) | |
return | |
} | |
for _, record := range report.Records { | |
row := record.Row | |
eval := row.PolicyEvaluated | |
if eval.Dispotision == "none" { | |
continue | |
} | |
resolvctx, resolvcancel := context.WithTimeout(context.Background(), 2*time.Second) | |
ret, err := net.DefaultResolver.LookupAddr(resolvctx, row.SourceIP) | |
resolvcancel() | |
var reverse string | |
if err != nil || len(ret) < 1 { | |
reverse = row.SourceIP | |
} else { | |
reverse = ret[0] | |
} | |
log.Printf( | |
"From: %s [%s] For: %s %s:%d", | |
reverse, row.SourceIP, record.Identifiers.HeaderFrom, eval.Dispotision, row.Count) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment