Email Authentication: MailParse vs Mailgun Inbound Routing

Compare MailParse and Mailgun Inbound Routing for Email Authentication. Features, performance, and developer experience.

Why Email Authentication Matters for Inbound Parsing

Email authentication is more than an outbound deliverability topic. If your app ingests email - support ticketing, user-generated content, automated workflows, or SaaS integrations - you need to know who actually sent a message before you trust it. Attackers spoof domains and users, mailing lists rewrite headers, and forwarders can break SPF alignment. A parsing service that does not evaluate SPF, DKIM, and DMARC leaves you to build and maintain that critical logic yourself.

Inbound email-authentication protects data integrity, prevents spoofing, and lets you make policy decisions like rejecting untrusted messages, flagging them for review, or gating automations. The most useful implementation validates SPF,, DKIM,, and DMARC on receipt, interprets alignment rules, understands ARC for forwarded mail, then exposes structured results in your webhook or API so you can decide how to act per message.

If your product roadmap includes automated routing, approvals, or content publishing from email, review your provider's authentication stack alongside MIME parsing. For a broader operational checklist, see the Email Infrastructure Checklist for SaaS Platforms and Top Inbound Email Processing Ideas for SaaS Platforms.

How MailParse Handles Email Authentication

MailParse evaluates authentication as a first-class step in the inbound pipeline and exposes machine-friendly results in both webhooks and REST API. The goal is to make decisions trivial: label a message as trusted, quarantined, or rejected without screen-scraping headers.

SPF evaluation

  • Captures the connecting IP, SMTP HELO, and envelope-from (mfrom) used to deliver the message.
  • Evaluates SPF per RFC 7208 and records the mechanism that matched. Supports recursive lookups with safe limits and DNS caching.
  • Exposes scope and alignment against the visible From domain to support DMARC decisions.

DKIM verification

  • Verifies all DKIM signatures on the message, not just the first valid one. This matters for forwarders and multi-signer messages.
  • Respects canonicalization and l= body length tags, with strict body hashing. Publishes per-signature results, selectors, and covered headers.
  • DNS fetches are cached and time-limited to prevent latency spikes.

DMARC policy and alignment

  • Computes DMARC alignment using the RFC 7489 algorithm with support for organizational domain discovery.
  • Parses DMARC policy records including p, sp, pct, and evaluates results for each message. Even though DMARC reporting is outbound, a correct inbound verdict is central to trust.
  • Exposes both pass or fail and whether the pass was via SPF alignment, DKIM alignment, or both.

ARC chain handling for forwarded mail

  • If a message has an ARC chain, verifies the ARC-SEAL and ARC-Message-Signature across the set.
  • Exposes chain depth and final verdict so you can decide whether to trust an intermediary's assessment when SPF fails due to forwarding.

Webhook and API shape

Authentication data is included in webhook payloads and REST responses under a concise schema that stays stable across versions. You do not need to parse raw headers to make decisions.

{
  "id": "evt_9f2e...b1",
  "timestamp": "2026-04-24T12:03:45.284Z",
  "from": {
    "header": "Alice <alice@example.com>",
    "address": "alice@example.com",
    "domain": "example.com"
  },
  "envelope": {
    "mail_from": "alice@example.com",
    "helo": "mx.example.com",
    "rcpt_to": ["ingest@yourapp.io"],
    "client_ip": "203.0.113.54"
  },
  "auth": {
    "spf": {
      "result": "pass",
      "domain": "example.com",
      "scope": "mfrom",
      "ip": "203.0.113.54",
      "aligned": true,
      "mechanism": "ip4:203.0.113.0/24"
    },
    "dkim": [
      {
        "domain": "example.com",
        "selector": "s1",
        "result": "pass",
        "aligned": true,
        "canonicalization": "relaxed/relaxed",
        "covered_headers": ["from","to","subject","date"]
      }
    ],
    "dmarc": {
      "result": "pass",
      "aligned": true,
      "policy": "reject",
      "org_domain": "example.com",
      "reason": "dkim_aligned"
    },
    "arc": {
      "result": "none",
      "chain": 0
    }
  },
  "subject": "Quarterly report",
  "text": "Hi team,...",
  "html": "<p>Hi team,...</p>",
  "attachments": [],
  "raw_mime_url": "https://api.your-inbox.com/messages/msg_123/raw"
}

