# Email Finder & Verifier (Pattern + SMTP Check) (`fetchcraft/email-finder-verifier`) Actor

Turn a name plus company domain into a verified work email. Generates common patterns (first.last, flast, first), checks MX, then probes candidates over SMTP without sending mail. Returns best guess + confidence. Pairs with AI Sales Personalizer. Free preview, $0.02 per resolved contact.

- **URL**: https://apify.com/fetchcraft/email-finder-verifier.md
- **Developed by:** [Emily Ward](https://apify.com/fetchcraft) (community)
- **Categories:** Lead generation, Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN 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.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.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/platform/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

## Email Finder & Verifier

Turn a name plus a company domain into a verified work email. No paid API keys. Built to close the loop on the AI Sales Personalizer pipeline: scrape leads, find emails, personalize, send.

### How it works

1. **Normalize** the name into first/last and the domain (accepts bare domains or full URLs).
2. **MX lookup** confirms the domain can receive mail and finds its mail server.
3. **Pattern generation** builds the common B2B address formats (first.last, flast, first, etc.), ranked by real-world frequency.
4. **Catch-all detection** probes a random address. If the server accepts it, the domain is catch-all and individual mailboxes cannot be confirmed, so confidence is capped.
5. **SMTP verification** probes each candidate with `RCPT TO` (no mail is ever sent). The first address the server accepts is the verified email.

### Graceful degradation

Some networks block outbound port 25. When SMTP probing is unavailable, the actor automatically falls back to pattern-plus-MX confidence (the same model Hunter.io uses for unverifiable domains) and labels the result `probable_pattern`. You always get the best-guess email.

### Output per contact

| Field | Meaning |
| --- | --- |
| `best_email` | The resolved (or best-guess) email |
| `confidence` | 0 to 100 |
| `status` | `verified`, `probable_pattern`, `unverified_pattern`, `catch_all`, or `no_mx` |
| `mx_valid` | Whether the domain has a working mail server |
| `catch_all` | Whether the domain accepts everything |
| `candidates` | All patterns considered |
| `smtp_results` | Per-candidate SMTP outcome when probing ran |

### Input

```json
{
  "contacts": [
    { "name": "Jane Smith", "domain": "acme.com" },
    { "first_name": "John", "last_name": "Doe", "domain": "https://www.example.com" }
  ],
  "verify_smtp": true,
  "detect_catch_all": true,
  "preview_mode": false
}
````

### Pricing

Free preview (first 3 contacts). $0.02 per resolved contact after that. Compare to Hunter.io at $34/mo for 500 (about $0.07 each) or Apollo at higher tiers.

### Pairs with

- **Show HN Lead Scraper / Greenhouse Jobs Scraper** to source the companies
- **AI Sales Personalizer** to write the opener once you have the email

### Notes

- Respects standard SMTP etiquette: one connection per candidate, never sends mail, short timeouts.
- Catch-all and greylisting are detected and reported rather than guessed past.
- No personal data is stored beyond the run dataset.

# Actor input Schema

## `contacts` (type: `array`):

List of contacts to resolve. Each item is an object: {"name": "Jane Smith", "domain": "acme.com"} OR {"first\_name": "Jane", "last\_name": "Smith", "domain": "acme.com"}. The domain can be a bare domain or a full URL; it is normalized automatically.

## `verify_smtp` (type: `boolean`):

If true, probe each candidate over SMTP (RCPT TO) without sending mail to confirm the mailbox accepts. Slower but far more accurate. If false, ranks candidates by pattern likelihood and MX validity only.

## `detect_catch_all` (type: `boolean`):

Probe a random non-existent address first. If the server accepts it, the domain is catch-all and SMTP verification cannot distinguish real mailboxes, so confidence is capped. Recommended ON.

## `max_concurrency` (type: `integer`):

How many contacts to resolve in parallel. SMTP probing is sequential per-domain to avoid rate limits, so this controls cross-domain parallelism.

## `preview_mode` (type: `boolean`):

Resolve only the first 3 contacts, free, so you can see output quality before paying.

## Actor input object example

```json
{
  "contacts": [
    {
      "name": "Patrick Collison",
      "domain": "stripe.com"
    },
    {
      "first_name": "Dylan",
      "last_name": "Field",
      "domain": "https://www.figma.com"
    }
  ],
  "verify_smtp": true,
  "detect_catch_all": true,
  "max_concurrency": 3,
  "preview_mode": false
}
```

# 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 = {
    "contacts": [
        {
            "name": "Patrick Collison",
            "domain": "stripe.com"
        },
        {
            "first_name": "Dylan",
            "last_name": "Field",
            "domain": "https://www.figma.com"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fetchcraft/email-finder-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 = { "contacts": [
        {
            "name": "Patrick Collison",
            "domain": "stripe.com",
        },
        {
            "first_name": "Dylan",
            "last_name": "Field",
            "domain": "https://www.figma.com",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("fetchcraft/email-finder-verifier").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 '{
  "contacts": [
    {
      "name": "Patrick Collison",
      "domain": "stripe.com"
    },
    {
      "first_name": "Dylan",
      "last_name": "Field",
      "domain": "https://www.figma.com"
    }
  ]
}' |
apify call fetchcraft/email-finder-verifier --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=fetchcraft/email-finder-verifier",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Email Finder & Verifier (Pattern + SMTP Check)",
        "description": "Turn a name plus company domain into a verified work email. Generates common patterns (first.last, flast, first), checks MX, then probes candidates over SMTP without sending mail. Returns best guess + confidence. Pairs with AI Sales Personalizer. Free preview, $0.02 per resolved contact.",
        "version": "0.1",
        "x-build-id": "n0dlk0WplP2HQXEd8"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/fetchcraft~email-finder-verifier/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-fetchcraft-email-finder-verifier",
                "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/fetchcraft~email-finder-verifier/runs": {
            "post": {
                "operationId": "runs-sync-fetchcraft-email-finder-verifier",
                "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/fetchcraft~email-finder-verifier/run-sync": {
            "post": {
                "operationId": "run-sync-fetchcraft-email-finder-verifier",
                "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": [
                    "contacts"
                ],
                "properties": {
                    "contacts": {
                        "title": "Contacts",
                        "type": "array",
                        "description": "List of contacts to resolve. Each item is an object: {\"name\": \"Jane Smith\", \"domain\": \"acme.com\"} OR {\"first_name\": \"Jane\", \"last_name\": \"Smith\", \"domain\": \"acme.com\"}. The domain can be a bare domain or a full URL; it is normalized automatically."
                    },
                    "verify_smtp": {
                        "title": "Verify over SMTP",
                        "type": "boolean",
                        "description": "If true, probe each candidate over SMTP (RCPT TO) without sending mail to confirm the mailbox accepts. Slower but far more accurate. If false, ranks candidates by pattern likelihood and MX validity only.",
                        "default": true
                    },
                    "detect_catch_all": {
                        "title": "Detect catch-all domains",
                        "type": "boolean",
                        "description": "Probe a random non-existent address first. If the server accepts it, the domain is catch-all and SMTP verification cannot distinguish real mailboxes, so confidence is capped. Recommended ON.",
                        "default": true
                    },
                    "max_concurrency": {
                        "title": "Max parallel contacts",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "integer",
                        "description": "How many contacts to resolve in parallel. SMTP probing is sequential per-domain to avoid rate limits, so this controls cross-domain parallelism.",
                        "default": 3
                    },
                    "preview_mode": {
                        "title": "Preview mode (free, first 3 contacts)",
                        "type": "boolean",
                        "description": "Resolve only the first 3 contacts, free, so you can see output quality before paying.",
                        "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
