# Email Verifier — Bulk Verification with Catch-All Detection (`apricot_blackberry/email-verifier-catchall`) Actor

Verify email lists before you send: syntax, disposable and role checks, MX/SPF/DMARC, and a live SMTP probe that tells catch-all domains apart from real mailboxes. Deliverable / risky / undeliverable with reasons. $0.60 per 1,000; unknowns free.

- **URL**: https://apify.com/apricot\_blackberry/email-verifier-catchall.md
- **Developed by:** [Creator Fusion](https://apify.com/apricot_blackberry) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 verified emails

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

## Email Verifier — Bulk Verification with Catch-All Detection

### What does Email Verifier do?

Paste a list of email addresses and get back, for each one, whether it is **deliverable**, **risky**, **undeliverable** or **unknown**, a 0–100 deliverability score, and the exact reasons. It runs syntax, disposable-domain and role-address checks, resolves MX/SPF/DMARC, then opens a real SMTP conversation with the mail server to ask whether the mailbox exists — and probes a random address on the same domain so a **catch-all** server (which says "yes" to everything) is never reported as a verified mailbox. No email is ever sent.

Between 15 % and 28 % of B2B domains are catch-all. Verifiers that stop at "the server accepted it" mark those as valid and you bounce anyway. This one tells you.

### What you get per address

| Field | Meaning |
|---|---|
| `status` | `deliverable` · `risky` · `undeliverable` · `unknown` |
| `deliverabilityScore` | 0–100 |
| `safeToSend` | `true` only for `deliverable` |
| `reasons[]` | e.g. `smtp-accepted`, `catch-all-domain`, `smtp-rejected-550`, `role-address`, `disposable-domain`, `no-mx-record`, `greylisted-451`, `gateway-proofpoint-accepts-all` |
| `catchAll` | domain accepts any local part |
| `isRoleAddress`, `isFreeProvider`, `isDisposable` | list-hygiene flags |
| `mailProvider`, `mxHosts`, `spf`, `dmarc`, `dmarcPolicy` | domain intel |
| `smtpCode`, `smtpReason`, `smtpTls` | raw server reply for auditing |

### How to use it

1. Paste emails (one per line) or send `emails[]` via API.
2. For mailbox-level verdicts (deliverable / catch-all / rejected), set **SMTP probe endpoint** — see below. Without it the run is DNS-only: syntax, disposable, role, MX/SPF/DMARC; mailbox-level results come back `unknown` and are **not charged**.
3. Filter the dataset on `safeToSend = true` for your send list; keep `risky` for a second-pass tool or manual review.

### Why a probe endpoint?

Apify (like every cloud sandbox) blocks outbound port 25, so no Actor can talk SMTP directly — any verifier on the Store that claims mailbox-level checks is relaying through a server somewhere. We make that explicit: you run a 30-line probe service on any VPS with port 25 open and paste its URL. Your list never leaves your own infrastructure for the SMTP step, and you're not paying a middleman per probe.

```js
// probe-server/server.mjs  —  PROBE_TOKEN=change-me PORT=8080 node server.mjs   (put HTTPS in front)
import http from 'node:http';
import { smtpProbe } from './smtp.js';           // same probe code this Actor uses
const TOKEN = process.env.PROBE_TOKEN;
http.createServer(async (req, res) => {
  if (req.method !== 'POST' || (TOKEN && req.headers.authorization !== `Bearer ${TOKEN}`)) return res.writeHead(401).end();
  let b = ''; for await (const c of req) b += c;
  const { email, mxHost, timeoutMs, heloDomain, fromAddress } = JSON.parse(b);
  res.writeHead(200, { 'content-type': 'application/json' })
     .end(JSON.stringify(await smtpProbe({ email, mxHost, timeoutMs, heloDomain, fromAddress })));
}).listen(process.env.PORT ?? 8080);
```

The full `smtp.js` (EHLO → STARTTLS → MAIL FROM → RCPT TO → random-address catch-all check, never DATA) ships in this Actor's source. Hetzner, OVH and Vultr open port 25 on request; a $4/month box handles ~50k probes/day.

### How much does it cost?

| Event | Price |
|---|---|
| `verified-email` — any address with a definitive verdict (deliverable, risky, undeliverable) | **$0.0006** ($0.60 per 1,000) |
| `unknown` (mail server unreachable or refused to answer) | **free** |
| Actor start | $0.00005 |

1,000 addresses ≈ $0.60. Set *Maximum cost per run* to cap spend.

### Sample output

```json
{ "email": "jane.doe@apify.com", "status": "deliverable", "deliverabilityScore": 95, "safeToSend": true,
  "reasons": ["smtp-accepted"], "catchAll": false, "isRoleAddress": false, "isFreeProvider": false, "isDisposable": false,
  "mailProvider": "Google Workspace", "mxHosts": ["aspmx.l.google.com"], "spf": true, "dmarc": true, "dmarcPolicy": "reject",
  "smtpChecked": true, "smtpStatus": "deliverable", "smtpCode": 250, "smtpTls": true, "checkedAt": "2026-09-25T04:50:00.000Z" }
```

### FAQ

**Why "risky" instead of a yes/no?** Catch-all domains, greylisting (451/450 "try later") and security gateways like Proofpoint or Mimecast — which accept every RCPT and filter later — cannot be resolved by any SMTP verifier. We say so rather than guess, and don't charge for `unknown`.

**Does it send anything?** No. The conversation stops after RCPT TO; DATA is never issued.

**Is it GDPR-safe?** It processes only the addresses you already hold and stores nothing beyond your run's dataset.

**Can I pair it with enrichment?** Yes — run *Reverse Email Lookup — Email to Name, LinkedIn & Company* by the same author on the `deliverable` rows to get the person and company behind each address.

***

Built by Creator Fusion LLC.

# Actor input Schema

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

Addresses to verify, one per line. Duplicates are removed.

## `smtpCheck` (type: `boolean`):

Connect to the domain's mail server and ask whether the mailbox exists (RCPT TO), then probe a random address to detect catch-all domains. No email is ever sent. Turn off for a DNS-only check.

## `maxEmails` (type: `integer`):

Stop after this many addresses. Leave empty to verify the whole list.

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

Parallel checks. 10 is safe; higher can trip greylisting on shared mail providers.

## `smtpTimeoutSecs` (type: `integer`):

Per-command timeout for the SMTP conversation.

## `probeEndpoint` (type: `string`):

Apify blocks outbound port 25, so live mailbox checks run through a tiny probe service you host on any VPS with port 25 open (one-file Node server, code in the README). Leave empty for a DNS-only pass: syntax, disposable, role, MX/SPF/DMARC — mailbox-level results then come back as "unknown" and are not charged.

## `probeToken` (type: `string`):

Bearer token your probe service expects.

## `heloDomain` (type: `string`):

Hostname announced in EHLO. Use a domain you control with a valid PTR if servers greylist the default.

## `fromAddress` (type: `string`):

Envelope sender used in the probe. Must be a real address on a domain with SPF for best acceptance.

## Actor input object example

```json
{
  "emails": [
    "jane.doe@apify.com",
    "info@mailinator.com",
    "nobody-here-12345@gmail.com",
    "not-an-email"
  ],
  "smtpCheck": true,
  "maxConcurrency": 10,
  "smtpTimeoutSecs": 8,
  "heloDomain": "verify.creatorfusion.net",
  "fromAddress": "verify@creatorfusion.net"
}
```

# Actor output Schema

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

One row per address: status, score, reasons, catch-all flag, provider, SMTP details.

## `stats` (type: `string`):

Counts per status.

# 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": [
        "jane.doe@apify.com",
        "info@mailinator.com",
        "nobody-here-12345@gmail.com",
        "not-an-email"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("apricot_blackberry/email-verifier-catchall").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": [
        "jane.doe@apify.com",
        "info@mailinator.com",
        "nobody-here-12345@gmail.com",
        "not-an-email",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("apricot_blackberry/email-verifier-catchall").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": [
    "jane.doe@apify.com",
    "info@mailinator.com",
    "nobody-here-12345@gmail.com",
    "not-an-email"
  ]
}' |
apify call apricot_blackberry/email-verifier-catchall --silent --output-dataset

```

## MCP server setup

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

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/EFbpQSMO8t98bGHku/builds/ugWldC2yDS1fzBQHq/openapi.json