Webhook requests are signed with HMAC SHA-256 using your signing secret. Each payload carries an idempotency key and timestamp so you can verify authenticity and deduplicate.

How Mailgun Inbound Routing Handles Email Authentication

Mailgun Inbound Routing focuses on flexible routing and posting message content to your HTTP endpoint. The route payload includes parsed fields and the original MIME if you enable storage. For authentication, the service does not compute DMARC alignment for you and does not include explicit SPF or DKIM verdicts in the standard route parameters. If you need those, you have two options:

  • Request the raw MIME and parse the Authentication-Results header added by upstream MTAs, then perform your own DKIM, SPF, and DMARC checks if that header is absent or untrusted.
  • Run your own verification against the raw message using libraries like dkimpy or OpenDKIM.

Typical route payload fields include sender, recipient, message-headers, body-plain, timestamp, token, and signature. Webhooks are signed and you can verify integrity using your API key. This design is flexible but puts the burden of inbound authentication on your application.

If your use case demands structured authentication outcomes, you will end up parsing headers or validating signatures yourself on top of mailgun inbound routing (also written as mailgun-inbound-routing in some docs). This is workable and common, especially if you already standardize on Mailgun's stack for outbound, but it increases implementation time and CPU cost within your app.

Side-by-Side Comparison of Email Authentication Features

Capability MailParse Mailgun Inbound Routing
SPF validation on inbound Built-in result and alignment exposed in JSON Not included in route fields - manual or parse headers
DKIM verification on inbound Built-in for all signatures with per-sig details Not included - verify via raw MIME in your app
DMARC evaluation and alignment Built-in with org-domain discovery and policy Not included - implement evaluation yourself
ARC chain verification Built-in with chain depth and verdict Not included
Structured auth.* fields in webhook Yes No
Authentication-Results header preserved Yes - parsed and available in raw headers Yes - available if you fetch raw MIME
Webhook signature scheme HMAC SHA-256 with timestamp and idempotency key HMAC SHA-256 with timestamp and token
Edge-case handling for forwarded mail ARC aware and DMARC-friendly decisions exposed Depends on your custom logic
Scaling cost of auth logic Included in service Runs in your app - more compute at scale

Code Examples

Example: Verify webhook and use authentication verdicts from MailParse

This Node.js snippet shows how to verify the request signature and branch logic on DMARC and DKIM alignment. The payload structure mirrors the earlier example.

import crypto from 'crypto';
import express from 'express';

const app = express();
app.use(express.json({ limit: '25mb' }));

const SIGNING_SECRET = process.env.SIGNING_SECRET;

function verifySignature(req) {
  const timestamp = req.header('X-Timestamp');
  const sig = req.header('X-Signature');
  const body = JSON.stringify(req.body);
  const h = crypto.createHmac('sha256', SIGNING_SECRET);
  h.update(timestamp + '.' + body);
  const digest = 'sha256=' + h.digest('hex');
  return crypto.timingSafeEqual(Buffer.from(sig || ''), Buffer.from(digest));
}

app.post('/inbound', (req, res) => {
  if (!verifySignature(req)) {
    return res.status(401).send('invalid signature');
  }
  const msg = req.body;

  // Simple policy: require DMARC pass via DKIM alignment or accept ARC-backed forwarded mail
  const dmarc = msg.auth?.dmarc?.result;
  const arcOk = msg.auth?.arc?.result === 'pass';
  const dkimAligned = (msg.auth?.dkim || []).some(s => s.result === 'pass' && s.aligned);

  if (dmarc === 'pass' && dkimAligned) {
    // trusted path
    processTrusted(msg);
  } else if (arcOk) {
    processForwarded(msg);
  } else {
    flagForReview(msg);
  }

  res.send('ok');
});

app.listen(3000);

Example: Verify Mailgun route signature and compute DKIM/DMARC yourself

First verify Mailgun's route signature, then validate DKIM using dkimpy on the raw MIME. Once you have DKIM and SPF results, compute DMARC alignment in your code.

# Flask + dkimpy example
from flask import Flask, request, abort
import hmac, hashlib, dkim

