MailAuth.DMARC.Report (MailAuth v0.1.0)

Copy Markdown View Source

Reads DMARC aggregate reports (RFC 9990), as mail providers send them: XML, gzip or zip. Reports in the older RFC 7489 format read the same way.

{:ok, report} = MailAuth.DMARC.Report.parse(File.read!("report.xml.gz"))
report.policy_published.domain
for record <- report.records, do: {record.source_ip, record.count, record.disposition}

Reports come from strangers, so the input is bounded: at most 50 MB once uncompressed, and no DTD (<!DOCTYPE), which rules out entity expansion attacks. Element names never become atoms.

Fields

  • :version: the report format version, when given
  • :metadata: :org_name, :email, :extra_contact_info, :report_id, :begin and :end (as DateTime), :generator, :errors
  • :policy_published: the record the reporter found: :domain, :p, :sp, :np, :adkim, :aspf, :testing, :discovery_method, :fo, :pct, as written
  • :records: one map per row: :source_ip, :count, :disposition, :dkim, :spf (the policy evaluation), :reasons, :header_from, :envelope_from, :envelope_to, and :auth_results with :dkim and :spf lists

Values are strings as written, except :count and the dates.

Summary

Functions

Parses a report: XML, or XML in gzip or zip.

Types

t()

@type t() :: %MailAuth.DMARC.Report{
  metadata: map(),
  policy_published: map(),
  records: [map()],
  version: String.t() | nil
}

Functions

parse(gzip)

@spec parse(binary()) :: {:ok, t()} | {:error, atom()}

Parses a report: XML, or XML in gzip or zip.