Self-hosted DMARC report viewer to aid your anti-SPAM effort

; Date: Tue Jul 12 2022

Tags: Docker »»»» Self Hosting

DMARC is an important tool for websites that send e-mails to do so legitimately. Implementation requires catching e-mails containing DMARC reports then using a tool to parse/summarize/report on their content. We look at a simple DMARC reporting tool that is easily deployable using Docker.

In the olden days of the Internet, email inboxes were flooded with SPAM e-mails and other kinds of junquemail. Early e-mail development on the Internet had no thought for security or authentication. But, over the last 25+ years, several tools have come along which add in security and authentication.

One of these tools is DMARC, or Domain-based Message Authentication, Reporting and Conformance. It requires that an e-mail domain owner publish a DNS record giving instructions on authenticating e-mails. Part of those instructions include an e-mail address to which to send DMARC reports. These reports are XML files containing data about e-mails sent by a domain.

Those reports are the subject of todays tutorial. While there are commercial services to process DMARC reports, there are open source tools for that purpose.

One such tool is this pair of projects:

To deploy these, I used the following:

This workspace includes a Docker Compose file to describe deployment of these services along with a database. The system is easy to setup, free to use, and is fully open source. The result is an easy-to-view DMARC report.

Deployment infrastructure for DMARC report

I have a virtual private server (VPS) on which I run two websites deployed with Docker. A couple of the websites send emails that must be safely delivered to website users. This means jumping through all the hoops of authenticating the emails to avoid being marked as SPAM.

I use NGINX Proxy Manager in front of the websites primarily because that's the easiest way to manage SSL certificates. It has built-in support for deploying and maintaining certificates from Lets Encrypt.

I also use Portainer to assist with monitoring and managing Docker services. Docker Swarm Mode is enabled - and no Kubernetes.

While I normally put Docker Compose files in the filesystem, and deploy using the docker-compose command, this time I pasted the Compose file into Portainer.

Preparing your e-mail domain to receive DMARC reports

Before deploying the server in the next section, we must implement DMARC on one or more domains.