API_KEY = b'your-mailgun-api-key'
app = Flask(__name__)

def valid_signature(timestamp, token, signature):
  mac = hmac.new(API_KEY, (timestamp + token).encode('utf-8'), hashlib.sha256).hexdigest()
  return hmac.compare_digest(mac, signature)

@app.route('/mg-inbound', methods=['POST'])
def mg_inbound():
  ts = request.form.get('timestamp','')
  token = request.form.get('token','')
  sig = request.form.get('signature','')
  if not valid_signature(ts, token, sig):
    abort(401)

  # If you enabled MIME storage, get the URL or raw content
  raw_mime = request.files.get('message').read()

  # DKIM verification
  dkim_result = dkim.verify(raw_mime)
  # Compute SPF separately using your SMTP logs or headers
  # Then evaluate DMARC alignment with your own function

  # Example decision
  if dkim_result:
    pass_message(raw_mime)
  else:
    quarantine(raw_mime)
  return 'ok'

If you choose to keep Mailgun Inbound Routing for flexibility, encapsulate your SPF, DKIM, and DMARC logic into a module so it is testable and fast. Cache DNS lookups aggressively and set timeouts to avoid backpressure.

Performance and Reliability

Latency and throughput

Authentication checks are DNS heavy. Cache layers and concurrency matter. The Mailgun route delivers a payload quickly because it does not perform DMARC evaluation for inbound by default. That shifts work to your app. If you roll your own checks, add a DNS cache and keep-per-query timeouts short to avoid latency spikes.

MailParse performs SPF, DKIM, DMARC, and optional ARC verification before completing the parse, then publishes a unified result. This keeps your webhooks lean and predictable because you do not need to fetch additional data or call out to DNS per request. Results stream with the rest of the parsed JSON, and the raw MIME is still available for audit.

Webhook delivery and retries

Both platforms sign webhooks and retry on non-2xx responses. If you are at scale, design for at-least-once processing. Use the provided event id or construct your own idempotency key to avoid duplicate work. Some teams report that Mailgun route deliveries can bunch during regional incidents or high volume, which may produce short bursts of retries. Size your worker pool accordingly and apply backpressure policies.

Edge cases that impact authentication

  • Forwarded mail: SPF will usually fail. ARC verification can rescue trust if the forwarder is trusted. If you rely on mailgun inbound routing, you will need to evaluate ARC yourself. With a structured ARC verdict, you can accept forwarded mail with confidence.
  • Mailing lists and rewriters: DKIM may fail if headers are modified. Look for multiple signatures and accept aligned ones where possible. Keep detailed per-signature results to avoid false negatives.
  • Subdomain policy and org domain: DMARC sp records differ from p at the organizational domain. Evaluate both correctly or you will misclassify mail from subdomains.
  • Header folding and MIME quirks: Canonicalization differences can break DKIM unexpectedly. Prefer relaxed canonicalization support and expose which headers were covered by the signature.

Scaling cost matters too. On Mailgun you are responsible for computing SPF, DKIM, DMARC at ingest time, so your CPU, DNS, and maintenance costs grow with inbound volume. On the other side, the structured approach centralizes the heavy lifting and simplifies your app logic.

For a broader operational perspective on reliability, see the Email Deliverability Checklist for SaaS Platforms.

Verdict: Which Is Better for Email Authentication?

If your primary criterion is robust, structured inbound email authentication that you can use immediately in code, MailParse is the better fit. You get SPF, DKIM, DMARC, and ARC results alongside parsed MIME, with alignment already computed. This shortens time to production and reduces the surface area of custom code you have to own.

If you already use Mailgun for outbound and need simple inbound routing with raw MIME, mailgun inbound routing remains a solid option. Just budget engineering time for dkimpy or OpenDKIM integration, SPF evaluation, and a correct DMARC implementation. At high volume, also account for the compute and DNS load that inbound authentication introduces when you run it yourself.

Most teams that need to take automated actions from email - creating issues, provisioning resources, or publishing content - benefit from a provider that handles authentication at the platform layer and exposes verdicts as JSON. That makes policy decisions easy, auditable, and consistent.

FAQ

Do I need SPF, DK

Ready to get started?

Start parsing inbound emails with MailParse today.

Get Started Free