# Technical Documentation: reacherhq/check-if-email-exists

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/reacherhq/check-if-email-exists)

### Overview (`README.md`)

[](https://crates.io/crates/check-if-email-exists)
[](https://docs.rs/check-if-email-exists)
[](https://hub.docker.com/r/reacherhq/backend)
[](https://github.com/reacherhq/check-if-email-exists/actions)

<br /><br />

<p align="center"><img align="center" src="https://storage.googleapis.com/saasify-uploads-prod/696e287ad79f0e0352bc201b36d701849f7d55e7.svg" height="96" alt="reacher" /></p>
<h1 align="center">check-if-email-exists</h1>
<h4 align="center">Check if an email address exists without sending any email.<br/>Comes with a <a href="./backend">⚙️ HTTP backend</a>.</h4>

<br /><br /><br />

## 👉 Live Demo: https://reacher.email

<img src="https://storage.googleapis.com/saasify-uploads-prod/696e287ad79f0e0352bc201b36d701849f7d55e7.svg" height="68" align="left" />

This is open-source, but I also offer a **SaaS** solution that has `check-if-email-exists` packaged in a nice friendly web interface. If you are interested, find out more at [No2Bounce.com](https://no2bounce.com/?ref=github). If you have any questions, you can contact me at amaury@reacher.email.

<br />

## Get Started

3 non-SaaS ways to get started with `check-if-email-exists`.

### 1. ⚙️ HTTP backend using Docker (popular method 🥇) [[Full docs](./backend/README.md)]

This option allows you to run a HTTP backend using Docker 🐳, on a cloud instance or your own server. Please note that outbound port 25 must be open.

```bash
docker run -p 8080:8080 reacherhq/backend:latest
```

Then send a `POST http://localhost:8080/v0/check_email` request with the following body:

```js
{
    "to_email": "someone@gmail.com",
    "proxy": {                        // (optional) SOCK5 proxy to run the verification through, default is empty
        "host": "my-proxy.io",
        "port": 1080,
        "username": "me",             // (optional) Proxy username
        "password": "pass"            // (optional) Proxy password
    }
}
```
**Note regarding proxy servers**
It is possible to operate Reacher with your own IP addresses. But if you wish to process more than very small volumes you will need SMTP proxy servers. For SMTP proxy servers please use [proxy25.com](https://proxy25.com/?ref=github)

### 2. Download the CLI [[Full docs](./cli/README.md)]

> Note: The CLI binary doesn't connect to any backend, it checks the email directly from your computer.

Head to the [releases page](https://github.com/reacherhq/check-if-email-exists/releases) and download the binary for your platform.

```bash
> $ check_if_email_exists --help
check_if_email_exists 0.9.1
Check if an email address exists without sending an email.

USAGE:
    check_if_email_exists [FLAGS] [OPTIONS] [TO_EMAIL]
```

Check out the [dedicated README.md](./cli/README.md) for all options and flags.

### 3. Programmatic Usage [[Full docs](https://docs.rs/check-if-email-exists)]

In your own Rust project, you can add `check-if-email-exists` in your `Cargo.toml`:

```toml
[dependencies]
check-if-email-exists = "0.9"
```

And use it in your code as follows:

```rust
use check_if_email_exists::{check_email, CheckEmailInput, CheckEmailInputProxy};

async fn check() {
    // Let's say we want to test the deliverability of someone@gmail.com.
    let mut input = CheckEmailInput::new(vec!["someone@gmail.com".into()]);

    // Verify this email, using async/await syntax.
    let result = check_email(&input).await;

    // `result` is a `Vec<CheckEmailOutput>`, where the CheckEmailOutput
    // struct contains all information about our email.
    println!("{:?}", result);
}
```

The reference docs are hosted on [docs.rs](https://docs.rs/check-if-email-exists).

## ✈️ JSON Output

The output will be a JSON with the below format, the fields should be self-explanatory. For `someone@gmail.com` (note that it is disabled by Gmail), here's the exact output:

```json
{
	"input": "someone@gmail.com",
	"is_reachable": "invalid",
	"misc": {
		"is_disposable": false,
		"is_role_account": false,
		"is_b2c": true
	},
	"mx": {
		"accepts_mail": true,
		"records": [
			"alt3.gmail-smtp-in.l.google.com.",
			"gmail-smtp-in.l.google.com.",
			"alt1.gmail-smtp-in.l.google.com.",
			"alt4.gmail-smtp-in.l.google.com.",
			"alt2.gmail-smtp-in.l.google.com."
		]
	},
	"smtp": {
		"can_connect_smtp": true,
		"has_full_inbox": false,
		"is_catch_all": false,
		"is_deliverable": false,
		"is_disabled": true
	},
	"syntax": {
		"domain": "gmail.com",
		"is_valid_syntax": true,
		"username": "someone",
		"suggestion": null
	}
}
```

## What Does This Tool Check?

| Included? | Feature                                       | Description                                                                                                                     | JSON field                                                                |
| --------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| ✅        | **Email reachability**                        | How confident are we in sending an email to this address? Can be one of `safe`, `risky`, `invalid` or `unknown`.                | `is_reachable`                                                            |
| ✅        | **Syntax validation**                         | Is the address syntactically valid?                                                                                             | `syntax.is_valid_syntax`                                                  |
| ✅        | **DNS records validation**                    | Does the domain of the email address have valid MX DNS records?                                                                 | `mx.accepts_mail`                                                         |
| ✅        | **Disposable email address (DEA) validation** | Is the address provided by a known [disposable email address](https://en.wikipedia.org/wiki/Disposable_email_address) provider? | `misc.is_disposable`                                                      |
| ✅        | **SMTP server validation**                    | Can the mail exchanger of the email address domain be contacted successfully?                                                   | `smtp.can_connect_smtp`                                                   |
| ✅        | **Email deliverability**                      | Is an email sent to this address deliverable?                                                                                   | `smtp.is_deliverable`                                                     |
| ✅        | **Mailbox disabled**                          | Has this email address been disabled by the email provider?                                                                     | `smtp.is_disabled`                                                        |
| ✅        | **Full inbox**                                | Is the inbox of this mailbox full?                                                                                              | `smtp.has_full_inbox`                                                     |
| ✅        | **Catch-all address**                         | Is this email address a [catch-all](https://debounce.io/blog/help/what-is-a-catch-all-or-accept-all/) address?                  | `smtp.is_catch_all`                                                       |
| ✅        | **Role account validation**                   | Is the email address a well-known role account?                                                                                 | `misc.is_role_account`                                                    |
| ✅        | **Gravatar Url**                              | The url of the [Gravatar](https://gravatar.com/) email address profile picture                                                  | `misc.gravatar_url`                                                       |
| ✅        | **Have I Been Pwned?**                        | Has this email been compromised in a [data breach](https://haveibeenpwned.com/)?                                                | `misc.haveibeenpwned`                                                     |
| 🔜        | **Free email provider check**                 | Is the email address bound to a known free email provider?                                                                      | [Issue #89](https://github.com/reacherhq/check-if-email-exists/issues/89) |
| 🔜        | **Syntax validation, provider-specific**      | According to the syntactic rules of the target mail provider, is the address syntactically valid?                               | [Issue #90](https://github.com/reacherhq/check-if-email-exists/issues/90) |
| 🔜        | **Honeypot detection**                        | Does email address under test hide a [honeypot](https://en.wikipedia.org/wiki/Spamtrap)?                                        | [Issue #91](https://github.com/reacherhq/check-if-email-exists/issues/91) |

## 🤔 Why?

Many online services (https://hunter.io, https://verify-email.org, https://email-checker.net) offer this service for a paid fee. Here is an open-source alternative to those tools.

## License

`check-if-email-exists`'s source code is provided under the [MIT License](./LICENSE.md).

---

### Overview (`backend/README.md`)

[](https://hub.docker.com/r/reacherhq/backend)
[](https://github.com/reacherhq/check-if-email-exists/actions)

<br /><br />

<p align="center"><img align="center" src="https://storage.googleapis.com/saasify-uploads-prod/696e287ad79f0e0352bc201b36d701849f7d55e7.svg" height="96" alt="reacher" /></p>
<h1 align="center">⚙️ Reacher Backend</h1>
<h4 align="center">REST Server for Reacher Email Verification API: https://reacher.email.</h4>

<br /><br />

This crate holds the backend for [Reacher](https://reacher.email). The backend is both a HTTP server and a email verification worker. It has with the following components:

-   [`check-if-email-exists`](https://github.com/reacherhq/check-if-email-exists), which performs the core email verification logic,
-   [`warp`](https://github.com/seanmonstar/warp) web framework,
-   [`RabbitMQ`](https://www.rabbitmq.com/) worker for consuming a queue of incoming verification requests.

## Get Started

The [Docker image](./Dockerfile) is hosted on Docker Hub: https://hub.docker.com/r/reacherhq/backend.

To run it, run the following command:

```bash
docker run -p 8080:8080 reacherhq/backend:latest
```

Then send a `POST http://localhost:8080/v0/check_email` request with the following body:

```js
{
    "to_email": "someone@gmail.com",
    "proxy": {                        // (optional) SOCK5 proxy to run the verification through, default is empty
        "host": "my-proxy.io",
        "port": 1080,
        "username": "me",             // (optional) Proxy username
        "password": "pass"            // (optional) Proxy password
    },
}
```

## Configuration

The backend is configured via its [`backend_config.toml`](./backend_config.toml) file.

## API Documentation

See the full [OpenAPI documentation](https://docs.reacher.email/advanced/openapi).

## Build From Source

You can build the backend from source to generate a binary, and run the server locally on your machine. First, [install Rust](https://www.rust-lang.org/tools/install); you'll need Rust 1.37.0 or later. Make sure `openssl` is installed too. Then, run the following commands:

```bash
# Download the code
$ git clone https://github.com/reacherhq/check-if-email-exists
$ cd check-if-email-exists/backend

# Run the backend binary in release mode (slower build, but more performant).
$ cargo run --release --bin reacher_backend
```

The server will then be listening on `http://127.0.0.1:8080`.

---

### Overview (`cli/README.md`)

<br /><br /><br />

<h1 align="center">check-if-email-exists CLI</h1>
<h4 align="center">Email verification from your terminal.</h4>

<br /><br /><br />

> Note: The CLI binary doesn't connect to any backend, it checks the email directly from your computer.

## Usage

Head to the [releases page](https://github.com/reacherhq/check-if-email-exists/releases) and download the binary for your platform.

Then run:

```
/* Detailed source-code truncated for AI context efficiency. */
```

**💡 PRO TIP:** To show debug logs when running the binary, run:

```bash
RUST_LOG=debug check_if_email_exists
```

## Build From Source

First, [install Rust](https://www.rust-lang.org/tools/install); you'll need Rust 1.37.0 or later. Then, run the following commands:

```bash
# Download the code
$ git clone https://github.com/reacherhq/check-if-email-exists
$ cd check-if-email-exists

# Build in release mode
$ cargo build --release

# Run the binary
$ ./target/release/check_if_email_exists --help
```

## Legacy Bash Script

The 1st version of this tool was a simple bash script that made a telnet call. If you would like to use that simpler version, have a look at the [`legacy`](https://github.com/reacherhq/check-if-email-exists/tree/legacy) branch. The reasons for porting the bash script to the current codebase are explained [in issue #4](https://github.com/reacherhq/check-if-email-exists/issues/4).

---

### Overview (`docs/README.md`)

---
cover: .gitbook/assets/docs_cover.jpg
coverY: 0
layout:
  cover:
    visible: true
    size: full
  title:
    visible: true
  description:
    visible: false
  tableOfContents:
    visible: true
  outline:
    visible: true
  pagination:
    visible: true
---

# Welcome to Reacher

Reacher is an open-source email verification API.

You can use Reacher to ensure the deliverability of your emails, clean your email lists, and prevent bounces. The API supports both individual email checks and bulk verification processes.

### Jump right in

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Getting Started</strong></td><td>Verify your 1st email</td><td><a href=".gitbook/assets/undraw_Mail_sent_re_0ofv.png">undraw_Mail_sent_re_0ofv.png</a></td><td></td><td><a href="getting-started/quickstart.md">quickstart.md</a></td></tr><tr><td><strong>Self-Hosting</strong></td><td>Install Reacher in 20 min</td><td><a href=".gitbook/assets/undraw_Server_re_twwj.png">undraw_Server_re_twwj.png</a></td><td></td><td><a href="self-hosting/install.md">install.md</a></td></tr><tr><td><strong>Proxies</strong></td><td>Verify emails using a proxy</td><td><a href=".gitbook/assets/undraw_online_transactions_02ka.png">undraw_online_transactions_02ka.png</a></td><td></td><td><a href="self-hosting/proxies/">proxies</a></td></tr></tbody></table>

---

### Overview (`sqs/README.md`)

# SQS

## Build Docker

```bash
make docker_deploy
```

---

### Overview (`backend/migrations/README.md`)

# Database and Migrations

## Migrations

All migrations in this folder are embedded directly in the `reacher_backend` binary, so you don't need to run the migrations manually.

The migrations come from 2 sources:

-   `sqlxmq` migrations
-   Reacher's own migrations

## `sqlxmq` migrations

The following migration files have been copied from the [sqlxmq repo](https://github.com/Diggsey/sqlxmq) as per the [given instructions](https://github.com/Diggsey/sqlxmq/blob/6d3ed6fb99e7592e370a7f3ec074ce0bebae62fd/README.md?plain=1#L111):

-   `20210316025847_setup.{up,down}.sql`
-   `20210921115907_clear.{up,down}.sql`
-   `20211013151757_fix_mq_latest_message.{up,down}.sql`
-   `20220208120856_fix_concurrent_poll.{up,down}.sql`
-   `20220713122907_fix-clear_all-keep-nil-message.{up,down}.sql`

## Reacher migrations

The following migrations are specific to Reacher:

-   `20220117025847_email_data.{up,down}.sql`: set up the `bulk_jobs` and `email_results` tables
-   `20220810141100_result_created_at.{up,down}.sql`: add a `created_at` column on `email_result`

## Advanced Usage

For more advanced usage (such as reverting to an old state), please use the `sqlx` CLI command.

See https://github.com/launchbadge/sqlx/blob/main/sqlx-cli/README.md

---

### Overview (`backend/tests/README.md`)

# Integration Tests

Files in this folder are Reacher backend's integration tests. They need the following to work:

-   a working internet connection.

---

### Overview (`docs/advanced/migrations/README.md`)

# Migrations

* [migrating-from-0.7-to-0.10-beta.md](migrating-from-0.7-to-0.10-beta.md "mention")

---

### Overview (`docs/advanced/openapi/README.md`)

# OpenAPI

* [v0-check\_email.md](v0-check_email.md "mention")
* [v1-check\_email.md](v1-check_email.md "mention")
* [v1-bulk.md](v1-bulk.md "mention")

---

### Overview (`docs/self-hosting/licensing/README.md`)

---
description: Is Reacher open-source? Can I use it in my commercial product?
---

# Licensing

## Yes, Reacher is Open-Source

Reacher is open-source and distributed under the [**MIT License**](https://github.com/reacherhq/check-if-email-exists/blob/master/LICENSE.md). You are free to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of Reacher, including as part of proprietary software or commercial services, as long as the copyright notice and license text are included.

The full license text is available in the [LICENSE.md](https://github.com/reacherhq/check-if-email-exists/blob/master/LICENSE.md) file of the repository.

---

### Overview (`docs/self-hosting/proxies/README.md`)

# Proxies

Maintaining a good IP reputation is hard. Reacher integrates seamlessly with SOCKS5 proxies.

## What is a SOCKS5 Proxy?

A **SOCKS5 proxy** is a flexible proxy protocol that supports various types of traffic, including SMTP. When using it for email verifications, the reputation of the **proxy’s IP** is what matters, not your own IP. This is crucial for maintaining deliverability and avoiding issues like blacklisting.

Choosing a reputable 3rd-party proxy will greatly improve the quality of your email verification results. For a list of recommended proxies, see [#which-3rd-party-proxies-does-reacher-recommend](./#which-3rd-party-proxies-does-reacher-recommend "mention")

{% hint style="info" %}
SMTP email verifications are not possible via a traditional HTTP proxy.
{% endhint %}

## Setting up a Proxy

Once you've purchased a proxy, run the Docker command (see how in [install.md](../install.md "mention")) and pass the following flags:

* `-e RCH__PROXY__HOST=<host>`: The IP or hostname of the proxy server.
* `-e RCH__PROXY__PORT=<port>`: The corresponding port.
* `-e RCH__PROXY__USERNAME=<username>`: Optional. A username to authenticate the proxy.
* `-e RCH__PROXY__PASSWORD=<password>`: Optional. The corresponding password.
* `-e RCH__HELLO_NAME=<domain>`: The identifier to use during the "HELO/EHLO" step. It should match a domain name owned by the proxy. Ask your proxy provider about this setting.
* `-e RCH__FROM_EMAIL=<email>`: The email to use during the "MAIL FROM" step. It should be an email from the same domain as the HELLO\_NAME. Ask your proxy provider about this setting.

{% hint style="info" %}
For advanced usage, you can configure [multiple-proxies.md](multiple-proxies.md "mention").
{% endhint %}

## Which 3rd-party proxies does Reacher recommend?

Reacher has been working closely with [Proxy4Smtp](https://www.proxy4smtp.com) since early 2024. The service is run by Jon, an email verification expert who has had over 10 years experience in the industry. He understands the complications and challenges that arise from large scale SMTP connections. His proxies integrate seamlessly with Reacher, and are tailored for B2B emails.

Ask [amaury@reacher.email](https://app.gitbook.com/u/F1LnsqPFtfUEGlcILLswbbp5cgk2 "mention") for an introduction to Jon.

---

### Overview (`docs/self-hosting/scaling-for-production/README.md`)

# Scaling for Production

Reacher's stateless architecture enables efficient horizontal scaling, allowing companies to tailor deployments to their specific needs. Below are the scaling options and pathways for a production setup.

1. [option-1-manage-scaling-yourself.md](option-1-manage-scaling-yourself.md "mention"): Leverage Reacher's statelessness and decide yourself how to deploy Reacher.
2. [option-2-rabbitmq-based-queue-architecture.md](option-2-rabbitmq-based-queue-architecture.md "mention"): Reacher includes a pre-integrated queue system based on [**RabbitMQ**](https://rabbitmq.com), enabling efficient task management and scaling.
3. Option 2: AWS SQS + Lambda (coming soon... or ask [amaury@reacher.email](https://app.gitbook.com/u/F1LnsqPFtfUEGlcILLswbbp5cgk2 "mention"))

Alternative scaling solutions were also explored, chat with [amaury@reacher.email](https://app.gitbook.com/u/F1LnsqPFtfUEGlcILLswbbp5cgk2 "mention") if you want to discuss more.

{% hint style="info" %}
For a high-volume setup, you will most likely need to purchase 3rd-party proxy IPs, see [proxies](../proxies/ "mention").
{% endhint %}

---

### Getting Started Quickstart (`docs/getting-started/quickstart.md`)

# Verify your 1st email

There are two ways to verify an email with Reacher:

1. Using the Reacher Dashboard (quick & easy).
2. Using the Reacher API (more advanced and powerful).

## 1. Using the Reacher Dashboard

The easiest way to verify an email verification is to create a free account on [https://app.reacher.email](https://app.reacher.email).

Then simply input the email address you want to verify, and click on the "Verify" button:

<figure><img src="../.gitbook/assets/Screenshot 2024-09-18 at 23.36.27.png" alt=""><figcaption><p>A screenshot of the Reacher Dashboard</p></figcaption></figure>

You will get a response with an "`is_reachable`" field, which can take on of the four values: `safe`, `invalid`, `risky` or `unknown`. You can learn more about these 4 values in [is-reachable.md](is-reachable.md "mention").

## 2. Using the Reacher API

{% hint style="info" %}
If you do not know what an API is, you can skip to the next page about [is-reachable.md](is-reachable.md "mention").
{% endhint %}

While the Reacher Dashboard offers a simple way to start verifying emails, the true potential of Reacher lies in its API. Through the API, you can integrate Reacher with your own applications, link it to platforms like Mailchimp or HubSpot, or even sync it with a CRM system.

After creating an account on [https://app.reacher.email](https://app.reacher.email), you will receive an unique API token. You can then run the following `curl` command in your terminal:

```bash
curl -X POST \
    https://api.reacher.email/v0/check_email \
    -H 'content-type: application/json' \
      -H 'authorization: <YOUR_API_TOKEN>' \
      -d '{"to_email": "amaury@reacher.email"}'
```

```json
// Output:
{
    "input":"amaury@reacher.email",
    "is_reachable":"safe",
    // --snip--
}
```

---

### SUMMARY (`docs/SUMMARY.md`)

# Table of contents

* [Welcome to Reacher](README.md)

## Getting Started

* [Verify your 1st email](getting-started/quickstart.md)
* [Understanding "is\_reachable"](getting-started/is-reachable.md)

## Self-Hosting

* [SaaS vs Self-Host](self-hosting/saas-vs-self-host.md)
* [Install Reacher in 20min](self-hosting/install.md)
* [Scaling for Production](self-hosting/scaling-for-production/README.md)
  * [Manage scaling yourself](self-hosting/scaling-for-production/option-1-manage-scaling-yourself.md)
  * [Option 1: RabbitMQ-based Queue Architecture](self-hosting/scaling-for-production/option-2-rabbitmq-based-queue-architecture.md)
* [Licensing](self-hosting/licensing/README.md)
* [Proxies](self-hosting/proxies/README.md)
  * [Multiple Proxies](self-hosting/proxies/multiple-proxies.md)
* [Reacher Configuration](self-hosting/reacher-configuration-v0.10.md)
* [Debugging Reacher](self-hosting/debugging-reacher.md)

## Advanced

* [OpenAPI](advanced/openapi/README.md)
  * [/v0/check\_email](advanced/openapi/v0-check_email.md)
  * [/v1/check\_email](advanced/openapi/v1-check_email.md)
  * [/v1/bulk](advanced/openapi/v1-bulk.md)
* [Run your own Proxy](advanced/run-your-own-proxy.md)
* [Migrations](advanced/migrations/README.md)
  * [Reacher Configuration (v0.10)](advanced/migrations/reacher-configuration-v0.10.md)
  * [Migrating from 0.7 to 0.10](advanced/migrations/migrating-from-0.7-to-0.10-beta.md)
  * [Bulk Verification (v0.7)](advanced/migrations/bulk.md)
  * [Docker Environment Variables (v0.7)](advanced/migrations/docker-environment-variables.md)

---

### Advanced Run Your Own Proxy (`docs/advanced/run-your-own-proxy.md`)

# Run your own Proxy

Reacher integrates seamlessy with [proxies](../self-hosting/proxies/ "mention"), and we propose some 3rd-party proxies to use. However, you may also choose to run your own Proxy.

If you're interested in this feature, please contact [amaury@reacher.email](https://app.gitbook.com/u/F1LnsqPFtfUEGlcILLswbbp5cgk2 "mention").

---

### Getting Started Is Reachable (`docs/getting-started/is-reachable.md`)

# Understanding "is\_reachable"

## `is_reachable`?

Reacher provides a confidence score for how likely an email is to be delivered. This score is shown in the `is_reachable` field and can have four values:

* **`safe`**: This email is very likely to be delivered (bounce rate below 2%). Some bounces may still rarely occur due to IP blacklisting.
* **`invalid`**: This email will almost certainly not be delivered.
* **`risky`**: The email exists but may have problems that could cause issues like bounces or low engagement. These could be:
  * A temporary (disposable) email
  * A shared account (e.g., support@ or admin@)
  * A catch-all address (accepts all emails for a domain)
  * A full inbox
* **`unknown`**: Sometimes, the email provider blocks our real-time verification, so we can’t determine deliverability. If you encounter this, let me know by email at amaury@reacher.email. I'm constantly working on ways to fix these issues case-by-case.

## Full Response

The full response contains more details about the email verification. It is provided in the following JSON format, with each field offering relevant information about the email deliverability.

```
/* Detailed source-code truncated for AI context efficiency. */
```

You can also check the [openapi](../advanced/openapi/ "mention")specification.

---

### Self Hosting Debugging Reacher (`docs/self-hosting/debugging-reacher.md`)

# Debugging Reacher

## How to debug Reacher?&#x20;

The reflex to have when debugging Reacher is to set the `-e RUST_LOG=debug` flag to Docker. This will show all debug logs useful to pinpoint where the error happened.

If you still don't understand the error after setting that flag, send an email to [amaury@reacher.email](https://app.gitbook.com/u/F1LnsqPFtfUEGlcILLswbbp5cgk2 "mention") along with those debug logs.

## How to check if port 25 is open?

{% hint style="info" %}
This only concerns users installing Reacher on a server without using [proxies](proxies/ "mention").&#x20;
{% endhint %}

When choosing a server to install Reacher on, you need to make sure that the server itself has port `25` open AND the chosen cloud provider allows outbound port `25` connections on its network.

To test this, there are two methods:

1. `curl` (try this first)
2. `telnet` (more advanced)

#### 1. Test port 25 with `curl`

Paste the following command in the shell of your server.

```bash
curl -sSf --verbose -k smtp://alt1.gmail-smtp-in.l.google.com:25 --ssl-reqd --mail-from test@gmail.com --mail-rcpt test@gmail.com
```

<details>

<summary>✅ Here's the expected output when port 25 works:</summary>

```
/* Detailed source-code truncated for AI context efficiency. */
```

</details>

#### 2. Test port 25 with `telnet`

Paste the following command in the shell of your server.

```bash
telnet alt1.gmail-smtp-in.l.google.com 25
```

<details>

<summary>✅ Click to see expected output when port 25 is open:</summary>

```bash
# This means that connection to port 25 on Google's server is established.
Trying 142.250.153.26...
Connected to alt1.gmail-smtp-in.l.google.com.
Escape character is '^]'.
220 mx.google.com ESMTP t2-20020a056402524200b0041d70e3a2b0si10608932edd.55 - gsmtp
# You can type 'QUIT' to quit this prompt
```

</details>

<details>

<summary>❌ Click to see unsuccessful output:</summary>

```bash
Trying 142.250.153.26...
# This step can hang for a couple of seconds...
telnet: Unable to connect to remote host: Connection refused
```

</details>

## **Which cloud providers have port 25 open?**

Here are details about some of the most well-known providers:

* :warning: AWS: Needs an application to open port 25, link to [apply](https://aws.amazon.com/premiumsupport/knowledge-center/ec2-port-25-throttle/) (Dec 2020).
* :warning: Digital Ocean: Your account needs to be 60d old, then you can [apply](https://www.digitalocean.com/community/questions/how-i-can-open-port-25-please?answer=67100) to open port 25 (Mar 2020).
* ❌ GCP: Port 25 closed, [source](https://cloud.google.com/compute/docs/tutorials/sending-mail).
* ❌ Heroku: Starting from July 2021, Heroku blocks port 25 intermittently according to [this document](https://help.heroku.com/IR3S6I5X/problem-in-sending-e-mails-through-smtp).
* :warning: Hetzner: Port 25 open according to [unofficial source](https://www.reddit.com/r/hetzner/comments/lb2o13/does_hetzner_block_port_25/) (Feb 2021), but seems now that you need to request manually.
* :warning: Linode: Port 25 closed for new accounts, but can be opened if reverse DNS is set up correctly, [source](https://www.linode.com/docs/guides/running-a-mail-server/#sending-email-on-linode=) (Apr 2022).
* :white\_check\_mark: OVH: Port 25 open on new instances, but outbound port 25 traffic is monitored to prevent spam (May 2022).
* :warning: Vultr: Create support ticket to open port 25, [source](https://www.vultr.com/docs/what-ports-are-blocked/), though [recent reports](https://github.com/LukeSmithxyz/emailwiz/issues/172) (May 2022) show that they won’t do it anymore.

## **How can I debug `"is_reachable": "unknown"`?**

In most cases, if you have a `TimeoutError`, it means that port 25 is closed. Refer to the questions above about opening port 25.

In other cases, you can enable the `RUST_LOG=debug` environment variable on your server or on your Docker container. Then, by looking at the logs when performing an email verification, you can debug why `is_reachable` is unknown. Some example of logs you might find:

*   IP Blacklisted:

    `5.7.1 Service unavailable; Client host [<YOUR_IP>] is blacklisted. Visit https://www.sophos.com/en-us/threat-center/ip-lookup.aspx?ip=<YOUR_IP> to request delisting`
* Your `FROM` field does not match the reverse DNS\
  `(mxgmx117) Nemesis ESMTP Service not available; No SMTP service;`

## Contact me

If you encounter any issue that you don't know how to solve, simply send me an email to [amaury@reacher.email](https://app.gitbook.com/u/F1LnsqPFtfUEGlcILLswbbp5cgk2 "mention").

---

### Self Hosting Install (`docs/self-hosting/install.md`)

# Install Reacher in 20min

Reacher is designed for seamless self-hosting, giving you full control over its operation on your infrastructure. This guide demonstrates how to install and run Reacher on your local computer in under 20 minutes, using the official [Docker image](https://hub.docker.com/r/reacherhq/backend).

## Prerequisites

* Docker installed on your system (follow the [Docker installation guide](https://docs.docker.com/get-docker/) for your OS).

## Tutorial Scope: Install Reacher on your local computer

Reacher’s stateless architecture enables easy horizontal scaling by deploying multiple containers, each running a Reacher instance for parallel email verifications. However, for simplicity, this tutorial focuses on a local installation. A further section focuses on [scaling-for-production](scaling-for-production/ "mention").

{% hint style="warning" %}
Reacher performs SMTP verifications over port 25. Many ISPs and cloud providers block outgoing requests on port 25, in which case you'll need to configure a proxy, see [proxies](proxies/ "mention").
{% endhint %}

## Step-by-Step Tutorial

1. Run Reacher's latest [Docker image](https://hub.docker.com/r/reacherhq/backend):

```bash
docker run -p 8080:8080 reacherhq/backend:latest
```

Expected output:

```bash
2024-09-19T12:58:32.918254Z  INFO reacher: Running Reacher version="0.10.0"
Starting ChromeDriver 124.0.6367.78 (a087f2dd364ddd58b9c016ef1bf563d2bc138711-refs/branch-heads/6367@{#954}) on port 9515
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
2024-09-19T12:58:32.976589Z  INFO reacher: Server is listening host=0.0.0.0 port=80
```

If you see errors, either try [debugging-reacher.md](debugging-reacher.md "mention") or send an email to [amaury@reacher.email](https://app.gitbook.com/u/F1LnsqPFtfUEGlcILLswbbp5cgk2 "mention").

Advanced users can also set additional [reacher-configuration-v0.10.md](reacher-configuration-v0.10.md "mention").

2. Verify an email by running the following command in another terminal.

<pre class="language-bash"><code class="lang-bash"><strong>curl -X POST \
</strong>	-H'Content-Type: application/json' \
	-d'{"to_email":"amaury@reacher.email"}' \
	http://localhost:8080/v1/check_email
</code></pre>

Advanced users can pass additional configuration fields to the  [v1-check\_email.md](../advanced/openapi/v1-check_email.md "mention") endpoint.

3. If successful, you'll see JSON object with an `is_reachable` field.

```json
{
    "input": "amaury@reacher.email",
    "is_reachable": "safe",
    // --snip--
}
```

You can read more about all the fields in [is-reachable.md](../getting-started/is-reachable.md "mention").

{% hint style="warning" %}
If this step hangs for a long time, or returns a JSON result with `is_reachable="unknown"`, see [debugging-reacher.md](debugging-reacher.md "mention")on how to fix this.
{% endhint %}

If you go back to check the terminal with the Docker command, you should see corresponding logs:

```log
// --snip--
2024-12-15T11:33:36.169891Z  INFO reacher: Starting verification email="amaury@reacher.email"
2024-12-15T11:33:45.015130Z  INFO reacher: Done verification email="amaury@reacher.email" is_reachable=Safe
```

Congratulations! You just successfully verified an email from your computer. Now it's time to think about [scaling-for-production](scaling-for-production/ "mention").

## Troubleshooting

If you have any issue in one of the steps above, you can try [debugging-reacher.md](debugging-reacher.md "mention")yourself, or send me an email [amaury@reacher.email](https://app.gitbook.com/u/F1LnsqPFtfUEGlcILLswbbp5cgk2 "mention").

---

### Self Hosting Reacher Configuration V0.10 (`docs/self-hosting/reacher-configuration-v0.10.md`)

# Reacher Configuration

{% hint style="info" %}
This configuration is for the current 0.11 version. For the older versions, please see:

* [reacher-configuration-v0.10.md](../advanced/migrations/reacher-configuration-v0.10.md "mention")
* [docker-environment-variables.md](../advanced/migrations/docker-environment-variables.md "mention").
{% endhint %}

You can find below the exhaustive list of configurable parameters to optimize Reacher.

To tweak a configuration, look at the "Env variable" name in the comments, and pass in the `-e ENV_VAR=VALUE` flag to Docker. See [#examples-with-docker](reacher-configuration-v0.10.md#examples-with-docker "mention").

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Examples with Docker

To overwrite the EHLO/HELO name:

```bash
docker run -e RCH__HELLO_NAME=my.company.com -p 8080:8080 reacherhq/backend:beta
```

To store all email verification results to a Postgres database:

```bash
docker run -e RCH__STORAGE__POSTGRES__DB_URL="postgres://user:pass@mydomain.mycompany.com/my_db_name" -p 8080:8080 reacherhq/backend:beta
```

For advanced users, if you prefer to pass in the full [`backend_config.toml`](../../backend/backend_config.toml) file instead of individual environment variable flags, run:

```bash
docker run -e RUST_LOG=reacher=debug -v /path/to/local/backend_config.toml:./backend_config.toml -p 8080:8080 reacherhq/backend:beta
```

We recommend passing in `-e RUST_LOG=reacher=debug`, at least on first run, as the debug logs will show the final configuration parsed by Reacher.

---

### Self Hosting Saas Vs Self Host (`docs/self-hosting/saas-vs-self-host.md`)

# SaaS vs Self-Host

When using Reacher, you can choose between two options: the SaaS version hosted by Reacher or self-hosting the service on your infrastructure. Each option offers distinct advantages depending on your needs, technical resources, and desired level of control.

## What is Reacher SaaS?

Reacher SaaS is the cloud-hosted version of the service, accessible at [https://app.reacher.email](https://app.reacher.email). It handles all infrastructure, updates, and scaling for you. You can verify emails directly via the Reacher Dashboard without managing technical details.

## What is Self-Hosting Reacher?

Reacher is also available for self-hosting, enabling you to run the service on your own servers. This approach provides full control over the environment and data while leveraging the same verification engine as Reacher SaaS. Reacher is designed to make self-hosting straightforward and efficient.

{% hint style="success" %}
Reacher's goal is to make Self-Hosting easy. You can [install.md](install.md "mention").
{% endhint %}

## Key Differences

| Feature               | SaaS                                   | Self-Hosting                                                                              |
| --------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------- |
| **Volume**            | Limited to 10k verifications per month | Unlimited verifications                                                                   |
| **Cost**              | Monthly subscription                   | Free (MIT License) + server costs + [proxy](proxies/) costs (optional)                    |
| **Setup Time**        | Instant                                | Requires installation and setup                                                           |
| **Maintenance**       | Fully managed by Reacher               | Managed by your IT team                                                                   |
| **Data Ownership**    | Data stored on Reacher servers         | Full ownership, no data is sent to Reacher                                                |
| **Bulk Verification** | Not supported                          | Supported, see [bulk.md](../advanced/migrations/bulk.md "mention")                        |

---

### Advanced Migrations Bulk (`docs/advanced/migrations/bulk.md`)

# Bulk Verification (v0.7)

The default Reacher API only exposes one endpoint, `/v0/check_email`, which allows verifying one email at a time. The optional Bulk Verification API allows you to queue up a list of emails in one go.

## Prerequisites

* A self-hosted setup, see [install.md](../../self-hosting/install.md "mention").
* A PostgreSQL database, you can start for free with [Supabase](https://supabase.com/) (no affiliation).

## Get Started

When running the Reacher backend, set two new environment variables:

* `RCH_ENABLE_BULK=1`
* `DATABASE_URL=<your_postgres_db>`

For example, if running with docker, run

```bash
docker run \
	-e RCH_ENABLE_BULK=1 \
	-e DATABASE_URL=<your_postgres_db> \
	# Other flags
	reacherhq/backend:v0.7.0
```

The `DATABASE_URL` value should look like `postgres://<user>:<password>@<hostname>/<db_name>`.You should see the backend running with the following logs:

```bash
[2022-08-15T19:54:23Z INFO  reacher] Running Reacher v0.7.0
[2022-08-15T19:54:23Z INFO  reacher] Bulk endpoints enabled.
Server is listening on 0.0.0.0:8080.
```

## How does Bulk email verification work?

<figure><img src="https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2F8fc90893-c1e2-426b-8b22-6e4e323244db%2F3fff2c3e-e65f-4306-abbd-b4037760b517%2Fbulk.svg%3Ftable%3Dblock%26id%3D2090bf73-99bb-462b-90f2-57b0af6733ab%26spaceId%3D8fc90893-c1e2-426b-8b22-6e4e323244db%26expirationTimestamp%3D1726833600000%26signature%3DCMRYdgntz2SsZnL8Krlve4pJS6mUB666K64SV9CiTHM?table=block&#x26;id=2090bf73-99bb-462b-90f2-57b0af6733ab&#x26;cache=v2" alt="Flow chart describing the bulk verification process."><figcaption><p>Flow chart describing the bulk verification process.</p></figcaption></figure>

Bulk email verification is done in 3 steps:

#### **1. Submit a list of emails: `POST /v0/bulk`**

The body of the request contains the list of emails, as well as a couple of configuration options.

```json
{
    // Required fields:
    "input_type": "array",             // Must be "array". Future versions might allow CSV uploading.
    "input": [                         // Endpoint accepts a list of emails.
        "support@reacher.email",
        "invalid@reacher.email"
    ],

    // All fields below are optional:
    "proxy": {
        "host": "my.proxy.com",
        "port": 9080,
        "username": "user",           // Optional authentication for proxy.
        "password": "pass",
    },
    "hello_name": "my.domain.com",    // The value to use in the EHLO handshake.
    "from_email": "me@my.domain.com", // The value to use in the MAIL FROM command.
    "smtp_ports": [25, 587]           // List of SMT ports to try for each email, in given order. Defaults to [25].
}
```

If successful, this endpoint will return a unique job ID, used to track the progress of the bulk verification job and fetch its results.

```json
{
    "job_id": 150970
}
```

#### **2. Verify the status of the job: `GET /v0/bulk/{job_id}`**

If the list of emails is long, then the bulk verification job can take some time. Ping regularly on the endpoint above to see the status of the job.When the job is still running, the `job_status` will be `Running`:

```json
{
    "job_id": 150970,                            // From previous step.
    "created_at": "2017-04-15T20:00:06:00.000Z", // Start time of the job.
    "finished_at": null,                         // Stays `null` as long as job is still running.
    "total_records": 24606,
    "total_processed": 10,                       // Shows job progress.
    "summary": {                                 // Summary of the list's health.
        "total_safe": 5,
        "total_invalid": 2,
        "total_risky": 2,
        "total_unknown": 1
    },
    "job_status": "Running"                      // Wait for "Completed".
}
```

And when the job is finished, we get `job_status = Completed`, and the `finished_at` field will be populated with the job’s end time.

#### **3. Download the job results: `GET /v0/bulk/{job_id}/results`**

Once the `job_status` field in from the previous step is `Completed`, this endpoint will show the results of all the emails in the list.

```json
{
    "results": [
		  {
          "input": "someone@gmail.com",
          "is_reachable": "risky",
          // --snip: all fields--
      },
      // --snip: other results--
    ]
}
```

To avoid returning a huge JSON payload, the `results` array by default only returns the first 50 email results. We recommend using pagination on the client side, using the 2 following query parameters:

* `?offset=<n>`: The offset from which we return the results, which is equivalent to the number of elements in the array to skip. Defaults to `0`.
* `?limit=<n>`: The number of results to return. Defaults to `50`.

For example, if your initial input has 100 emails to verify, and you want the results for emails #61-#70, you should add the query parameters: `GET /v0/bulk/{job_id}/results?offset=60&limit=10`.

{% hint style="success" %}
Pro Tip: You can also download the results as CSV, by passing the `?format=csv` query paramter: `GET /v0/bulk/{job_id}/results?format=csv`.
{% endhint %}

## Questions?

This Bulk email verification feature is still new, so feel free to send me an email [amaury@reacher.email](https://app.gitbook.com/u/F1LnsqPFtfUEGlcILLswbbp5cgk2 "mention").

---

### Advanced Migrations Docker Environment Variables (`docs/advanced/migrations/docker-environment-variables.md`)

# Docker Environment Variables (v0.7)

{% hint style="info" %}
This page only applies to Reacher version 0.7. For the `beta` v0.10 version, see [reacher-configuration-v0.10.md](../../self-hosting/reacher-configuration-v0.10.md "mention").
{% endhint %}

Reacher's software is available on [Docker Hub](https://hub.docker.com/r/reacherhq/backend/tags). You can get started using the default parameters:

```bash
docker run -p 8080:8080 reacherhq/backend:latest
```

Below are the environment variables used to configure the HTTP server. To pass them to the Docker container, use the `-e {ENV_VAR}={VALUE}` flag.

<table><thead><tr><th width="220">Env Var</th><th width="107">Required?</th><th width="264">Description</th><th>Default</th></tr></thead><tbody><tr><td><code>RUST_LOG</code></td><td>No</td><td>One of <code>trace,debug,warn,error,info</code>. <code>RUST_LOG=debug</code> is very handful for debugging purposes.</td><td><code>info</code></td></tr><tr><td><code>RCH_HTTP_HOST</code></td><td>No</td><td>The host name to bind the HTTP server to.</td><td><code>0.0.0.0</code></td></tr><tr><td><code>PORT</code></td><td>No</td><td>The port to bind the HTTP server to, often populated by the cloud provider.</td><td><code>8080</code></td></tr><tr><td><code>RCH_SENTRY_DSN</code></td><td>No</td><td>If set, bug reports will be sent to this <a href="https://sentry.io">Sentry</a> DSN.</td><td>not defined</td></tr><tr><td><code>RCH_HEADER_SECRET</code></td><td>No</td><td>If set, then all HTTP requests must have the <code>x-reacher-secret</code> header set to this value. This is used to protect the backend against public unwanted HTTP requests.</td><td>undefined</td></tr><tr><td><code>RCH_FROM_EMAIL</code></td><td>No</td><td>Email to use in the <code>&#x3C;MAIL FROM:></code> SMTP step. Can be overwritten by each API request's <code>from_email</code> field.</td><td><a href="mailto:reacher.email@gmail.com">reacher.email@gmail.com</a></td></tr><tr><td><code>RCH_HELLO_NAME</code></td><td>No</td><td>Name to use in the <code>&#x3C;EHLO></code> SMTP step. Can be overwritten by each API request's <code>hello_name</code> field.</td><td>gmail.com</td></tr><tr><td><code>RCH_SMTP_TIMEOUT</code></td><td>No</td><td>Timeout for each SMTP connection.</td><td>45s</td></tr><tr><td><code>RCH_WEBDRIVER_ADDR</code></td><td>No</td><td>Set to a running WebDriver process endpoint (e.g. <code>http://localhost:9515</code>) to use a headless navigator to password recovery pages to check Yahoo and Hotmail/Outlook addresses. We recommend <code>chromedriver</code> as it allows parallel requests.</td><td><code>http://localhost:9515</code></td></tr><tr><td><strong>For Bulk Verification:</strong></td><td></td><td></td><td></td></tr><tr><td><code>RCH_ENABLE_BULK</code></td><td>No</td><td>If set to <code>1</code>, then bulk verification endpoints will be added to the backend.</td><td>0</td></tr><tr><td><code>DATABASE_URL</code></td><td>Yes if <code>RCH_ENABLE_BULK==1</code></td><td>[Bulk] Database connection string for storing results and task queue</td><td>not defined</td></tr><tr><td><code>RCH_DATABASE_MAX_CONNECTIONS</code></td><td>No</td><td>[Bulk] Connections created for the database pool</td><td>5</td></tr><tr><td><code>RCH_MINIMUM_TASK_CONCURRENCY</code></td><td>No</td><td>[Bulk] Minimum number of concurrent running tasks below which more tasks are fetched</td><td>10</td></tr><tr><td><code>RCH_MAXIMUM_CONCURRENT_TASK_FETCH</code></td><td>No</td><td>[Bulk] Maximum number of tasks fetched at once</td><td>20</td></tr></tbody></table>

---

### Advanced Migrations Migrating From 0.7 To 0.10 Beta (`docs/advanced/migrations/migrating-from-0.7-to-0.10-beta.md`)

# Migrating from 0.7 to 0.10

Reacher v0.10 introduces the `/v1/*` endpoints, namely:

* `/v1/check_email`: Performs a single email verification while respecting the optional throttle and concurrency settings set in [reacher-configuration-v0.10.md](../../self-hosting/reacher-configuration-v0.10.md "mention").
* `/v1/bulk`, `/v1/bulk/{job_id}`, `/v1/bulk/{job_id}/results`: Create a bulk verification job, and query its progress and status. Docs coming soon.

The `/v0/check_email` endpoint **DOES NOT** change, neither in API nor in behavior. More specifically, even if you specify throttle and concurrency settings in the newly introduced Reacher Configuration, they will not be taken into account by the `/v0/check_email` endpoint, which will perform email verification as soon as it receives the request.

## Environment Variables

With the introduction of [reacher-configuration-v0.10.md](../../self-hosting/reacher-configuration-v0.10.md "mention"), some of the Environment Variables have changed names.

<table><thead><tr><th width="220">Old name</th><th width="211">New name</th><th width="264">Description</th></tr></thead><tbody><tr><td><code>RCH_HTTP_HOST</code></td><td><code>RCH__HTTP_HOST</code></td><td>The host name to bind the HTTP server to.</td></tr><tr><td><code>PORT</code></td><td><code>RCH__HTTP_PORT</code></td><td>The port to bind the HTTP server to, often populated by the cloud provider.</td></tr><tr><td><code>RCH_SENTRY_DSN</code></td><td><code>RCH__SENTRY_DSN</code></td><td>If set, bug reports will be sent to this <a href="https://sentry.io">Sentry</a> DSN.</td></tr><tr><td><code>RCH_HEADER_SECRET</code></td><td><code>RCH__HEADER_SECRET</code></td><td>If set, then all HTTP requests must have the <code>x-reacher-secret</code> header set to this value. This is used to protect the backend against public unwanted HTTP requests.</td></tr><tr><td><code>RCH_FROM_EMAIL</code></td><td><code>RCH__FROM_EMAIL</code></td><td>Email to use in the <code>&#x3C;MAIL FROM:></code> SMTP step. Can be overwritten by each API request's <code>from_email</code> field.</td></tr><tr><td><code>RCH_HELLO_NAME</code></td><td><code>RCH__HELLO_NAME</code></td><td>Name to use in the <code>&#x3C;EHLO></code> SMTP step. Can be overwritten by each API request's <code>hello_name</code> field.</td></tr><tr><td><code>RCH_SMTP_TIMEOUT</code></td><td><code>RCH__SMTP_TIMEOUT</code></td><td>Timeout for each SMTP connection.</td></tr><tr><td><code>RCH_WEBDRIVER_ADDR</code></td><td><code>RCH__WEBDRIVER_ADDR</code></td><td>Set to a running WebDriver process endpoint (e.g. <code>http://localhost:9515</code>) to use a headless navigator to password recovery pages to check Yahoo and Hotmail/Outlook addresses. We recommend <code>chromedriver</code> as it allows parallel requests.</td></tr><tr><td><strong>For Bulk Verification:</strong></td><td></td><td></td></tr><tr><td><code>RCH_ENABLE_BULK</code></td><td><code>RCH__WORKER__ENABLE</code></td><td></td></tr><tr><td><code>DATABASE_URL</code></td><td><code>RCH__WORKER__POSTGRES__DB_URL</code></td><td>[Bulk] Database connection string for storing results and task queue</td></tr><tr><td><code>RCH_DATABASE_MAX_CONNECTIONS</code></td><td>Removed</td><td>[Bulk] Connections created for the database pool</td></tr><tr><td><code>RCH_MINIMUM_TASK_CONCURRENCY</code></td><td>Removed</td><td>[Bulk] Minimum number of concurrent running tasks below which more tasks are fetched</td></tr><tr><td><code>RCH_MAXIMUM_CONCURRENT_TASK_FETCH</code></td><td>Removed</td><td>[Bulk] Maximum number of tasks fetched at once</td></tr></tbody></table>

## Bulk Verification

The `/v0/bulk` endpoints are deprecated, in favor of a RabbitMQ-based queue system. Docs for `/v1/bulk` endpoints are coming soon.

---

### Advanced Migrations Reacher Configuration V0.10 (`docs/advanced/migrations/reacher-configuration-v0.10.md`)

# Reacher Configuration (v0.10)

You can find below the exhaustive list of configurable parameters to optimize Reacher.

To tweak a configuration, look at the "Env variable" name in the comments, and pass in the `-e ENV_VAR=VALUE` flag to Docker. See [#examples-with-docker](reacher-configuration-v0.10.md#examples-with-docker "mention").

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Examples with Docker

To overwrite the EHLO/HELO name:

```bash
docker run -e RCH__HELLO_NAME=my.company.com -p 8080:8080 reacherhq/backend:beta
```

To store all email verification results to a Postgres database:

```bash
docker run -e RCH__STORAGE__POSTGRES__DB_URL="postgres://user:pass@mydomain.mycompany.com/my_db_name" -p 8080:8080 reacherhq/backend:beta
```

For advanced users, if you prefer to pass in the full [`backend_config.toml`](../../../backend/backend_config.toml) file instead of individual environment variable flags, run:

```bash
docker run -e RUST_LOG=reacher=debug -v /path/to/local/backend_config.toml:./backend_config.toml -p 8080:8080 reacherhq/backend:beta
```

We recommend passing in `-e RUST_LOG=reacher=debug`, at least on first run, as the debug logs will show the final configuration parsed by Reacher.

---

### Advanced Openapi V0 Check Email (`docs/advanced/openapi/v0-check_email.md`)

# /v0/check\_email

{% swagger src="https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json" path="/v0/check_email" method="post" %}
[https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json](https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json)
{% endswagger %}

---

### Advanced Openapi V1 Bulk (`docs/advanced/openapi/v1-bulk.md`)

# /v1/bulk

{% swagger src="https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json" path="/v1/bulk" method="post" %}
[https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json](https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json)
{% endswagger %}

{% swagger src="https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json" path="/v1/bulk/{job_id}" method="get" %}
[https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json](https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json)
{% endswagger %}

{% swagger src="https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json" path="/v1/bulk/{job_id}/results" method="get" %}
[https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json](https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json)
{% endswagger %}

---

### Advanced Openapi V1 Check Email (`docs/advanced/openapi/v1-check_email.md`)

# /v1/check\_email

{% swagger src="https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json" path="/v1/check_email" method="post" %}
[https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json](https://raw.githubusercontent.com/reacherhq/check-if-email-exists/refs/heads/master/backend/openapi.json)
{% endswagger %}

---

### Self Hosting Proxies Multiple Proxies (`docs/self-hosting/proxies/multiple-proxies.md`)

# Multiple Proxies

{% hint style="info" %}
This feature is only available starting from Reacher v0.11.0.
{% endhint %}

For advanced use cases, Reacher supports a routing mechanism to route email verification requests to different proxies depending on the MX host.

The configuration is divided in 2 steps:

1. Define a list of proxies. e.g. `"proxy1"`, `"proxy2"`etc., each with their configuration data.
2. Define routing rules, e.g. `route Gmail to "proxy1"`, `route Hotmail B2B to "proxy2"`etc...

### 1. Define a list of Proxies

The simple Reacher configuration allows to define a default proxy via the following environmental variables:

* `RCH__PROXY__HOST`: The hostname of the proxy.
* `RCH__PROXY__PORT`: The port of the proxy.
* `RCH__PROXY__USERNAME`: (Optional) A username for authentication.
* `RCH__PROXY__PASSWORD`: (Optional) A password for authentication.

On top of the default proxy, Reacher allows you to configure multiple other proxies:

* `RCH__OVERRIDES__PROXIES__{your-proxy-id-uppercase}__HOST`&#x20;
* `RCH__OVERRIDES__PROXIES__{your-proxy-id-uppercase}__PORT`&#x20;
* `RCH__OVERRIDES__PROXIES__{your-proxy-id-uppercase}__USERNAME`&#x20;
* `RCH__OVERRIDES__PROXIES__{your-proxy-id-uppercase}__PASSWORD`&#x20;

Replace `{your-proxy-id-uppercase}`with any unique name of your choosing. We recommend to use `PROXY1`, `PROXY2` for simplicity.

### 2. Define routing rules

Reacher allows to configure custom routing rules based on the MX host. To do so, set the following environment variables:

* `RCH__OVERRIDES__{email-provider}__TYPE=smtp`
* `RCH__OVERRIDES__{email-provider}__PROXY={your-proxy-id-lowercase}`

where you replace:

* `{email-provider}` with one of the following `GMAIL`, `HOTMAILB2B`, `HOTMAILB2C`, `PROOFPOINT`, `MIMECAST`, `YAHOO`.
* `{your-proxy-id-lowercase}` with one of the proxies you defined in step 1. Make sure to respect the lowercase here.

You can define multiple of these `RCH__OVERRIDES__`  environment variables for different MX hosts. All the remaining emails which don't match any of the overrides will go through the default proxy.

### Example

Below is a [Docker Compose](https://docs.docker.com/compose/) file showcasing:

* routing Gmail and Proofpoint emails to proxy1
* routing Hotmail B2B emails to proxy2
* routing everything else to the default proxy

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Self Hosting Scaling For Production Option 1 Manage Scaling Yourself (`docs/self-hosting/scaling-for-production/option-1-manage-scaling-yourself.md`)

# Manage scaling yourself

Reacher is stateless by design. This means that you can spawn instances of Reacher concurrently, and they don't need coordinate to perform email verifications.

However, in most cases, some coordination is desired. For example, when using a proxy, you might want to respect the proxy's concurrency and throttling limits to avoid seeing your connection refused.

The best scaling solution for you is the one that fits into your architecture. Below are several scaling solutions, including both traditional and advanced approaches. They are often not mutually exclusive.

#### 1. Install Reacher on dedicated servers (proxies optional).

* **Description**: Install Reacher on dedicated servers. This setup is straightforward and allows you to manage IP quality directly.
* **Pros**:
  * Complete control over IP maintenance (if desired).
  * Independence from 3rd-party proxies.
* **Cons**:
  * Limited scalability compared to cloud-based solutions.
  * Higher initial infrastructure cost.

#### 2. Pure serverless architecture.

* **Description**: Deploy Reacher as a stateless function using serverless platforms like AWS Lambda or Google Cloud Functions.
* **Pros**:
  * Infinite horizontal scaling.
  * No infrastructure management.
* **Cons**:
  * Complexity in managing rate-limiting and proxy usage (see those limits in [proxies](../proxies/ "mention")).
  * Higher cost for large-scale, constant usage.

#### 3. **Amazon SQS with Worker Instances.**

* **Description**: Use [Amazon SQS](https://aws.amazon.com/sqs/) (or similar message queues) to distribute email verification tasks to worker instances running Reacher.
* **Architecture**:
  * Task requests are queued in SQS (or another broker).
  * Reacher workers (Docker containers or serverless functions) poll the queue to process tasks.
* **Pros**:
  * Efficient task distribution.
  * Built-in concurrency control via SQS throttling.
* **Cons**:
  * Requires managing worker instances.

This solution is explor more in details in [option-2-rabbitmq-based-queue-architecture.md](option-2-rabbitmq-based-queue-architecture.md "mention"), using [RabbitMQ](https://rabbitmq.com) instead of Amazon SQS.

#### **4. Kubernetes (k8s) Clusters**

* **Description**: Run Reacher instances as pods within a Kubernetes cluster for high availability and scalability.
* **Architecture**:
  * Use Kubernetes' Horizontal Pod Autoscaler (HPA) to scale Reacher pods based on task load.
  * Integrate with RabbitMQ for task queuing and distribution (see [option-2-rabbitmq-based-queue-architecture.md](option-2-rabbitmq-based-queue-architecture.md "mention"))
* **Pros**:
  * Highly scalable and resilient.
  * Centralized monitoring and orchestration.
* **Cons**:
  * Higher operational complexity.
  * Requires Kubernetes expertise.

---

### Self Hosting Scaling For Production Option 2 Rabbitmq Based Queue Architecture (`docs/self-hosting/scaling-for-production/option-2-rabbitmq-based-queue-architecture.md`)

# Option 1: RabbitMQ-based Queue Architecture

Reacher includes an optional, opinionated queue-based architecture designed to scale efficiently and handle high email verification volumes. This architecture comprises 4 main components and is highly configurable to meet specific business needs.

<table><thead><tr><th width="183">Component</th><th width="295">Description</th><th>Docker image</th></tr></thead><tbody><tr><td><strong>HTTP server</strong></td><td>Accepts incoming email verification requests, and post them into the queue.</td><td><code>reacherhq/backend</code></td></tr><tr><td><a href="https://rabbitmq.com">RabbitMQ</a></td><td>Reacher uses a reliable, mature and open-source queue implementation.</td><td><code>rabbitmq:4.0-management</code></td></tr><tr><td><strong>Workers</strong></td><td>One or more consumers of the queue, which perform the actual email verification task.</td><td><code>reacherhq/backend</code></td></tr><tr><td><strong>Storage</strong></td><td>A place to store all results, currently only PostgresDB is supported.</td><td><code>postgres:14</code></td></tr></tbody></table>

Note that Reacher provides the same Docker image `reacherhq/backend` which can act as both a **Worker** and a **HTTP server**.

<figure><img src="../../.gitbook/assets/Screenshot 2024-11-30 at 15.33.27.png" alt=""><figcaption><p>Reacher queue architecture</p></figcaption></figure>

With this architecture, it's possible to horizontally scale the number of workers.

### Worker Configuration

#### **Enabling the Architecture**

To enable the worker-based architecture, configure the following parameters in your deployment. The parameters are given in their `backend_config.toml` format (e.g. `worker.enable`) as well as in the environment variable format (e.g. `RCH__WORKER__ENABLE`):

* `worker.enable` or `RCH__WORKER__ENABLE`: Set to `true` to activate the worker role.
* `worker.rabbitmq.url` or `RCH__WORKER__RABBITMQ__URL`: URL of the RabbitMQ instance for task queuing.
* `postgres.storage.postgres.db_url` or `RCH__STORAGE__POSTGRES__DB_URL`: URL of a PostgreSQL database to store verification results.

#### Using Proxies for Workers

Since spawning workers on cloud providers doesn't guarantee a reputable IP assigned to the worker, we configure all workers to use a proxy.

* `proxy.{host,port}` or `RCH__PROXY__{HOST,PORT}`: Set a proxy to route all SMTP requests through. You can optionally pass in `username` and `password` if required.

#### Optional Concurrency and Throttling Parameters

You may also configure the following parameters:

* **Concurrency**:
  * `worker.rabbitmq.concurrency`: Set to `5`. Each worker processes up to 5 emails concurrently.
* **Throttling**:
  * `throttle.max_requests_per_minute`: Set to `60`. Limits request spikes to prevent SMTP server flags.
  * `throttle.max_requests_per_day`: Set to `10,000`.&#x20;

## Understanding the architecture with Docker Compose

We do not recommend using Docker Compose for a high-volume production setup. However, for understanding or learning the architecture, this [`docker_compose.yaml`](../../../rabbitmq/docker-compose.yaml) file can be useful.

## More questions?

Contact [amaury@reacher.email](https://app.gitbook.com/u/F1LnsqPFtfUEGlcILLswbbp5cgk2 "mention")if you have more questions about this architecture, such as:

* deploying on Kubernetes (Ansible playbook, Pulumi)
* more specialized workers (e.g. some workers doing headless verification only, others doing SMTP only)

---

--- METRICS ---
- Files Extracted: 30
- Estimated Token Budget: ~16177 tokens
- Canonical Reference: https://codewiki.google/github.com/reacherhq/check-if-email-exists
