Dev.to Security πŸ” Cybersecurity πŸ‘ 0 πŸ“– 9 min read

MailGuard Digest: Engineering a Local-First DMARC Analysis Pipeline with Python

What if analyzing email authentication failures didn't require uploading your organization's email infrastructure data to a cloud AI service? That question became the starting point for MailGuard Digest, an open-source

What if analyzing email authentication failures didn't require uploading your organization's email infrastructure data to a cloud AI service?

That question became the starting point for MailGuard Digest, an open-source Python application that transforms DMARC aggregate reports into structured security findings and readable briefings.

πŸ”— Source code: https://github.com/kiddsaut07/mailguard-digest

This project sits at the intersection of email security, defensive engineering, data validation, local persistence, and optional local AI.

But the interesting part isn't simply parsing an XML file or adding a language model to a Flask application. It's designing a pipeline that can process untrusted input, produce traceable results, preserve the distinction between evidence and interpretation, and remain useful even when AI is unavailable.

That's the engineering problem I wanted to tackle for Hacktoberfest 2026.

1. The engineering problem: turning DMARC XML into actionable evidence

DMARC aggregate reports provide visibility into how receiving systems evaluate messages claiming to originate from a domain.

Depending on the report, they can contain:

  • Reporting organization and report-period metadata.
  • Published SPF, DKIM, and DMARC policy information.
  • Source IP addresses and message counts.
  • SPF and DKIM authentication results.
  • DMARC disposition and alignment-related information.

These reports are valuable for identifying misconfigured sending services, unexpected sources, and authentication failures. However, they are commonly delivered as XML documents, often compressed or bundled in archives.

Manually inspecting multiple reports quickly becomes tedious.

A useful analysis tool therefore needs to do more than deserialize XML. It needs to validate the input, normalize the relevant fields, calculate meaningful statistics, identify noteworthy conditions, preserve the results, and communicate the findings without overstating what the evidence proves.

The core challenge: build a reliable analysis pipeline in which security-relevant facts are produced by explicit application logicβ€”not invented by a language model.

2. Architecture: deterministic analysis first, AI second

MailGuard Digest follows a deliberately lightweight architecture built around Flask, Python, SQLite, Pydantic, and defusedxml.

At a conceptual level, the processing pipeline is:

DMARC report upload
        |
        v
File type and size checks
        |
        v
Safe XML / archive processing
        |
        v
Schema validation and normalization
        |
        v
Deterministic analysis engine
        |
        +----------------------+
        |                      |
        v                      v
Structured findings     Optional AI narration
        |                      |
        +-----------+----------+
                    |
                    v
          Readable security briefing
                    |
                    v
        SQLite / JSON / CSV / print

The diagram represents the application's intended processing flow rather than a claim that every operation runs in a separate service.

The main architectural decision is the separation between analysis and explanation.

The deterministic layer calculates counts, evaluates explicit conditions, and produces structured findings. Optional AI narration can help explain those findings in natural language, but it is not the authority for the underlying statistics or security conclusions.

This separation makes the application easier to test, reason about, and debug.

3. Secure ingestion: treat uploaded files as untrusted input

A report parser should not assume that every uploaded file is well-formed, harmless, or even the format its filename claims it is.

MailGuard Digest supports:

  • .xml
  • .xml.gz
  • .zip

Supporting these formats introduces several input-handling concerns: malformed XML, unexpected archive contents, oversized inputs, excessive record counts, and resource consumption.

XML parsing with defusedxml

XML parsing is a security boundary, not just a data extraction step.

MailGuard Digest uses defusedxml to reduce exposure to dangerous XML constructs associated with entity expansion and related parser attacks.

This is one layer of defense, not a guarantee that every malicious input is harmless. File validation, processing limits, error handling, and dependency maintenance still matter.

Bounded processing

The application also applies limits to archive and record processing.

This matters because a compressed file can expand dramatically, and a report containing a large number of records can consume significant CPU and memory even when the compressed upload appears small.

The objective is to make resource consumption more predictable and reject inputs that exceed the application's configured boundaries.

Validation with Pydantic

Parsing and validation are different operations.

A document can be syntactically valid XML but still contain missing, malformed, or inconsistent values. Pydantic models provide a structured validation layer for the data the application expects to work with.

Together, these controls establish a more disciplined ingestion boundary:

Accept supported input, reject invalid data where appropriate, normalize what can be processed safely, and handle failures explicitly.

4. Deterministic security analysis: facts before interpretation

Once a report has been parsed and validated, the application can calculate its statistics and identify relevant conditions.

The analysis focuses on information such as:

  • Total reported message counts.
  • SPF and DKIM authentication outcomes.
  • DMARC evaluation and disposition information.
  • Sources associated with authentication failures.
  • Conditions that may warrant configuration review or further investigation.

The important distinction is between a measurement, a finding, and a conclusion.

For example:

  • Measurement: a set of messages has an SPF failure result.
  • Finding: the affected source deserves investigation, especially if it is expected to send mail for the domain.
  • Conclusion: the source is malicious.

The first can be extracted from the report. The second depends on context and explicit analysis rules. The third cannot be established from an authentication failure alone.

A legitimate sender can fail authentication because of configuration errors, forwarding behavior, or other delivery-path issues. Conversely, passing authentication does not prove that a message is benign.

MailGuard Digest is therefore designed to support investigation, not to act as a definitive email threat-detection engine.

This distinction is essential in defensive security: an authentication result is evidence, not a complete verdict.

5. Local-first storage and export

A local security tool should make its results useful without requiring a separate infrastructure stack.

