# Bulk DMARC Checker with SPF, DKIM & MX Audit (`davidbenittah/dmarc-rfc9989-auditor`) Actor

Run an email authentication check on up to 100 domains at once. Reads public DNS for DMARC, SPF, MX and the DKIM selectors you name, parses the p, sp and RFC 9989 np policies, and returns a 0-100 score per domain with the raw records and the anti-spoofing fixes to apply first.

- **URL**: https://apify.com/davidbenittah/dmarc-rfc9989-auditor.md
- **Developed by:** [David](https://apify.com/davidbenittah) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## Bulk DMARC Checker with SPF, DKIM & MX Audit

Check the email authentication of up to 100 domains in one run. This bulk DMARC checker reads public DNS, parses the DMARC and SPF records, confirms MX hosts answer, probes the DKIM selectors you list, and returns one row per domain with a 0-100 score, a letter grade, the issues in priority order and the record to publish next.

The distinguishing field is `nonexistentSubdomainPolicy`: it exposes the `np` tag introduced by DMARC RFC 9989 in May 2026. The Actor also reports `p` and `sp`, so teams can compare the policy for the organizational domain, existing subdomains, and non-existent subdomains without opening DNS tools domain by domain.

### SPF, DKIM and MX checks

SPF is read and returned raw, and multiple SPF records are flagged because receivers can treat them as invalid. MX presence and mail-host names are reported so a domain that sends mail without receiving it stands out. DKIM cannot be discovered without a selector name, so the Actor probes the selectors you pass and reports which ones resolved to a public key. "No tested DKIM selector found" means none of your selector names resolved, not that DKIM is absent.

### Who uses this email authentication checker

- IT administrators auditing a portfolio of company domains.
- Email-deliverability agencies checking client DNS before a campaign.
- Security teams reviewing anti-spoofing posture after a domain migration.
- Marketing operations teams validating SPF, DKIM, and DMARC before changing providers.

### Ready-to-run example

```json
{
  "domains": ["example.com", "google.com", "dmarcwise.io"],
  "dkimSelectors": ["default", "google", "selector1", "selector2"],
  "issuesOnly": false
}
````

The default input is valid and runs without an API key, proxy, login, or external account.

### Data returned for each domain

Each dataset item includes:

- the normalized domain, a 0–100 score, and a letter grade;
- the raw DMARC and SPF records;
- parsed DMARC `p`, `sp`, `np`, `pct`, `rua`, and `ruf` values;
- MX presence and mail-host names;
- which requested DKIM selectors were found;
- plain-language issues and recommended next actions;
- the exact audit timestamp.

A `SUMMARY` record contains the number of domains checked, the number needing attention, and the grade distribution. Enable **Return only domains needing attention** to make the dataset convenient for alerts or scheduled workflows.

### Reading the result

A missing DMARC record is a high-priority issue. `p=none` is reported as monitoring-only rather than enforcement. Multiple DMARC records are flagged because receivers can treat them as invalid. A `pct` below 100 is shown explicitly. Absence of `np` is a recommendation, not automatically an error: under RFC 9989 the applicable parent policy still provides fallback behavior.

Before reading the DKIM column, add the selectors used by the domain’s mail providers: the check only covers the names you supply.

### Limits and responsible use

- Maximum 100 domains per run.
- Maximum 20 DKIM selectors per run.
- Only public DNS records are queried.
- The output contains configuration data, not personal data.
- Scores are deterministic guidance, not a guarantee of inbox placement or complete RFC compliance.
- DNS caching and propagation can make recent changes appear later.

This Actor is an **unofficial** independent utility. It is not affiliated with the IETF, Google, Yahoo, Microsoft, or any email provider. Review proposed DNS changes with the person responsible for your mail system before applying them.

# Actor input Schema

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

Domain names only. Hard maximum: 100 per run.

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

Common selector names to check. Add selectors used by your mail providers.

## `issuesOnly` (type: `boolean`):

Omit domains with no detected configuration issue.

## Actor input object example

```json
{
  "domains": [
    "example.com",
    "google.com",
    "dmarcwise.io"
  ],
  "dkimSelectors": [
    "default",
    "google",
    "selector1",
    "selector2"
  ],
  "issuesOnly": false
}
```

# Actor output Schema

## `results` (type: `string`):

Structured domain audit items.

## `summary` (type: `string`):

Counts and posture distribution.

# 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": [
        "example.com",
        "google.com",
        "dmarcwise.io"
    ],
    "dkimSelectors": [
        "default",
        "google",
        "selector1",
        "selector2"
    ],
    "issuesOnly": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("davidbenittah/dmarc-rfc9989-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": [
        "example.com",
        "google.com",
        "dmarcwise.io",
    ],
    "dkimSelectors": [
        "default",
        "google",
        "selector1",
        "selector2",
    ],
    "issuesOnly": False,
}

# Run the Actor and wait for it to finish
run = client.actor("davidbenittah/dmarc-rfc9989-auditor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": [
    "example.com",
    "google.com",
    "dmarcwise.io"
  ],
  "dkimSelectors": [
    "default",
    "google",
    "selector1",
    "selector2"
  ],
  "issuesOnly": false
}' |
apify call davidbenittah/dmarc-rfc9989-auditor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=davidbenittah/dmarc-rfc9989-auditor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Bulk DMARC Checker with SPF, DKIM & MX Audit",
        "description": "Run an email authentication check on up to 100 domains at once. Reads public DNS for DMARC, SPF, MX and the DKIM selectors you name, parses the p, sp and RFC 9989 np policies, and returns a 0-100 score per domain with the raw records and the anti-spoofing fixes to apply first.",
        "version": "1.0",
        "x-build-id": "vIIyeMAxuhf5DfNxb"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/davidbenittah~dmarc-rfc9989-auditor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-davidbenittah-dmarc-rfc9989-auditor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/davidbenittah~dmarc-rfc9989-auditor/runs": {
            "post": {
                "operationId": "runs-sync-davidbenittah-dmarc-rfc9989-auditor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/davidbenittah~dmarc-rfc9989-auditor/run-sync": {
            "post": {
                "operationId": "run-sync-davidbenittah-dmarc-rfc9989-auditor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "domains"
                ],
                "properties": {
                    "domains": {
                        "title": "Domains to audit",
                        "type": "array",
                        "description": "Domain names only. Hard maximum: 100 per run.",
                        "default": [
                            "example.com"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "dkimSelectors": {
                        "title": "DKIM selectors to probe",
                        "type": "array",
                        "description": "Common selector names to check. Add selectors used by your mail providers.",
                        "default": [
                            "default",
                            "google",
                            "selector1",
                            "selector2"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "issuesOnly": {
                        "title": "Return only domains needing attention",
                        "type": "boolean",
                        "description": "Omit domains with no detected configuration issue.",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
