# DMARC & SPF Checker - Google/Yahoo Bulk Sender Compliance (`lentic_labs/dmarc-spf-bulk-sender-check`) Actor

Fast bulk DMARC and SPF check with a pass/fail against the DNS side of the Google and Yahoo bulk-sender rules: valid SPF, DMARC p=none or stricter, DKIM key found. Flags spoofable domains and SPF over 10 lookups. $1 per 1,000 domains.

- **URL**: https://apify.com/lentic_labs/dmarc-spf-bulk-sender-check.md
- **Developed by:** [Lentic Labs](https://apify.com/lentic_labs) (community)
- **Categories:** Developer tools, Lead generation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 domains

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## DMARC & SPF Checker - Google/Yahoo Bulk Sender Compliance (Bulk)

Will your sending domains pass the **Gmail and Yahoo bulk sender requirements**? Paste a domain list and get a **pass/fail for each domain on the DNS side of those rules**: valid SPF, a DMARC record at p=none or stricter, and a DKIM key found. Each row also flags SPF records over the **10-lookup limit**, `+all`, missing `rua` reporting and **spoofable** domains with no enforced DMARC, with every issue in plain English. Check thousands of domains before a campaign, not one at a time, for **$1 per 1,000 domains**.

### What does it check?

For each domain:

- **SPF**: published, valid, not `+all`, and within the **10-DNS-lookup limit** (counted through all includes).
- **DMARC**: published and valid, the effective policy (`none` / `quarantine` / `reject`, including policies inherited from the parent domain), `pct`, and `rua` reporting.
- **DKIM**: looks for a public key under 30 common selectors (Microsoft `selector1/2`, Google `google`, Mailchimp `k1`...). You can add your own in `extraDkimSelectors`.
- **Spoofable**: true unless DMARC is enforced (quarantine/reject at 100%).

### Pass/fail result (`bulkSenderResult`)

| Result | Meaning |
|---|---|
| `pass` | Valid SPF, DMARC published (p=none or stricter), DKIM key found |
| `pass-dkim-unverified` | SPF and DMARC OK; no DKIM key found among common selectors (it may use a custom one) |
| `fail` | SPF or DMARC missing, invalid, or SPF `+all` |

`issues` lists every problem in plain English.

The result is measured against the **Gmail and Yahoo** rules only. Google and Yahoo also require **alignment** (the From domain matching SPF/DKIM), one-click unsubscribe and a low spam rate. Those can only be seen in real email, so this tool checks the DNS requirements only.

### Who is it for?

- **Cold-email and deliverability teams / agents**: check sending domains before a campaign.
- **Agencies, MSPs and security sellers**: check client domains, or find spoofable prospects (`spoofable = true`, DMARC `p=none`).
- **IT teams**: audit every domain you own in one run.
- **AI agents**: a cheap compliance pass/fail through the Apify API or MCP server.

### How much does it cost?

**$0.001 per domain ($1 per 1,000 domains).** No subscription. Duplicates, invalid input, non-existent (NXDOMAIN) domains and DNS failures are free. Set a maximum total charge per run and the Actor stops cleanly at your budget.
On Apify's free plan, the $5 monthly usage credit covers up to about 5,000 domains a month (less if you use other Apify Actors or services).

### How does it work?

Passive **public DNS queries only**. It sends no email and makes no web requests. It collects no personal data.

Use it only on domains you own or are authorized to assess, or for research on public DNS data. Results come only from public DNS records; no personal data is collected.

### FAQ

**What are the Gmail bulk sender requirements?**
From February 1, 2024, senders of more than 5,000 messages a day to Gmail must use SPF and DKIM, publish DMARC (p=none is allowed), align the From domain with SPF or DKIM, support one-click unsubscribe, keep the spam rate below 0.3%, use TLS and have valid PTR records ([Google](https://support.google.com/a/answer/81126)).

**What are the Yahoo bulk sender requirements?**
Yahoo requires SPF and DKIM, a valid DMARC policy of at least p=none that passes, a From domain aligned with SPF or DKIM, one-click unsubscribe honored within 2 days, and a spam rate below 0.3% ([Yahoo](https://senders.yahooinc.com/best-practices/)).

**Does it check Microsoft Outlook's requirements too?**
Not as a separate verdict. Since May 5, 2025, Outlook.com (hotmail.com, live.com, outlook.com) has required SPF, DKIM and DMARC (at least p=none) from domains sending more than 5,000 emails a day, and Microsoft's April 29, 2025 update says non-compliant mail is rejected with "550; 5.7.515 Access denied" ([Microsoft](https://techcommunity.microsoft.com/blog/microsoftdefenderforoffice365blog/strengthening-email-ecosystem-outlook%E2%80%99s-new-requirements-for-high%E2%80%90volume-senders/4399730)). The SPF, DKIM and DMARC fields in each row are useful for that check, but `bulkSenderResult` is defined against the Gmail and Yahoo rules.

**Does a "pass" mean my domain is fully compliant?**
No. It means the DNS side passes. Alignment, one-click unsubscribe, spam rate, TLS and PTR can only be seen in real mail or your sending infrastructure, so the Actor doesn't claim to check them.

**Is DMARC p=none enough for Gmail and Yahoo?**
For their bulk-sender rules, yes. Both accept p=none. But p=none takes no action on failing mail, so the domain stays spoofable. RFC 9989, the current DMARC standard that obsoletes RFC 7489, describes quarantine and reject as the enforcement policies ([RFC 9989](https://www.rfc-editor.org/info/rfc9989/)).

**Why does my SPF record show "too many lookups"?**
RFC 7208 §4.6.4 caps SPF at 10 DNS-querying terms (`include`, `a`, `mx`, `ptr`, `exists`, `redirect`). Going over the cap is a permerror ([RFC 7208](https://www.rfc-editor.org/rfc/rfc7208#section-4.6.4)). The Actor counts lookups through nested includes.

**Why is DKIM "unverified" when we do sign mail?**
DKIM selectors can't be listed from DNS. If your provider uses a custom selector, add it in `extraDkimSelectors`. Otherwise the result is `pass-dkim-unverified`, not `fail`.

### Use it from an AI agent or API

Call the Actor through the Apify API (`run-sync-get-dataset-items`) or Apify's MCP server (`https://mcp.apify.com?tools=lentic_labs/dmarc-spf-bulk-sender-check`), with JSON input `{"domains": ["example.com"]}`. Agents without an Apify account can use Apify's agentic payments (experimental): buy a prepaid token with x402, or pay per request with Skyfire.

### Related Lentic Labs Actors

- Need MTA-STS, TLS-RPT, BIMI, the mail provider, a 0-100 score and a fix list? [DMARC Checker Bulk - SPF, DKIM & Email Security](https://apify.com/lentic_labs/email-dmarc-security-prospector)
- Segment the list by email provider first: [Email Provider Lookup - Bulk MX for Microsoft 365 & Google](https://apify.com/lentic_labs/mail-provider-detector)
- Check the sites' certificates too: [SSL Certificate Expiry Checker](https://apify.com/lentic_labs/ssl-certificate-expiry-checker)

***

Microsoft 365 and Outlook are trademarks of Microsoft Corporation. Google Workspace and Gmail are trademarks of Google LLC. Yahoo is a trademark of Yahoo. Names are used only to describe the providers checked; Lentic Labs is not affiliated with or endorsed by them.

# Actor input Schema

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

Domains to check. URLs, 'www.' hosts and email addresses are accepted and normalized; duplicates are removed.

## `domainsText` (type: `string`):

Paste a list or CSV column. Anything that looks like a domain is extracted; other text is ignored.

## `checkDkim` (type: `boolean`):

Probe 30 common DKIM selectors (selector1, google, k1, ...). DKIM selectors can't be listed, so 'not found' doesn't prove DKIM is missing.

## `extraDkimSelectors` (type: `array`):

Your own selectors to probe in addition to the common ones.

## `maxDomains` (type: `integer`):

Stop after this many unique entries (0 = no limit). The run also stops cleanly when your maximum total charge is reached.

## `maxConcurrency` (type: `integer`):

Domains checked in parallel.

## Actor input object example

```json
{
  "domains": [
    "google.com",
    "microsoft.com",
    "apple.com",
    "github.com",
    "cloudflare.com",
    "mozilla.org",
    "python.org",
    "zoho.com"
  ],
  "checkDkim": true,
  "maxDomains": 0,
  "maxConcurrency": 10
}
```

# Actor output Schema

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

Default dataset, overview view.

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

Counts and distribution summary.

# 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": [
        "google.com",
        "microsoft.com",
        "apple.com",
        "github.com",
        "cloudflare.com",
        "mozilla.org",
        "python.org",
        "zoho.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lentic_labs/dmarc-spf-bulk-sender-check").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": [
        "google.com",
        "microsoft.com",
        "apple.com",
        "github.com",
        "cloudflare.com",
        "mozilla.org",
        "python.org",
        "zoho.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("lentic_labs/dmarc-spf-bulk-sender-check").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": [
    "google.com",
    "microsoft.com",
    "apple.com",
    "github.com",
    "cloudflare.com",
    "mozilla.org",
    "python.org",
    "zoho.com"
  ]
}' |
apify call lentic_labs/dmarc-spf-bulk-sender-check --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lentic_labs/dmarc-spf-bulk-sender-check"
        }
    }
}
```

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/wtFUb7lHr1mccVPCv/builds/kzQXVkJk3krnsHA5z/openapi.json
