# Bulk Email Verifier - Real SMTP & Catch-All Detection (`mihai.zap/bulk-email-verifier`) Actor

Verifies email deliverability with real SMTP probing, not DNS guesswork. Detects catch-all domains per tenant, disposable addresses, role accounts and typos. Returns a confidence score and the evidence instead of a misleading valid/invalid.

- **URL**: https://apify.com/mihai.zap/bulk-email-verifier.md
- **Developed by:** [Mihai Z](https://apify.com/mihai.zap) (community)
- **Categories:** Lead generation, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$80.00 / 1,000 email verifieds

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

## Bulk Email Verifier — Real SMTP, Not Guesswork

Verifies email deliverability by **actually connecting to the mail server**. Returns a confidence score and the evidence behind it, never a misleading binary verdict.

### What separates this from the alternatives

The two most-used email verifiers on this platform **cannot perform SMTP verification at all.** That is not a marketing claim — it is visible in their own output.

**The leading paid verifier returns `reason: "smtp_unreachable"` on 10 of 23 test addresses.** Outbound port 25 is blocked in most cloud environments, so tools that cannot reach it fall back to DNS records and heuristics, then present the guess as a verdict.

**The leading free verifier answered `"Mailbox does not exist"` for two mailboxes that accepted mail on a live SMTP connection** (`postmaster@hetzner.com`, `abuse@hetzner.com` — both returned `250`). Deleting real customers from your list is the expensive failure, and it is the one most verifiers make.

This actor runs its SMTP probe on dedicated infrastructure with a clean IP, matching forward and reverse DNS, and per-domain rate limiting.

#### Test methodology

Both competitors were run on an identical 23-address corpus alongside this actor on 2026-09-11. The corpus covered valid mailboxes, non-existent mailboxes at the same domains, catch-all domains, disposable domains, dead domains, malformed syntax and typo domains. Ground truth was established by live SMTP where possible.

| | Correct verdicts | Recall on known-good |
|---|---|---|
| **This actor** | **23 / 23** | **4 / 4** |
| Leading paid verifier | 18 / 23 | 3 / 4 |
| Leading free verifier | 11 / 21 | 1 / 4 |

**Caveat, stated plainly:** the corpus is 23 addresses, and its known-good entries are RFC 2142 role accounts (`postmaster@`, `abuse@`) rather than ordinary user mailboxes. It is a small sample and should be read as an indication, not a guarantee. The capability difference above — that competitors cannot reach port 25 — is the durable point, and you can verify it yourself by inspecting their output.

### Catch-all is measured, not assumed

Whether a mail server accepts unknown recipients is a **per-tenant setting** and cannot be inferred from the MX record. Verified live:

| Domain | Mail provider | Accepts unknown recipients? |
|---|---|---|
| `gmail.com` | Google | **No** — verifiable |
| `segment.com` | Google | **Yes** — catch-all |
| `bosch.com` | Microsoft 365 | **No** — verifiable |
| `outlook.com` | Microsoft | **Yes** — catch-all |

Any tool that decides from the MX host gets these backwards. This one probes each domain and caches the result.

### What you get per address

```json
{
  "email": "someone@company.com",
  "status": "deliverable",
  "confidence": 95,
  "reason": "smtp_accepted",
  "suggestion": null,
  "checks": {
    "syntax": true, "mx": true, "disposable": false,
    "role": false, "free_provider": false, "catch_all": false
  }
}
```

**Statuses:** `deliverable` · `undeliverable` · `risky` · `unknown`

**No false confidence.** A catch-all domain returns `risky` with `reason: catch_all_domain`, because no verifier can confirm an individual mailbox there. Greylisting returns `unknown` rather than a guess — re-run later for a definitive answer.

### Checks performed

- RFC 5322 syntax, including leading/trailing/consecutive-dot rejection
- Typo detection with correction (`gmial.com` → `gmail.com`)
- MX records, with A-record fallback per RFC 5321
- **12,146 disposable / throwaway domains**, refreshed from maintained public blocklists
- Role accounts (`info@`, `admin@`, `postmaster@`…)
- **Catch-all detection**, probed per domain and cached
- **SMTP `RCPT TO` mailbox check** — never sends mail; the conversation ends before `DATA`

### Typical uses

- Clean a list before a campaign — bounces damage sender reputation
- Validate signups and block disposable addresses at entry
- Verify scraped or enriched leads, where addresses are guesses
- Ongoing CRM hygiene — lists decay roughly 2% per month

# Actor input Schema

## `emails` (type: `array`):

Addresses to verify. Duplicates are removed automatically.

## `smtpEnabled` (type: `boolean`):

Run a live SMTP mailbox check. Disable for a faster DNS-only pass.

## `dnsTimeoutMs` (type: `integer`):

How long to wait for DNS lookups before treating a domain as unresolvable.

## Actor input object example

```json
{
  "emails": [
    "support@github.com",
    "ceo@stripe.com",
    "info@mailinator.com",
    "user@gmial.com",
    "definitely-not-real-9f2a@volkswagen.de",
    "postmaster@ovh.com"
  ],
  "smtpEnabled": true,
  "dnsTimeoutMs": 5000
}
```

# Actor output Schema

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

Every address with status (deliverable, undeliverable, risky, unknown), confidence 0-100, the reason code, and the per-stage checks.

## `csv` (type: `string`):

The same results as a CSV file, ready for your CRM or sending tool.

# 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 = {
    "emails": [
        "support@github.com",
        "ceo@stripe.com",
        "info@mailinator.com",
        "user@gmial.com",
        "definitely-not-real-9f2a@volkswagen.de",
        "postmaster@ovh.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mihai.zap/bulk-email-verifier").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 = { "emails": [
        "support@github.com",
        "ceo@stripe.com",
        "info@mailinator.com",
        "user@gmial.com",
        "definitely-not-real-9f2a@volkswagen.de",
        "postmaster@ovh.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("mihai.zap/bulk-email-verifier").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 '{
  "emails": [
    "support@github.com",
    "ceo@stripe.com",
    "info@mailinator.com",
    "user@gmial.com",
    "definitely-not-real-9f2a@volkswagen.de",
    "postmaster@ovh.com"
  ]
}' |
apify call mihai.zap/bulk-email-verifier --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mihai.zap/bulk-email-verifier"
        }
    }
}
```

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/FSfHTJ1BgkHUSBwaQ/builds/gh0EqTD2vjqgm6XFb/openapi.json
