# Email Deliverability & DNS Security Auditor (SPF, DKIM, DMARC) (`plotbench/email-dns-security-auditor`) Actor

Check email deliverability and DNS security for any list of domains: SPF, DKIM, DMARC, MX, DNSSEC, MTA-STS, TLS-RPT and BIMI audited in one run. Deterministic scoring, actionable findings, no API keys.

- **URL**: https://apify.com/plotbench/email-dns-security-auditor.md
- **Developed by:** [Plotbench Studio](https://apify.com/plotbench) (community)
- **Categories:** Developer tools, SEO tools
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 domain auditeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Email Deliverability & DNS Security Auditor (SPF, DKIM, DMARC, MTA-STS)

Audit the **email deliverability and DNS security** posture of **any list of domains** in one run: MX, SPF, DKIM (selector probing with wildcard-zone detection), DMARC, DNSSEC, MTA-STS (record + live policy fetch), TLS-RPT and BIMI — with a deterministic **0–100 score, A–F grade, and actionable findings** for every domain. If mail is landing in spam, this is the audit that finds the DNS causes.

![Example output: one scored row per domain — SPF, DMARC, DKIM, DNSSEC, MTA-STS](https://api.apify.com/v2/key-value-stores/yJ8cPT71eR5WeekTb/records/email-dns-security-auditor-1.png)

![Findings with severity and a concrete fix, per domain](https://api.apify.com/v2/key-value-stores/yJ8cPT71eR5WeekTb/records/email-dns-security-auditor-2.png)

Built for the people who audit domains in bulk:

- **MSPs and IT agencies** — audit every client domain weekly; catch the DMARC record someone deleted before spoofed invoices go out.
- **Deliverability consultants** — a client-ready evidence table in minutes, not an afternoon of `dig`.
- **Security / compliance teams** — track your whole domain estate (including forgotten marketing domains, which are exactly the ones that get spoofed).
- **Domain portfolio owners** — parked domains without a restrictive SPF/DMARC are spoofing targets; find them.

### Why this auditor (honest differentiators)

- **No API keys, no accounts, no scraping.** Everything is answered over public DNS via DNS-over-HTTPS (Cloudflare primary, Google automatic fallback).
- **Wildcard-zone detection.** Many tools "find" DKIM keys on zones that answer every TXT query (wildcards). This actor probes a canary selector first and reports `DKIM_WILDCARD_ZONE` instead of lying to you — verified live against gov.uk, which wildcards TXT.
- **Deterministic.** Same DNS state in, same score out. No AI, no sampling, no flakiness. Safe to schedule and diff week-on-week.
- **Findings, not just data.** Every issue comes with severity, a stable machine-readable code (e.g. `SPF_LOOKUP_LIMIT`, `DMARC_P_NONE`) and a concrete recommendation.

### What it checks

| Check | Detail |
|---|---|
| MX | Records, priorities, null-MX (RFC 7505) detection |
| SPF | Presence, multiple-record permerror, `all` policy strength, 10-DNS-lookup limit |
| DMARC | Presence, `p=`/`sp=` policy, `pct`, `rua` reporting, alignment modes |
| DKIM | 15 common selectors probed (configurable), wildcard-zone canary |
| DNSSEC | Validation status (AD flag from a validating resolver) |
| MTA-STS | DNS record **and** live policy file fetch + mode |
| TLS-RPT | `_smtp._tls` reporting record |
| BIMI | `default._bimi` record |

### Input (all optional except domains)

```json
{
    "domains": ["yourdomain.com", "client-domain.co.uk"],
    "dkimSelectors": ["default", "google", "selector1", "selector2"],
    "resolver": "cloudflare"
}
```

### Output (one dataset row per domain)

```json
{
    "domain": "microsoft.com",
    "score": 88,
    "grade": "B",
    "checks": { "mx": {}, "spf": {}, "dmarc": {}, "dkim": { "foundSelectors": ["selector2"] }, "dnssec": {}, "mtaSts": {}, "tlsRpt": {}, "bimi": {} },
    "findings": [ { "severity": "info", "code": "DNSSEC_OFF", "message": "Zone is not DNSSEC-validated.", "recommendation": "Consider enabling DNSSEC at your registrar/DNS host." } ]
}
```

### Pricing (pay per event)

| Event | Price |
|---|---|
| Actor start | $0.02 per run |
| Domain audited | $0.01 per domain |

Auditing 50 client domains costs about **$0.52 per run** — schedule it weekly and diff the scores.

### Scheduling & integrations

Run it on an Apify **Schedule** (e.g. every Monday 07:00), then use Apify integrations to send the dataset to Slack, email, Google Sheets, Make or Zapier. Alert on any domain whose score drops.

### Fair use & data sources

All lookups are standard DNS queries over public resolvers (Cloudflare 1.1.1.1, Google 8.8.8.8) — public data, published by the domain owners themselves precisely so that other mail servers read it. The optional MTA-STS policy fetch reads the standard well-known URL defined by RFC 8461. No websites are scraped, no rate limits are strained, no personal data is processed.

### Limitations (told straight)

- DKIM selector probing can only find selectors you probe; a custom selector not in your list won't be found. Absence of DKIM findings is reported as "not found at probed selectors", never "domain has no DKIM".
- On wildcard TXT zones, DKIM probing is inconclusive and flagged as such.
- Scores are a posture heuristic, not a deliverability guarantee.

# Actor input Schema

## `domains` (type: `array`):

List of domains to audit (bare domains, e.g. example.com — no scheme or path).

## `dkimSelectors` (type: `array`):

Common DKIM selector names to probe at <selector>.\_domainkey.<domain>. Add your provider's selector if you know it.

## `resolver` (type: `string`):

Primary resolver; the other one is used automatically as fallback.

## Actor input object example

```json
{
  "domains": [
    "gov.uk",
    "example.com"
  ],
  "dkimSelectors": [
    "default",
    "google",
    "selector1",
    "selector2",
    "k1",
    "k2",
    "mail",
    "s1",
    "s2",
    "dkim",
    "mx",
    "zoho",
    "pm",
    "mandrill",
    "fm1"
  ],
  "resolver": "cloudflare"
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "domains": [
        "gov.uk",
        "example.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("plotbench/email-dns-security-auditor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "domains": [
        "gov.uk",
        "example.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("plotbench/email-dns-security-auditor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "domains": [
    "gov.uk",
    "example.com"
  ]
}' |
apify call plotbench/email-dns-security-auditor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,plotbench/email-dns-security-auditor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ITgo1LCyB0q3DMVbq/builds/qm8cQBY1d8TulAKvR/openapi.json
