How to build a DMARC Report Dashboard with Python

Email security is a vital concern for organizations and individuals alike. One of the powerful tools in the fight against email abuse is Domain-based Message Authentication, Reporting, and Conformance (DMARC). DMARC enables email senders to specify how email servers should handle unauthenticated emails, reducing the risk of phishing and spam. To gain insights into the effectiveness of DMARC policies, we can create a DMARC Report Dashboard using Python and Dash, a web application framework. In this article, we'll walk you through the process of building such a dashboard.

Project Overview

The DMARC Report Dashboard is a web-based tool that parses and visualizes DMARC reports. These reports contain essential information about email delivery, including source IP addresses, email counts, and pass/fail status. Our goal is to create an interactive dashboard that displays this information in tabular and graphical formats. By the end of this project, you'll have a web application that provides insights into your email domain's DMARC status.

Building the Dashboard

The DMARC Report Dashboard can be divided into several key components. Let's break down the code and its functionalities:

Importing Libraries

import os
import xml.etree.ElementTree as ET
import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
import matplotlib.pyplot as plt
import plotly.express as px
from dash.dependencies import Input, Output

In this section, we import the necessary libraries, including Dash for building the web application, Matplotlib for creating graphical visualizations, and Plotly Express for generating pie charts.

Parsing and Processing DMARC Data

# Function to parse DMARC report
def parse_dmarc_report(report_xml):
    # Parsing XML data
    root = ET.fromstring(report_xml)
    return {
        "Source IP": root.find(".//record/row/source_ip").text,
        "Date": root.find(".//date_range/begin").text,
        "Count": int(root.find(".//record/row/count").text),
        "SPF Result": root.find(".//record/row/policy_evaluated/spf").text,
        "DKIM Result": root.find(".//record/row/policy_evaluated/dkim").text,
        "DMARC Result": root.find(".//record/row/policy_evaluated/disposition").text
    }

The parse_dmarc_report function takes DMARC report data in XML format, extracts relevant information, and returns a dictionary containing source IP, date, count, SPF result, DKIM result, and DMARC result.

Processing DMARC Reports

# Function to process DMARC reports
def process_dmarc_reports(report_dir):
    data = []

    for filename in os.listdir(report_dir):
        if filename.endswith(".xml"):
            with open(os.path.join(report_dir, filename), "r") as report_file:
                report_xml = report_file.read()
                parsed_data = parse_dmarc_report(report_xml)
                data.append(parsed_data)

    df = pd.DataFrame(data)
    return df

The process_dmarc_reports function processes DMARC reports in a specified directory. It iterates through each report, parses it, and stores the data in a Pandas DataFrame.

Creating the Pie Chart

# Create a pie chart for pass vs. fail percentages
def create_pass_fail_pie_chart():
    dmarc_result_counts = df["DMARC Result"].value_counts()
    pass_fail_counts = dmarc_result_counts.get("pass", 0), dmarc_result_counts.get("fail", 0)

    labels = ['Pass', 'Fail']
    fig = px.pie(names=labels, values=pass_fail_counts, title='DMARC Pass vs. Fail')
    return fig

The create_pass_fail_pie_chart function calculates the percentages of passed and failed DMARC results and creates a pie chart using Plotly Express to visualize the distribution.

Building the Dash Application

app = dash.Dash(__name__)

# Define the layout for the Dash app
app.layout = html.Div([
    html.H1("DMARC Report Dashboard"),

    # Display the table-like graphical output
    html.Div([
        dcc.Graph(
            id='dmarc-table',
            config={'displayModeBar': False},
            figure={
                'data': [
                    {
                        'type': 'table',
                        'header': {
                            'values': df.columns,
                            'fill': {'color': '#f2f2f2'},
                            'align': 'center',
                            'font': {'size': 14}
                        },
                        'cells': {
                            'values': df.values.T,
                            'align': 'center',
                            'font': {'size': 12}
                        }
                    }
                ],
                'layout': {'autosize': True}
            }
        )
    ]),

    # Display the DMARC pass vs. fail pie chart
    html.Div([
        dcc.Graph(figure=create_pass_fail_pie_chart(), id='dmarc-pie-chart')
    ])
])

if __name__ == "__main__":
    app.run_server(debug=True)

In this final section, we create a Dash application (app) that includes the layout of our dashboard. It consists of an H1 header, a table-like graphical output of DMARC report data, and the DMARC pass vs. fail pie chart. We define the layout using HTML and Dash components.

Full Code

import os
import xml.etree.ElementTree as ET
import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
import matplotlib.pyplot as plt
import plotly.express as px
from dash.dependencies import Input, Output

app = dash.Dash(__name__)

# Function to parse DMARC report
def parse_dmarc_report(report_xml):
    root = ET.fromstring(report_xml)
    return {
        "Source IP": root.find(".//record/row/source_ip").text,
        "Date": root.find(".//date_range/begin").text,
        "Count": int(root.find(".//record/row/count").text),
        "SPF Result": root.find(".//record/row/policy_evaluated/spf").text,
        "DKIM Result": root.find(".//record/row/policy_evaluated/dkim").text,
        "DMARC Result": root.find(".//record/row/policy_evaluated/disposition").text
    }

# Function to process DMARC reports
def process_dmarc_reports(report_dir):
    data = []

    for filename in os.listdir(report_dir):
        if filename.endswith(".xml"):
            with open(os.path.join(report_dir, filename), "r") as report_file:
                report_xml = report_file.read()
                parsed_data = parse_dmarc_report(report_xml)
                data.append(parsed_data)

    df = pd.DataFrame(data)
    return df

# Process the DMARC reports
report_dir = "dmarc_reports"
df = process_dmarc_reports(report_dir)

# Create a pie chart for pass vs. fail percentages
def create_pass_fail_pie_chart():
    dmarc_result_counts = df["DMARC Result"].value_counts()
    pass_fail_counts = dmarc_result_counts.get("pass", 0), dmarc_result_counts.get("fail", 0)
    
    labels = ['Pass', 'Fail']
    fig = px.pie(names=labels, values=pass_fail_counts, title='DMARC Pass vs. Fail')
    return fig

# Define the layout for the Dash app
app.layout = html.Div([
    html.H1("DMARC Report Dashboard"),
    
    # Display the table-like graphical output
    html.Div([
        dcc.Graph(
            id='dmarc-table',
            config={'displayModeBar': False},
            figure={
                'data': [
                    {
                        'type': 'table',
                        'header': {
                            'values': df.columns,
                            'fill': {'color': '#f2f2f2'},
                            'align': 'center',
                            'font': {'size': 14}
                        },
                        'cells': {
                            'values': df.values.T,
                            'align': 'center',
                            'font': {'size': 12}
                        }
                    }
                ],
                'layout': {'autosize': True}
            }
        )
    ]),
    
    # Display the DMARC pass vs. fail pie chart
    html.Div([
        dcc.Graph(figure=create_pass_fail_pie_chart(), id='dmarc-pie-chart')
    ])
])

if __name__ == "__main__":
    app.run_server(debug=True)

Output

Dashboard Report

Conclusion

In this article, we've demonstrated how to build a DMARC Report Dashboard using Python and Dash. This dashboard combines data processing and visualization to provide valuable insights into the DMARC status of your email domain. You now have a web-based tool to monitor email security and delivery. Building a DMARC report dashboard is a valuable skill for system administrators, email security professionals, and anyone interested in enhancing email security strategies.

By customizing and expanding on this project, organizations can gain even deeper insights from DMARC reports and improve their email security practices. This is a practical application of Python and web development for email security, and it showcases the power of open-source tools to address real-world challenges.


Similar Articles