Files
parsedmarc/index.html
Sean Whalen 22a49f828f Update docs
2022-09-10 14:33:26 -04:00

2693 lines
216 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>parsedmarc documentation - Open source DMARC report analyzer and visualizer &mdash; parsedmarc 8.3.1 documentation</title>
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
<!--[if lt IE 9]>
<script src="_static/js/html5shiv.min.js"></script>
<![endif]-->
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
<script src="_static/doctools.js"></script>
<script src="_static/js/theme.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="#" class="icon icon-home"> parsedmarc
</a>
<div class="version">
8.3.1
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<!-- Local TOC -->
<div class="local-toc"><ul>
<li><a class="reference internal" href="#">parsedmarc documentation - Open source DMARC report analyzer and visualizer</a><ul>
<li><a class="reference internal" href="#features">Features</a></li>
<li><a class="reference internal" href="#resources">Resources</a><ul>
<li><a class="reference internal" href="#dmarc-guides">DMARC guides</a></li>
<li><a class="reference internal" href="#spf-and-dmarc-record-validation">SPF and DMARC record validation</a></li>
<li><a class="reference internal" href="#lookalike-domains">Lookalike domains</a></li>
</ul>
</li>
<li><a class="reference internal" href="#cli-help">CLI help</a></li>
<li><a class="reference internal" href="#configuration-file">Configuration file</a></li>
<li><a class="reference internal" href="#sample-aggregate-report-output">Sample aggregate report output</a><ul>
<li><a class="reference internal" href="#json">JSON</a></li>
<li><a class="reference internal" href="#csv">CSV</a></li>
</ul>
</li>
<li><a class="reference internal" href="#sample-forensic-report-output">Sample forensic report output</a><ul>
<li><a class="reference internal" href="#id1">JSON</a></li>
<li><a class="reference internal" href="#id2">CSV</a></li>
</ul>
</li>
<li><a class="reference internal" href="#bug-reports">Bug reports</a></li>
<li><a class="reference internal" href="#installation">Installation</a><ul>
<li><a class="reference internal" href="#geoipupdate-setup">geoipupdate setup</a></li>
<li><a class="reference internal" href="#installing-parsedmarc">Installing parsedmarc</a></li>
<li><a class="reference internal" href="#optional-dependencies">Optional dependencies</a></li>
<li><a class="reference internal" href="#testing-multiple-report-analyzers">Testing multiple report analyzers</a></li>
<li><a class="reference internal" href="#accessing-an-inbox-using-owa-ews">Accessing an inbox using OWA/EWS</a><ul>
<li><a class="reference internal" href="#running-davmail-as-a-systemd-service">Running DavMail as a systemd service</a></li>
<li><a class="reference internal" href="#configuring-parsedmarc-for-davmail">Configuring parsedmarc for DavMail</a></li>
</ul>
</li>
<li><a class="reference internal" href="#elasticsearch-and-kibana">Elasticsearch and Kibana</a><ul>
<li><a class="reference internal" href="#upgrading-kibana-index-patterns">Upgrading Kibana index patterns</a></li>
<li><a class="reference internal" href="#records-retention">Records retention</a></li>
</ul>
</li>
<li><a class="reference internal" href="#splunk">Splunk</a></li>
<li><a class="reference internal" href="#running-parsedmarc-as-a-systemd-service">Running parsedmarc as a systemd service</a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-the-kibana-dashboards">Using the Kibana dashboards</a><ul>
<li><a class="reference internal" href="#dmarc-summary">DMARC Summary</a></li>
<li><a class="reference internal" href="#dmarc-forensic-samples">DMARC Forensic Samples</a></li>
</ul>
</li>
<li><a class="reference internal" href="#dmarc-alignment-guide">DMARC Alignment Guide</a></li>
<li><a class="reference internal" href="#what-if-a-sender-wont-support-dkim-dmarc">What if a sender wont support DKIM/DMARC?</a></li>
<li><a class="reference internal" href="#what-about-mailing-lists">What about mailing lists?</a><ul>
<li><a class="reference internal" href="#mailing-list-list-best-practices">Mailing list list best practices</a><ul>
<li><a class="reference internal" href="#do">Do</a></li>
<li><a class="reference internal" href="#do-not">Do not</a></li>
<li><a class="reference internal" href="#mailman-2">Mailman 2</a></li>
<li><a class="reference internal" href="#mailman-3">Mailman 3</a></li>
</ul>
</li>
<li><a class="reference internal" href="#workarounds">Workarounds</a><ul>
<li><a class="reference internal" href="#id3">Mailman 2</a></li>
<li><a class="reference internal" href="#id4">Mailman 3</a></li>
<li><a class="reference internal" href="#listserv">LISTSERV</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#module-parsedmarc">API</a><ul>
<li><a class="reference internal" href="#module-parsedmarc.elastic">parsedmarc.elastic</a></li>
<li><a class="reference internal" href="#module-parsedmarc.splunk">parsedmarc.splunk</a></li>
<li><a class="reference internal" href="#module-parsedmarc.utils">parsedmarc.utils</a></li>
</ul>
</li>
<li><a class="reference internal" href="#indices-and-tables">Indices and tables</a></li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="#">parsedmarc</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="#" class="icon icon-home"></a> &raquo;</li>
<li>parsedmarc documentation - Open source DMARC report analyzer and visualizer</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/index.md.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section class="tex2jax_ignore mathjax_ignore" id="parsedmarc-documentation-open-source-dmarc-report-analyzer-and-visualizer">
<h1>parsedmarc documentation - Open source DMARC report analyzer and visualizer<a class="headerlink" href="#parsedmarc-documentation-open-source-dmarc-report-analyzer-and-visualizer" title="Permalink to this heading"></a></h1>
<p><a class="reference external" href="https://github.com/domainaware/parsedmarc/actions/workflows/python-tests.yml"><img alt="BuildStatus" src="https://github.com/domainaware/parsedmarc/actions/workflows/python-tests.yml/badge.svg" /></a>
<a class="reference external" href="https://codecov.io/gh/domainaware/parsedmarc"><img alt="CodeCoverage" src="https://codecov.io/gh/domainaware/parsedmarc/branch/master/graph/badge.svg" /></a>
<a class="reference external" href="https://pypi.org/project/parsedmarc/"><img alt="PyPIPackage" src="https://img.shields.io/pypi/v/parsedmarc.svg" /></a></p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p><strong>Help Wanted</strong></p>
<p>This is a project is maintained by one developer.
Please consider reviewing the open <a class="reference external" href="https://github.com/domainaware/parsedmarc/issues">issues</a> to see how you can contribute code, documentation, or user support.
Assistance on the pinned issues would be particularly helpful.</p>
<p>Thanks to all <a class="reference external" href="https://github.com/domainaware/parsedmarc/graphs/contributors">contributors</a>!</p>
</div>
<a class="reference external image-reference" href="_static/screenshots/dmarc-summary-charts.png"><img alt="A screenshot of DMARC summary charts in Kibana" class="align-center" src="_images/dmarc-summary-charts.png" style="width: 754.0px; height: 449.0px;" /></a>
<p><code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> is a Python module and CLI utility for parsing DMARC reports.
When used with Elasticsearch and Kibana (or Splunk), it works as a self-hosted
open source alternative to commercial DMARC report processing services such
as Agari Brand Protection, Dmarcian, OnDMARC, ProofPoint Email Fraud Defense,
and Valimail.</p>
<section id="features">
<h2>Features<a class="headerlink" href="#features" title="Permalink to this heading"></a></h2>
<ul class="simple">
<li><p>Parses draft and 1.0 standard aggregate/rua reports</p></li>
<li><p>Parses forensic/failure/ruf reports</p></li>
<li><p>Can parse reports from an inbox over IMAP, Microsoft Graph, or Gmail API</p></li>
<li><p>Transparently handles gzip or zip compressed reports</p></li>
<li><p>Consistent data structures</p></li>
<li><p>Simple JSON and/or CSV output</p></li>
<li><p>Optionally email the results</p></li>
<li><p>Optionally send the results to Elasticsearch and/or Splunk, for use with
premade dashboards</p></li>
<li><p>Optionally send reports to Apache Kafka</p></li>
</ul>
</section>
<section id="resources">
<h2>Resources<a class="headerlink" href="#resources" title="Permalink to this heading"></a></h2>
<section id="dmarc-guides">
<h3>DMARC guides<a class="headerlink" href="#dmarc-guides" title="Permalink to this heading"></a></h3>
<ul class="simple">
<li><p><a class="reference external" href="https://seanthegeek.net/459/demystifying-dmarc/">Demystifying DMARC</a> - A complete guide to SPF, DKIM, and DMARC</p></li>
</ul>
</section>
<section id="spf-and-dmarc-record-validation">
<h3>SPF and DMARC record validation<a class="headerlink" href="#spf-and-dmarc-record-validation" title="Permalink to this heading"></a></h3>
<p>If you are looking for SPF and DMARC record validation and parsing,
check out the sister project,
<a class="reference external" href="https://domainaware.github.io/checkdmarc/">checkdmarc</a>.</p>
</section>
<section id="lookalike-domains">
<h3>Lookalike domains<a class="headerlink" href="#lookalike-domains" title="Permalink to this heading"></a></h3>
<p>DMARC protects against domain spoofing, not lookalike domains. for open source
lookalike domain monitoring, check out <a class="reference external" href="https://github.com/seanthegeek/domainaware">DomainAware</a>.</p>
</section>
</section>
<section id="cli-help">
<h2>CLI help<a class="headerlink" href="#cli-help" title="Permalink to this heading"></a></h2>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>usage: parsedmarc [-h] [-c CONFIG_FILE] [--strip-attachment-payloads] [-o OUTPUT]
[--aggregate-json-filename AGGREGATE_JSON_FILENAME]
[--forensic-json-filename FORENSIC_JSON_FILENAME]
[--aggregate-csv-filename AGGREGATE_CSV_FILENAME]
[--forensic-csv-filename FORENSIC_CSV_FILENAME]
[-n NAMESERVERS [NAMESERVERS ...]] [-t DNS_TIMEOUT] [--offline]
[-s] [--verbose] [--debug] [--log-file LOG_FILE] [-v]
[file_path ...]
Parses DMARC reports
positional arguments:
file_path one or more paths to aggregate or forensic report
files, emails, or mbox files&#39;
optional arguments:
-h, --help show this help message and exit
-c CONFIG_FILE, --config-file CONFIG_FILE
a path to a configuration file (--silent implied)
--strip-attachment-payloads
remove attachment payloads from forensic report output
-o OUTPUT, --output OUTPUT
write output files to the given directory
--aggregate-json-filename AGGREGATE_JSON_FILENAME
filename for the aggregate JSON output file
--forensic-json-filename FORENSIC_JSON_FILENAME
filename for the forensic JSON output file
--aggregate-csv-filename AGGREGATE_CSV_FILENAME
filename for the aggregate CSV output file
--forensic-csv-filename FORENSIC_CSV_FILENAME
filename for the forensic CSV output file
-n NAMESERVERS [NAMESERVERS ...], --nameservers NAMESERVERS [NAMESERVERS ...]
nameservers to query
-t DNS_TIMEOUT, --dns_timeout DNS_TIMEOUT
number of seconds to wait for an answer from DNS
(default: 2.0)
--offline do not make online queries for geolocation or DNS
-s, --silent only print errors and warnings
--verbose more verbose output
--debug print debugging information
--log-file LOG_FILE output logging to a file
-v, --version show program&#39;s version number and exit
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Starting in <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> 6.0.0, most CLI options were moved to a
configuration file, described below.</p>
</div>
</section>
<section id="configuration-file">
<h2>Configuration file<a class="headerlink" href="#configuration-file" title="Permalink to this heading"></a></h2>
<p><code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> can be configured by supplying the path to an INI file</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>parsedmarc -c /etc/parsedmarc.ini
</pre></div>
</div>
<p>For example</p>
<div class="highlight-ini notranslate"><div class="highlight"><pre><span></span><span class="c1"># This is an example comment</span><span class="w"></span>
<span class="k">[general]</span><span class="w"></span>
<span class="na">save_aggregate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">True</span><span class="w"></span>
<span class="na">save_forensic</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">True</span><span class="w"></span>
<span class="k">[imap]</span><span class="w"></span>
<span class="na">host</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">imap.example.com</span><span class="w"></span>
<span class="na">user</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">dmarcresports@example.com</span><span class="w"></span>
<span class="na">password</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">$uperSecure</span><span class="w"></span>
<span class="k">[mailbox]</span><span class="w"></span>
<span class="na">watch</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">True</span><span class="w"></span>
<span class="na">delete</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">False</span><span class="w"></span>
<span class="k">[elasticsearch]</span><span class="w"></span>
<span class="na">hosts</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">127.0.0.1:9200</span><span class="w"></span>
<span class="na">ssl</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">False</span><span class="w"></span>
<span class="k">[splunk_hec]</span><span class="w"></span>
<span class="na">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">https://splunkhec.example.com</span><span class="w"></span>
<span class="na">token</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">HECTokenGoesHere</span><span class="w"></span>
<span class="na">index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">email</span><span class="w"></span>
<span class="k">[s3]</span><span class="w"></span>
<span class="na">bucket</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">my-bucket</span><span class="w"></span>
<span class="na">path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">parsedmarc</span><span class="w"></span>
<span class="k">[syslog]</span><span class="w"></span>
<span class="na">server</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">localhost</span><span class="w"></span>
<span class="na">port</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">514</span><span class="w"></span>
</pre></div>
</div>
<p>The full set of configuration options are:</p>
<ul>
<li><dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">general</span></code></dt><dd><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">save_aggregate</span></code> - bool: Save aggregate report data to
Elasticsearch, Splunk and/or S3</p></li>
</ul>
</dd>
</dl>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">save_forensic</span></code> - bool: Save forensic report data to
Elasticsearch, Splunk and/or S3</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">strip_attachment_payloads</span></code> - bool: Remove attachment
payloads from results</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">output</span></code> - str: Directory to place JSON and CSV files in</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">aggregate_json_filename</span></code> - str: filename for the aggregate
JSON output file</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">forensic_json_filename</span></code> - str: filename for the forensic
JSON output file</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ip_db_path</span></code> - str: An optional custom path to a MMDB file</p></li>
<li><p>from MaxMind or DBIP</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">offline</span></code> - bool: Do not use online queries for geolocation
or DNS</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">nameservers</span></code> - str: A comma separated list of
DNS resolvers (Default: <a class="reference external" href="https://1.1.1.1/">Cloudflares public resolvers</a>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">dns_timeout</span></code> - float: DNS timeout period</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">debug</span></code> - bool: Print debugging messages</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">silent</span></code> - bool: Only print errors (Default: True)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">log_file</span></code> - str: Write log messages to a file at this path</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">n_procs</span></code> - int: Number of process to run in parallel when
parsing in CLI mode (Default: 1)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">chunk_size</span></code> - int: Number of files to give to each process
when running in parallel.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Setting this to a number larger than one can improve
performance when processing thousands of files</p>
</div>
</li>
</ul>
</li>
<li><dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">mailbox</span></code></dt><dd><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">reports_folder</span></code> - str: The mailbox folder (or label for
Gmail) where the incoming reports can be found (Default: INBOX)</p></li>
</ul>
</dd>
</dl>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">archive_folder</span></code> - str: The mailbox folder (or label for
Gmail) to sort processed emails into (Default: Archive)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">watch</span></code> - bool: Use the IMAP <code class="docutils literal notranslate"><span class="pre">IDLE</span></code> command to process</p></li>
<li><p>messages as they arrive or poll MS Graph for new messages</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">delete</span></code> - bool: Delete messages after processing them,</p></li>
<li><p>instead of archiving them</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">test</span></code> - bool: Do not move or delete messages</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">batch_size</span></code> - int: Number of messages to read and process
before saving. Default 10. Use 0 for no limit.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">check_timeout</span></code> - int: Number of seconds to wait for a IMAP
IDLE response or the number of seconds until the next mai
check (Default: 30)</p></li>
</ul>
</li>
<li><dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">imap</span></code></dt><dd><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">host</span></code> - str: The IMAP server hostname or IP address</p></li>
</ul>
</dd>
</dl>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">port</span></code> - int: The IMAP server port (Default: 993)</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p><code class="docutils literal notranslate"><span class="pre">%</span></code> characters must be escaped with another <code class="docutils literal notranslate"><span class="pre">%</span></code> character,
so use <code class="docutils literal notranslate"><span class="pre">%%</span></code> wherever a <code class="docutils literal notranslate"><span class="pre">%</span></code> character is used.</p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Starting in version 8.0.0, most options from the <code class="docutils literal notranslate"><span class="pre">imap</span></code>
section have been moved to the <code class="docutils literal notranslate"><span class="pre">mailbox</span></code> section.</p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If your host recommends another port, still try 993</p>
</div>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">ssl</span></code> - bool: Use an encrypted SSL/TLS connection
(Default: True)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">skip_certificate_verification</span></code> - bool: Skip certificate
verification (not recommended)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">user</span></code> - str: The IMAP user</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">password</span></code> - str: The IMAP password</p></li>
</ul>
</li>
<li><dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">msgraph</span></code></dt><dd><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">auth_method</span></code> - str: Authentication method, valid types are
UsernamePassword, DeviceCode, or ClientSecret
(Default: UsernamePassword).</p></li>
</ul>
</dd>
</dl>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">user</span></code> - str: The M365 user, required when the auth method is
UsernamePassword</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">password</span></code> - str: The user password, required when the auth
method is UsernamePassword</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">client_id</span></code> - str: The app registrations client ID</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">client_secret</span></code> - str: The app registrations secret</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">tenant_id</span></code> - str: The Azure AD tenant ID. This is required
for all auth methods except UsernamePassword.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">mailbox</span></code> - str: The mailbox name. This defaults to the
current user if using the UsernamePassword auth method, but
could be a shared mailbox if the user has access to the mailbox</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">token_file</span></code> - str: Path to save the token file
(Default: .token)</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>You must create an app registration in Azure AD and have an
admin grant the Microsoft Graph <code class="docutils literal notranslate"><span class="pre">Mail.ReadWrite</span></code>
(delegated) permission to the app. If you are using
<code class="docutils literal notranslate"><span class="pre">UsernamePassword</span></code> auth and the mailbox is different from the
username, you must grant the app <code class="docutils literal notranslate"><span class="pre">Mail.ReadWrite.Shared</span></code>.</p>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>If you are using the <code class="docutils literal notranslate"><span class="pre">ClientSecret</span></code> auth method, you need to
grant the <code class="docutils literal notranslate"><span class="pre">Mail.ReadWrite</span></code> (application) permission to the
app. You must also restrict the applications access to a
specific mailbox since it allows all mailboxes by default.
Use the <code class="docutils literal notranslate"><span class="pre">New-ApplicationAccessPolicy</span></code> command in the
Exchange PowerShell module. If you need to scope the policy to
shared mailboxes, you can add them to a mail enabled security
group and use that as the group id.</p>
<div class="highlight-powershell notranslate"><div class="highlight"><pre><span></span><span class="nb">New-ApplicationAccessPolicy</span> <span class="n">-AccessRight</span> <span class="n">RestrictAccess</span>
<span class="n">-AppId</span> <span class="s2">&quot;&lt;CLIENT_ID&gt;&quot;</span> <span class="n">-PolicyScopeGroupId</span> <span class="s2">&quot;&lt;MAILBOX&gt;&quot;</span>
<span class="n">-Description</span> <span class="s2">&quot;Restrict access to dmarc reports mailbox.&quot;</span>
</pre></div>
</div>
</div>
</li>
</ul>
</li>
<li><dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">elasticsearch</span></code></dt><dd><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">hosts</span></code> - str: A comma separated list of hostnames and ports
or URLs (e.g. <code class="docutils literal notranslate"><span class="pre">127.0.0.1:9200</span></code> or
<code class="docutils literal notranslate"><span class="pre">https://user:secret&#64;localhost</span></code>)</p></li>
</ul>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Special characters in the username or password must be
<a class="reference external" href="https://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding_reserved_characters">URL encoded</a>.</p>
</div>
</dd>
</dl>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">ssl</span></code> - bool: Use an encrypted SSL/TLS connection (Default: True)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">cert_path</span></code> - str: Path to a trusted certificates</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">index_suffix</span></code> - str: A suffix to apply to the index names</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">monthly_indexes</span></code> - bool: Use monthly indexes instead of daily indexes</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">number_of_shards</span></code> - int: The number of shards to use when creating the index (Default: 1)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">number_of_replicas</span></code> - int: The number of replicas to use when creating the index (Default: 1)</p></li>
</ul>
</li>
<li><dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">splunk_hec</span></code></dt><dd><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">url</span></code> - str: The URL of the Splunk HTTP Events Collector (HEC)</p></li>
</ul>
</dd>
</dl>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">token</span></code> - str: The HEC token</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">index</span></code> - str: The Splunk index to use</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">skip_certificate_verification</span></code> - bool: Skip certificate
verification (not recommended)</p></li>
</ul>
</li>
<li><dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">kafka</span></code></dt><dd><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">hosts</span></code> - str: A comma separated list of Kafka hosts</p></li>
</ul>
</dd>
</dl>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">user</span></code> - str: The Kafka user</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">passsword</span></code> - str: The Kafka password</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ssl</span></code> - bool: Use an encrypted SSL/TLS connection (Default: True)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">skip_certificate_verification</span></code> - bool: Skip certificate
verification (not recommended)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">aggregate_topic</span></code> - str: The Kafka topic for aggregate reports</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">forensic_topic</span></code> - str: The Kafka topic for forensic reports</p></li>
</ul>
</li>
<li><dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">smtp</span></code></dt><dd><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">host</span></code> - str: The SMTP hostname</p></li>
</ul>
</dd>
</dl>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">port</span></code> - int: The SMTP port (Default: 25)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ssl</span></code> - bool: Require SSL/TLS instead of using STARTTLS</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">skip_certificate_verification</span></code> - bool: Skip certificate
verification (not recommended)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">user</span></code> - str: the SMTP username</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">password</span></code> - str: the SMTP password</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">from</span></code> - str: The From header to use in the email</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">to</span></code> - list: A list of email addresses to send to</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">subject</span></code> - str: The Subject header to use in the email
(Default: parsedmarc report)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">attachment</span></code> - str: The ZIP attachment filenames</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">message</span></code> - str: The email message
(Default: Please see the attached parsedmarc report.)</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p><code class="docutils literal notranslate"><span class="pre">%</span></code> characters must be escaped with another <code class="docutils literal notranslate"><span class="pre">%</span></code> character,
so use <code class="docutils literal notranslate"><span class="pre">%%</span></code> wherever a <code class="docutils literal notranslate"><span class="pre">%</span></code> character is used.</p>
</div>
</li>
</ul>
</li>
<li><dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">s3</span></code></dt><dd><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">bucket</span></code> - str: The S3 bucket name</p></li>
</ul>
</dd>
</dl>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">path</span></code> - str: The path to upload reports to (Default: /)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">region_name</span></code> - str: The region name (Optional)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">endpoint_url</span></code> - str: The endpoint URL (Optional)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">access_key_id</span></code> - str: The access key id (Optional)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">secret_access_key</span></code> - str: The secret access key (Optional)</p></li>
</ul>
</li>
<li><dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">syslog</span></code></dt><dd><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">server</span></code> - str: The Syslog server name or IP address</p></li>
</ul>
</dd>
</dl>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">port</span></code> - int: The UDP port to use (Default: 514)</p></li>
</ul>
</li>
<li><dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">gmail_api</span></code></dt><dd><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">credentials_file</span></code> - str: Path to file containing the
credentials, None to disable (Default: None)</p></li>
</ul>
</dd>
</dl>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">token_file</span></code> - str: Path to save the token file
(Default: .token)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">include_spam_trash</span></code> - bool: Include messages in Spam and
Trash when searching reports (Default: False)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">scopes</span></code> - str: Comma separated list of scopes to use when
acquiring credentials (Default: <a class="reference external" href="https://www.googleapis.com/auth/gmail.modify">https://www.googleapis.com/auth/gmail.modify</a>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">oauth2_port</span></code> - int: The TCP port for the local server to
listen on for the OAuth2 response (Default: 8080)</p></li>
</ul>
</li>
</ul>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>It is <strong>strongly recommended</strong> to <strong>not</strong> use the <code class="docutils literal notranslate"><span class="pre">nameservers</span></code>
setting. By default, <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> uses
<a class="reference external" href="https://1.1.1.1/">Cloudflares public resolvers</a>, which are much faster and more
reliable than Google, Cisco OpenDNS, or even most local resolvers.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">nameservers</span></code> option should only be used if your network
blocks DNS requests to outside resolvers.</p>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p><code class="docutils literal notranslate"><span class="pre">save_aggregate</span></code> and <code class="docutils literal notranslate"><span class="pre">save_forensic</span></code> are separate options
because you may not want to save forensic reports
(also known as failure reports) to your Elasticsearch instance,
particularly if you are in a highly-regulated industry that
handles sensitive data, such as healthcare or finance. If your
legitimate outgoing email fails DMARC, it is possible
that email may appear later in a forensic report.</p>
<p>Forensic reports contain the original headers of an email that
failed a DMARC check, and sometimes may also include the
full message body, depending on the policy of the reporting
organization.</p>
<p>Most reporting organizations do not send forensic reports of any
kind for privacy reasons. While aggregate DMARC reports are sent
at least daily, it is normal to receive very few forensic reports.</p>
<p>An alternative approach is to still collect forensic/failure/ruf
reports in your DMARC inbox, but run <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> with
<code class="docutils literal notranslate"><span class="pre">save_forensic</span> <span class="pre">=</span> <span class="pre">True``manually</span> <span class="pre">on</span> <span class="pre">a</span> <span class="pre">separate</span> <span class="pre">IMAP</span> <span class="pre">folder</span> <span class="pre">(using</span> <span class="pre">the</span>&#160; <span class="pre">``reports_folder</span></code> option), after you have manually moved
known samples you want to save to that folder
(e.g. malicious samples and non-sensitive legitimate samples).</p>
</div>
</section>
<section id="sample-aggregate-report-output">
<h2>Sample aggregate report output<a class="headerlink" href="#sample-aggregate-report-output" title="Permalink to this heading"></a></h2>
<p>Here are the results from parsing the <a class="reference external" href="https://dmarc.org/wiki/FAQ#I_need_to_implement_aggregate_reports.2C_what_do_they_look_like.3F">example</a>
report from the <a class="reference external" href="http://dmarc.org">dmarc.org</a> wiki. Its actually an older draft of the the 1.0
report schema standardized in
<a class="reference external" href="https://tools.ietf.org/html/rfc7489#appendix-C">RFC 7480 Appendix C</a>.
This draft schema is still in wide use.</p>
<p><code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> produces consistent, normalized output, regardless
of the report schema.</p>
<section id="json">
<h3>JSON<a class="headerlink" href="#json" title="Permalink to this heading"></a></h3>
<div class="highlight-json notranslate"><div class="highlight"><pre><span></span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;xml_schema&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;draft&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;report_metadata&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;org_name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;acme.com&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;org_email&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;noreply-dmarc-support@acme.com&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;org_extra_contact_info&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;http://acme.com/dmarc/support&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;report_id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;9391651994964116463&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;begin_date&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;2012-04-27 20:00:00&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;end_date&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;2012-04-28 19:59:59&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;errors&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;policy_published&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;domain&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;example.com&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;adkim&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;r&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;aspf&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;r&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;p&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;none&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;sp&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;none&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;pct&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;100&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;fo&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;records&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;source&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;ip_address&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;72.150.241.94&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;country&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;US&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;reverse_dns&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;adsl-72-150-241-94.shv.bellsouth.net&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;base_domain&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;bellsouth.net&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;count&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;alignment&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;spf&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;dkim&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;dmarc&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;policy_evaluated&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;disposition&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;none&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;dkim&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;fail&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;spf&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;pass&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;policy_override_reasons&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;identifiers&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;header_from&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;example.com&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;envelope_from&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;example.com&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;envelope_to&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;auth_results&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;dkim&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;domain&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;example.com&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;selector&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;none&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;result&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;fail&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">],</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;spf&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;domain&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;example.com&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;scope&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;mfrom&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;result&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;pass&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">]</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
</section>
<section id="csv">
<h3>CSV<a class="headerlink" href="#csv" title="Permalink to this heading"></a></h3>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>xml_schema,org_name,org_email,org_extra_contact_info,report_id,begin_date,end_date,errors,domain,adkim,aspf,p,sp,pct,fo,source_ip_address,source_country,source_reverse_dns,source_base_domain,count,spf_aligned,dkim_aligned,dmarc_aligned,disposition,policy_override_reasons,policy_override_comments,envelope_from,header_from,envelope_to,dkim_domains,dkim_selectors,dkim_results,spf_domains,spf_scopes,spf_results
draft,acme.com,noreply-dmarc-support@acme.com,http://acme.com/dmarc/support,9391651994964116463,2012-04-27 20:00:00,2012-04-28 19:59:59,,example.com,r,r,none,none,100,0,72.150.241.94,US,adsl-72-150-241-94.shv.bellsouth.net,bellsouth.net,2,True,False,True,none,,,example.com,example.com,,example.com,none,fail,example.com,mfrom,pass
</pre></div>
</div>
</section>
</section>
<section id="sample-forensic-report-output">
<h2>Sample forensic report output<a class="headerlink" href="#sample-forensic-report-output" title="Permalink to this heading"></a></h2>
<p>Thanks to Github user <a class="reference external" href="https://github.com/xennn">xennn</a> for the anonymized
<a class="reference external" href="https://github.com/domainaware/parsedmarc/raw/master/samples/forensic/DMARC%20Failure%20Report%20for%20domain.de%20(mail-from%3Dsharepoint%40domain.de%2C%20ip%3D10.10.10.10).eml">forensic report email sample</a>.</p>
<section id="id1">
<h3>JSON<a class="headerlink" href="#id1" title="Permalink to this heading"></a></h3>
<div class="highlight-json notranslate"><div class="highlight"><pre><span></span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;feedback_type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;auth-failure&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;user_agent&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Lua/1.0&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;1.0&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;original_mail_from&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;sharepoint@domain.de&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;original_rcpt_to&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;peter.pan@domain.de&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;arrival_date&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Mon, 01 Oct 2018 11:20:27 +0200&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;message_id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;&lt;38.E7.30937.BD6E1BB5@ mailrelay.de&gt;&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;authentication_results&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;dmarc=fail (p=none, dis=none) header.from=domain.de&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;delivery_result&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;policy&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;auth_failure&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="s2">&quot;dmarc&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">],</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;reported_domain&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;domain.de&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;arrival_date_utc&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;2018-10-01 09:20:27&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;source&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;ip_address&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;10.10.10.10&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;country&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;reverse_dns&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;base_domain&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;authentication_mechanisms&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;original_envelope_id&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;dkim_domain&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;sample_headers_only&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;sample&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Received: from Servernameone.domain.local (Servernameone.domain.local [10.10.10.10])\n\tby mailrelay.de (mail.DOMAIN.de) with SMTP id 38.E7.30937.BD6E1BB5; Mon, 1 Oct 2018 11:20:27 +0200 (CEST)\nDate: 01 Oct 2018 11:20:27 +0200\nMessage-ID: &lt;38.E7.30937.BD6E1BB5@ mailrelay.de&gt;\nTo: &lt;peter.pan@domain.de&gt;\nfrom: \&quot;=?utf-8?B?SW50ZXJha3RpdmUgV2V0dGJld2VyYmVyLcOcYmVyc2ljaHQ=?=\&quot; &lt;sharepoint@domain.de&gt;\nSubject: Subject\nMIME-Version: 1.0\nX-Mailer: Microsoft SharePoint Foundation 2010\nContent-Type: text/html; charset=utf-8\nContent-Transfer-Encoding: quoted-printable\n\n&lt;html&gt;&lt;head&gt;&lt;base href=3D&#39;\nwettbewerb&#39; /&gt;&lt;/head&gt;&lt;body&gt;&lt;!DOCTYPE HTML PUBLIC \&quot;-//W3C//DTD HTML 3.2//EN\&quot;=\n&gt;&lt;HTML&gt;&lt;HEAD&gt;&lt;META NAME=3D\&quot;Generator\&quot; CONTENT=3D\&quot;MS Exchange Server version=\n 08.01.0240.003\&quot;&gt;&lt;/html&gt;\n&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;parsed_sample&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;from&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;display_name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Interaktive Wettbewerber-Übersicht&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;address&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;sharepoint@domain.de&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;local&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;sharepoint&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;domain&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;domain.de&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;to_domains&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="s2">&quot;domain.de&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">],</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;to&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;display_name&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;address&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;peter.pan@domain.de&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;local&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;peter.pan&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;domain&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;domain.de&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">],</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;subject&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Subject&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;timezone&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;+2&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;mime-version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;1.0&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;date&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;2018-10-01 09:20:27&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;content-type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;text/html; charset=utf-8&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;x-mailer&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Microsoft SharePoint Foundation 2010&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;body&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;&lt;html&gt;&lt;head&gt;&lt;base href=&#39;\nwettbewerb&#39; /&gt;&lt;/head&gt;&lt;body&gt;&lt;!DOCTYPE HTML PUBLIC \&quot;-//W3C//DTD HTML 3.2//EN\&quot;&gt;&lt;HTML&gt;&lt;HEAD&gt;&lt;META NAME=\&quot;Generator\&quot; CONTENT=\&quot;MS Exchange Server version 08.01.0240.003\&quot;&gt;&lt;/html&gt;&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;received&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;from&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Servernameone.domain.local Servernameone.domain.local 10.10.10.10&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;by&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;mailrelay.de mail.DOMAIN.de&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;with&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;SMTP id 38.E7.30937.BD6E1BB5&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;date&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Mon, 1 Oct 2018 11:20:27 +0200 CEST&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;hop&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;date_utc&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;2018-10-01 09:20:27&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;delay&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">],</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;content-transfer-encoding&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;quoted-printable&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;message-id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;&lt;38.E7.30937.BD6E1BB5@ mailrelay.de&gt;&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;has_defects&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;headers&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;Received&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;from Servernameone.domain.local (Servernameone.domain.local [10.10.10.10])\n\tby mailrelay.de (mail.DOMAIN.de) with SMTP id 38.E7.30937.BD6E1BB5; Mon, 1 Oct 2018 11:20:27 +0200 (CEST)&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;Date&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;01 Oct 2018 11:20:27 +0200&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;Message-ID&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;&lt;38.E7.30937.BD6E1BB5@ mailrelay.de&gt;&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;To&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;&lt;peter.pan@domain.de&gt;&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;from&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;\&quot;Interaktive Wettbewerber-Übersicht\&quot; &lt;sharepoint@domain.de&gt;&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;Subject&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Subject&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;MIME-Version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;1.0&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;X-Mailer&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Microsoft SharePoint Foundation 2010&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;Content-Type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;text/html; charset=utf-8&quot;</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;Content-Transfer-Encoding&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;quoted-printable&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;reply_to&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;cc&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;bcc&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;attachments&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;filename_safe_subject&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Subject&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
</pre></div>
</div>
</section>
<section id="id2">
<h3>CSV<a class="headerlink" href="#id2" title="Permalink to this heading"></a></h3>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>feedback_type,user_agent,version,original_envelope_id,original_mail_from,original_rcpt_to,arrival_date,arrival_date_utc,subject,message_id,authentication_results,dkim_domain,source_ip_address,source_country,source_reverse_dns,source_base_domain,delivery_result,auth_failure,reported_domain,authentication_mechanisms,sample_headers_only
auth-failure,Lua/1.0,1.0,,sharepoint@domain.de,peter.pan@domain.de,&quot;Mon, 01 Oct 2018 11:20:27 +0200&quot;,2018-10-01 09:20:27,Subject,&lt;38.E7.30937.BD6E1BB5@ mailrelay.de&gt;,&quot;dmarc=fail (p=none, dis=none) header.from=domain.de&quot;,,10.10.10.10,,,,policy,dmarc,domain.de,,False
</pre></div>
</div>
</section>
</section>
<section id="bug-reports">
<h2>Bug reports<a class="headerlink" href="#bug-reports" title="Permalink to this heading"></a></h2>
<p>Please report bugs on the GitHub issue tracker</p>
<p><a class="reference external" href="https://github.com/domainaware/parsedmarc/issues">https://github.com/domainaware/parsedmarc/issues</a></p>
</section>
<section id="installation">
<h2>Installation<a class="headerlink" href="#installation" title="Permalink to this heading"></a></h2>
<p><code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> works with Python 3 only.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If your system is behind a web proxy, you need to configure your system
to use that proxy. To do this, edit <code class="docutils literal notranslate"><span class="pre">/etc/environment</span></code> and add your
proxy details there, for example:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nv">http_proxy</span><span class="o">=</span>http://user:password@prox-server:3128
<span class="nv">https_proxy</span><span class="o">=</span>https://user:password@prox-server:3128
<span class="nv">ftp_proxy</span><span class="o">=</span>http://user:password@prox-server:3128
</pre></div>
</div>
<p>Or if no credentials are needed:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nv">http_proxy</span><span class="o">=</span>http://prox-server:3128
<span class="nv">https_proxy</span><span class="o">=</span>https://prox-server:3128
<span class="nv">ftp_proxy</span><span class="o">=</span>http://prox-server:3128
</pre></div>
</div>
<p>This will set the the proxy up for use system-wide, including for
<code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code>.</p>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>If your mail server is Microsoft Exchange, ensure that it is patched to at
least:</p>
<ul class="simple">
<li><p>Exchange Server 2010 Update Rollup 22 (<a class="reference external" href="https://support.microsoft.com/KB/4295699">KB4295699</a>)</p></li>
<li><p>Exchange Server 2013 Cumulative Update 21 (<a class="reference external" href="https://support.microsoft.com/KB/4099855">KB4099855</a>)</p></li>
<li><p>Exchange Server 2016 Cumulative Update 11 (<a class="reference external" href="https://support.microsoft.com/kb/4134118">KB4134118</a>)</p></li>
</ul>
</div>
<section id="geoipupdate-setup">
<h3>geoipupdate setup<a class="headerlink" href="#geoipupdate-setup" title="Permalink to this heading"></a></h3>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Starting in <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> 7.1.0, a static copy of the <a class="reference external" href="https://db-ip.com/db/download/ip-to-country-lite">IP to Country Lite database</a> from IPDB is
distributed with <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code>, under the terms of the <a class="reference external" href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>. as
a fallback if the <a class="reference external" href="https://dev.maxmind.com/geoip/geolite2-free-geolocation-data">MaxMind GeoLite2 Country database</a> is not installed However, <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> cannot install updated
versions of these databases as they are released, so MaxMinds databases and <a class="reference external" href="https://github.com/maxmind/geoipupdate">geoipupdate</a> tool is still the
preferable solution.</p>
<p>The location of the database file can be overridden by using the <code class="docutils literal notranslate"><span class="pre">ip_db_path</span></code> setting.</p>
</div>
<p>On Debian 10 (Buster) or later, run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo apt-get install -y geoipupdate
</pre></div>
</div>
<p>On Ubuntu systems run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo add-apt-repository ppa:maxmind/ppa
sudo apt update
sudo apt install -y geoipupdate
</pre></div>
</div>
<p>On CentOS or RHEL systems, run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo dnf install -y geoipupdate
</pre></div>
</div>
<p>The latest builds for Linux, macOS, and Windows can be downloaded
from the <a class="reference external" href="https://github.com/maxmind/geoipupdate/releases">geoipupdate releases page on GitHub</a>.</p>
<p>On December 30th, 2019, MaxMind started requiring free accounts to
access the free Geolite2 databases, in order <a class="reference external" href="https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases/">to
comply with various privacy regulations</a>.</p>
<p>Start by <a class="reference external" href="https://www.maxmind.com/en/geolite2/signup">registering for a free GeoLite2 account</a>, and signing in.</p>
<p>Then, navigate the to the <a class="reference external" href="https://www.maxmind.com/en/accounts/current/license-key">License Keys</a> page under your account,
and create a new license key for the version of
<code class="docutils literal notranslate"><span class="pre">geoipupdate</span></code> that was installed.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>The configuration file format is different for older (i.e. &lt;=3.1.1) and newer (i.e. &gt;=3.1.1) versions
of <code class="docutils literal notranslate"><span class="pre">geoipupdate</span></code>. Be sure to select the correct version for your system.</p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>To check the version of <code class="docutils literal notranslate"><span class="pre">geoipupdate</span></code> that is installed, run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>geoipupdate -V
</pre></div>
</div>
</div>
<p>You can use <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> as the description for the key.</p>
<p>Once you have generated a key, download the config pre-filled
configuration file. This file should be saved at <code class="docutils literal notranslate"><span class="pre">/etc/GeoIP.conf</span></code>
on Linux or macOS systems, or at
<code class="docutils literal notranslate"><span class="pre">%SystemDrive%\ProgramData\MaxMind\GeoIPUpdate\GeoIP.conf</span></code> on
Windows systems.</p>
<p>Then run</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo geoipupdate
</pre></div>
</div>
<p>To download the databases for the first time.</p>
<p>The GeoLite2 Country, City, and ASN databases are updated weekly,
every Tuesday. <code class="docutils literal notranslate"><span class="pre">geoipupdate</span></code> can be run weekly by adding a cron
job or scheduled task.</p>
<p>More information about <code class="docutils literal notranslate"><span class="pre">geoipupdate</span></code> can be found at the
<a class="reference external" href="https://dev.maxmind.com/geoip/geoipupdate/">MaxMind geoipupdate page</a>.</p>
</section>
<section id="installing-parsedmarc">
<h3>Installing parsedmarc<a class="headerlink" href="#installing-parsedmarc" title="Permalink to this heading"></a></h3>
<p>On Debian or Ubuntu systems, run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo apt-get install -y python3-pip python3-virtualenv python3-dev libxml2-dev libxslt-dev
</pre></div>
</div>
<p>On CentOS or RHEL systems, run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo dnf install -y python39 python3-virtualenv python3-setuptools python3-devel libxml2-devel libxslt-devel
</pre></div>
</div>
<p>Python 3 installers for Windows and macOS can be found at
<a class="reference external" href="https://www.python.org/downloads/">https://www.python.org/downloads/</a></p>
<p>Create a system user</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo mkdir /opt
sudo useradd parsedmarc -r -s /bin/false -m -b /opt
</pre></div>
</div>
<p>Install parsedmarc in a virtualenv</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo -u parsedmarc virtualenv /opt/parsedmarc/venv
</pre></div>
</div>
<p>CentOS/RHEL 8 systems use Python 3.6 by default, so on those systems
explicitly tell <code class="docutils literal notranslate"><span class="pre">virtualenv</span></code> to use <code class="docutils literal notranslate"><span class="pre">python3.9</span></code> instead</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo -u parsedmarc virtualenv -p python3.9 /opt/parsedmarc/venv
</pre></div>
</div>
<p>To install or upgrade <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> inside the virtualenv, run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo -u parsedmarc /opt/parsedmarc/venv -U parsedmarc
</pre></div>
</div>
</section>
<section id="optional-dependencies">
<h3>Optional dependencies<a class="headerlink" href="#optional-dependencies" title="Permalink to this heading"></a></h3>
<p>If you would like to be able to parse emails saved from Microsoft Outlook
(i.e. OLE .msg files), install <code class="docutils literal notranslate"><span class="pre">msgconvert</span></code>:</p>
<p>On Debian or Ubuntu systems, run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo apt-get install libemail-outlook-message-perl
</pre></div>
</div>
</section>
<section id="testing-multiple-report-analyzers">
<h3>Testing multiple report analyzers<a class="headerlink" href="#testing-multiple-report-analyzers" title="Permalink to this heading"></a></h3>
<p>If you would like to test parsedmarc and another report processing solution
at the same time, you can have up to two mailto URIs each in the rua and ruf
tags in your DMARC record, separated by commas.</p>
</section>
<section id="accessing-an-inbox-using-owa-ews">
<h3>Accessing an inbox using OWA/EWS<a class="headerlink" href="#accessing-an-inbox-using-owa-ews" title="Permalink to this heading"></a></h3>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Starting in 8.0.0, parsedmarc supports accessing Microsoft/Office 365
inboxes via the Microsoft Graph API, which is preferred over Davmail.</p>
</div>
<p>Some organizations do not allow IMAP or the Microsoft Graph API,
and only support Exchange Web Services (EWS)/Outlook Web Access (OWA).
In that case, Davmail will need to be set up
as a local EWS/OWA IMAP gateway. It can even work where
<a class="reference external" href="http://davmail.sourceforge.net/faq.html">Modern Auth/multi-factor authentication</a> is required.</p>
<p>To do this, download the latest <code class="docutils literal notranslate"><span class="pre">davmail-version.zip</span></code> from
<a class="reference external" href="https://sourceforge.net/projects/davmail/files/">https://sourceforge.net/projects/davmail/files/</a></p>
<p>Extract the zip using the <code class="docutils literal notranslate"><span class="pre">unzip</span></code> command.</p>
<p>Install Java:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo apt-get install default-jre-headless
</pre></div>
</div>
<p>Configure Davmail by creating a <code class="docutils literal notranslate"><span class="pre">davmail.properties</span></code> file</p>
<div class="highlight-properties notranslate"><div class="highlight"><pre><span></span><span class="c"># DavMail settings, see http://davmail.sourceforge.net/ for documentation</span><span class="w"></span>
<span class="c">#############################################################</span><span class="w"></span>
<span class="c"># Basic settings</span><span class="w"></span>
<span class="c"># Server or workstation mode</span><span class="w"></span>
<span class="na">davmail.server</span><span class="o">=</span><span class="s">true</span><span class="w"></span>
<span class="c"># connection mode auto, EWS or WebDav</span><span class="w"></span>
<span class="na">davmail.enableEws</span><span class="o">=</span><span class="s">auto</span><span class="w"></span>
<span class="c"># base Exchange OWA or EWS url</span><span class="w"></span>
<span class="na">davmail.url</span><span class="o">=</span><span class="s">https://outlook.office365.com/EWS/Exchange.asmx</span><span class="w"></span>
<span class="c"># Listener ports</span><span class="w"></span>
<span class="na">davmail.imapPort</span><span class="o">=</span><span class="s">1143</span><span class="w"></span>
<span class="c">#############################################################</span><span class="w"></span>
<span class="c"># Network settings</span><span class="w"></span>
<span class="c"># Network proxy settings</span><span class="w"></span>
<span class="na">davmail.enableProxy</span><span class="o">=</span><span class="s">false</span><span class="w"></span>
<span class="na">davmail.useSystemProxies</span><span class="o">=</span><span class="s">false</span><span class="w"></span>
<span class="na">davmail.proxyHost</span><span class="o">=</span><span class="w"></span>
<span class="na">davmail.proxyPort</span><span class="o">=</span><span class="w"></span>
<span class="na">davmail.proxyUser</span><span class="o">=</span><span class="w"></span>
<span class="na">davmail.proxyPassword</span><span class="o">=</span><span class="w"></span>
<span class="c"># proxy exclude list</span><span class="w"></span>
<span class="na">davmail.noProxyFor</span><span class="o">=</span><span class="w"></span>
<span class="c"># block remote connection to DavMail</span><span class="w"></span>
<span class="na">davmail.allowRemote</span><span class="o">=</span><span class="s">false</span><span class="w"></span>
<span class="c"># bind server sockets to the loopback address</span><span class="w"></span>
<span class="na">davmail.bindAddress</span><span class="o">=</span><span class="s">127.0.0.1</span><span class="w"></span>
<span class="c"># disable SSL for specified listeners</span><span class="w"></span>
<span class="na">davmail.ssl.nosecureimap</span><span class="o">=</span><span class="s">true</span><span class="w"></span>
<span class="c"># Send keepalive character during large folder and messages download</span><span class="w"></span>
<span class="na">davmail.enableKeepalive</span><span class="o">=</span><span class="s">true</span><span class="w"></span>
<span class="c"># Message count limit on folder retrieval</span><span class="w"></span>
<span class="na">davmail.folderSizeLimit</span><span class="o">=</span><span class="s">0</span><span class="w"></span>
<span class="c">#############################################################</span><span class="w"></span>
<span class="c"># IMAP settings</span><span class="w"></span>
<span class="c"># Delete messages immediately on IMAP STORE \Deleted flag</span><span class="w"></span>
<span class="na">davmail.imapAutoExpunge</span><span class="o">=</span><span class="s">true</span><span class="w"></span>
<span class="c"># Enable IDLE support, set polling delay in minutes</span><span class="w"></span>
<span class="na">davmail.imapIdleDelay</span><span class="o">=</span><span class="s">1</span><span class="w"></span>
<span class="c"># Always reply to IMAP RFC822.SIZE requests with Exchange approximate</span><span class="w"></span>
<span class="c"># message size for performance reasons</span><span class="w"></span>
<span class="na">davmail.imapAlwaysApproxMsgSize</span><span class="o">=</span><span class="s">true</span><span class="w"></span>
<span class="c"># Client connection timeout in seconds - default 300, 0 to disable</span><span class="w"></span>
<span class="na">davmail.clientSoTimeout</span><span class="o">=</span><span class="s">0</span><span class="w"></span>
<span class="c">#############################################################</span><span class="w"></span>
</pre></div>
</div>
<section id="running-davmail-as-a-systemd-service">
<h4>Running DavMail as a systemd service<a class="headerlink" href="#running-davmail-as-a-systemd-service" title="Permalink to this heading"></a></h4>
<p>Use systemd to run <code class="docutils literal notranslate"><span class="pre">davmail</span></code> as a service.</p>
<p>Create a system user</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo useradd davmail -r -s /bin/false
</pre></div>
</div>
<p>Protect the <code class="docutils literal notranslate"><span class="pre">davmail</span></code> configuration file from prying eyes</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo chown root:davmail /opt/davmail/davmail.properties
sudo chmod <span class="nv">u</span><span class="o">=</span>rw,g<span class="o">=</span>r,o<span class="o">=</span> /opt/davmail/davmail.properties
</pre></div>
</div>
<p>Create the service configuration file</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo nano /etc/systemd/system/davmail.service
</pre></div>
</div>
<div class="highlight-ini notranslate"><div class="highlight"><pre><span></span><span class="k">[Unit]</span><span class="w"></span>
<span class="na">Description</span><span class="o">=</span><span class="s">DavMail gateway service</span><span class="w"></span>
<span class="na">Documentation</span><span class="o">=</span><span class="s">https://sourceforge.net/projects/davmail/</span><span class="w"></span>
<span class="na">Wants</span><span class="o">=</span><span class="s">network-online.target</span><span class="w"></span>
<span class="na">After</span><span class="o">=</span><span class="s">syslog.target network.target</span><span class="w"></span>
<span class="k">[Service]</span><span class="w"></span>
<span class="na">ExecStart</span><span class="o">=</span><span class="s">/opt/davmail/davmail /opt/davmail/davmail.properties</span><span class="w"></span>
<span class="na">User</span><span class="o">=</span><span class="s">davmail</span><span class="w"></span>
<span class="na">Group</span><span class="o">=</span><span class="s">davmail</span><span class="w"></span>
<span class="na">Restart</span><span class="o">=</span><span class="s">always</span><span class="w"></span>
<span class="na">RestartSec</span><span class="o">=</span><span class="s">5m</span><span class="w"></span>
<span class="k">[Install]</span><span class="w"></span>
<span class="na">WantedBy</span><span class="o">=</span><span class="s">multi-user.target</span><span class="w"></span>
</pre></div>
</div>
<p>Then, enable the service</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo systemctl daemon-reload
sudo systemctl <span class="nb">enable</span> parsedmarc.service
sudo service davmail restart
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>You must also run the above commands whenever you edit
<code class="docutils literal notranslate"><span class="pre">davmail.service</span></code>.</p>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Always restart the service every time you upgrade to a new version of
<code class="docutils literal notranslate"><span class="pre">davmail</span></code>:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo service davmail restart
</pre></div>
</div>
</div>
<p>To check the status of the service, run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>service davmail status
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>In the event of a crash, systemd will restart the service after 5 minutes,
but the <code class="docutils literal notranslate"><span class="pre">service</span> <span class="pre">davmail</span> <span class="pre">status</span></code> command will only show the logs for the
current process. To vew the logs for previous runs as well as the
current process (newest to oldest), run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>journalctl -u davmail.service -r
</pre></div>
</div>
</div>
</section>
<section id="configuring-parsedmarc-for-davmail">
<h4>Configuring parsedmarc for DavMail<a class="headerlink" href="#configuring-parsedmarc-for-davmail" title="Permalink to this heading"></a></h4>
<p>Because you are interacting with DavMail server over the loopback
(i.e. <code class="docutils literal notranslate"><span class="pre">127.0.0.1</span></code>), add the following options to <code class="docutils literal notranslate"><span class="pre">parsedmarc.ini</span></code>
config file:</p>
<div class="highlight-ini notranslate"><div class="highlight"><pre><span></span><span class="k">[imap]</span><span class="w"></span>
<span class="na">host</span><span class="o">=</span><span class="s">127.0.0.1</span><span class="w"></span>
<span class="na">port</span><span class="o">=</span><span class="s">1143</span><span class="w"></span>
<span class="na">ssl</span><span class="o">=</span><span class="s">False</span><span class="w"></span>
<span class="na">watch</span><span class="o">=</span><span class="s">True</span><span class="w"></span>
</pre></div>
</div>
</section>
</section>
<section id="elasticsearch-and-kibana">
<h3>Elasticsearch and Kibana<a class="headerlink" href="#elasticsearch-and-kibana" title="Permalink to this heading"></a></h3>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Splunk is also supported starting with <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> 4.3.0</p>
</div>
<p>To set up visual dashboards of DMARC data, install Elasticsearch and Kibana.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Elasticsearch and Kibana 6 or later are required</p>
</div>
<p>On Debian/Ubuntu based systems, run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo apt-get install -y apt-transport-https
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch <span class="p">|</span> sudo apt-key add -
<span class="nb">echo</span> <span class="s2">&quot;deb https://artifacts.elastic.co/packages/7.x/apt stable main&quot;</span> <span class="p">|</span> sudo tee -a /etc/apt/sources.list.d/elastic-7.x.list
sudo apt-get update
sudo apt-get install -y default-jre-headless elasticsearch kibana
</pre></div>
</div>
<p>For CentOS, RHEL, and other RPM systems, follow the Elastic RPM guides for
<a class="reference external" href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rpm.html">Elasticsearch</a> and <a class="reference external" href="https://www.elastic.co/guide/en/kibana/current/rpm.html">Kibana</a>.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>The default JVM heap size for Elasticsearch is very small (1g), which will
cause it to crash under a heavy load. To fix this, increase the minimum and
maximum JVM heap sizes in <code class="docutils literal notranslate"><span class="pre">/etc/elasticsearch/jvm.options</span></code> to more
reasonable levels, depending on your servers resources.</p>
<p>Make sure the system has at least 2 GB more RAM then the assigned JVM
heap size.</p>
<p>Always set the minimum and maximum JVM heap sizes to the same
value.</p>
<p>For example, to set a 4 GB heap size, set</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>-Xms4g
-Xmx4g
</pre></div>
</div>
<p>See <a class="reference external" href="https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html">https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html</a>
for more information.</p>
</div>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo systemctl daemon-reload
sudo systemctl <span class="nb">enable</span> elasticsearch.service
sudo systemctl <span class="nb">enable</span> kibana.service
sudo service elasticsearch start
sudo service kibana start
</pre></div>
</div>
<p>Without the commercial <a class="reference external" href="https://www.elastic.co/products/x-pack">X-Pack</a> or <a class="reference external" href="https://readonlyrest.com/">ReadonlyREST</a> products, Kibana
does not have any authentication
mechanism of its own. You can use nginx as a reverse proxy that provides basic
authentication.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo apt-get install -y nginx apache2-utils
</pre></div>
</div>
<p>Or, on CentOS:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo yum install -y nginx httpd-tools
</pre></div>
</div>
<p>Create a directory to store the certificates and keys:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>mkdir ~/ssl
<span class="nb">cd</span> ~/ssl
</pre></div>
</div>
<p>To create a self-signed certificate, run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>openssl req -x509 -nodes -days <span class="m">365</span> -newkey rsa:4096 -keyout kibana.key -out kibana.crt
</pre></div>
</div>
<p>Or, to create a Certificate Signing Request (CSR) for a CA, run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>openssl req -newkey rsa:4096-nodes -keyout kibana.key -out kibana.csr
</pre></div>
</div>
<p>Fill in the prompts. Watch out for Common Name (e.g. server FQDN or YOUR
domain name), which is the IP address or domain name that you will be hosting
Kibana on. it is the most important field.</p>
<p>If you generated a CSR, remove the CSR after you have your certs</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>rm -f kibana.csr
</pre></div>
</div>
<p>Move the keys into place and secure them:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nb">cd</span>
sudo mv ssl /etc/nginx
sudo chown -R root:www-data /etc/nginx/ssl
sudo chmod -R <span class="nv">u</span><span class="o">=</span>rX,g<span class="o">=</span>rX,o<span class="o">=</span> /etc/nginx/ssl
</pre></div>
</div>
<p>Disable the default nginx configuration:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo rm /etc/nginx/sites-enabled/default
</pre></div>
</div>
<p>Create the web server configuration</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo nano /etc/nginx/sites-available/kibana
</pre></div>
</div>
<div class="highlight-nginx notranslate"><div class="highlight"><pre><span></span><span class="k">server</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kn">listen</span><span class="w"> </span><span class="mi">443</span><span class="w"> </span><span class="s">ssl</span><span class="w"> </span><span class="s">http2</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">ssl_certificate</span><span class="w"> </span><span class="s">/etc/nginx/ssl/kibana.crt</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">ssl_certificate_key</span><span class="w"> </span><span class="s">/etc/nginx/ssl/kibana.key</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">ssl_session_timeout</span><span class="w"> </span><span class="s">1d</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">ssl_session_cache</span><span class="w"> </span><span class="s">shared:SSL:50m</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">ssl_session_tickets</span><span class="w"> </span><span class="no">off</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="c1"># modern configuration. tweak to your needs.</span>
<span class="w"> </span><span class="kn">ssl_protocols</span><span class="w"> </span><span class="s">TLSv1.2</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">ssl_ciphers</span><span class="w"> </span><span class="s">&#39;ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256&#39;</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">ssl_prefer_server_ciphers</span><span class="w"> </span><span class="no">on</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="c1"># Uncomment this next line if you are using a signed, trusted cert</span>
<span class="w"> </span><span class="c1">#add_header Strict-Transport-Security &quot;max-age=63072000; includeSubdomains; preload&quot;;</span>
<span class="w"> </span><span class="kn">add_header</span><span class="w"> </span><span class="s">X-Frame-Options</span><span class="w"> </span><span class="s">SAMEORIGIN</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">add_header</span><span class="w"> </span><span class="s">X-Content-Type-Options</span><span class="w"> </span><span class="s">nosniff</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">auth_basic</span><span class="w"> </span><span class="s">&quot;Login</span><span class="w"> </span><span class="s">required&quot;</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">auth_basic_user_file</span><span class="w"> </span><span class="s">/etc/nginx/htpasswd</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">location</span><span class="w"> </span><span class="s">/</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kn">proxy_pass</span><span class="w"> </span><span class="s">http://127.0.0.1:5601</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">Host</span><span class="w"> </span><span class="nv">$host</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Real-IP</span><span class="w"> </span><span class="nv">$remote_addr</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-For</span><span class="w"> </span><span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
<span class="k">server</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kn">listen</span><span class="w"> </span><span class="mi">80</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="kn">return</span><span class="w"> </span><span class="mi">301</span><span class="w"> </span><span class="s">https://</span><span class="nv">$host$request_uri</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>Enable the nginx configuration for Kibana:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo ln -s /etc/nginx/sites-available/kibana /etc/nginx/sites-enabled/kibana
</pre></div>
</div>
<p>Add a user to basic authentication:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo htpasswd -c /etc/nginx/htpasswd exampleuser
</pre></div>
</div>
<p>Where <code class="docutils literal notranslate"><span class="pre">exampleuser</span></code> is the name of the user you want to add.</p>
<p>Secure the permissions of the httpasswd file:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo chown root:www-data /etc/nginx/htpasswd
sudo chmod <span class="nv">u</span><span class="o">=</span>rw,g<span class="o">=</span>r,o<span class="o">=</span> /etc/nginx/htpasswd
</pre></div>
</div>
<p>Restart nginx:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo service nginx restart
</pre></div>
</div>
<p>Now that Elasticsearch is up and running, use <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> to send data to
it.</p>
<p>Download (right click the link and click save as) <a class="reference external" href="https://raw.githubusercontent.com/domainaware/parsedmarc/master/kibana/export.ndjson">export.ndjson</a>.</p>
<p>Import <code class="docutils literal notranslate"><span class="pre">export.ndjson</span></code> the Saved Objects tab of the Stack management
page of Kibana.</p>
<p>It will give you the option to overwrite existing saved dashboards or
visualizations, which could be used to restore them if you or someone else
breaks them, as there are no permissions/access controls in Kibana without
the commercial <a class="reference external" href="https://www.elastic.co/products/x-pack">X-Pack</a>.</p>
<a class="reference external image-reference" href="_static/screenshots/saved-objects.png"><img alt="A screenshot of setting the Saved Objects Stack management UI in Kibana" class="align-center" src="_images/saved-objects.png" /></a>
<a class="reference external image-reference" href="_static/screenshots/confirm-overwrite.png"><img alt="A screenshot of the overwrite conformation prompt" class="align-center" src="_images/confirm-overwrite.png" /></a>
<section id="upgrading-kibana-index-patterns">
<h4>Upgrading Kibana index patterns<a class="headerlink" href="#upgrading-kibana-index-patterns" title="Permalink to this heading"></a></h4>
<p><code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> 5.0.0 makes some changes to the way data is indexed in
Elasticsearch. if you are upgrading from a previous release of
<code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code>, you need to complete the following steps to replace the
Kibana index patterns with versions that match the upgraded indexes:</p>
<ol class="arabic simple">
<li><p>Login in to Kibana, and click on Management</p></li>
<li><p>Under Kibana, click on Saved Objects</p></li>
<li><p>Check the checkboxes for the <code class="docutils literal notranslate"><span class="pre">dmarc_aggregate</span></code> and <code class="docutils literal notranslate"><span class="pre">dmarc_forensic</span></code>
index patterns</p></li>
<li><p>Click Delete</p></li>
<li><p>Click Delete on the conformation message</p></li>
<li><p>Download (right click the link and click save as)
the latest version of <a class="reference external" href="https://raw.githubusercontent.com/domainaware/parsedmarc/master/kibana/export.ndjson">export.ndjson</a></p></li>
<li><p>Import <code class="docutils literal notranslate"><span class="pre">export.ndjson</span></code> by clicking Import from the Kibana
Saved Objects page</p></li>
</ol>
</section>
<section id="records-retention">
<h4>Records retention<a class="headerlink" href="#records-retention" title="Permalink to this heading"></a></h4>
<p>Starting in version 5.0.0, <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> stores data in a separate
index for each day to make it easy to comply with records
retention regulations such as GDPR. For fore information,
check out the Elastic guide to <a class="reference external" href="https://www.elastic.co/blog/managing-time-based-indices-efficiently">managing time-based indexes efficiently</a>.</p>
</section>
</section>
<section id="splunk">
<h3>Splunk<a class="headerlink" href="#splunk" title="Permalink to this heading"></a></h3>
<p>Starting in version 4.3.0 <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> supports sending aggregate and/or
forensic DMARC data to a Splunk <a class="reference external" href="http://docs.splunk.com/Documentation/Splunk/latest/Data/AboutHEC">HTTP Event collector (HEC)</a>.</p>
<p>The project repository contains <a class="reference external" href="https://github.com/domainaware/parsedmarc/tree/master/splunk">XML files</a> for premade Splunk dashboards for
aggregate and forensic DMARC reports.</p>
<p>Copy and paste the contents of each file into a separate Splunk dashboard XML
editor.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Change all occurrences of <code class="docutils literal notranslate"><span class="pre">index=&quot;email&quot;</span></code> in the XML to
match your own index name.</p>
</div>
<p>The Splunk dashboards display the same content and layout as the Kibana
dashboards, although the Kibana dashboards have slightly easier and more
flexible filtering options.</p>
</section>
<section id="running-parsedmarc-as-a-systemd-service">
<h3>Running parsedmarc as a systemd service<a class="headerlink" href="#running-parsedmarc-as-a-systemd-service" title="Permalink to this heading"></a></h3>
<p>Use systemd to run <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> as a service and process reports as they
arrive.</p>
<p>Protect the <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> configuration file from prying eyes</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo chown root:parsedmarc /etc/parsedmarc.ini
sudo chmod <span class="nv">u</span><span class="o">=</span>rw,g<span class="o">=</span>r,o<span class="o">=</span> /etc/parsedmarc.ini
</pre></div>
</div>
<p>Create the service configuration file</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo nano /etc/systemd/system/parsedmarc.service
</pre></div>
</div>
<div class="highlight-ini notranslate"><div class="highlight"><pre><span></span><span class="k">[Unit]</span><span class="w"></span>
<span class="na">Description</span><span class="o">=</span><span class="s">parsedmarc mailbox watcher</span><span class="w"></span>
<span class="na">Documentation</span><span class="o">=</span><span class="s">https://domainaware.github.io/parsedmarc/</span><span class="w"></span>
<span class="na">Wants</span><span class="o">=</span><span class="s">network-online.target</span><span class="w"></span>
<span class="na">After</span><span class="o">=</span><span class="s">network.target network-online.target elasticsearch.service</span><span class="w"></span>
<span class="k">[Service]</span><span class="w"></span>
<span class="na">ExecStart</span><span class="o">=</span><span class="s">/opt/parsedmarc/venv/bin/parsedmarc -c /etc/parsedmarc.ini</span><span class="w"></span>
<span class="na">User</span><span class="o">=</span><span class="s">parsedmarc</span><span class="w"></span>
<span class="na">Group</span><span class="o">=</span><span class="s">parsedmarc</span><span class="w"></span>
<span class="na">Restart</span><span class="o">=</span><span class="s">always</span><span class="w"></span>
<span class="na">RestartSec</span><span class="o">=</span><span class="s">5m</span><span class="w"></span>
<span class="k">[Install]</span><span class="w"></span>
<span class="na">WantedBy</span><span class="o">=</span><span class="s">multi-user.target</span><span class="w"></span>
</pre></div>
</div>
<p>Then, enable the service</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo systemctl daemon-reload
sudo systemctl <span class="nb">enable</span> parsedmarc.service
sudo service parsedmarc restart
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>You must also run the above commands whenever you edit
<code class="docutils literal notranslate"><span class="pre">parsedmarc.service</span></code>.</p>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Always restart the service every time you upgrade to a new version of
<code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code>:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo service parsedmarc restart
</pre></div>
</div>
</div>
<p>To check the status of the service, run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>service parsedmarc status
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>In the event of a crash, systemd will restart the service after 10 minutes,
but the <code class="docutils literal notranslate"><span class="pre">service</span> <span class="pre">parsedmarc</span> <span class="pre">status</span></code> command will only show the logs for the
current process. To vew the logs for previous runs as well as the
current process (newest to oldest), run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>journalctl -u parsedmarc.service -r
</pre></div>
</div>
</div>
</section>
</section>
<section id="using-the-kibana-dashboards">
<h2>Using the Kibana dashboards<a class="headerlink" href="#using-the-kibana-dashboards" title="Permalink to this heading"></a></h2>
<p>The Kibana DMARC dashboards are a human-friendly way to understand the results
from incoming DMARC reports.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The default dashboard is DMARC Summary. To switch between dashboards,
click on the Dashboard link in the left side menu of Kibana.</p>
</div>
<section id="dmarc-summary">
<h3>DMARC Summary<a class="headerlink" href="#dmarc-summary" title="Permalink to this heading"></a></h3>
<p>As the name suggests, this dashboard is the best place to start reviewing your
aggregate DMARC data.</p>
<p>Across the top of the dashboard, three pie charts display the percentage of
alignment pass/fail for SPF, DKIM, and DMARC. Clicking on any chart segment
will filter for that value.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Messages should not be considered malicious just because they failed to pass
DMARC; especially if you have just started collecting data. It may be a
legitimate service that needs SPF and DKIM configured correctly.</p>
</div>
<p>Start by filtering the results to only show failed DKIM alignment. While DMARC
passes if a message passes SPF or DKIM alignment, only DKIM alignment remains
valid when a message is forwarded without changing the from address, which is
often caused by a mailbox forwarding rule. This is because DKIM signatures are
part of the message headers, whereas SPF relies on SMTP session headers.</p>
<p>Underneath the pie charts. you can see graphs of DMARC passage and message
disposition over time.</p>
<p>Under the graphs you will find the most useful data tables on the dashboard. On
the left, there is a list of organizations that are sending you DMARC reports.
In the center, there is a list of sending servers grouped by the base domain
in their reverse DNS. On the right, there is a list of email from domains,
sorted by message volume.</p>
<p>By hovering your mouse over a data table value and using the magnifying glass
icons, you can filter on our filter out different values. Start by looking at
the Message Sources by Reverse DNS table. Find a sender that you recognize,
such as an email marketing service, hover over it, and click on the plus (+)
magnifying glass icon, to add a filter that only shows results for that sender.
Now, look at the Message From Header table to the right. That shows you the
domains that a sender is sending as, which might tell you which brand/business
is using a particular service. With that information, you can contact them and
have them set up DKIM.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If you have a lot of B2C customers, you may see a high volume of emails as
your domains coming from consumer email services, such as Google/Gmail and
Yahoo! This occurs when customers have mailbox rules in place that forward
emails from an old account to a new account, which is why DKIM
authentication is so important, as mentioned earlier. Similar patterns may
be observed with businesses who send from reverse DNS addressees of
parent, subsidiary, and outdated brands.</p>
</div>
<p>Further down the dashboard, you can filter by source country or source IP
address.</p>
<p>Tables showing SPF and DKIM alignment details are located under the IP address
table.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Previously, the alignment tables were included in a separate dashboard
called DMARC Alignment Failures. That dashboard has been consolidated into
the DMARC Summary dashboard. To view failures only, use the pie chart.</p>
</div>
<p>Any other filters work the same way. You can also add your own custom temporary
filters by clicking on Add Filter at the upper right of the page.</p>
</section>
<section id="dmarc-forensic-samples">
<h3>DMARC Forensic Samples<a class="headerlink" href="#dmarc-forensic-samples" title="Permalink to this heading"></a></h3>
<p>The DMARC Forensic Samples dashboard contains information on DMARC forensic
reports (also known as failure reports or ruf reports). These reports contain
samples of emails that have failed to pass DMARC.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Most recipients do not send forensic/failure/ruf reports at all to avoid
privacy leaks. Some recipients (notably Chinese webmail services) will only
supply the headers of sample emails. Very few provide the entire email.</p>
</div>
</section>
</section>
<section id="dmarc-alignment-guide">
<h2>DMARC Alignment Guide<a class="headerlink" href="#dmarc-alignment-guide" title="Permalink to this heading"></a></h2>
<p>DMARC ensures that SPF and DKM authentication mechanisms actually authenticate
against the same domain that the end user sees.</p>
<p>A message passes a DMARC check by passing DKIM or SPF, <strong>as long as the related
indicators are also in alignment</strong>.</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<tbody>
<tr class="row-odd"><td></td>
<td><p><strong>DKIM</strong></p></td>
<td><p><strong>SPF</strong></p></td>
</tr>
<tr class="row-even"><td><p><strong>Passing</strong></p></td>
<td><p>The signature in the
DKIM header is
validated using a
public key that is
published as a DNS
record of the domain
name specified in the
signature</p></td>
<td><p>The mail servers IP
address is listed in
the SPF record of the
domain in the SMTP
envelopes mail from
header</p></td>
</tr>
<tr class="row-odd"><td><p><strong>Alignment</strong></p></td>
<td><p>The signing domain
aligns with the
domain in the
messages from header</p></td>
<td><p>The domain in the
SMTP envelopes mail
from header aligns
with the domain in
the messages from
header</p></td>
</tr>
</tbody>
</table>
</section>
<section id="what-if-a-sender-wont-support-dkim-dmarc">
<h2>What if a sender wont support DKIM/DMARC?<a class="headerlink" href="#what-if-a-sender-wont-support-dkim-dmarc" title="Permalink to this heading"></a></h2>
<ol class="arabic simple">
<li><p>Some vendors dont know about DMARC yet; ask about SPF and DKIM/email
authentication.</p></li>
<li><p>Check if they can send through your email relays instead of theirs.</p></li>
<li><p>Do they really need to spoof your domain? Why not use the display
name instead?</p></li>
<li><p>Worst case, have that vendor send email as a specific subdomain of
your domain (e.g. <code class="docutils literal notranslate"><span class="pre">noreply&#64;news.example.com</span></code>), and then create
separate SPF and DMARC records on <code class="docutils literal notranslate"><span class="pre">news.example.com</span></code>, and set
<code class="docutils literal notranslate"><span class="pre">p=none</span></code> in that DMARC record.</p></li>
</ol>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Do not alter the <code class="docutils literal notranslate"><span class="pre">p</span></code> or <code class="docutils literal notranslate"><span class="pre">sp</span></code> values of the DMARC record on the
Top-Level Domain (TLD) that would leave you vulnerable to
spoofing of your TLD and/or any subdomain.</p>
</div>
</section>
<section id="what-about-mailing-lists">
<h2>What about mailing lists?<a class="headerlink" href="#what-about-mailing-lists" title="Permalink to this heading"></a></h2>
<p>When you deploy DMARC on your domain, you might find that messages
relayed by mailing lists are failing DMARC, most likely because the mailing
list is spoofing your from address, and modifying the subject,
footer, or other part of the message, thereby breaking the
DKIM signature.</p>
<section id="mailing-list-list-best-practices">
<h3>Mailing list list best practices<a class="headerlink" href="#mailing-list-list-best-practices" title="Permalink to this heading"></a></h3>
<p>Ideally, a mailing list should forward messages without altering the
headers or body content at all. <a class="reference external" href="https://begriffs.com/posts/2018-09-18-dmarc-mailing-list.html">Joe Nelson</a> does a fantastic job of
explaining exactly what mailing lists should and shouldnt do to be
fully DMARC compliant. Rather than repeat his fine work, heres a
summary:</p>
<section id="do">
<h4>Do<a class="headerlink" href="#do" title="Permalink to this heading"></a></h4>
<ul class="simple">
<li><p>Retain headers from the original message</p></li>
<li><p>Add <a class="reference external" href="https://tools.ietf.org/html/rfc2369">RFC 2369</a> List-Unsubscribe headers to outgoing messages, instead of
adding unsubscribe links to the body</p></li>
</ul>
<blockquote>
<div><p>List-Unsubscribe: <a class="reference external" href="https://list.example.com/unsubscribe-link">https://list.example.com/unsubscribe-link</a></p>
</div></blockquote>
<ul>
<li><p>Add <a class="reference external" href="https://tools.ietf.org/html/rfc2919">RFC 2919</a> List-Id headers instead of modifying the subject</p>
<blockquote>
<div><p>List-Id: Example Mailing List &lt;<a class="reference external" href="http://list.example.com">list.example.com</a>&gt;</p>
</div></blockquote>
</li>
</ul>
<p>Modern mail clients and webmail services generate unsubscribe buttons based on
these headers.</p>
</section>
<section id="do-not">
<h4>Do not<a class="headerlink" href="#do-not" title="Permalink to this heading"></a></h4>
<ul class="simple">
<li><p>Remove or modify any existing headers from the original message, including
From, Date, Subject, etc.</p></li>
<li><p>Add to or remove content from the message body, <strong>including traditional
disclaimers and unsubscribe footers</strong></p></li>
</ul>
<p>In addition to complying with DMARC, this configuration ensures that Reply
and Reply All actions work like they would with any email message. Reply
replies to the message sender, and Reply All replies to the sender and the
list.</p>
<p>Even without a subject prefix or body footer, mailing list users can still
tell that a message came from the mailing list, because the message was sent
to the mailing list post address, and not their email address.</p>
<p>Configuration steps for common mailing list platforms are listed below.</p>
</section>
<section id="mailman-2">
<h4>Mailman 2<a class="headerlink" href="#mailman-2" title="Permalink to this heading"></a></h4>
<p>Navigate to General Settings, and configure the settings below</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 74%" />
<col style="width: 26%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p><strong>Setting</strong></p></td>
<td><p><strong>Value</strong></p></td>
</tr>
<tr class="row-even"><td><p><strong>subject_prefix</strong></p></td>
<td></td>
</tr>
<tr class="row-odd"><td><p><strong>from_is_list</strong></p></td>
<td><p>No</p></td>
</tr>
<tr class="row-even"><td><p><strong>first_strip_reply_to</strong></p></td>
<td><p>No</p></td>
</tr>
<tr class="row-odd"><td><p><strong>reply_goes_to_list</strong></p></td>
<td><p>Poster</p></td>
</tr>
<tr class="row-even"><td><p><strong>include_rfc2369_headers</strong></p></td>
<td><p>Yes</p></td>
</tr>
<tr class="row-odd"><td><p><strong>include_list_post_header</strong></p></td>
<td><p>Yes</p></td>
</tr>
<tr class="row-even"><td><p><strong>include_sender_header</strong></p></td>
<td><p>No</p></td>
</tr>
</tbody>
</table>
<p>Navigate to Non-digest options, and configure the settings below</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 66%" />
<col style="width: 34%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p><strong>Setting</strong></p></td>
<td><p><strong>Value</strong></p></td>
</tr>
<tr class="row-even"><td><p><strong>msg_header</strong></p></td>
<td></td>
</tr>
<tr class="row-odd"><td><p><strong>msg_footer</strong></p></td>
<td></td>
</tr>
<tr class="row-even"><td><p><strong>scrub_nondigest</strong></p></td>
<td><p>No</p></td>
</tr>
</tbody>
</table>
<p>Navigate to Privacy Options&gt; Sending Filters, and configure the settings below</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 79%" />
<col style="width: 21%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p><strong>Setting</strong></p></td>
<td><p><strong>Value</strong></p></td>
</tr>
<tr class="row-even"><td><p><strong>dmarc_moderation_action</strong></p></td>
<td><p>Accept</p></td>
</tr>
<tr class="row-odd"><td><p><strong>dmarc_quarantine_moderation_action</strong></p></td>
<td><p>Yes</p></td>
</tr>
<tr class="row-even"><td><p><strong>dmarc_none_moderation_action</strong></p></td>
<td><p>Yes</p></td>
</tr>
</tbody>
</table>
</section>
<section id="mailman-3">
<h4>Mailman 3<a class="headerlink" href="#mailman-3" title="Permalink to this heading"></a></h4>
<p>Navigate to Settings&gt; List Identity</p>
<p>Make Subject prefix blank.</p>
<p>Navigate to Settings&gt; Alter Messages</p>
<p>Configure the settings below</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 79%" />
<col style="width: 21%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p><strong>Setting</strong></p></td>
<td><p><strong>Value</strong></p></td>
</tr>
<tr class="row-even"><td><p><strong>Convert html to plaintext</strong></p></td>
<td><p>No</p></td>
</tr>
<tr class="row-odd"><td><p><strong>Include RFC2369 headers</strong></p></td>
<td><p>Yes</p></td>
</tr>
<tr class="row-even"><td><p><strong>Include the list post header</strong></p></td>
<td><p>Yes</p></td>
</tr>
<tr class="row-odd"><td><p><strong>Explicit reply-to address</strong></p></td>
<td></td>
</tr>
<tr class="row-even"><td><p><strong>First strip replyto</strong></p></td>
<td><p>No</p></td>
</tr>
<tr class="row-odd"><td><p><strong>Reply goes to list</strong></p></td>
<td><p>No munging</p></td>
</tr>
</tbody>
</table>
<p>Navigate to Settings&gt; DMARC Mitigation</p>
<p>Configure the settings below</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 52%" />
<col style="width: 48%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p><strong>Setting</strong></p></td>
<td><p><strong>Value</strong></p></td>
</tr>
<tr class="row-even"><td><p><strong>DMARC mitigation action</strong></p></td>
<td><p>No DMARC mitigations</p></td>
</tr>
<tr class="row-odd"><td><p><strong>DMARC mitigate unconditionally</strong></p></td>
<td><p>No</p></td>
</tr>
</tbody>
</table>
<p>Create a blank footer template for your mailing list to remove the message
footer. Unfortunately, the Postorius mailing list admin UI will not allow you
to create an empty template, so youll have to create one using the systems
command line instead, for example:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>touch var/templates/lists/list.example.com/en/list:member:regular:footer
</pre></div>
</div>
<p>Where <code class="docutils literal notranslate"><span class="pre">list.example.com</span></code> the list ID, and <code class="docutils literal notranslate"><span class="pre">en</span></code> is the language.</p>
<p>Then restart mailman core.</p>
</section>
</section>
<section id="workarounds">
<h3>Workarounds<a class="headerlink" href="#workarounds" title="Permalink to this heading"></a></h3>
<p>If a mailing list must go <strong>against</strong> best practices and
modify the message (e.g. to add a required legal footer), the mailing
list administrator must configure the list to replace the From address of the
message (also known as munging) with the address of the mailing list, so they
no longer spoof email addresses with domains protected by DMARC.</p>
<p>Configuration steps for common mailing list platforms are listed below.</p>
<section id="id3">
<h4>Mailman 2<a class="headerlink" href="#id3" title="Permalink to this heading"></a></h4>
<p>Navigate to Privacy Options&gt; Sending Filters, and configure the settings below</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 79%" />
<col style="width: 21%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p><strong>Setting</strong></p></td>
<td><p><strong>Value</strong></p></td>
</tr>
<tr class="row-even"><td><p><strong>dmarc_moderation_action</strong></p></td>
<td><p>Munge From</p></td>
</tr>
<tr class="row-odd"><td><p><strong>dmarc_quarantine_moderation_action</strong></p></td>
<td><p>Yes</p></td>
</tr>
<tr class="row-even"><td><p><strong>dmarc_none_moderation_action</strong></p></td>
<td><p>Yes</p></td>
</tr>
</tbody>
</table>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Message wrapping could be used as the DMARC mitigation action instead. In
that case, the original message is added as an attachment to the mailing
list message, but that could interfere with inbox searching, or mobile
clients.</p>
<p>On the other hand, replacing the From address might cause users to
accidentally reply to the entire list, when they only intended to reply to
the original sender.</p>
<p>Choose the option that best fits your community.</p>
</div>
</section>
<section id="id4">
<h4>Mailman 3<a class="headerlink" href="#id4" title="Permalink to this heading"></a></h4>
<p>In the DMARC Mitigations tab of the Settings page, configure the settings below</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 49%" />
<col style="width: 51%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p><strong>Setting</strong></p></td>
<td><p><strong>Value</strong></p></td>
</tr>
<tr class="row-even"><td><p><strong>DMARC mitigation action</strong></p></td>
<td><p>Replace From: with list address</p></td>
</tr>
<tr class="row-odd"><td><p><strong>DMARC mitigate unconditionally</strong></p></td>
<td><p>No</p></td>
</tr>
</tbody>
</table>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Message wrapping could be used as the DMARC mitigation action instead. In
that case, the original message is added as an attachment to the mailing
list message, but that could interfere with inbox searching, or mobile
clients.</p>
<p>On the other hand, replacing the From address might cause users to
accidentally reply to the entire list, when they only intended to reply to
the original sender.</p>
</div>
</section>
<section id="listserv">
<h4>LISTSERV<a class="headerlink" href="#listserv" title="Permalink to this heading"></a></h4>
<p><a class="reference external" href="https://www.lsoft.com/news/dmarc-issue1-2018.asp">LISTSERV 16.0-2017a</a> and higher will rewrite the From header for domains
that enforce with a DMARC quarantine or reject policy.</p>
<p>Some additional steps are needed for Linux hosts.</p>
</section>
</section>
</section>
<section id="module-parsedmarc">
<span id="api"></span><h2>API<a class="headerlink" href="#module-parsedmarc" title="Permalink to this heading"></a></h2>
<p>A Python package for parsing DMARC reports</p>
<dl class="py exception">
<dt class="sig sig-object py" id="parsedmarc.InvalidAggregateReport">
<em class="property"><span class="pre">exception</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">InvalidAggregateReport</span></span><a class="reference internal" href="_modules/parsedmarc.html#InvalidAggregateReport"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.InvalidAggregateReport" title="Permalink to this definition"></a></dt>
<dd><p>Raised when an invalid DMARC aggregate report is encountered</p>
</dd></dl>
<dl class="py exception">
<dt class="sig sig-object py" id="parsedmarc.InvalidDMARCReport">
<em class="property"><span class="pre">exception</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">InvalidDMARCReport</span></span><a class="reference internal" href="_modules/parsedmarc.html#InvalidDMARCReport"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.InvalidDMARCReport" title="Permalink to this definition"></a></dt>
<dd><p>Raised when an invalid DMARC report is encountered</p>
</dd></dl>
<dl class="py exception">
<dt class="sig sig-object py" id="parsedmarc.InvalidForensicReport">
<em class="property"><span class="pre">exception</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">InvalidForensicReport</span></span><a class="reference internal" href="_modules/parsedmarc.html#InvalidForensicReport"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.InvalidForensicReport" title="Permalink to this definition"></a></dt>
<dd><p>Raised when an invalid DMARC forensic report is encountered</p>
</dd></dl>
<dl class="py exception">
<dt class="sig sig-object py" id="parsedmarc.ParserError">
<em class="property"><span class="pre">exception</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">ParserError</span></span><a class="reference internal" href="_modules/parsedmarc.html#ParserError"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.ParserError" title="Permalink to this definition"></a></dt>
<dd><p>Raised whenever the parser fails for some reason</p>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.email_results">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">email_results</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">results</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">host</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">mail_from</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">mail_to</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">mail_cc</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">mail_bcc</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">port</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">require_encryption</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">verify</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">username</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">password</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">subject</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">attachment_filename</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">message</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#email_results"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.email_results" title="Permalink to this definition"></a></dt>
<dd><p>Emails parsing results as a zip file</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>results</strong> (<em>OrderedDict</em>) Parsing results</p></li>
<li><p><strong>host</strong> Mail server hostname or IP address</p></li>
<li><p><strong>mail_from</strong> The value of the message from header</p></li>
<li><p><strong>mail_to</strong> (<em>list</em>) A list of addresses to mail to</p></li>
<li><p><strong>mail_cc</strong> (<em>list</em>) A list of addresses to CC</p></li>
<li><p><strong>mail_bcc</strong> (<em>list</em>) A list addresses to BCC</p></li>
<li><p><strong>port</strong> (<em>int</em>) Port to use</p></li>
<li><p><strong>require_encryption</strong> (<em>bool</em>) Require a secure connection from the start</p></li>
<li><p><strong>verify</strong> (<em>bool</em>) verify the SSL/TLS certificate</p></li>
<li><p><strong>username</strong> (<em>str</em>) An optional username</p></li>
<li><p><strong>password</strong> (<em>str</em>) An optional password</p></li>
<li><p><strong>subject</strong> (<em>str</em>) Overrides the default message subject</p></li>
<li><p><strong>attachment_filename</strong> (<em>str</em>) Override the default attachment filename</p></li>
<li><p><strong>(</strong><strong>str</strong> (<em>message</em>) Override the default plain text body</p></li>
</ul>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.extract_xml">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">extract_xml</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">input_</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#extract_xml"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.extract_xml" title="Permalink to this definition"></a></dt>
<dd><p>Extracts xml from a zip or gzip file at the given path, file-like object,
or bytes.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>input</strong> A path to a file, a file like object, or bytes</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The extracted XML</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>str</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.get_dmarc_reports_from_mailbox">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">get_dmarc_reports_from_mailbox</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">connection</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">MailboxConnection</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">reports_folder</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'INBOX'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">archive_folder</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'Archive'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">delete</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">test</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">ip_db_path</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">offline</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">nameservers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dns_timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">6.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">strip_attachment_payloads</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">results</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">batch_size</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">10</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">create_folders</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#get_dmarc_reports_from_mailbox"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.get_dmarc_reports_from_mailbox" title="Permalink to this definition"></a></dt>
<dd><p>Fetches and parses DMARC reports from a mailbox</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>connection</strong> A Mailbox connection object</p></li>
<li><p><strong>reports_folder</strong> The folder where reports can be found</p></li>
<li><p><strong>archive_folder</strong> The folder to move processed mail to</p></li>
<li><p><strong>delete</strong> (<em>bool</em>) Delete messages after processing them</p></li>
<li><p><strong>test</strong> (<em>bool</em>) Do not move or delete messages after processing them</p></li>
<li><p><strong>ip_db_path</strong> (<em>str</em>) Path to a MMDB file from MaxMind or DBIP</p></li>
<li><p><strong>offline</strong> (<em>bool</em>) Do not query online for geolocation or DNS</p></li>
<li><p><strong>nameservers</strong> (<em>list</em>) A list of DNS nameservers to query</p></li>
<li><p><strong>dns_timeout</strong> (<em>float</em>) Set the DNS query timeout</p></li>
<li><p><strong>strip_attachment_payloads</strong> (<em>bool</em>) Remove attachment payloads from
forensic report results</p></li>
<li><p><strong>results</strong> (<em>dict</em>) Results from the previous run</p></li>
<li><p><strong>batch_size</strong> (<em>int</em>) Number of messages to read and process before saving
(use 0 for no limit)</p></li>
<li><p><strong>create_folders</strong> (<em>bool</em>) Whether to create the destination folders
(not used in watch)</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>Lists of <code class="docutils literal notranslate"><span class="pre">aggregate_reports</span></code> and <code class="docutils literal notranslate"><span class="pre">forensic_reports</span></code></p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>OrderedDict</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.get_dmarc_reports_from_mbox">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">get_dmarc_reports_from_mbox</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">input_</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">nameservers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dns_timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">strip_attachment_payloads</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">ip_db_path</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">offline</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">parallel</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#get_dmarc_reports_from_mbox"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.get_dmarc_reports_from_mbox" title="Permalink to this definition"></a></dt>
<dd><p>Parses a mailbox in mbox format containing e-mails with attached
DMARC reports</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>input</strong> A path to a mbox file</p></li>
<li><p><strong>nameservers</strong> (<em>list</em>) A list of one or more nameservers to use</p></li>
<li><p><strong>default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's public DNS resolvers by</em>) </p></li>
<li><p><strong>dns_timeout</strong> (<em>float</em>) Sets the DNS timeout in seconds</p></li>
<li><p><strong>strip_attachment_payloads</strong> (<em>bool</em>) Remove attachment payloads from</p></li>
<li><p><strong>results</strong> (<em>forensic report</em>) </p></li>
<li><p><strong>ip_db_path</strong> (<em>str</em>) Path to a MMDB file from MaxMind or DBIP</p></li>
<li><p><strong>offline</strong> (<em>bool</em>) Do not make online queries for geolocation or DNS</p></li>
<li><p><strong>parallel</strong> (<em>bool</em>) Parallel processing</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>Lists of <code class="docutils literal notranslate"><span class="pre">aggregate_reports</span></code> and <code class="docutils literal notranslate"><span class="pre">forensic_reports</span></code></p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>OrderedDict</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.get_report_zip">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">get_report_zip</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">results</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#get_report_zip"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.get_report_zip" title="Permalink to this definition"></a></dt>
<dd><p>Creates a zip file of parsed report output</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>results</strong> (<em>OrderedDict</em>) The parsed results</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>zip file bytes</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>bytes</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.parse_aggregate_report_file">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">parse_aggregate_report_file</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">_input</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">offline</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">ip_db_path</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">nameservers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dns_timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">parallel</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">keep_alive</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parse_aggregate_report_file"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.parse_aggregate_report_file" title="Permalink to this definition"></a></dt>
<dd><p>Parses a file at the given path, a file-like object. or bytes as an
aggregate DMARC report</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>_input</strong> A path to a file, a file like object, or bytes</p></li>
<li><p><strong>offline</strong> (<em>bool</em>) Do not query online for geolocation or DNS</p></li>
<li><p><strong>ip_db_path</strong> (<em>str</em>) Path to a MMDB file from MaxMind or DBIP</p></li>
<li><p><strong>nameservers</strong> (<em>list</em>) A list of one or more nameservers to use</p></li>
<li><p><strong>default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's public DNS resolvers by</em>) </p></li>
<li><p><strong>dns_timeout</strong> (<em>float</em>) Sets the DNS timeout in seconds</p></li>
<li><p><strong>parallel</strong> (<em>bool</em>) Parallel processing</p></li>
<li><p><strong>keep_alive</strong> (<em>callable</em>) Keep alive function</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The parsed DMARC aggregate report</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>OrderedDict</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.parse_aggregate_report_xml">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">parse_aggregate_report_xml</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">xml</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">ip_db_path</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">offline</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">nameservers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">parallel</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">keep_alive</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parse_aggregate_report_xml"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.parse_aggregate_report_xml" title="Permalink to this definition"></a></dt>
<dd><p>Parses a DMARC XML report string and returns a consistent OrderedDict</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>xml</strong> (<em>str</em>) A string of DMARC aggregate report XML</p></li>
<li><p><strong>ip_db_path</strong> (<em>str</em>) Path to a MMDB file from MaxMind or DBIP</p></li>
<li><p><strong>offline</strong> (<em>bool</em>) Do not query online for geolocation or DNS</p></li>
<li><p><strong>nameservers</strong> (<em>list</em>) A list of one or more nameservers to use</p></li>
<li><p><strong>default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's public DNS resolvers by</em>) </p></li>
<li><p><strong>timeout</strong> (<em>float</em>) Sets the DNS timeout in seconds</p></li>
<li><p><strong>parallel</strong> (<em>bool</em>) Parallel processing</p></li>
<li><p><strong>keep_alive</strong> (<em>callable</em>) Keep alive function</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The parsed aggregate DMARC report</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>OrderedDict</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.parse_forensic_report">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">parse_forensic_report</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">feedback_report</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">sample</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">msg_date</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">offline</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">ip_db_path</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">nameservers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dns_timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">strip_attachment_payloads</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">parallel</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parse_forensic_report"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.parse_forensic_report" title="Permalink to this definition"></a></dt>
<dd><p>Converts a DMARC forensic report and sample to a <code class="docutils literal notranslate"><span class="pre">OrderedDict</span></code></p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>feedback_report</strong> (<em>str</em>) A messages feedback report as a string</p></li>
<li><p><strong>ip_db_path</strong> (<em>str</em>) Path to a MMDB file from MaxMind or DBIP</p></li>
<li><p><strong>offline</strong> (<em>bool</em>) Do not query online for geolocation or DNS</p></li>
<li><p><strong>sample</strong> (<em>str</em>) The RFC 822 headers or RFC 822 message sample</p></li>
<li><p><strong>msg_date</strong> (<em>str</em>) The messages date header</p></li>
<li><p><strong>nameservers</strong> (<em>list</em>) A list of one or more nameservers to use</p></li>
<li><p><strong>default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's public DNS resolvers by</em>) </p></li>
<li><p><strong>dns_timeout</strong> (<em>float</em>) Sets the DNS timeout in seconds</p></li>
<li><p><strong>strip_attachment_payloads</strong> (<em>bool</em>) Remove attachment payloads from</p></li>
<li><p><strong>results</strong> (<em>forensic report</em>) </p></li>
<li><p><strong>parallel</strong> (<em>bool</em>) Parallel processing</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>A parsed report and sample</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>OrderedDict</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.parse_report_email">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">parse_report_email</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">input_</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">offline</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">ip_db_path</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">nameservers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dns_timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">strip_attachment_payloads</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">parallel</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">keep_alive</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parse_report_email"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.parse_report_email" title="Permalink to this definition"></a></dt>
<dd><p>Parses a DMARC report from an email</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>input</strong> An emailed DMARC report in RFC 822 format, as bytes or a string</p></li>
<li><p><strong>ip_db_path</strong> (<em>str</em>) Path to a MMDB file from MaxMind or DBIP</p></li>
<li><p><strong>offline</strong> (<em>bool</em>) Do not query online for geolocation on DNS</p></li>
<li><p><strong>nameservers</strong> (<em>list</em>) A list of one or more nameservers to use</p></li>
<li><p><strong>dns_timeout</strong> (<em>float</em>) Sets the DNS timeout in seconds</p></li>
<li><p><strong>strip_attachment_payloads</strong> (<em>bool</em>) Remove attachment payloads from</p></li>
<li><p><strong>results</strong> (<em>forensic report</em>) </p></li>
<li><p><strong>parallel</strong> (<em>bool</em>) Parallel processing</p></li>
<li><p><strong>keep_alive</strong> (<em>callable</em>) keep alive function</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">report_type</span></code>: <code class="docutils literal notranslate"><span class="pre">aggregate</span></code> or <code class="docutils literal notranslate"><span class="pre">forensic</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">report</span></code>: The parsed report</p></li>
</ul>
</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>OrderedDict</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.parse_report_file">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">parse_report_file</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">input_</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">nameservers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dns_timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">strip_attachment_payloads</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">ip_db_path</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">offline</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">parallel</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">keep_alive</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parse_report_file"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.parse_report_file" title="Permalink to this definition"></a></dt>
<dd><p>Parses a DMARC aggregate or forensic file at the given path, a
file-like object. or bytes</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>input</strong> A path to a file, a file like object, or bytes</p></li>
<li><p><strong>nameservers</strong> (<em>list</em>) A list of one or more nameservers to use</p></li>
<li><p><strong>default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's public DNS resolvers by</em>) </p></li>
<li><p><strong>dns_timeout</strong> (<em>float</em>) Sets the DNS timeout in seconds</p></li>
<li><p><strong>strip_attachment_payloads</strong> (<em>bool</em>) Remove attachment payloads from</p></li>
<li><p><strong>results</strong> (<em>forensic report</em>) </p></li>
<li><p><strong>ip_db_path</strong> (<em>str</em>) Path to a MMDB file from MaxMind or DBIP</p></li>
<li><p><strong>offline</strong> (<em>bool</em>) Do not make online queries for geolocation or DNS</p></li>
<li><p><strong>parallel</strong> (<em>bool</em>) Parallel processing</p></li>
<li><p><strong>keep_alive</strong> (<em>callable</em>) Keep alive function</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The parsed DMARC report</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>OrderedDict</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.parsed_aggregate_reports_to_csv">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">parsed_aggregate_reports_to_csv</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">reports</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parsed_aggregate_reports_to_csv"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.parsed_aggregate_reports_to_csv" title="Permalink to this definition"></a></dt>
<dd><p>Converts one or more parsed aggregate reports to flat CSV format, including
headers</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>reports</strong> A parsed aggregate report or list of parsed aggregate reports</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>Parsed aggregate report data in flat CSV format, including headers</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>str</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.parsed_aggregate_reports_to_csv_rows">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">parsed_aggregate_reports_to_csv_rows</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">reports</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parsed_aggregate_reports_to_csv_rows"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.parsed_aggregate_reports_to_csv_rows" title="Permalink to this definition"></a></dt>
<dd><p>Converts one or more parsed aggregate reports to list of dicts in flat CSV
format</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>reports</strong> A parsed aggregate report or list of parsed aggregate reports</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>Parsed aggregate report data as a list of dicts in flat CSV
format</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>list</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.parsed_forensic_reports_to_csv">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">parsed_forensic_reports_to_csv</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">reports</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parsed_forensic_reports_to_csv"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.parsed_forensic_reports_to_csv" title="Permalink to this definition"></a></dt>
<dd><p>Converts one or more parsed forensic reports to flat CSV format, including
headers</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>reports</strong> A parsed forensic report or list of parsed forensic reports</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>Parsed forensic report data in flat CSV format, including headers</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>str</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.parsed_forensic_reports_to_csv_rows">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">parsed_forensic_reports_to_csv_rows</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">reports</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parsed_forensic_reports_to_csv_rows"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.parsed_forensic_reports_to_csv_rows" title="Permalink to this definition"></a></dt>
<dd><p>Converts one or more parsed forensic reports to a list of dicts in flat CSV
format</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>reports</strong> A parsed forensic report or list of parsed forensic reports</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>Parsed forensic report data as a list of dicts in flat CSV format</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>list</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.save_output">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">save_output</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">results</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">output_directory</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'output'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">aggregate_json_filename</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'aggregate.json'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">forensic_json_filename</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'forensic.json'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">aggregate_csv_filename</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'aggregate.csv'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">forensic_csv_filename</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'forensic.csv'</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#save_output"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.save_output" title="Permalink to this definition"></a></dt>
<dd><p>Save report data in the given directory</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>results</strong> (<em>OrderedDict</em>) Parsing results</p></li>
<li><p><strong>output_directory</strong> (<em>str</em>) The path to the directory to save in</p></li>
<li><p><strong>aggregate_json_filename</strong> (<em>str</em>) Filename for the aggregate JSON file</p></li>
<li><p><strong>forensic_json_filename</strong> (<em>str</em>) Filename for the forensic JSON file</p></li>
<li><p><strong>aggregate_csv_filename</strong> (<em>str</em>) Filename for the aggregate CSV file</p></li>
<li><p><strong>forensic_csv_filename</strong> (<em>str</em>) Filename for the forensic CSV file</p></li>
</ul>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.watch_inbox">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.</span></span><span class="sig-name descname"><span class="pre">watch_inbox</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">mailbox_connection</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">MailboxConnection</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">callback</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Callable</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">reports_folder</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'INBOX'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">archive_folder</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'Archive'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">delete</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">test</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">check_timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">30</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">ip_db_path</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">offline</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">nameservers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dns_timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">6.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">strip_attachment_payloads</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">batch_size</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#watch_inbox"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.watch_inbox" title="Permalink to this definition"></a></dt>
<dd><dl class="simple">
<dt>Watches the mailbox for new messages and</dt><dd><p>sends the results to a callback function</p>
</dd>
</dl>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>mailbox_connection</strong> The mailbox connection object</p></li>
<li><p><strong>callback</strong> The callback function to receive the parsing results</p></li>
<li><p><strong>reports_folder</strong> The IMAP folder where reports can be found</p></li>
<li><p><strong>archive_folder</strong> The folder to move processed mail to</p></li>
<li><p><strong>delete</strong> (<em>bool</em>) Delete messages after processing them</p></li>
<li><p><strong>test</strong> (<em>bool</em>) Do not move or delete messages after processing them</p></li>
<li><p><strong>check_timeout</strong> (<em>int</em>) Number of seconds to wait for a IMAP IDLE response
or the number of seconds until the next mail check</p></li>
<li><p><strong>ip_db_path</strong> (<em>str</em>) Path to a MMDB file from MaxMind or DBIP</p></li>
<li><p><strong>offline</strong> (<em>bool</em>) Do not query online for geolocation or DNS</p></li>
<li><p><strong>nameservers</strong> (<em>list</em>) A list of one or more nameservers to use</p></li>
<li><p><strong>default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's public DNS resolvers by</em>) </p></li>
<li><p><strong>dns_timeout</strong> (<em>float</em>) Set the DNS query timeout</p></li>
<li><p><strong>strip_attachment_payloads</strong> (<em>bool</em>) Replace attachment payloads in</p></li>
<li><p><strong>None</strong> (<em>forensic report samples with</em>) </p></li>
<li><p><strong>batch_size</strong> (<em>int</em>) Number of messages to read and process before saving</p></li>
</ul>
</dd>
</dl>
</dd></dl>
<section id="module-parsedmarc.elastic">
<span id="parsedmarc-elastic"></span><h3>parsedmarc.elastic<a class="headerlink" href="#module-parsedmarc.elastic" title="Permalink to this heading"></a></h3>
<dl class="py exception">
<dt class="sig sig-object py" id="parsedmarc.elastic.AlreadySaved">
<em class="property"><span class="pre">exception</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">parsedmarc.elastic.</span></span><span class="sig-name descname"><span class="pre">AlreadySaved</span></span><a class="reference internal" href="_modules/parsedmarc/elastic.html#AlreadySaved"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.elastic.AlreadySaved" title="Permalink to this definition"></a></dt>
<dd><p>Raised when a report to be saved matches an existing report</p>
</dd></dl>
<dl class="py exception">
<dt class="sig sig-object py" id="parsedmarc.elastic.ElasticsearchError">
<em class="property"><span class="pre">exception</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">parsedmarc.elastic.</span></span><span class="sig-name descname"><span class="pre">ElasticsearchError</span></span><a class="reference internal" href="_modules/parsedmarc/elastic.html#ElasticsearchError"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.elastic.ElasticsearchError" title="Permalink to this definition"></a></dt>
<dd><p>Raised when an Elasticsearch error occurs</p>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.elastic.create_indexes">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.elastic.</span></span><span class="sig-name descname"><span class="pre">create_indexes</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">names</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">settings</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/elastic.html#create_indexes"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.elastic.create_indexes" title="Permalink to this definition"></a></dt>
<dd><p>Create Elasticsearch indexes</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>names</strong> (<em>list</em>) A list of index names</p></li>
<li><p><strong>settings</strong> (<em>dict</em>) Index settings</p></li>
</ul>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.elastic.migrate_indexes">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.elastic.</span></span><span class="sig-name descname"><span class="pre">migrate_indexes</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">aggregate_indexes</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">forensic_indexes</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/elastic.html#migrate_indexes"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.elastic.migrate_indexes" title="Permalink to this definition"></a></dt>
<dd><p>Updates index mappings</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>aggregate_indexes</strong> (<em>list</em>) A list of aggregate index names</p></li>
<li><p><strong>forensic_indexes</strong> (<em>list</em>) A list of forensic index names</p></li>
</ul>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.elastic.save_aggregate_report_to_elasticsearch">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.elastic.</span></span><span class="sig-name descname"><span class="pre">save_aggregate_report_to_elasticsearch</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">aggregate_report</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">index_suffix</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">monthly_indexes</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">number_of_shards</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">1</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">number_of_replicas</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/elastic.html#save_aggregate_report_to_elasticsearch"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.elastic.save_aggregate_report_to_elasticsearch" title="Permalink to this definition"></a></dt>
<dd><p>Saves a parsed DMARC aggregate report to ElasticSearch</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>aggregate_report</strong> (<em>OrderedDict</em>) A parsed forensic report</p></li>
<li><p><strong>index_suffix</strong> (<em>str</em>) The suffix of the name of the index to save to</p></li>
<li><p><strong>monthly_indexes</strong> (<em>bool</em>) Use monthly indexes instead of daily indexes</p></li>
<li><p><strong>number_of_shards</strong> (<em>int</em>) The number of shards to use in the index</p></li>
<li><p><strong>number_of_replicas</strong> (<em>int</em>) The number of replicas to use in the index</p></li>
</ul>
</dd>
<dt class="field-even">Raises</dt>
<dd class="field-even"><p><a class="reference internal" href="#parsedmarc.elastic.AlreadySaved" title="parsedmarc.elastic.AlreadySaved"><strong>AlreadySaved</strong></a> </p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.elastic.save_forensic_report_to_elasticsearch">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.elastic.</span></span><span class="sig-name descname"><span class="pre">save_forensic_report_to_elasticsearch</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">forensic_report</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">index_suffix</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">monthly_indexes</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">number_of_shards</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">1</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">number_of_replicas</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/elastic.html#save_forensic_report_to_elasticsearch"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.elastic.save_forensic_report_to_elasticsearch" title="Permalink to this definition"></a></dt>
<dd><p>Saves a parsed DMARC forensic report to ElasticSearch</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>forensic_report</strong> (<em>OrderedDict</em>) A parsed forensic report</p></li>
<li><p><strong>index_suffix</strong> (<em>str</em>) The suffix of the name of the index to save to</p></li>
<li><p><strong>monthly_indexes</strong> (<em>bool</em>) Use monthly indexes instead of daily
indexes</p></li>
<li><p><strong>number_of_shards</strong> (<em>int</em>) The number of shards to use in the index</p></li>
<li><p><strong>number_of_replicas</strong> (<em>int</em>) The number of replicas to use in the
index</p></li>
</ul>
</dd>
<dt class="field-even">Raises</dt>
<dd class="field-even"><p><a class="reference internal" href="#parsedmarc.elastic.AlreadySaved" title="parsedmarc.elastic.AlreadySaved"><strong>AlreadySaved</strong></a> </p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.elastic.set_hosts">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.elastic.</span></span><span class="sig-name descname"><span class="pre">set_hosts</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">hosts</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">use_ssl</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">ssl_cert_path</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">username</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">password</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">60.0</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/elastic.html#set_hosts"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.elastic.set_hosts" title="Permalink to this definition"></a></dt>
<dd><p>Sets the Elasticsearch hosts to use</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>hosts</strong> (<em>str</em>) A single hostname or URL, or list of hostnames or URLs</p></li>
<li><p><strong>use_ssl</strong> (<em>bool</em>) Use a HTTPS connection to the server</p></li>
<li><p><strong>ssl_cert_path</strong> (<em>str</em>) Path to the certificate chain</p></li>
<li><p><strong>username</strong> (<em>str</em>) The username to use for authentication</p></li>
<li><p><strong>password</strong> (<em>str</em>) The password to use for authentication</p></li>
<li><p><strong>timeout</strong> (<em>float</em>) Timeout in seconds</p></li>
</ul>
</dd>
</dl>
</dd></dl>
<div class="toctree-wrapper compound">
</div>
</section>
<section id="module-parsedmarc.splunk">
<span id="parsedmarc-splunk"></span><h3>parsedmarc.splunk<a class="headerlink" href="#module-parsedmarc.splunk" title="Permalink to this heading"></a></h3>
<dl class="py class">
<dt class="sig sig-object py" id="parsedmarc.splunk.HECClient">
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">parsedmarc.splunk.</span></span><span class="sig-name descname"><span class="pre">HECClient</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">url</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">access_token</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">index</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">source</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'parsedmarc'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">verify</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">60</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/splunk.html#HECClient"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.splunk.HECClient" title="Permalink to this definition"></a></dt>
<dd><p>Initializes the HECClient
:param url: The URL of the HEC
:type url: str
:param access_token: The HEC access token
:type access_token: str
:param index: The name of the index
:type index: str
:param source: The source name
:type source: str
:param verify: Verify SSL certificates
:type verify: bool
:param timeout: Number of seconds to wait for the server to send
:type timeout: float
:param data before giving up:</p>
<dl class="py method">
<dt class="sig sig-object py" id="parsedmarc.splunk.HECClient.save_aggregate_reports_to_splunk">
<span class="sig-name descname"><span class="pre">save_aggregate_reports_to_splunk</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">aggregate_reports</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/splunk.html#HECClient.save_aggregate_reports_to_splunk"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.splunk.HECClient.save_aggregate_reports_to_splunk" title="Permalink to this definition"></a></dt>
<dd><p>Saves aggregate DMARC reports to Splunk</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>aggregate_reports</strong> A list of aggregate report dictionaries</p></li>
<li><p><strong>Splunk</strong> (<em>to save in</em>) </p></li>
</ul>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="parsedmarc.splunk.HECClient.save_forensic_reports_to_splunk">
<span class="sig-name descname"><span class="pre">save_forensic_reports_to_splunk</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">forensic_reports</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/splunk.html#HECClient.save_forensic_reports_to_splunk"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.splunk.HECClient.save_forensic_reports_to_splunk" title="Permalink to this definition"></a></dt>
<dd><p>Saves forensic DMARC reports to Splunk</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>forensic_reports</strong> (<em>list</em>) A list of forensic report dictionaries</p></li>
<li><p><strong>Splunk</strong> (<em>to save in</em>) </p></li>
</ul>
</dd>
</dl>
</dd></dl>
</dd></dl>
<dl class="py exception">
<dt class="sig sig-object py" id="parsedmarc.splunk.SplunkError">
<em class="property"><span class="pre">exception</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">parsedmarc.splunk.</span></span><span class="sig-name descname"><span class="pre">SplunkError</span></span><a class="reference internal" href="_modules/parsedmarc/splunk.html#SplunkError"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.splunk.SplunkError" title="Permalink to this definition"></a></dt>
<dd><p>Raised when a Splunk API error occurs</p>
</dd></dl>
<div class="toctree-wrapper compound">
</div>
</section>
<section id="module-parsedmarc.utils">
<span id="parsedmarc-utils"></span><h3>parsedmarc.utils<a class="headerlink" href="#module-parsedmarc.utils" title="Permalink to this heading"></a></h3>
<p>Utility functions that might be useful for other projects</p>
<dl class="py exception">
<dt class="sig sig-object py" id="parsedmarc.utils.DownloadError">
<em class="property"><span class="pre">exception</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">DownloadError</span></span><a class="reference internal" href="_modules/parsedmarc/utils.html#DownloadError"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.DownloadError" title="Permalink to this definition"></a></dt>
<dd><p>Rasied when an error occurs when downloading a file</p>
</dd></dl>
<dl class="py exception">
<dt class="sig sig-object py" id="parsedmarc.utils.EmailParserError">
<em class="property"><span class="pre">exception</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">EmailParserError</span></span><a class="reference internal" href="_modules/parsedmarc/utils.html#EmailParserError"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.EmailParserError" title="Permalink to this definition"></a></dt>
<dd><p>Raised when an error parsing the email occurs</p>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.convert_outlook_msg">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">convert_outlook_msg</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">msg_bytes</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#convert_outlook_msg"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.convert_outlook_msg" title="Permalink to this definition"></a></dt>
<dd><p>Uses the <code class="docutils literal notranslate"><span class="pre">msgconvert</span></code> Perl utility to convert an Outlook MS file to
standard RFC 822 format</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>msg_bytes</strong> (<em>bytes</em>) the content of the .msg file</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>A RFC 822 string</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.decode_base64">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">decode_base64</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">data</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#decode_base64"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.decode_base64" title="Permalink to this definition"></a></dt>
<dd><p>Decodes a base64 string, with padding being optional</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>data</strong> A base64 encoded string</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The decoded bytes</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>bytes</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.get_base_domain">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">get_base_domain</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">domain</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">use_fresh_psl</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#get_base_domain"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.get_base_domain" title="Permalink to this definition"></a></dt>
<dd><p>Gets the base domain name for the given domain</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Results are based on a list of public domain suffixes at
<a class="reference external" href="https://publicsuffix.org/list/public_suffix_list.dat">https://publicsuffix.org/list/public_suffix_list.dat</a>.</p>
</div>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>domain</strong> (<em>str</em>) A domain or subdomain</p></li>
<li><p><strong>use_fresh_psl</strong> (<em>bool</em>) Download a fresh Public Suffix List</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The base domain of the given domain</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>str</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.get_filename_safe_string">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">get_filename_safe_string</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">string</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#get_filename_safe_string"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.get_filename_safe_string" title="Permalink to this definition"></a></dt>
<dd><p>Converts a string to a string that is safe for a filename
:param string: A string to make safe for a filename
:type string: str</p>
<dl class="field-list simple">
<dt class="field-odd">Returns</dt>
<dd class="field-odd"><p>A string safe for a filename</p>
</dd>
<dt class="field-even">Return type</dt>
<dd class="field-even"><p>str</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.get_ip_address_country">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">get_ip_address_country</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">ip_address</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">db_path</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#get_ip_address_country"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.get_ip_address_country" title="Permalink to this definition"></a></dt>
<dd><p>Returns the ISO code for the country associated
with the given IPv4 or IPv6 address</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>ip_address</strong> (<em>str</em>) The IP address to query for</p></li>
<li><p><strong>db_path</strong> (<em>str</em>) Path to a MMDB file from MaxMind or DBIP</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>And ISO country code associated with the given IP address</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>str</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.get_ip_address_info">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">get_ip_address_info</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">ip_address</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">ip_db_path</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">cache</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">offline</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">nameservers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">parallel</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#get_ip_address_info"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.get_ip_address_info" title="Permalink to this definition"></a></dt>
<dd><p>Returns reverse DNS and country information for the given IP address</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>ip_address</strong> (<em>str</em>) The IP address to check</p></li>
<li><p><strong>ip_db_path</strong> (<em>str</em>) path to a MMDB file from MaxMind or DBIP</p></li>
<li><p><strong>cache</strong> (<em>ExpiringDict</em>) Cache storage</p></li>
<li><p><strong>offline</strong> (<em>bool</em>) Do not make online queries for geolocation or DNS</p></li>
<li><p><strong>nameservers</strong> (<em>list</em>) A list of one or more nameservers to use</p></li>
<li><p><strong>default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's public DNS resolvers by</em>) </p></li>
<li><p><strong>timeout</strong> (<em>float</em>) Sets the DNS timeout in seconds</p></li>
<li><p><strong>parallel</strong> (<em>bool</em>) parallel processing</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p><code class="docutils literal notranslate"><span class="pre">ip_address</span></code>, <code class="docutils literal notranslate"><span class="pre">reverse_dns</span></code></p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>OrderedDict</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.get_reverse_dns">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">get_reverse_dns</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">ip_address</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">cache</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">nameservers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2.0</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#get_reverse_dns"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.get_reverse_dns" title="Permalink to this definition"></a></dt>
<dd><p>Resolves an IP address to a hostname using a reverse DNS query</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>ip_address</strong> (<em>str</em>) The IP address to resolve</p></li>
<li><p><strong>cache</strong> (<em>ExpiringDict</em>) Cache storage</p></li>
<li><p><strong>nameservers</strong> (<em>list</em>) A list of one or more nameservers to use</p></li>
<li><p><strong>default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's public DNS resolvers by</em>) </p></li>
<li><p><strong>timeout</strong> (<em>float</em>) Sets the DNS query timeout in seconds</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The reverse DNS hostname (if any)</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>str</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.human_timestamp_to_datetime">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">human_timestamp_to_datetime</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">human_timestamp</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">to_utc</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#human_timestamp_to_datetime"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.human_timestamp_to_datetime" title="Permalink to this definition"></a></dt>
<dd><p>Converts a human-readable timestamp into a Python <code class="docutils literal notranslate"><span class="pre">DateTime</span></code> object</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>human_timestamp</strong> (<em>str</em>) A timestamp string</p></li>
<li><p><strong>to_utc</strong> (<em>bool</em>) Convert the timestamp to UTC</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The converted timestamp</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>DateTime</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.human_timestamp_to_timestamp">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">human_timestamp_to_timestamp</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">human_timestamp</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#human_timestamp_to_timestamp"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.human_timestamp_to_timestamp" title="Permalink to this definition"></a></dt>
<dd><p>Converts a human-readable timestamp into a UNIX timestamp</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>human_timestamp</strong> (<em>str</em>) A timestamp in <cite>YYYY-MM-DD HH:MM:SS`</cite> format</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The converted timestamp</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>float</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.is_mbox">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">is_mbox</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">path</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#is_mbox"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.is_mbox" title="Permalink to this definition"></a></dt>
<dd><p>Checks if the given content is a MBOX mailbox file</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>path</strong> Content to check</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>A flag the indicates if a file is a MBOX mailbox file</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>bool</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.is_outlook_msg">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">is_outlook_msg</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">content</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#is_outlook_msg"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.is_outlook_msg" title="Permalink to this definition"></a></dt>
<dd><p>Checks if the given content is a Outlook msg OLE file</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>content</strong> Content to check</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>A flag the indicates if a file is a Outlook MSG file</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>bool</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.parse_email">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">parse_email</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">data</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">strip_attachment_payloads</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#parse_email"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.parse_email" title="Permalink to this definition"></a></dt>
<dd><p>A simplified email parser</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>data</strong> The RFC 822 message string, or MSG binary</p></li>
<li><p><strong>strip_attachment_payloads</strong> (<em>bool</em>) Remove attachment payloads</p></li>
</ul>
</dd>
</dl>
<p>Returns (dict): Parsed email data</p>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.query_dns">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">query_dns</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">domain</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">record_type</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">cache</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">nameservers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2.0</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#query_dns"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.query_dns" title="Permalink to this definition"></a></dt>
<dd><p>Queries DNS</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>domain</strong> (<em>str</em>) The domain or subdomain to query about</p></li>
<li><p><strong>record_type</strong> (<em>str</em>) The record type to query for</p></li>
<li><p><strong>cache</strong> (<em>ExpiringDict</em>) Cache storage</p></li>
<li><p><strong>nameservers</strong> (<em>list</em>) A list of one or more nameservers to use</p></li>
<li><p><strong>default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's public DNS resolvers by</em>) </p></li>
<li><p><strong>timeout</strong> (<em>float</em>) Sets the DNS timeout in seconds</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>A list of answers</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>list</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.timestamp_to_datetime">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">timestamp_to_datetime</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">timestamp</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#timestamp_to_datetime"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.timestamp_to_datetime" title="Permalink to this definition"></a></dt>
<dd><p>Converts a UNIX/DMARC timestamp to a Python <code class="docutils literal notranslate"><span class="pre">DateTime</span></code> object</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>timestamp</strong> (<em>int</em>) The timestamp</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The converted timestamp as a Python <code class="docutils literal notranslate"><span class="pre">DateTime</span></code> object</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>DateTime</p>
</dd>
</dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="parsedmarc.utils.timestamp_to_human">
<span class="sig-prename descclassname"><span class="pre">parsedmarc.utils.</span></span><span class="sig-name descname"><span class="pre">timestamp_to_human</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">timestamp</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#timestamp_to_human"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#parsedmarc.utils.timestamp_to_human" title="Permalink to this definition"></a></dt>
<dd><p>Converts a UNIX/DMARC timestamp to a human-readable string</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>timestamp</strong> The timestamp</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The converted timestamp in <code class="docutils literal notranslate"><span class="pre">YYYY-MM-DD</span> <span class="pre">HH:MM:SS</span></code> format</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p>str</p>
</dd>
</dl>
</dd></dl>
<div class="toctree-wrapper compound">
</div>
</section>
</section>
<section id="indices-and-tables">
<h2>Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this heading"></a></h2>
<ul class="simple">
<li><p><a class="reference internal" href="genindex.html"><span class="std std-ref">Index</span></a></p></li>
<li><p><a class="reference internal" href="py-modindex.html"><span class="std std-ref">Module Index</span></a></p></li>
<li><p><a class="reference internal" href="search.html"><span class="std std-ref">Search Page</span></a></p></li>
</ul>
</section>
</section>
</div>
</div>
<footer>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2018, Sean Whalen.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>