MailGuard Digest uses SQLite to retain analyzed report results and their history. It also supports exporting results to JSON and CSV, with browser-based printing for PDF output.

These choices keep the MVP relatively lightweight:

Component Purpose
Flask Application routes and user-facing workflow
defusedxml Safer XML parsing
Pydantic Structured data validation
SQLite Local persistence
JSON / CSV Portable analysis exports
pytest Automated verification
Ollama Optional local AI narration

A deliberate privacy choice is that the application does not retain the original uploaded XML reports by default. This reduces unnecessary raw-report retention, although the structured analysis stored in the database can still contain sensitive infrastructure information.

Local storage should not be confused with automatic security: database files, exports, backups, and the machine itself still need appropriate protection.

6. Optional local AI with Ollama

The next question was how to make technical findings easier to understand without making a paid cloud AI API a requirement.

MailGuard Digest includes an optional integration with Ollama for local language-model narration.

The intended workflow is straightforward:

  1. The deterministic analysis produces structured findings.
  2. The application prepares the information needed for an explanation.
  3. A compatible local model can generate a natural-language briefing.
  4. The briefing complements the structured results rather than replacing them.

The key design constraint is that AI narration is optional. The application should not depend on a model to calculate authentication statistics or determine whether the underlying report was parsed correctly.

Running a model locally can avoid sending its input to a remote AI provider, provided the workflow is genuinely local and no other component transmits that data. It also shifts the resource burden to the user's machine.

Local inference is not free of trade-offs: model availability, RAM, CPU performance, latency, and output quality all affect the experience.

I also distinguish between implementing an integration and validating it in a real environment. Compatibility with a particular model and successful end-to-end inference should be reported only when verified with that model and configuration.

7. Web application security is part of the implementation

Even a local-first tool needs a threat model.

MailGuard Digest includes CSRF protection and security-related response headers, alongside its input-processing controls.

These mechanisms address different risks:

  • CSRF protection: helps defend state-changing requests against cross-site request forgery.
  • Security headers: provide browser-side protections depending on the specific headers and deployment configuration.
  • Input validation and processing limits: reduce exposure to malformed files and resource-exhaustion conditions.
  • Loopback-oriented deployment: limits the intended exposure of an MVP that does not yet implement authentication and authorization.

That final point is especially important.

MailGuard Digest is intended for local use and development, not as a ready-made multi-user security service. It should not be exposed directly to an untrusted network without a proper deployment review and additional access controls.

Security is not a checklist that makes an application invulnerable. It is a set of controls whose effectiveness depends on the threat model, implementation, configuration, and testing.

8. Testing the application, not just the happy path

A parser that works for one sample report is not enough.

The project's final acceptance audit reported 417 passing tests. The reported test coverage spans areas including parsing, analysis rules, persistence, web routes, security protections, exports, and AI-related safeguards.

The audit also included a fresh virtual-environment installation and Python compilation checks.

These checks provide evidence that the implementation passed the project's automated acceptance suite in the tested environment. They do not prove the absence of defects, establish universal compatibility, or replace dedicated penetration testing and broader deployment testing.

Further useful work includes additional resource-exhaustion testing, accessibility checks, and verification across different supported runtime environments.

I consider this distinction important: a passing test suite is a meaningful engineering result, but it is not a certification of security.

9. Why keep the stack lightweight?

I deliberately chose a conventional Python stack instead of introducing a frontend framework, a separate API service, a distributed database, and container orchestration into the MVP.

The reasoning was practical:

  • Fewer moving parts to configure and maintain.
  • A smaller operational footprint for local execution.
  • A straightforward path from uploaded data to analysis results.
  • A testable separation between parsing, validation, analysis, persistence, and narration.
  • No mandatory paid AI API.

The goal was not to avoid complexity at all costs. It was to spend complexity where it matters: input safety, data correctness, explainable rules, failure handling, and tests.

10. Current limitations and next steps

MailGuard Digest is an open-source project for local DMARC analysis. It is not yet presented as a production-ready, multi-user service.

Current limitations include:

  • No authentication or authorization system.
  • A loopback-oriented deployment model.
  • The need for additional adversarial resource-exhaustion testing.
  • Further browser accessibility and deployment hardening work.
  • Dependence on local hardware and configuration for optional AI inference.

These limitations are part of the project's current scope, not details to hide behind a polished interface.

Possible future work includes broader adversarial test cases, clearer analysis provenance, additional report-format edge cases, and improved accessibility.

11. What this project taught me

MailGuard Digest was an opportunity to work on several connected engineering problems rather than just build a user interface.

It brought together:

  • Python application design with Flask.
  • Parsing untrusted XML and compressed archives.
  • Data modeling and validation with Pydantic.
  • Explicit, deterministic analysis rules.
  • Local persistence with SQLite.
  • Automated testing with pytest.
  • Web security controls.
  • Optional local language-model integration.

The biggest lesson is architectural: adding AI to a security tool should not weaken the reliability of its underlying analysis.

A model can help communicate complex findings. It should not be allowed to quietly replace measured values with plausible-sounding guesses.

My guiding principle for MailGuard Digest is simple: use deterministic code for facts, and use AI to make those facts easier to understand.

Explore the repository

πŸ”— GitHub: https://github.com/kiddsaut07/mailguard-digest

If you work with Python, email authentication, defensive security, XML processing, or local AI, I would appreciate feedback on the architecture, threat model, testing strategy, and user experience.

Issues, suggestions, and contributions are welcome.

MailGuard Digest is intended to support DMARC monitoring and investigation. It is not a definitive verdict on whether a message is malicious, and its current local-first design should not be interpreted as a production security guarantee.

πŸ“° Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.