The first step is setting up a DMARC record in the DNS for your configuration. In my case, email from the domain is distributed using both the main domain name ( and a subdomain ( That meant configuring two DNS entries:


Each of these DNS entries must be a TXT record, and in my case they contain:

v=DMARC1; p=none; fo=1;;;pct=100

All of this is public record on my domain name, so I'm not revealing anything sensitive. Obviously you substitute your domain in place of as appropriate.

There are two email addresses, dmarc_agg and dmarc_forensic. In my case, and I don't remember why I did this, I configured both of these as aliases which forward to dmarc.

I then configured an email address, dmarc, with my web hosting provider that in turn provides an IMAP mailbox. After a few days DMARC reports started showing up in that IMAP mailbox.

It is important to keep DMARC reports out of your normal email inbox. These reports are meant for software to read, and are not meant for human consumption. An application like what we discuss in the next section is designed for reading and digesting DMARC reports.

Docker Compose file for deploying DMARC reporting system

The Compose file I used is modified a little from the example in gutmensch/docker-dmarc-report.

version: "3.6"

    image: "gutmensch/dmarc-report:latest"
    hostname: dmarc-report
    container_name: dmarc-report
      - dmarcdb
      - "1080:80"
      - servernet
      - dmarcdbnet
      - "REPORT_DB_HOST=dmarcdb"
      - "REPORT_DB_PORT=3306"
      - "REPORT_DB_NAME=dmarc_report"
      - "REPORT_DB_USER=dmarc_report"
      - "PARSER_IMAP_PORT=143"
      - "PARSER_IMAP_MOVE_FOLDER=processed"

    image: mariadb:10
    command: --skip-innodb-read-only-compressed
       - /opt/dmarc/db:/var/lib/mysql
       - /opt/dmarc:/db
       - dmarcdbnet
    restart: always
      - "MYSQL_DATABASE=dmarc_report"
      - "MYSQL_USER=dmarc_report"

            name: servernet
            name: dmarcdbnet

The gutmensch/dmarc-report:latest container includes the two services mentioned earlier, and everything else required to make a working service. The GitHub repository contains a Dockerfile and instructions.

Within my Docker Swarm, the servernet virtual network connects between NGINX Proxy Manager and the individual services. That means the dmarc-report container is registered as the hostname dmarc-report on the servernet network.

That means NGINX Proxy Manager must be configured to proxy the public domain name for this DMARC report viewer to http://dmarc-report:1080.

The database, on the other hand, must not be visible to NGINX Proxy Manager, and must not be visible to the public. For this purpose, I used Portainer to create a new network, dmarcdbnet, making sure to use the Overlay driver because this is a Docker Swarm. The network is therefore declared here as external, and is used to connect the two services.

For dmarcdb the volumes mounts are there to ensure the data is persistently saved. Otherwise the database is stored within the container storage, and will be deleted any time the container is rebuilt. The /opt/dmarc path is on the host server.

In the dmarc service some of the environment variables begin with PARSER_IMAP. These control access to an IMAP server. In the previous section I outlined how to configure DMARC records in the DNS, and to setup an email address. The DMARC DNS records designate this email address as the recipient of DMARC reports.

Simply put the IMAP configuration settings into these environment variables.

The REPORT_DB variables in turn correspond to the environment variables for the database.

Launching the DMARC Report stack on Docker

Now that you have the docker-compose.yaml configured, head to the command line and run this:

$ docker compose up

In older Docker implementations it was required to install a second package, docker-compose. If this is what you hve installed, use docker-compose up instead. But, the new way of launching Compose files is with the docker compose feature built-in to the the docker command. Notice that the two commands differ by the - which is missing in the new version. Docker Compose is now bundled with Docker.

Launching it this way lets you see the logging output to diagnose any issues.

Once you're satisfied it's working right add -d to the command line.

In my case, I instead pasted the Compose file into a Stack in Portainer. Afterward I clicked the button to deploy the stack.

MariaDB and MySQL containers have a behavior where the first time they're launched takes awhile to initialize the database. Be patient the first time around. The dmarc-report service will likewise take awhile to get going.

After The DMARC reporting service is launched, you can paste the corresponding URL into your browser.

Viewing DMARC reports

There is no authentication to access the DMARC report viewer. Immediately when visiting the URL in your browser you'll see something like this:

The buttons along the top allow you to select specific reports. The hamburger menu button at the far right opens a settings window letting you further customize the user experience.

Clicking on one of the rows causes details to show up at the bottom:

The raw XML shows up by making a setting in the settings area.

I don't know yet how to interpret these results. Whatever DKIM Align means is currently a failure for my site.

Securing access to the DMARC reports

Since there is no authentication, anyone who comes across your DMARC report server can view the data. Isn't it a good idea to have a password or something? But, this specific service has no such protection.

It is deployed behind NGINX Proxy Manager, and that tool has an Access Lists feature. Simply create an access list, then enable it for the domain where the report service is deployed.

Your deployment scenario may have a different way to control access.


This DMARC report viewer seems to be limited to handling reports for one domain name per instance. For example, there is no method to configure multiple DMARC IMAP mailboxes.

That means you may be deploying multiple instances of this tool. Does it make sense to deploy multiple databases?

It's probably best to follow this approach:

  • Create one Compose file for the database, attaching it to the dmarcdb network as shown here.
  • Create another Compose file to house one or more instances of the dmarc-report service.
  • Also deploy PHPMyAdmin so you can create additional databases in the dmarcdb server

I have a pair of previous articles discussing the setup of multiple databases in a Docker-hosted MySQL instance:

Bottom line is that this particular tool is an easy way to digest DMARC reports. There are 3rd party services for this purpose, but I was reluctant to hand them my data. This tool makes sure that my data stays in my hands, while avoiding the service fees required by the 3rd party tools.

It is a little finnicky to set this up. And it's troubling that there's no authentication required to view the reports. That means you must take some measures outside the DMARC service to control access.

Remember that the purpose of this exercise is to do your part to stop the spread of SPAM emails. It is important to learn what the reports mean, and to take action.

About the Author(s)

( David Herron : David Herron is a writer and software engineer focusing on the wise use of technology. He is especially interested in clean energy technologies like solar power, wind power, and electric cars. David worked for nearly 30 years in Silicon Valley on software ranging from electronic mail systems, to video streaming, to the Java programming language, and has published several books on Node.js programming and electric vehicles.