Files
parsedmarc/index.html
Sean Whalen e2aa356fa1 6.3.5
2019-04-29 18:04:53 -04:00

2445 lines
167 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>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>parsedmarc documentation - Open source DMARC report analyzer and visualizer &mdash; parsedmarc 6.3.5 documentation</title>
<script type="text/javascript" src="_static/js/modernizr.min.js"></script>
<script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/language_data.js"></script>
<script type="text/javascript" src="_static/js/theme.js"></script>
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<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">
6.3.5
</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="main navigation">
<!-- 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="#installation-using-pypy3">Installation using pypy3</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-won-t-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="#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="#parsedmarc-splunk">parsedmarc.splunk</a><ul>
</ul>
</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="top navigation">
<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="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="#">Docs</a> &raquo;</li>
<li>parsedmarc documentation - Open source DMARC report analyzer and visualizer</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/index.rst.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">
<div class="section" 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 headline"></a></h1>
<p><a class="reference external" href="https://travis-ci.org/domainaware/parsedmarc"><img alt="Build Status" src="https://travis-ci.org/domainaware/parsedmarc.svg?branch=master" /></a> <a class="reference external" href="https://codecov.io/gh/domainaware/parsedmarc"><img alt="Code Coverage" 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="PyPI Package" src="https://img.shields.io/pypi/v/parsedmarc.svg" /></a></p>
<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>
<div class="section" id="features">
<h2>Features<a class="headerlink" href="#features" title="Permalink to this headline"></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</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>
</div>
<div class="section" id="resources">
<h2>Resources<a class="headerlink" href="#resources" title="Permalink to this headline"></a></h2>
<div class="section" id="dmarc-guides">
<h3>DMARC guides<a class="headerlink" href="#dmarc-guides" title="Permalink to this headline"></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>
</div>
<div class="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 headline"></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>
</div>
<div class="section" id="lookalike-domains">
<h3>Lookalike domains<a class="headerlink" href="#lookalike-domains" title="Permalink to this headline"></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>
</div>
</div>
<div class="section" id="cli-help">
<h2>CLI help<a class="headerlink" href="#cli-help" title="Permalink to this headline"></a></h2>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">usage</span><span class="p">:</span> <span class="n">parsedmarc</span> <span class="p">[</span><span class="o">-</span><span class="n">h</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="n">c</span> <span class="n">CONFIG_FILE</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span><span class="n">strip</span><span class="o">-</span><span class="n">attachment</span><span class="o">-</span><span class="n">payloads</span><span class="p">]</span>
<span class="p">[</span><span class="o">-</span><span class="n">o</span> <span class="n">OUTPUT</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="n">n</span> <span class="n">NAMESERVERS</span> <span class="p">[</span><span class="n">NAMESERVERS</span> <span class="o">...</span><span class="p">]]</span>
<span class="p">[</span><span class="o">-</span><span class="n">t</span> <span class="n">DNS_TIMEOUT</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="n">s</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span><span class="n">debug</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span><span class="n">log</span><span class="o">-</span><span class="n">file</span> <span class="n">LOG_FILE</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="n">v</span><span class="p">]</span>
<span class="p">[</span><span class="n">file_path</span> <span class="p">[</span><span class="n">file_path</span> <span class="o">...</span><span class="p">]]</span>
<span class="n">Parses</span> <span class="n">DMARC</span> <span class="n">reports</span>
<span class="n">positional</span> <span class="n">arguments</span><span class="p">:</span>
<span class="n">file_path</span> <span class="n">one</span> <span class="ow">or</span> <span class="n">more</span> <span class="n">paths</span> <span class="n">to</span> <span class="n">aggregate</span> <span class="ow">or</span> <span class="n">forensic</span> <span class="n">report</span>
<span class="n">files</span> <span class="ow">or</span> <span class="n">emails</span>
<span class="n">optional</span> <span class="n">arguments</span><span class="p">:</span>
<span class="o">-</span><span class="n">h</span><span class="p">,</span> <span class="o">--</span><span class="n">help</span> <span class="n">show</span> <span class="n">this</span> <span class="n">help</span> <span class="n">message</span> <span class="ow">and</span> <span class="n">exit</span>
<span class="o">-</span><span class="n">c</span> <span class="n">CONFIG_FILE</span><span class="p">,</span> <span class="o">--</span><span class="n">config</span><span class="o">-</span><span class="n">file</span> <span class="n">CONFIG_FILE</span>
<span class="n">A</span> <span class="n">path</span> <span class="n">to</span> <span class="n">a</span> <span class="n">configuration</span> <span class="n">file</span> <span class="p">(</span><span class="o">--</span><span class="n">silent</span> <span class="n">implied</span><span class="p">)</span>
<span class="o">--</span><span class="n">strip</span><span class="o">-</span><span class="n">attachment</span><span class="o">-</span><span class="n">payloads</span>
<span class="n">remove</span> <span class="n">attachment</span> <span class="n">payloads</span> <span class="kn">from</span> <span class="nn">forensic</span> <span class="n">report</span> <span class="n">output</span>
<span class="o">-</span><span class="n">o</span> <span class="n">OUTPUT</span><span class="p">,</span> <span class="o">--</span><span class="n">output</span> <span class="n">OUTPUT</span>
<span class="n">write</span> <span class="n">output</span> <span class="n">files</span> <span class="n">to</span> <span class="n">the</span> <span class="n">given</span> <span class="n">directory</span>
<span class="o">-</span><span class="n">n</span> <span class="n">NAMESERVERS</span> <span class="p">[</span><span class="n">NAMESERVERS</span> <span class="o">...</span><span class="p">],</span> <span class="o">--</span><span class="n">nameservers</span> <span class="n">NAMESERVERS</span> <span class="p">[</span><span class="n">NAMESERVERS</span> <span class="o">...</span><span class="p">]</span>
<span class="n">nameservers</span> <span class="n">to</span> <span class="n">query</span> <span class="p">(</span><span class="n">default</span> <span class="ow">is</span> <span class="n">Cloudflare</span><span class="s1">&#39;s</span>
<span class="n">nameservers</span><span class="p">)</span>
<span class="o">-</span><span class="n">t</span> <span class="n">DNS_TIMEOUT</span><span class="p">,</span> <span class="o">--</span><span class="n">dns_timeout</span> <span class="n">DNS_TIMEOUT</span>
<span class="n">number</span> <span class="n">of</span> <span class="n">seconds</span> <span class="n">to</span> <span class="n">wait</span> <span class="k">for</span> <span class="n">an</span> <span class="n">answer</span> <span class="kn">from</span> <span class="nn">DNS</span>
<span class="p">(</span><span class="n">default</span><span class="p">:</span> <span class="mf">6.0</span><span class="p">)</span>
<span class="o">-</span><span class="n">s</span><span class="p">,</span> <span class="o">--</span><span class="n">silent</span> <span class="n">only</span> <span class="nb">print</span> <span class="n">errors</span> <span class="ow">and</span> <span class="n">warnings</span>
<span class="o">--</span><span class="n">debug</span> <span class="nb">print</span> <span class="n">debugging</span> <span class="n">information</span>
<span class="o">--</span><span class="n">log</span><span class="o">-</span><span class="n">file</span> <span class="n">LOG_FILE</span> <span class="n">output</span> <span class="n">logging</span> <span class="n">to</span> <span class="n">a</span> <span class="n">file</span>
<span class="o">-</span><span class="n">v</span><span class="p">,</span> <span class="o">--</span><span class="n">version</span> <span class="n">show</span> <span class="n">program</span><span class="s1">&#39;s version number and exit</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>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>
</div>
<div class="section" id="configuration-file">
<h2>Configuration file<a class="headerlink" href="#configuration-file" title="Permalink to this headline"></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="k">[general]</span>
<span class="na">save_aggregate</span> <span class="o">=</span> <span class="s">True</span>
<span class="na">save_forensic</span> <span class="o">=</span> <span class="s">True</span>
<span class="k">[imap]</span>
<span class="na">host</span> <span class="o">=</span> <span class="s">imap.example.com</span>
<span class="na">user</span> <span class="o">=</span> <span class="s">dmarcresports@example.com</span>
<span class="na">password</span> <span class="o">=</span> <span class="s">$uperSecure</span>
<span class="na">watch</span> <span class="o">=</span> <span class="s">True</span>
<span class="k">[elasticsearch]</span>
<span class="na">hosts</span> <span class="o">=</span> <span class="s">127.0.0.1:9200</span>
<span class="na">ssl</span> <span class="o">=</span> <span class="s">False</span>
<span class="k">[splunk_hec]</span>
<span class="na">url</span> <span class="o">=</span> <span class="s">https://splunkhec.example.com</span>
<span class="na">token</span> <span class="o">=</span> <span class="s">HECTokenGoesHere</span>
<span class="na">index</span> <span class="o">=</span> <span class="s">email</span>
</pre></div>
</div>
<p>The full set of configuration options are:</p>
<ul>
<li><dl class="simple">
<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 the Elasticsearch and/or Splunk</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">save_forensic</span></code> - bool: Save forensic report data to the Elasticsearch and/or Splunk</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">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. Setting this to a number larger than one can improve performance when processing thousands of files</p></li>
</ul>
</dd>
</dl>
</li>
<li><dl class="simple">
<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>
<li><p><code class="docutils literal notranslate"><span class="pre">port</span></code> - int: The IMAP server port (Default: 993)</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">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>
<li><p><code class="docutils literal notranslate"><span class="pre">reports_folder</span></code> - str: The IMAP folder where the incoming reports can be found (Default: INBOX)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">archive_folder</span></code> - str: The IMAP folder 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 messages as they arrive</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">delete</span></code> - bool: Delete messages after processing them, 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>
</ul>
</dd>
</dl>
</li>
<li><dl>
<dt><code class="docutils literal notranslate"><span class="pre">elasticsearch</span></code></dt><dd><ul>
<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>
<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>
</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">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>
</ul>
</dd>
</dl>
</li>
<li><dl class="simple">
<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>
<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>
</dd>
</dl>
</li>
<li><dl class="simple">
<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>
<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>
</dd>
</dl>
</li>
<li><dl class="simple">
<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>
<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></li>
</ul>
</dd>
</dl>
</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</span></code>
manually on a separate IMAP folder (using the <code class="docutils literal notranslate"><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>
</div>
<div class="section" id="sample-aggregate-report-output">
<h2>Sample aggregate report output<a class="headerlink" href="#sample-aggregate-report-output" title="Permalink to this headline"></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 dmarc.org 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>
<div class="section" id="json">
<h3>JSON<a class="headerlink" href="#json" title="Permalink to this headline"></a></h3>
<div class="highlight-json notranslate"><div class="highlight"><pre><span></span><span class="p">{</span>
<span class="nt">&quot;xml_schema&quot;</span><span class="p">:</span> <span class="s2">&quot;draft&quot;</span><span class="p">,</span>
<span class="nt">&quot;report_metadata&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;org_name&quot;</span><span class="p">:</span> <span class="s2">&quot;acme.com&quot;</span><span class="p">,</span>
<span class="nt">&quot;org_email&quot;</span><span class="p">:</span> <span class="s2">&quot;noreply-dmarc-support@acme.com&quot;</span><span class="p">,</span>
<span class="nt">&quot;org_extra_contact_info&quot;</span><span class="p">:</span> <span class="s2">&quot;http://acme.com/dmarc/support&quot;</span><span class="p">,</span>
<span class="nt">&quot;report_id&quot;</span><span class="p">:</span> <span class="s2">&quot;9391651994964116463&quot;</span><span class="p">,</span>
<span class="nt">&quot;begin_date&quot;</span><span class="p">:</span> <span class="s2">&quot;2012-04-27 20:00:00&quot;</span><span class="p">,</span>
<span class="nt">&quot;end_date&quot;</span><span class="p">:</span> <span class="s2">&quot;2012-04-28 19:59:59&quot;</span><span class="p">,</span>
<span class="nt">&quot;errors&quot;</span><span class="p">:</span> <span class="p">[]</span>
<span class="p">},</span>
<span class="nt">&quot;policy_published&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;domain&quot;</span><span class="p">:</span> <span class="s2">&quot;example.com&quot;</span><span class="p">,</span>
<span class="nt">&quot;adkim&quot;</span><span class="p">:</span> <span class="s2">&quot;r&quot;</span><span class="p">,</span>
<span class="nt">&quot;aspf&quot;</span><span class="p">:</span> <span class="s2">&quot;r&quot;</span><span class="p">,</span>
<span class="nt">&quot;p&quot;</span><span class="p">:</span> <span class="s2">&quot;none&quot;</span><span class="p">,</span>
<span class="nt">&quot;sp&quot;</span><span class="p">:</span> <span class="s2">&quot;none&quot;</span><span class="p">,</span>
<span class="nt">&quot;pct&quot;</span><span class="p">:</span> <span class="s2">&quot;100&quot;</span><span class="p">,</span>
<span class="nt">&quot;fo&quot;</span><span class="p">:</span> <span class="s2">&quot;0&quot;</span>
<span class="p">},</span>
<span class="nt">&quot;records&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="nt">&quot;source&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;ip_address&quot;</span><span class="p">:</span> <span class="s2">&quot;72.150.241.94&quot;</span><span class="p">,</span>
<span class="nt">&quot;country&quot;</span><span class="p">:</span> <span class="s2">&quot;US&quot;</span><span class="p">,</span>
<span class="nt">&quot;reverse_dns&quot;</span><span class="p">:</span> <span class="s2">&quot;adsl-72-150-241-94.shv.bellsouth.net&quot;</span><span class="p">,</span>
<span class="nt">&quot;base_domain&quot;</span><span class="p">:</span> <span class="s2">&quot;bellsouth.net&quot;</span>
<span class="p">},</span>
<span class="nt">&quot;count&quot;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nt">&quot;alignment&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;spf&quot;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="nt">&quot;dkim&quot;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="nt">&quot;dmarc&quot;</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">},</span>
<span class="nt">&quot;policy_evaluated&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;disposition&quot;</span><span class="p">:</span> <span class="s2">&quot;none&quot;</span><span class="p">,</span>
<span class="nt">&quot;dkim&quot;</span><span class="p">:</span> <span class="s2">&quot;fail&quot;</span><span class="p">,</span>
<span class="nt">&quot;spf&quot;</span><span class="p">:</span> <span class="s2">&quot;pass&quot;</span><span class="p">,</span>
<span class="nt">&quot;policy_override_reasons&quot;</span><span class="p">:</span> <span class="p">[]</span>
<span class="p">},</span>
<span class="nt">&quot;identifiers&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;header_from&quot;</span><span class="p">:</span> <span class="s2">&quot;example.com&quot;</span><span class="p">,</span>
<span class="nt">&quot;envelope_from&quot;</span><span class="p">:</span> <span class="s2">&quot;example.com&quot;</span><span class="p">,</span>
<span class="nt">&quot;envelope_to&quot;</span><span class="p">:</span> <span class="kc">null</span>
<span class="p">},</span>
<span class="nt">&quot;auth_results&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;dkim&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="nt">&quot;domain&quot;</span><span class="p">:</span> <span class="s2">&quot;example.com&quot;</span><span class="p">,</span>
<span class="nt">&quot;selector&quot;</span><span class="p">:</span> <span class="s2">&quot;none&quot;</span><span class="p">,</span>
<span class="nt">&quot;result&quot;</span><span class="p">:</span> <span class="s2">&quot;fail&quot;</span>
<span class="p">}</span>
<span class="p">],</span>
<span class="nt">&quot;spf&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="nt">&quot;domain&quot;</span><span class="p">:</span> <span class="s2">&quot;example.com&quot;</span><span class="p">,</span>
<span class="nt">&quot;scope&quot;</span><span class="p">:</span> <span class="s2">&quot;mfrom&quot;</span><span class="p">,</span>
<span class="nt">&quot;result&quot;</span><span class="p">:</span> <span class="s2">&quot;pass&quot;</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="csv">
<h3>CSV<a class="headerlink" href="#csv" title="Permalink to this headline"></a></h3>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">xml_schema</span><span class="p">,</span><span class="n">org_name</span><span class="p">,</span><span class="n">org_email</span><span class="p">,</span><span class="n">org_extra_contact_info</span><span class="p">,</span><span class="n">report_id</span><span class="p">,</span><span class="n">begin_date</span><span class="p">,</span><span class="n">end_date</span><span class="p">,</span><span class="n">errors</span><span class="p">,</span><span class="n">domain</span><span class="p">,</span><span class="n">adkim</span><span class="p">,</span><span class="n">aspf</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="n">sp</span><span class="p">,</span><span class="n">pct</span><span class="p">,</span><span class="n">fo</span><span class="p">,</span><span class="n">source_ip_address</span><span class="p">,</span><span class="n">source_country</span><span class="p">,</span><span class="n">source_reverse_dns</span><span class="p">,</span><span class="n">source_base_domain</span><span class="p">,</span><span class="n">count</span><span class="p">,</span><span class="n">disposition</span><span class="p">,</span><span class="n">dkim_alignment</span><span class="p">,</span><span class="n">spf_alignment</span><span class="p">,</span><span class="n">policy_override_reasons</span><span class="p">,</span><span class="n">policy_override_comments</span><span class="p">,</span><span class="n">envelope_from</span><span class="p">,</span><span class="n">header_from</span><span class="p">,</span><span class="n">envelope_to</span><span class="p">,</span><span class="n">dkim_domains</span><span class="p">,</span><span class="n">dkim_selectors</span><span class="p">,</span><span class="n">dkim_results</span><span class="p">,</span><span class="n">spf_domains</span><span class="p">,</span><span class="n">spf_scopes</span><span class="p">,</span><span class="n">spf_results</span>
<span class="n">draft</span><span class="p">,</span><span class="n">acme</span><span class="o">.</span><span class="n">com</span><span class="p">,</span><span class="n">noreply</span><span class="o">-</span><span class="n">dmarc</span><span class="o">-</span><span class="n">support</span><span class="nd">@acme</span><span class="o">.</span><span class="n">com</span><span class="p">,</span><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">acme</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">dmarc</span><span class="o">/</span><span class="n">support</span><span class="p">,</span><span class="mi">9391651994964116463</span><span class="p">,</span><span class="mi">2012</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">27</span> <span class="mi">20</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span><span class="p">,</span><span class="mi">2012</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">28</span> <span class="mi">19</span><span class="p">:</span><span class="mi">59</span><span class="p">:</span><span class="mi">59</span><span class="p">,,</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="p">,</span><span class="n">r</span><span class="p">,</span><span class="n">r</span><span class="p">,</span><span class="n">none</span><span class="p">,</span><span class="n">none</span><span class="p">,</span><span class="mi">100</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mf">72.150</span><span class="o">.</span><span class="mf">241.94</span><span class="p">,</span><span class="n">US</span><span class="p">,</span><span class="n">adsl</span><span class="o">-</span><span class="mi">72</span><span class="o">-</span><span class="mi">150</span><span class="o">-</span><span class="mi">241</span><span class="o">-</span><span class="mf">94.</span><span class="n">shv</span><span class="o">.</span><span class="n">bellsouth</span><span class="o">.</span><span class="n">net</span><span class="p">,</span><span class="n">bellsouth</span><span class="o">.</span><span class="n">net</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="n">none</span><span class="p">,</span><span class="n">fail</span><span class="p">,</span><span class="k">pass</span><span class="p">,,,</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="p">,</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="p">,,</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="p">,</span><span class="n">none</span><span class="p">,</span><span class="n">fail</span><span class="p">,</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="p">,</span><span class="n">mfrom</span><span class="p">,</span><span class="k">pass</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="sample-forensic-report-output">
<h2>Sample forensic report output<a class="headerlink" href="#sample-forensic-report-output" title="Permalink to this headline"></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>
<div class="section" id="id1">
<h3>JSON<a class="headerlink" href="#id1" title="Permalink to this headline"></a></h3>
<div class="highlight-json notranslate"><div class="highlight"><pre><span></span><span class="p">{</span>
<span class="nt">&quot;feedback_type&quot;</span><span class="p">:</span> <span class="s2">&quot;auth-failure&quot;</span><span class="p">,</span>
<span class="nt">&quot;user_agent&quot;</span><span class="p">:</span> <span class="s2">&quot;Lua/1.0&quot;</span><span class="p">,</span>
<span class="nt">&quot;version&quot;</span><span class="p">:</span> <span class="s2">&quot;1.0&quot;</span><span class="p">,</span>
<span class="nt">&quot;original_mail_from&quot;</span><span class="p">:</span> <span class="s2">&quot;sharepoint@domain.de&quot;</span><span class="p">,</span>
<span class="nt">&quot;original_rcpt_to&quot;</span><span class="p">:</span> <span class="s2">&quot;peter.pan@domain.de&quot;</span><span class="p">,</span>
<span class="nt">&quot;arrival_date&quot;</span><span class="p">:</span> <span class="s2">&quot;Mon, 01 Oct 2018 11:20:27 +0200&quot;</span><span class="p">,</span>
<span class="nt">&quot;message_id&quot;</span><span class="p">:</span> <span class="s2">&quot;&lt;38.E7.30937.BD6E1BB5@ mailrelay.de&gt;&quot;</span><span class="p">,</span>
<span class="nt">&quot;authentication_results&quot;</span><span class="p">:</span> <span class="s2">&quot;dmarc=fail (p=none, dis=none) header.from=domain.de&quot;</span><span class="p">,</span>
<span class="nt">&quot;delivery_result&quot;</span><span class="p">:</span> <span class="s2">&quot;policy&quot;</span><span class="p">,</span>
<span class="nt">&quot;auth_failure&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="s2">&quot;dmarc&quot;</span>
<span class="p">],</span>
<span class="nt">&quot;reported_domain&quot;</span><span class="p">:</span> <span class="s2">&quot;domain.de&quot;</span><span class="p">,</span>
<span class="nt">&quot;arrival_date_utc&quot;</span><span class="p">:</span> <span class="s2">&quot;2018-10-01 09:20:27&quot;</span><span class="p">,</span>
<span class="nt">&quot;source&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;ip_address&quot;</span><span class="p">:</span> <span class="s2">&quot;10.10.10.10&quot;</span><span class="p">,</span>
<span class="nt">&quot;country&quot;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="nt">&quot;reverse_dns&quot;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="nt">&quot;base_domain&quot;</span><span class="p">:</span> <span class="kc">null</span>
<span class="p">},</span>
<span class="nt">&quot;authentication_mechanisms&quot;</span><span class="p">:</span> <span class="p">[],</span>
<span class="nt">&quot;original_envelope_id&quot;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="nt">&quot;dkim_domain&quot;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="nt">&quot;sample_headers_only&quot;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="nt">&quot;sample&quot;</span><span class="p">:</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="nt">&quot;parsed_sample&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;from&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;display_name&quot;</span><span class="p">:</span> <span class="s2">&quot;Interaktive Wettbewerber-Übersicht&quot;</span><span class="p">,</span>
<span class="nt">&quot;address&quot;</span><span class="p">:</span> <span class="s2">&quot;sharepoint@domain.de&quot;</span><span class="p">,</span>
<span class="nt">&quot;local&quot;</span><span class="p">:</span> <span class="s2">&quot;sharepoint&quot;</span><span class="p">,</span>
<span class="nt">&quot;domain&quot;</span><span class="p">:</span> <span class="s2">&quot;domain.de&quot;</span>
<span class="p">},</span>
<span class="nt">&quot;to_domains&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="s2">&quot;domain.de&quot;</span>
<span class="p">],</span>
<span class="nt">&quot;to&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="nt">&quot;display_name&quot;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="nt">&quot;address&quot;</span><span class="p">:</span> <span class="s2">&quot;peter.pan@domain.de&quot;</span><span class="p">,</span>
<span class="nt">&quot;local&quot;</span><span class="p">:</span> <span class="s2">&quot;peter.pan&quot;</span><span class="p">,</span>
<span class="nt">&quot;domain&quot;</span><span class="p">:</span> <span class="s2">&quot;domain.de&quot;</span>
<span class="p">}</span>
<span class="p">],</span>
<span class="nt">&quot;subject&quot;</span><span class="p">:</span> <span class="s2">&quot;Subject&quot;</span><span class="p">,</span>
<span class="nt">&quot;timezone&quot;</span><span class="p">:</span> <span class="s2">&quot;+2&quot;</span><span class="p">,</span>
<span class="nt">&quot;mime-version&quot;</span><span class="p">:</span> <span class="s2">&quot;1.0&quot;</span><span class="p">,</span>
<span class="nt">&quot;date&quot;</span><span class="p">:</span> <span class="s2">&quot;2018-10-01 09:20:27&quot;</span><span class="p">,</span>
<span class="nt">&quot;content-type&quot;</span><span class="p">:</span> <span class="s2">&quot;text/html; charset=utf-8&quot;</span><span class="p">,</span>
<span class="nt">&quot;x-mailer&quot;</span><span class="p">:</span> <span class="s2">&quot;Microsoft SharePoint Foundation 2010&quot;</span><span class="p">,</span>
<span class="nt">&quot;body&quot;</span><span class="p">:</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="nt">&quot;received&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="nt">&quot;from&quot;</span><span class="p">:</span> <span class="s2">&quot;Servernameone.domain.local Servernameone.domain.local 10.10.10.10&quot;</span><span class="p">,</span>
<span class="nt">&quot;by&quot;</span><span class="p">:</span> <span class="s2">&quot;mailrelay.de mail.DOMAIN.de&quot;</span><span class="p">,</span>
<span class="nt">&quot;with&quot;</span><span class="p">:</span> <span class="s2">&quot;SMTP id 38.E7.30937.BD6E1BB5&quot;</span><span class="p">,</span>
<span class="nt">&quot;date&quot;</span><span class="p">:</span> <span class="s2">&quot;Mon, 1 Oct 2018 11:20:27 +0200 CEST&quot;</span><span class="p">,</span>
<span class="nt">&quot;hop&quot;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nt">&quot;date_utc&quot;</span><span class="p">:</span> <span class="s2">&quot;2018-10-01 09:20:27&quot;</span><span class="p">,</span>
<span class="nt">&quot;delay&quot;</span><span class="p">:</span> <span class="mi">0</span>
<span class="p">}</span>
<span class="p">],</span>
<span class="nt">&quot;content-transfer-encoding&quot;</span><span class="p">:</span> <span class="s2">&quot;quoted-printable&quot;</span><span class="p">,</span>
<span class="nt">&quot;message-id&quot;</span><span class="p">:</span> <span class="s2">&quot;&lt;38.E7.30937.BD6E1BB5@ mailrelay.de&gt;&quot;</span><span class="p">,</span>
<span class="nt">&quot;has_defects&quot;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="nt">&quot;headers&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;Received&quot;</span><span class="p">:</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="nt">&quot;Date&quot;</span><span class="p">:</span> <span class="s2">&quot;01 Oct 2018 11:20:27 +0200&quot;</span><span class="p">,</span>
<span class="nt">&quot;Message-ID&quot;</span><span class="p">:</span> <span class="s2">&quot;&lt;38.E7.30937.BD6E1BB5@ mailrelay.de&gt;&quot;</span><span class="p">,</span>
<span class="nt">&quot;To&quot;</span><span class="p">:</span> <span class="s2">&quot;&lt;peter.pan@domain.de&gt;&quot;</span><span class="p">,</span>
<span class="nt">&quot;from&quot;</span><span class="p">:</span> <span class="s2">&quot;\&quot;Interaktive Wettbewerber-Übersicht\&quot; &lt;sharepoint@domain.de&gt;&quot;</span><span class="p">,</span>
<span class="nt">&quot;Subject&quot;</span><span class="p">:</span> <span class="s2">&quot;Subject&quot;</span><span class="p">,</span>
<span class="nt">&quot;MIME-Version&quot;</span><span class="p">:</span> <span class="s2">&quot;1.0&quot;</span><span class="p">,</span>
<span class="nt">&quot;X-Mailer&quot;</span><span class="p">:</span> <span class="s2">&quot;Microsoft SharePoint Foundation 2010&quot;</span><span class="p">,</span>
<span class="nt">&quot;Content-Type&quot;</span><span class="p">:</span> <span class="s2">&quot;text/html; charset=utf-8&quot;</span><span class="p">,</span>
<span class="nt">&quot;Content-Transfer-Encoding&quot;</span><span class="p">:</span> <span class="s2">&quot;quoted-printable&quot;</span>
<span class="p">},</span>
<span class="nt">&quot;reply_to&quot;</span><span class="p">:</span> <span class="p">[],</span>
<span class="nt">&quot;cc&quot;</span><span class="p">:</span> <span class="p">[],</span>
<span class="nt">&quot;bcc&quot;</span><span class="p">:</span> <span class="p">[],</span>
<span class="nt">&quot;attachments&quot;</span><span class="p">:</span> <span class="p">[],</span>
<span class="nt">&quot;filename_safe_subject&quot;</span><span class="p">:</span> <span class="s2">&quot;Subject&quot;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="id2">
<h3>CSV<a class="headerlink" href="#id2" title="Permalink to this headline"></a></h3>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">feedback_type</span><span class="p">,</span><span class="n">user_agent</span><span class="p">,</span><span class="n">version</span><span class="p">,</span><span class="n">original_envelope_id</span><span class="p">,</span><span class="n">original_mail_from</span><span class="p">,</span><span class="n">original_rcpt_to</span><span class="p">,</span><span class="n">arrival_date</span><span class="p">,</span><span class="n">arrival_date_utc</span><span class="p">,</span><span class="n">subject</span><span class="p">,</span><span class="n">message_id</span><span class="p">,</span><span class="n">authentication_results</span><span class="p">,</span><span class="n">dkim_domain</span><span class="p">,</span><span class="n">source_ip_address</span><span class="p">,</span><span class="n">source_country</span><span class="p">,</span><span class="n">source_reverse_dns</span><span class="p">,</span><span class="n">source_base_domain</span><span class="p">,</span><span class="n">delivery_result</span><span class="p">,</span><span class="n">auth_failure</span><span class="p">,</span><span class="n">reported_domain</span><span class="p">,</span><span class="n">authentication_mechanisms</span><span class="p">,</span><span class="n">sample_headers_only</span>
<span class="n">auth</span><span class="o">-</span><span class="n">failure</span><span class="p">,</span><span class="n">Lua</span><span class="o">/</span><span class="mf">1.0</span><span class="p">,</span><span class="mf">1.0</span><span class="p">,,</span><span class="n">sharepoint</span><span class="nd">@domain</span><span class="o">.</span><span class="n">de</span><span class="p">,</span><span class="n">peter</span><span class="o">.</span><span class="n">pan</span><span class="nd">@domain</span><span class="o">.</span><span class="n">de</span><span class="p">,</span><span class="s2">&quot;Mon, 01 Oct 2018 11:20:27 +0200&quot;</span><span class="p">,</span><span class="mi">2018</span><span class="o">-</span><span class="mi">10</span><span class="o">-</span><span class="mi">01</span> <span class="mi">09</span><span class="p">:</span><span class="mi">20</span><span class="p">:</span><span class="mi">27</span><span class="p">,</span><span class="n">Subject</span><span class="p">,</span><span class="o">&lt;</span><span class="mf">38.E7</span><span class="o">.</span><span class="mf">30937.</span><span class="n">BD6E1BB5</span><span class="o">@</span> <span class="n">mailrelay</span><span class="o">.</span><span class="n">de</span><span class="o">&gt;</span><span class="p">,</span><span class="s2">&quot;dmarc=fail (p=none, dis=none) header.from=domain.de&quot;</span><span class="p">,,</span><span class="mf">10.10</span><span class="o">.</span><span class="mf">10.10</span><span class="p">,,,,</span><span class="n">policy</span><span class="p">,</span><span class="n">dmarc</span><span class="p">,</span><span class="n">domain</span><span class="o">.</span><span class="n">de</span><span class="p">,,</span><span class="kc">False</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="bug-reports">
<h2>Bug reports<a class="headerlink" href="#bug-reports" title="Permalink to this headline"></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>
</div>
<div class="section" id="installation">
<h2>Installation<a class="headerlink" href="#installation" title="Permalink to this headline"></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 neeed 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-default notranslate"><div class="highlight"><pre><span></span><span class="n">http_proxy</span><span class="o">=</span><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">user</span><span class="p">:</span><span class="n">password</span><span class="nd">@prox</span><span class="o">-</span><span class="n">server</span><span class="p">:</span><span class="mi">3128</span>
<span class="n">https_proxy</span><span class="o">=</span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">user</span><span class="p">:</span><span class="n">password</span><span class="nd">@prox</span><span class="o">-</span><span class="n">server</span><span class="p">:</span><span class="mi">3128</span>
<span class="n">ftp_proxy</span><span class="o">=</span><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">user</span><span class="p">:</span><span class="n">password</span><span class="nd">@prox</span><span class="o">-</span><span class="n">server</span><span class="p">:</span><span class="mi">3128</span>
</pre></div>
</div>
<p>Or if no credentials are needed:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">http_proxy</span><span class="o">=</span><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">prox</span><span class="o">-</span><span class="n">server</span><span class="p">:</span><span class="mi">3128</span>
<span class="n">https_proxy</span><span class="o">=</span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">prox</span><span class="o">-</span><span class="n">server</span><span class="p">:</span><span class="mi">3128</span>
<span class="n">ftp_proxy</span><span class="o">=</span><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">prox</span><span class="o">-</span><span class="n">server</span><span class="p">:</span><span class="mi">3128</span>
</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>
<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 geoipupdate
</pre></div>
</div>
<p>On CentOS systems, run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo yum install -y python34-setuptools GeoIP-Update
sudo easy_install-3.4 pip
sudo geoipupdate
</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>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Windows users should also download a copy of Maxminds free
<a class="reference external" href="https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz">GeoLite2-Country.mmdb</a> to <code class="docutils literal notranslate"><span class="pre">C:\GeoIP\GeoLite2-Country.mmdb</span></code>.</p>
</div>
<p>To install or upgrade to the latest stable release of <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> on
macOS or Linux, run</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo -H pip3 install -U parsedmarc
</pre></div>
</div>
<p>Or, install the latest development release directly from GitHub:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo -H pip3 install -U git+https://github.com/domainaware/parsedmarc.git
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>On Windows, <code class="docutils literal notranslate"><span class="pre">pip3</span></code> is <code class="docutils literal notranslate"><span class="pre">pip</span></code>, even with Python 3. So on Windows,
substitute <code class="docutils literal notranslate"><span class="pre">pip</span></code> as an administrator in place of <code class="docutils literal notranslate"><span class="pre">sudo</span> <span class="pre">pip3</span></code>, in the
above commands.</p>
</div>
<div class="section" id="installation-using-pypy3">
<h3>Installation using pypy3<a class="headerlink" href="#installation-using-pypy3" title="Permalink to this headline"></a></h3>
<p>For the best possible processing speed, consider using <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> inside a <code class="docutils literal notranslate"><span class="pre">pypy3</span></code>
virtualenv. First, <a class="reference external" href="https://github.com/squeaky-pl/portable-pypy#portable-pypy-distribution-for-linux">download the latest portable Linux version of pypy3</a>. Extract it to
<code class="docutils literal notranslate"><span class="pre">/opt/pypy3</span></code> (<code class="docutils literal notranslate"><span class="pre">sudo</span> <span class="pre">mkdir</span> <span class="pre">/opt</span></code> if <code class="docutils literal notranslate"><span class="pre">/opt</span></code> does not exist), then create a
symlink:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>wget https://bitbucket.org/squeaky/portable-pypy/downloads/pypy3.5-7.0.0-linux_x86_64-portable.tar.bz2
tar -jxf pypy3.5-7.0.0-linux_x86_64-portable.tar.bz2
rm pypy3.5-6.0.0-linux_x86_64-portable.tar.bz2
sudo chown -R root:root pypy3.5-7.0.0-linux_x86_64-portable
sudo mv pypy3.5-7.0.0-linux_x86_64-portable /opt/pypy3
sudo ln -s /opt/pypy3/bin/pypy3 /usr/local/bin/pypy3
</pre></div>
</div>
<p>Install <code class="docutils literal notranslate"><span class="pre">virtualenv</span></code> on your system:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo apt-get install python3-pip
sudo -H pip3 install -U virtualenv
</pre></div>
</div>
<p>Uninstall any instance of <code class="docutils literal notranslate"><span class="pre">parsedmarc</span></code> that you may have installed globally</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo -H pip3 uninstall -y parsedmarc
</pre></div>
</div>
<p>Next, create a <code class="docutils literal notranslate"><span class="pre">pypy3</span></code> virtualenv for parsedmarc</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo mkdir /opt/venvs
<span class="nb">cd</span> /opt/venvs
sudo -H pip3 install -U virtualenv
sudo virtualenv --download -p /usr/local/bin/pypy3 parsedmarc
sudo -H /opt/venvs/parsedmarc/bin/pip3 install -U parsedmarc
sudo ln -s /opt/venvs/parsedmarc/bin/parsedmarc /usr/local/bin/parsedmarc
</pre></div>
</div>
<p>To 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 -H /opt/venvs/parsedmarc/bin/pip3 install -U parsedmarc
</pre></div>
</div>
<p>Or, install the latest development release directly from GitHub:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo -H /opt/venvs/parsedmarc/bin/pip3 install -U git+https://github.com/domainaware/parsedmarc.git
</pre></div>
</div>
</div>
<div class="section" id="optional-dependencies">
<h3>Optional dependencies<a class="headerlink" href="#optional-dependencies" title="Permalink to this headline"></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>
</div>
<div class="section" id="testing-multiple-report-analyzers">
<h3>Testing multiple report analyzers<a class="headerlink" href="#testing-multiple-report-analyzers" title="Permalink to this headline"></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>
</div>
<div class="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 headline"></a></h3>
<p>Some organisations do not allow IMAP, 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="c">#############################################################</span>
<span class="c"># Basic settings</span>
<span class="c"># Server or workstation mode</span>
<span class="na">davmail.server</span><span class="o">=</span><span class="s">true</span>
<span class="c"># connection mode auto, EWS or WebDav</span>
<span class="na">davmail.enableEws</span><span class="o">=</span><span class="s">auto</span>
<span class="c"># base Exchange OWA or EWS url</span>
<span class="na">davmail.url</span><span class="o">=</span><span class="s">https://outlook.office365.com/EWS/Exchange.asmx</span>
<span class="c"># Listener ports</span>
<span class="na">davmail.imapPort</span><span class="o">=</span><span class="s">1143</span>
<span class="c">#############################################################</span>
<span class="c"># Network settings</span>
<span class="c"># Network proxy settings</span>
<span class="na">davmail.enableProxy</span><span class="o">=</span><span class="s">false</span>
<span class="na">davmail.useSystemProxies</span><span class="o">=</span><span class="s">false</span>
<span class="na">davmail.proxyHost</span><span class="o">=</span>
<span class="na">davmail.proxyPort</span><span class="o">=</span>
<span class="na">davmail.proxyUser</span><span class="o">=</span>
<span class="na">davmail.proxyPassword</span><span class="o">=</span>
<span class="c"># proxy exclude list</span>
<span class="na">davmail.noProxyFor</span><span class="o">=</span>
<span class="c"># block remote connection to DavMail</span>
<span class="na">davmail.allowRemote</span><span class="o">=</span><span class="s">false</span>
<span class="c"># bind server sockets to the loopback address</span>
<span class="na">davmail.bindAddress</span><span class="o">=</span><span class="s">127.0.0.1</span>
<span class="c"># disable SSL for specified listeners</span>
<span class="na">davmail.ssl.nosecureimap</span><span class="o">=</span><span class="s">true</span>
<span class="c"># Send keepalive character during large folder and messages download</span>
<span class="na">davmail.enableKeepalive</span><span class="o">=</span><span class="s">true</span>
<span class="c"># Message count limit on folder retrieval</span>
<span class="na">davmail.folderSizeLimit</span><span class="o">=</span><span class="s">0</span>
<span class="c">#############################################################</span>
<span class="c"># IMAP settings</span>
<span class="c"># Delete messages immediately on IMAP STORE \Deleted flag</span>
<span class="na">davmail.imapAutoExpunge</span><span class="o">=</span><span class="s">true</span>
<span class="c"># Enable IDLE support, set polling delay in minutes</span>
<span class="na">davmail.imapIdleDelay</span><span class="o">=</span><span class="s">1</span>
<span class="c"># Always reply to IMAP RFC822.SIZE requests with Exchange approximate</span>
<span class="c"># message size for performance reasons</span>
<span class="na">davmail.imapAlwaysApproxMsgSize</span><span class="o">=</span><span class="s">true</span>
<span class="c"># Client connection timeout in seconds - default 300, 0 to disable</span>
<span class="na">davmail.clientSoTimeout</span><span class="o">=</span><span class="s">0</span>
<span class="c">#############################################################</span>
</pre></div>
</div>
<div class="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 headline"></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="na">Description</span><span class="o">=</span><span class="s">DavMail gateway service</span>
<span class="na">Documentation</span><span class="o">=</span><span class="s">https://sourceforge.net/projects/davmail/</span>
<span class="na">Wants</span><span class="o">=</span><span class="s">network-online.target</span>
<span class="na">After</span><span class="o">=</span><span class="s">syslog.target network.target</span>
<span class="k">[Service]</span>
<span class="na">ExecStart</span><span class="o">=</span><span class="s">/opt/davmail/davmail /opt/davmail/davmail.properties</span>
<span class="na">User</span><span class="o">=</span><span class="s">davmail</span>
<span class="na">Group</span><span class="o">=</span><span class="s">davmail</span>
<span class="na">Restart</span><span class="o">=</span><span class="s">always</span>
<span class="na">RestartSec</span><span class="o">=</span><span class="s">5m</span>
<span class="k">[Install]</span>
<span class="na">WantedBy</span><span class="o">=</span><span class="s">multi-user.target</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 <cite>service davmail status</cite> 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>
</div>
<div class="section" id="configuring-parsedmarc-for-davmail">
<h4>Configuring parsedmarc for DavMail<a class="headerlink" href="#configuring-parsedmarc-for-davmail" title="Permalink to this headline"></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="na">host</span><span class="o">=</span><span class="s">127.0.0.1</span>
<span class="na">port</span><span class="o">=</span><span class="s">1143</span>
<span class="na">ssl</span><span class="o">=</span><span class="s">False</span>
<span class="na">watch</span><span class="o">=</span><span class="s">True</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="elasticsearch-and-kibana">
<h3>Elasticsearch and Kibana<a class="headerlink" href="#elasticsearch-and-kibana" title="Permalink to this headline"></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="p">{</span>
<span class="kn">listen</span> <span class="mi">443</span> <span class="s">ssl</span> <span class="s">http2</span><span class="p">;</span>
<span class="kn">ssl_certificate</span> <span class="s">/etc/nginx/ssl/kibana.crt</span><span class="p">;</span>
<span class="kn">ssl_certificate_key</span> <span class="s">/etc/nginx/ssl/kibana.key</span><span class="p">;</span>
<span class="kn">ssl_session_timeout</span> <span class="s">1d</span><span class="p">;</span>
<span class="kn">ssl_session_cache</span> <span class="s">shared:SSL:50m</span><span class="p">;</span>
<span class="kn">ssl_session_tickets</span> <span class="no">off</span><span class="p">;</span>
<span class="c1"># modern configuration. tweak to your needs.</span>
<span class="kn">ssl_protocols</span> <span class="s">TLSv1.2</span><span class="p">;</span>
<span class="kn">ssl_ciphers</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="kn">ssl_prefer_server_ciphers</span> <span class="no">on</span><span class="p">;</span>
<span class="c1"># Uncomment this next line if you are using a signed, trusted cert</span>
<span class="c1">#add_header Strict-Transport-Security &quot;max-age=63072000; includeSubdomains; preload&quot;;</span>
<span class="kn">add_header</span> <span class="s">X-Frame-Options</span> <span class="s">SAMEORIGIN</span><span class="p">;</span>
<span class="kn">add_header</span> <span class="s">X-Content-Type-Options</span> <span class="s">nosniff</span><span class="p">;</span>
<span class="kn">auth_basic</span> <span class="s">&quot;Login</span> <span class="s">required&quot;</span><span class="p">;</span>
<span class="kn">auth_basic_user_file</span> <span class="s">/etc/nginx/htpasswd</span><span class="p">;</span>
<span class="kn">location</span> <span class="s">/</span> <span class="p">{</span>
<span class="kn">proxy_pass</span> <span class="s">http://127.0.0.1:5601</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">Host</span> <span class="nv">$host</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">X-Real-IP</span> <span class="nv">$remote_addr</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-For</span> <span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">server</span> <span class="p">{</span>
<span class="kn">listen</span> <span class="mi">80</span><span class="p">;</span>
<span class="kn">return</span> <span class="mi">301</span> <span class="s">https://</span><span class="nv">$host$request_uri</span><span class="p">;</span>
<span class="p">}</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/kibana_saved_objects.json">kibana_saved_objects.json</a>.</p>
<p>Import <code class="docutils literal notranslate"><span class="pre">kibana_saved_objects.json</span></code> the Saved Objects tab of the 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 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>
<div class="section" id="upgrading-kibana-index-patterns">
<h4>Upgrading Kibana index patterns<a class="headerlink" href="#upgrading-kibana-index-patterns" title="Permalink to this headline"></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/kibana_saved_objects.json">kibana_saved_objects.json</a></p></li>
<li><p>Import <code class="docutils literal notranslate"><span class="pre">kibana_saved_objects.json</span></code> by clicking Import from the Kibana
Saved Objects page</p></li>
</ol>
</div>
<div class="section" id="records-retention">
<h4>Records retention<a class="headerlink" href="#records-retention" title="Permalink to this headline"></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>
</div>
</div>
<div class="section" id="splunk">
<h3>Splunk<a class="headerlink" href="#splunk" title="Permalink to this headline"></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>
</div>
<div class="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 headline"></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>Create a system user</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>sudo useradd parsedmarc -r -s /bin/false
</pre></div>
</div>
<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="na">Description</span><span class="o">=</span><span class="s">parsedmarc mailbox watcher</span>
<span class="na">Documentation</span><span class="o">=</span><span class="s">https://domainaware.github.io/parsedmarc/</span>
<span class="na">Wants</span><span class="o">=</span><span class="s">network-online.target</span>
<span class="na">After</span><span class="o">=</span><span class="s">network.target network-online.target elasticsearch.service</span>
<span class="k">[Service]</span>
<span class="na">ExecStart</span><span class="o">=</span><span class="s">/usr/local/bin/parsedmarc -c /etc/parsedmarc.ini</span>
<span class="na">User</span><span class="o">=</span><span class="s">parsedmarc</span>
<span class="na">Group</span><span class="o">=</span><span class="s">parsedmarc</span>
<span class="na">Restart</span><span class="o">=</span><span class="s">always</span>
<span class="na">RestartSec</span><span class="o">=</span><span class="s">5m</span>
<span class="k">[Install]</span>
<span class="na">WantedBy</span><span class="o">=</span><span class="s">multi-user.target</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 <cite>service parsedmarc status</cite> 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>
</div>
</div>
<div class="section" id="using-the-kibana-dashboards">
<h2>Using the Kibana dashboards<a class="headerlink" href="#using-the-kibana-dashboards" title="Permalink to this headline"></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>
<div class="section" id="dmarc-summary">
<h3>DMARC Summary<a class="headerlink" href="#dmarc-summary" title="Permalink to this headline"></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>
</div>
<div class="section" id="dmarc-forensic-samples">
<h3>DMARC Forensic Samples<a class="headerlink" href="#dmarc-forensic-samples" title="Permalink to this headline"></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>
</div>
</div>
<div class="section" id="dmarc-alignment-guide">
<h2>DMARC Alignment Guide<a class="headerlink" href="#dmarc-alignment-guide" title="Permalink to this headline"></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-center">
<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>
</div>
<div class="section" id="what-if-a-sender-won-t-support-dkim-dmarc">
<h2>What if a sender wont support DKIM/DMARC?<a class="headerlink" href="#what-if-a-sender-won-t-support-dkim-dmarc" title="Permalink to this headline"></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>
</div>
<div class="section" id="what-about-mailing-lists">
<h2>What about mailing lists?<a class="headerlink" href="#what-about-mailing-lists" title="Permalink to this headline"></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>
<div class="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 headline"></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>
<p><strong>Do</strong></p>
<ul>
<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>
<blockquote>
<div><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">List</span><span class="o">-</span><span class="n">Unsubscribe</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="nb">list</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">unsubscribe</span><span class="o">-</span><span class="n">link</span><span class="o">&gt;</span>
</pre></div>
</div>
</div></blockquote>
</li>
<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><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">List</span><span class="o">-</span><span class="n">Id</span><span class="p">:</span> <span class="n">Example</span> <span class="n">Mailing</span> <span class="n">List</span> <span class="o">&lt;</span><span class="nb">list</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">&gt;</span>
</pre></div>
</div>
</div></blockquote>
</li>
</ul>
<p>Modern mail clients and webmail services generate unsubscribe buttons based on
these headers.</p>
<p><strong>Do not</strong></p>
<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>
<div class="section" id="mailman-2">
<h4>Mailman 2<a class="headerlink" href="#mailman-2" title="Permalink to this headline"></a></h4>
<p>Navigate to General Settings, and configure the settings below</p>
<table class="docutils align-center">
<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-center">
<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-center">
<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_quarentine_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>
<div class="section" id="mailman-3">
<h4>Mailman 3<a class="headerlink" href="#mailman-3" title="Permalink to this headline"></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-center">
<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 replyo</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-center">
<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>
</div>
</div>
<div class="section" id="workarounds">
<h3>Workarounds<a class="headerlink" href="#workarounds" title="Permalink to this headline"></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>
<div class="section" id="id3">
<h4>Mailman 2<a class="headerlink" href="#id3" title="Permalink to this headline"></a></h4>
<p>Navigate to Privacy Options&gt; Sending Filters, and configure the settings below</p>
<table class="docutils align-center">
<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_quarentine_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>
</div>
<div class="section" id="id4">
<h4>Mailman 3<a class="headerlink" href="#id4" title="Permalink to this headline"></a></h4>
<p>In the DMARC Mitigations tab of the Settings page, configure the settings below</p>
<table class="docutils align-center">
<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>
</div>
<div class="section" id="listserv">
<h4>LISTSERV<a class="headerlink" href="#listserv" title="Permalink to this headline"></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>
</div>
</div>
</div>
<div class="section" id="module-parsedmarc">
<span id="api"></span><h2>API<a class="headerlink" href="#module-parsedmarc" title="Permalink to this headline"></a></h2>
<p>A Python package for parsing DMARC reports</p>
<dl class="exception">
<dt id="parsedmarc.IMAPError">
<em class="property">exception </em><code class="descclassname">parsedmarc.</code><code class="descname">IMAPError</code><a class="reference internal" href="_modules/parsedmarc.html#IMAPError"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#parsedmarc.IMAPError" title="Permalink to this definition"></a></dt>
<dd><p>Raised when an IMAP error occurs</p>
</dd></dl>
<dl class="exception">
<dt id="parsedmarc.InvalidAggregateReport">
<em class="property">exception </em><code class="descclassname">parsedmarc.</code><code class="descname">InvalidAggregateReport</code><a class="reference internal" href="_modules/parsedmarc.html#InvalidAggregateReport"><span class="viewcode-link">[source]</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="exception">
<dt id="parsedmarc.InvalidDMARCReport">
<em class="property">exception </em><code class="descclassname">parsedmarc.</code><code class="descname">InvalidDMARCReport</code><a class="reference internal" href="_modules/parsedmarc.html#InvalidDMARCReport"><span class="viewcode-link">[source]</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="exception">
<dt id="parsedmarc.InvalidForensicReport">
<em class="property">exception </em><code class="descclassname">parsedmarc.</code><code class="descname">InvalidForensicReport</code><a class="reference internal" href="_modules/parsedmarc.html#InvalidForensicReport"><span class="viewcode-link">[source]</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="exception">
<dt id="parsedmarc.ParserError">
<em class="property">exception </em><code class="descclassname">parsedmarc.</code><code class="descname">ParserError</code><a class="reference internal" href="_modules/parsedmarc.html#ParserError"><span class="viewcode-link">[source]</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="exception">
<dt id="parsedmarc.SMTPError">
<em class="property">exception </em><code class="descclassname">parsedmarc.</code><code class="descname">SMTPError</code><a class="reference internal" href="_modules/parsedmarc.html#SMTPError"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#parsedmarc.SMTPError" title="Permalink to this definition"></a></dt>
<dd><p>Raised when a SMTP error occurs</p>
</dd></dl>
<dl class="function">
<dt id="parsedmarc.email_results">
<code class="descclassname">parsedmarc.</code><code class="descname">email_results</code><span class="sig-paren">(</span><em>results</em>, <em>host</em>, <em>mail_from</em>, <em>mail_to</em>, <em>port=0</em>, <em>ssl=False</em>, <em>user=None</em>, <em>password=None</em>, <em>subject=None</em>, <em>attachment_filename=None</em>, <em>message=None</em>, <em>ssl_context=None</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#email_results"><span class="viewcode-link">[source]</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> A list of addresses to mail to</p></li>
<li><p><strong>port</strong> (<em>int</em>) Port to use</p></li>
<li><p><strong>ssl</strong> (<em>bool</em>) Require a SSL connection from the start</p></li>
<li><p><strong>user</strong> An optional username</p></li>
<li><p><strong>password</strong> An optional password</p></li>
<li><p><strong>subject</strong> Overrides the default message subject</p></li>
<li><p><strong>attachment_filename</strong> Override the default attachment filename</p></li>
<li><p><strong>message</strong> Override the default plain text body</p></li>
<li><p><strong>ssl_context</strong> SSL context options</p></li>
</ul>
</dd>
</dl>
</dd></dl>
<dl class="function">
<dt id="parsedmarc.extract_xml">
<code class="descclassname">parsedmarc.</code><code class="descname">extract_xml</code><span class="sig-paren">(</span><em>input_</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#extract_xml"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.get_dmarc_reports_from_inbox">
<code class="descclassname">parsedmarc.</code><code class="descname">get_dmarc_reports_from_inbox</code><span class="sig-paren">(</span><em>host=None</em>, <em>user=None</em>, <em>password=None</em>, <em>connection=None</em>, <em>port=None</em>, <em>ssl=True</em>, <em>ssl_context=None</em>, <em>move_supported=None</em>, <em>reports_folder='INBOX'</em>, <em>archive_folder='Archive'</em>, <em>delete=False</em>, <em>test=False</em>, <em>nameservers=None</em>, <em>dns_timeout=6.0</em>, <em>strip_attachment_payloads=False</em>, <em>results=None</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#get_dmarc_reports_from_inbox"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#parsedmarc.get_dmarc_reports_from_inbox" title="Permalink to this definition"></a></dt>
<dd><p>Fetches and parses DMARC reports from sn inbox</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>host</strong> The mail server hostname or IP address</p></li>
<li><p><strong>user</strong> The mail server user</p></li>
<li><p><strong>password</strong> The mail server password</p></li>
<li><p><strong>connection</strong> An IMAPCLient connection to reuse</p></li>
<li><p><strong>port</strong> The mail server port</p></li>
<li><p><strong>ssl</strong> (<em>bool</em>) Use SSL/TLS</p></li>
<li><p><strong>ssl_context</strong> (<em>SSLContext</em>) A SSL context</p></li>
<li><p><strong>move_supported</strong> Indicate if the IMAP server supports the MOVE command</p></li>
<li><p><strong>if None</strong><strong>)</strong> (<em>(</em><em>autodetect</em>) </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>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</p></li>
<li><p><strong>report results</strong> (<em>forensic</em>) </p></li>
<li><p><strong>results</strong> (<em>dict</em>) Results from the previous run</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="function">
<dt id="parsedmarc.get_imap_capabilities">
<code class="descclassname">parsedmarc.</code><code class="descname">get_imap_capabilities</code><span class="sig-paren">(</span><em>server</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#get_imap_capabilities"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#parsedmarc.get_imap_capabilities" title="Permalink to this definition"></a></dt>
<dd><p>Returns a list of an IMAP servers capabilities</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>server</strong> (<em>imapclient.IMAPClient</em>) An instance of imapclient.IMAPClient</p>
</dd>
</dl>
<p>Returns (list): A list of capabilities</p>
</dd></dl>
<dl class="function">
<dt id="parsedmarc.get_report_zip">
<code class="descclassname">parsedmarc.</code><code class="descname">get_report_zip</code><span class="sig-paren">(</span><em>results</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#get_report_zip"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.parse_aggregate_report_file">
<code class="descclassname">parsedmarc.</code><code class="descname">parse_aggregate_report_file</code><span class="sig-paren">(</span><em>_input</em>, <em>nameservers=None</em>, <em>dns_timeout=2.0</em>, <em>parallel=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parse_aggregate_report_file"><span class="viewcode-link">[source]</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 a
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>nameservers</strong> (<em>list</em>) A list of one or more nameservers to use</p></li>
<li><p><strong>public DNS resolvers by default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's</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>
</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="function">
<dt id="parsedmarc.parse_aggregate_report_xml">
<code class="descclassname">parsedmarc.</code><code class="descname">parse_aggregate_report_xml</code><span class="sig-paren">(</span><em>xml</em>, <em>nameservers=None</em>, <em>timeout=2.0</em>, <em>parallel=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parse_aggregate_report_xml"><span class="viewcode-link">[source]</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>nameservers</strong> (<em>list</em>) A list of one or more nameservers to use</p></li>
<li><p><strong>public DNS resolvers by default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's</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>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="function">
<dt id="parsedmarc.parse_forensic_report">
<code class="descclassname">parsedmarc.</code><code class="descname">parse_forensic_report</code><span class="sig-paren">(</span><em>feedback_report</em>, <em>sample</em>, <em>msg_date</em>, <em>nameservers=None</em>, <em>dns_timeout=2.0</em>, <em>strip_attachment_payloads=False</em>, <em>parallel=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parse_forensic_report"><span class="viewcode-link">[source]</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>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>public DNS resolvers by default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's</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>report results</strong> (<em>forensic</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="function">
<dt id="parsedmarc.parse_report_email">
<code class="descclassname">parsedmarc.</code><code class="descname">parse_report_email</code><span class="sig-paren">(</span><em>input_</em>, <em>nameservers=None</em>, <em>dns_timeout=2.0</em>, <em>strip_attachment_payloads=False</em>, <em>parallel=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parse_report_email"><span class="viewcode-link">[source]</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>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>report results</strong> (<em>forensic</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><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="function">
<dt id="parsedmarc.parse_report_file">
<code class="descclassname">parsedmarc.</code><code class="descname">parse_report_file</code><span class="sig-paren">(</span><em>input_</em>, <em>nameservers=None</em>, <em>dns_timeout=2.0</em>, <em>strip_attachment_payloads=False</em>, <em>parallel=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parse_report_file"><span class="viewcode-link">[source]</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>public DNS resolvers by default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's</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>report results</strong> (<em>forensic</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>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="function">
<dt id="parsedmarc.parsed_aggregate_reports_to_csv">
<code class="descclassname">parsedmarc.</code><code class="descname">parsed_aggregate_reports_to_csv</code><span class="sig-paren">(</span><em>reports</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parsed_aggregate_reports_to_csv"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.parsed_forensic_reports_to_csv">
<code class="descclassname">parsedmarc.</code><code class="descname">parsed_forensic_reports_to_csv</code><span class="sig-paren">(</span><em>reports</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#parsed_forensic_reports_to_csv"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.save_output">
<code class="descclassname">parsedmarc.</code><code class="descname">save_output</code><span class="sig-paren">(</span><em>results</em>, <em>output_directory='output'</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#save_output"><span class="viewcode-link">[source]</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> The patch to the directory to save in</p></li>
</ul>
</dd>
</dl>
</dd></dl>
<dl class="function">
<dt id="parsedmarc.watch_inbox">
<code class="descclassname">parsedmarc.</code><code class="descname">watch_inbox</code><span class="sig-paren">(</span><em>host</em>, <em>username</em>, <em>password</em>, <em>callback</em>, <em>port=None</em>, <em>ssl=True</em>, <em>ssl_context=None</em>, <em>reports_folder='INBOX'</em>, <em>archive_folder='Archive'</em>, <em>delete=False</em>, <em>test=False</em>, <em>wait=30</em>, <em>nameservers=None</em>, <em>dns_timeout=6.0</em>, <em>strip_attachment_payloads=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc.html#watch_inbox"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#parsedmarc.watch_inbox" title="Permalink to this definition"></a></dt>
<dd><p>Use an IDLE IMAP connection to parse incoming emails, and pass the results
to a callback function</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>host</strong> The mail server hostname or IP address</p></li>
<li><p><strong>username</strong> The mail server username</p></li>
<li><p><strong>password</strong> The mail server password</p></li>
<li><p><strong>callback</strong> The callback function to receive the parsing results</p></li>
<li><p><strong>port</strong> The mail server port</p></li>
<li><p><strong>ssl</strong> (<em>bool</em>) Use SSL/TLS</p></li>
<li><p><strong>ssl_context</strong> (<em>SSLContext</em>) A SSL context</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>wait</strong> (<em>int</em>) Number of seconds to wait for a IMAP IDLE response</p></li>
<li><p><strong>nameservers</strong> (<em>list</em>) A list of one or more nameservers to use</p></li>
<li><p><strong>public DNS resolvers by default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's</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>report samples with None</strong> (<em>forensic</em>) </p></li>
</ul>
</dd>
</dl>
</dd></dl>
<div class="section" id="module-parsedmarc.elastic">
<span id="parsedmarc-elastic"></span><h3>parsedmarc.elastic<a class="headerlink" href="#module-parsedmarc.elastic" title="Permalink to this headline"></a></h3>
<dl class="exception">
<dt id="parsedmarc.elastic.AlreadySaved">
<em class="property">exception </em><code class="descclassname">parsedmarc.elastic.</code><code class="descname">AlreadySaved</code><a class="reference internal" href="_modules/parsedmarc/elastic.html#AlreadySaved"><span class="viewcode-link">[source]</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="exception">
<dt id="parsedmarc.elastic.ElasticsearchError">
<em class="property">exception </em><code class="descclassname">parsedmarc.elastic.</code><code class="descname">ElasticsearchError</code><a class="reference internal" href="_modules/parsedmarc/elastic.html#ElasticsearchError"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.elastic.create_indexes">
<code class="descclassname">parsedmarc.elastic.</code><code class="descname">create_indexes</code><span class="sig-paren">(</span><em>names</em>, <em>settings=None</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/elastic.html#create_indexes"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.elastic.migrate_indexes">
<code class="descclassname">parsedmarc.elastic.</code><code class="descname">migrate_indexes</code><span class="sig-paren">(</span><em>aggregate_indexes=None</em>, <em>forensic_indexes=None</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/elastic.html#migrate_indexes"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.elastic.save_aggregate_report_to_elasticsearch">
<code class="descclassname">parsedmarc.elastic.</code><code class="descname">save_aggregate_report_to_elasticsearch</code><span class="sig-paren">(</span><em>aggregate_report</em>, <em>index_suffix=None</em>, <em>monthly_indexes=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/elastic.html#save_aggregate_report_to_elasticsearch"><span class="viewcode-link">[source]</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>
</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="function">
<dt id="parsedmarc.elastic.save_forensic_report_to_elasticsearch">
<code class="descclassname">parsedmarc.elastic.</code><code class="descname">save_forensic_report_to_elasticsearch</code><span class="sig-paren">(</span><em>forensic_report</em>, <em>index_suffix=None</em>, <em>monthly_indexes=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/elastic.html#save_forensic_report_to_elasticsearch"><span class="viewcode-link">[source]</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>
</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="function">
<dt id="parsedmarc.elastic.set_hosts">
<code class="descclassname">parsedmarc.elastic.</code><code class="descname">set_hosts</code><span class="sig-paren">(</span><em>hosts</em>, <em>use_ssl=False</em>, <em>ssl_cert_path=None</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/elastic.html#set_hosts"><span class="viewcode-link">[source]</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>
</ul>
</dd>
</dl>
</dd></dl>
<div class="toctree-wrapper compound">
</div>
</div>
<div class="section" id="parsedmarc-splunk">
<h3>parsedmarc.splunk<a class="headerlink" href="#parsedmarc-splunk" title="Permalink to this headline"></a></h3>
<div class="toctree-wrapper compound">
</div>
<span class="target" id="module-parsedmarc.splunk"></span><dl class="class">
<dt id="parsedmarc.splunk.HECClient">
<em class="property">class </em><code class="descclassname">parsedmarc.splunk.</code><code class="descname">HECClient</code><span class="sig-paren">(</span><em>url</em>, <em>access_token</em>, <em>index</em>, <em>source='parsedmarc'</em>, <em>verify=True</em>, <em>timeout=60</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/splunk.html#HECClient"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#parsedmarc.splunk.HECClient" title="Permalink to this definition"></a></dt>
<dd><p>A client for a Splunk HTTP Events Collector (HEC)</p>
<dl class="method">
<dt id="parsedmarc.splunk.HECClient.save_aggregate_reports_to_splunk">
<code class="descname">save_aggregate_reports_to_splunk</code><span class="sig-paren">(</span><em>aggregate_reports</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">[source]</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>save in Splunk</strong> (<em>to</em>) </p></li>
</ul>
</dd>
</dl>
</dd></dl>
<dl class="method">
<dt id="parsedmarc.splunk.HECClient.save_forensic_reports_to_splunk">
<code class="descname">save_forensic_reports_to_splunk</code><span class="sig-paren">(</span><em>forensic_reports</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">[source]</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>save in Splunk</strong> (<em>to</em>) </p></li>
</ul>
</dd>
</dl>
</dd></dl>
</dd></dl>
<dl class="exception">
<dt id="parsedmarc.splunk.SplunkError">
<em class="property">exception </em><code class="descclassname">parsedmarc.splunk.</code><code class="descname">SplunkError</code><a class="reference internal" href="_modules/parsedmarc/splunk.html#SplunkError"><span class="viewcode-link">[source]</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>
</div>
<div class="section" id="module-parsedmarc.utils">
<span id="parsedmarc-utils"></span><h3>parsedmarc.utils<a class="headerlink" href="#module-parsedmarc.utils" title="Permalink to this headline"></a></h3>
<p>Utility functions that might be useful for other projects</p>
<dl class="exception">
<dt id="parsedmarc.utils.EmailParserError">
<em class="property">exception </em><code class="descclassname">parsedmarc.utils.</code><code class="descname">EmailParserError</code><a class="reference internal" href="_modules/parsedmarc/utils.html#EmailParserError"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.utils.convert_outlook_msg">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">convert_outlook_msg</code><span class="sig-paren">(</span><em>msg_bytes</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#convert_outlook_msg"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.utils.decode_base64">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">decode_base64</code><span class="sig-paren">(</span><em>data</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#decode_base64"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.utils.get_base_domain">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">get_base_domain</code><span class="sig-paren">(</span><em>domain</em>, <em>use_fresh_psl=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#get_base_domain"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.utils.get_filename_safe_string">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">get_filename_safe_string</code><span class="sig-paren">(</span><em>string</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#get_filename_safe_string"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.utils.get_ip_address_country">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">get_ip_address_country</code><span class="sig-paren">(</span><em>ip_address</em>, <em>parallel=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#get_ip_address_country"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#parsedmarc.utils.get_ip_address_country" title="Permalink to this definition"></a></dt>
<dd><p>Uses the MaxMind Geolite2 Country database to return 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>parallel</strong> (<em>bool</em>) Parallel processing</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="function">
<dt id="parsedmarc.utils.get_ip_address_info">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">get_ip_address_info</code><span class="sig-paren">(</span><em>ip_address</em>, <em>cache=None</em>, <em>nameservers=None</em>, <em>timeout=2.0</em>, <em>parallel=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#get_ip_address_info"><span class="viewcode-link">[source]</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>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>public DNS resolvers by default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's</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="function">
<dt id="parsedmarc.utils.get_reverse_dns">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">get_reverse_dns</code><span class="sig-paren">(</span><em>ip_address</em>, <em>cache=None</em>, <em>nameservers=None</em>, <em>timeout=2.0</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#get_reverse_dns"><span class="viewcode-link">[source]</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>public DNS resolvers by default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's</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="function">
<dt id="parsedmarc.utils.human_timestamp_to_datetime">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">human_timestamp_to_datetime</code><span class="sig-paren">(</span><em>human_timestamp</em>, <em>to_utc=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#human_timestamp_to_datetime"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.utils.human_timestamp_to_timestamp">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">human_timestamp_to_timestamp</code><span class="sig-paren">(</span><em>human_timestamp</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#human_timestamp_to_timestamp"><span class="viewcode-link">[source]</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 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="function">
<dt id="parsedmarc.utils.is_outlook_msg">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">is_outlook_msg</code><span class="sig-paren">(</span><em>content</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#is_outlook_msg"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.utils.parse_email">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">parse_email</code><span class="sig-paren">(</span><em>data</em>, <em>strip_attachment_payloads=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#parse_email"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.utils.query_dns">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">query_dns</code><span class="sig-paren">(</span><em>domain</em>, <em>record_type</em>, <em>cache=None</em>, <em>nameservers=None</em>, <em>timeout=2.0</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#query_dns"><span class="viewcode-link">[source]</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>public DNS resolvers by default</strong><strong>)</strong> (<em>(</em><em>Cloudflare's</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="function">
<dt id="parsedmarc.utils.timestamp_to_datetime">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">timestamp_to_datetime</code><span class="sig-paren">(</span><em>timestamp</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#timestamp_to_datetime"><span class="viewcode-link">[source]</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="function">
<dt id="parsedmarc.utils.timestamp_to_human">
<code class="descclassname">parsedmarc.utils.</code><code class="descname">timestamp_to_human</code><span class="sig-paren">(</span><em>timestamp</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/parsedmarc/utils.html#timestamp_to_human"><span class="viewcode-link">[source]</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>
</div>
</div>
<div class="section" id="indices-and-tables">
<h2>Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this headline"></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>
</div>
</div>
</div>
</div>
<footer>
<hr/>
<div role="contentinfo">
<p>
&copy; Copyright 2018, Sean Whalen
</p>
</div>
Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>