# 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="/files/OZyb4JkHMLcCeREUeSD4">/files/OZyb4JkHMLcCeREUeSD4</a></td><td></td><td><a href="/pages/CyH2xJQs9yWJ1S8BYNav">/pages/CyH2xJQs9yWJ1S8BYNav</a></td></tr><tr><td><strong>Self-Hosting</strong></td><td>Install Reacher in 20 min</td><td><a href="/files/1OPW954m3nNgcyjTQnWp">/files/1OPW954m3nNgcyjTQnWp</a></td><td></td><td><a href="/pages/cEHgDv7NGBquDGHeLyQ4">/pages/cEHgDv7NGBquDGHeLyQ4</a></td></tr><tr><td><strong>Proxies</strong></td><td>Verify emails using a proxy</td><td><a href="/files/8azqhEi7nUR6SpN1IWJ8">/files/8azqhEi7nUR6SpN1IWJ8</a></td><td></td><td><a href="/pages/QwHFLVleY7QejI9V4gc3">/pages/QwHFLVleY7QejI9V4gc3</a></td></tr></tbody></table>


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

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

<figure><img src="/files/t00fUNohgCS4Chw3tnlo" 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 [Understanding "is\_reachable"](/getting-started/is-reachable).

## 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 [Understanding "is\_reachable"](/getting-started/is-reachable).
{% 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>, 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--
}
```


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

```json
{
  // The input email address that was checked
  "input": "someone@gmail.com",
  
  // The deliverability status of the email (safe, risky, invalid or unknown)
  "is_reachable": "invalid",
  
  "misc": {
    // Indicates if the email is a disposable (temporary) email
    "is_disposable": false,
    
    // Indicates if the email is a role-based account (e.g., admin@, support@)
    "is_role_account": false,
    
    // The URL to the Gravatar associated with this email, if available
    "gravatar_url": null,
    
    // Information from the "Have I Been Pwned" breach database, if applicable
    "haveibeenpwned": null
  },
  
  "mx": {
    // Whether the domain's MX (Mail Exchange) server accepts email
    "accepts_mail": true,
    
    // A list of MX records for the domain (email servers that handle mail)
    "records": [
      "gmail-smtp-in.l.google.com.",
      "alt3.gmail-smtp-in.l.google.com.",
      "alt2.gmail-smtp-in.l.google.com.",
      "alt4.gmail-smtp-in.l.google.com.",
      "alt1.gmail-smtp-in.l.google.com."
    ]
  },
  
  "smtp": {
    // Indicates if the SMTP server can be connected to
    "can_connect_smtp": true,
    
    // Whether the inbox for this email address is full
    "has_full_inbox": false,
    
    // Indicates if the domain uses a catch-all email address (accepts mail for any address)
    "is_catch_all": false,
    
    // Whether the email is deliverable based on SMTP verification
    "is_deliverable": false,
    
    // Whether the email address is disabled or inactive
    "is_disabled": true
  },
  
  "syntax": {
    // The original email address being checked
    "address": "someone@gmail.com",
    
    // The domain part of the email (e.g., gmail.com)
    "domain": "gmail.com",
    
    // Whether the email has valid syntax (e.g., correct format)
    "is_valid_syntax": true,
    
    // The username part of the email (before the @ symbol)
    "username": "someone",
    
    // The normalized version of the email (no extra spaces, proper formatting)
    "normalized_email": "someone@gmail.com",
    
    // A suggested correction if the email syntax was incorrect (null if no suggestion)
    "suggestion": null
  },
    
  "smtp": {
    // Details of the SMTP verification method used
    "verif_method": {
      // The type of verification (SMTP in this case)
      "type": "Smtp",
      
      // The SMTP server that was contacted for verification
      "host": "alt1.gmail-smtp-in.l.google.com.",
      
      // The port used to connect to the SMTP server
      "port": 25,
      
      // Indicates if a proxy was used during the verification
      "used_proxy": false
    }
  },
    
  "debug": {
    // The server used to process the email verification
    "server_name": "backend1-ovh",
    
    // The time the verification process started
    "start_time": "2024-09-18T21:53:16.012753011Z",
    
    // The time the verification process ended
    "end_time": "2024-09-18T21:53:16.350005307Z",
    
    "duration": {
      // The total time taken for the verification in seconds and nanoseconds
      "secs": 0,
      "nanos": 337252296
    },
  }
}

```

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


# 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>. 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 Reacher in 20min](/self-hosting/install) as part of your **Commercial License Trial**.
{% endhint %}

## Key Differences

| Feature               | SaaS                                   | Self-Hosting                                                                                           |
| --------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| **Volume**            | Limited to 10k verifications per month | Unlimited verifications                                                                                |
| **Cost**              | Monthly subscription                   | Monthly subscription + server costs (lower at scale) + [proxy](/self-hosting/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 Verification (v0.7)](/advanced/migrations/bulk)                                   |


# 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 a Dockerfile that is provided you as part of the [Commercial License Trial](/self-hosting/licensing/commercial-license-trial).

## Prerequisites

* An account on <https://reacher.email> (required for the Commercial License Trial and access to the Dockerfile).
* 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](/self-hosting/scaling-for-production).

The provided Dockerfile includes a pre-configured proxy, resolving the common ISP restriction on outgoing requests to port 25 used by Reacher to perform SMTP verifications.

<details>

<summary>Understand the features and limitations of the Commercial License Trial.</summary>

The Dockerfile provided as part of the Commercial License Trial is designed to enable quick setup for email verifications. Below are its key features and limitations:

* **Built-in Proxy Configuration**: we use [**Proxy4Smtp**](https://www.proxy4smtp.com), a 3rd-party proxy with carefully maintained IPs optimized for SMTP verifications. This ensures reliable email verification even in cloud environments with restricted SMTP access. Learn more in [Proxies](/self-hosting/proxies).
* **Daily Verification Limit**: capped at 60 per minute at **10,000 per day**.
* **Usage Tracking**: verification results are anonymized and sent back to Reacher, and used to monitor daily usage and detect potential abuse.

You can also read more in [Commercial License Trial](/self-hosting/licensing/commercial-license-trial).

</details>

## Step-by-Step Tutorial

1. Navigate to the **Commercial License Trial** tab of your Reacher Dashboard ([go there directly](https://app.reacher.email/en/dashboard/commercial_license)). You'll see a command to run Reacher's latest (v0.10) [Docker image](https://hub.docker.com/r/reacherhq/backend):

```bash
docker run -e RCH__COMMERCIAL_LICENSE_TRIAL__API_TOKEN=<YOUR_UNIQUE_TOKEN> -p 8080:8080 reacherhq/commercial-license-trial:latest # v0.10
```

Replace `<YOUR_UNIQUE_TOKEN>` with your unique API token shown in the dashboard.

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 an error message, such as `` Error: missing field `api_token` ``, double-check the `-e RCH__COMMERCIAL_LICENSE_TRIAL__API_TOKEN` flag you passed. If you see other errors, either try [Debugging Reacher](/self-hosting/debugging-reacher) or send an email to [amaury@reacher.email](mailto:undefined).

Advanced users can also set additional [Reacher Configuration](/self-hosting/reacher-configuration-v0.10).

4. 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](/advanced/openapi/v1-check_email) endpoint.

4. 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 [Understanding "is\_reachable"](/getting-started/is-reachable).

{% hint style="warning" %}
If this step hangs for a long time, or returns a JSON result with `is_reachable="unknown"`, see [Debugging Reacher](/self-hosting/debugging-reacher)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](/self-hosting/scaling-for-production).

## Troubleshooting

If you have any issue in one of the steps above, you can try [Debugging Reacher](/self-hosting/debugging-reacher)yourself, or send me an email [amaury@reacher.email](mailto:undefined).


# 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. [Manage scaling yourself](/self-hosting/scaling-for-production/option-1-manage-scaling-yourself): Leverage Reacher's statelessness and decide yourself how to deploy Reacher.
2. [Option 1: RabbitMQ-based Queue Architecture](/self-hosting/scaling-for-production/option-2-rabbitmq-based-queue-architecture): 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](mailto:undefined))

Alternative scaling solutions were also explored, chat with [amaury@reacher.email](mailto:undefined) if you want to discuss more.

## Scaling beyond the Commercial License Trial

The documentation in this section mentions the Dockerfile provided as part of the [Commercial License Trial](/self-hosting/licensing/commercial-license-trial), which:

* has a built-in proxy,
* &#x20;limits the number of daily verifications to 10000.

The strategies documented in this section apply both to the Commercial License Trial as well as a high-volume setup beyond this limit.  Once you're ready to transition from the former to the latter, you must:

1. **Purchase a Commercial License**. This will grant you access to an unrestricted Dockerfile.
2. **Purchase 3rd-party proxy IPs**. You will receive configuration details for the proxy to be passed into the unrestricted Dockerfile.

Get in touch with [amaury@reacher.email](mailto:undefined) when you're there.


# 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](/self-hosting/proxies)).
  * 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 1: RabbitMQ-based Queue Architecture](/self-hosting/scaling-for-production/option-2-rabbitmq-based-queue-architecture), 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 1: RabbitMQ-based Queue Architecture](/self-hosting/scaling-for-production/option-2-rabbitmq-based-queue-architecture))
* **Pros**:
  * Highly scalable and resilient.
  * Centralized monitoring and orchestration.
* **Cons**:
  * Higher operational complexity.
  * Requires Kubernetes expertise.


# 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/commercial-license-trial</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/commercial-license-trial</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/commercial-license-trial` which can act as both a **Worker** and a **HTTP server**.

<figure><img src="/files/BXDWpmJ59wqlobQ2e7sQ" 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.

{% hint style="info" %}
The Dockerfile provided in the Commercial License Trial already has these parameters set up.
{% endhint %}

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

{% hint style="info" %}
The Dockerfile provided in the Commercial License Trial already has these parameters set up.
{% endhint %}

## 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`](https://github.com/reacherhq/check-if-email-exists/blob/master/rabbitmq/docker-compose.yaml) file can be useful.

## More questions?

Contact [amaury@reacher.email](mailto:undefined)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)


# Licensing

Is Reacher open-source? Does it mean it's free? When should you pay for a Commercial License?

## Yes, Reacher is Open-Source

Reacher is proudly open-source and distributed under the [**AGPL-3.0 license**](https://www.gnu.org/licenses/agpl-3.0.en.html) (GNU Affero General Public License). This license ensures that Reacher’s source code is freely available, and any modifications or improvements made to the code must also be shared under the same license.

However, companies **cannot use** the open-source version if they plan to integrate Reacher into **proprietary software** or services without sharing their modifications. The AGPL-3.0 requires that if you offer the software as part of a web service, you must make your code (including any modifications) publicly available. For more details, check [GNU’s AGPL-3.0 guide](https://www.gnu.org/licenses/agpl-3.0.en.html).

## Commercial License required for Proprietary applications

The Commercial License allows companies to integrate Reacher into their proprietary software or services without being bound by the open-source license terms (such as making their own code publicly available). By obtaining a Commercial License, businesses can use Reacher with full control over how the software is implemented and distributed within their products.

Check Reacher's [pricing page](https://reacher.email/pricing) to buy a Commercial License, or read the [full terms of the Commercial License](https://github.com/reacherhq/policies/blob/master/license/commercial.en.md).

{% hint style="info" %}
Both the open-source and Commercial License give you access to the same Reacher software.
{% endhint %}

## Does Reacher offer a Free Trial?

Yes, Reacher offers a free trial for the Commercial License, see [Commercial License Trial](/self-hosting/licensing/commercial-license-trial).


# Commercial License Trial

The Commercial License Trial allows you to test the self-hosted software for a limited period of time, for **internal testing** and **non-commercial purposes**.

## Features and Limitations

As part of the Commercial License Trial, you'll receive a Dockerfile designed to enable quick setup for email verifications. Below are its key features and limitations:

* **Built-in Proxy Configuration**: we embed [**Proxy4Smtp**](https://www.proxy4smtp.com), a 3rd-party proxy with carefully maintained IPs optimized for SMTP verifications. All verifications using the Dockerfile go through this proxy. This ensures reliable email verification even in cloud environments with restricted SMTP access. Learn more in [Proxies](/self-hosting/proxies).
* **Daily Verification Limit**: capped at **60 per minute** and **10,000 per day.**
* **Usage Tracking**: verification results are anonymized and sent back to Reacher, and used to monitor daily usage and detect potential abuse.
* **For testing purposes only**. The Dockerfile can only be used internally, for testing purposes, and can in no case be used in production environments for commercial applications.

{% hint style="danger" %}
All abuse of the Commercial License Trial will result in an immediate account ban.
{% endhint %}

## Get Started

To start your Commercial License Trial, sign up on [https://reacher.email](https://app.reacher.email/en/signup). Then, navigate to the "Commercial License Trial" tab of the Reacher Dashboard ([go there directly](https://app.reacher.email/en/dashboard/commercial_license)) and follow instructions.

## After the Trial

The Commercial License Trial cannot be used for full-scale production use or commercial applications. Once you've tested Reacher extensively, purchase a Commercial License.

Once you purchased the Commercial License, you'll need to perform the two following steps:

1. Replace the Docker image from `reacherhq/commercial-license-trial`to `reacherhq/backend`. This will give you access to an unrestricted Dockerfile to perform unlimited verifications.
2. (If applicable) Configure proxy setting on the Docker container, via the `RCH__PROXY__*`environment variables. See [Proxies](/self-hosting/proxies)for more information.


# 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 Reacher in 20min](/self-hosting/install)) 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" %}
If you're using the [Commercial License Trial](/self-hosting/licensing/commercial-license-trial), these fields are already populated with the built-in proxy. However, you can overwrite them by passing these flags again, pointing to a proxy of your own choosing.
{% endhint %}

{% hint style="info" %}
For advanced usage, you can configure [Multiple Proxies](/self-hosting/proxies/multiple-proxies).
{% 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](mailto:undefined) for an introduction to Jon.


# 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

```yaml
services:
  worker:
    image: reacherhq/commercial-license-trial:v0.11.0
    container_name: test
    ports:
      - "8080:8080"
    environment:
      RCH__BACKEND_NAME: backend4-do
      RUST_LOG: reacher=info
      # Default proxy
      RCH__PROXY__HOST: my.default.proxy.com
      RCH__PROXY__PORT: 1081
      RCH__PROXY__USERNAME: user0
      RCH__PROXY__PASSWORD: pass0
      RCH__HELLO_NAME: my.default.proxy.com
      RCH__FROM_EMAIL: hello@my.default.proxy.com
      # Proxy 1
      RCH__OVERRIDES__PROXIES__PROXY1__HOST: 11.22.33.44
      RCH__OVERRIDES__PROXIES__PROXY1__PORT: 1081
      RCH__OVERRIDES__PROXIES__PROXY1__USERNAME: user1
      RCH__OVERRIDES__PROXIES__PROXY1__PASSWORD: pass1
      # Proxy 2
      RCH__OVERRIDES__PROXIES__PROXY2__HOST: 55.66.77.88
      RCH__OVERRIDES__PROXIES__PROXY2__PORT: 1081
      RCH__OVERRIDES__PROXIES__PROXY2__USERNAME: user2
      RCH__OVERRIDES__PROXIES__PROXY2__PASSWORD: pass2
      # Route Google to Proxy 1
      RCH__OVERRIDES__GMAIL__TYPE: smtp
      RCH__OVERRIDES__GMAIL__PROXY: proxy1
      # Route Proofpoint to Proxy 1
      RCH__OVERRIDES__PROOFPOINT__TYPE: smtp
      RCH__OVERRIDES__PROOFPOINT__PROXY: proxy1
      # Route Hotmail B2B to Proxy 2
      RCH__OVERRIDES__HOTMAILB2B__TYPE: smtp
      RCH__OVERRIDES__HOTMAILB2B__PROXY: proxy2
      RCH__OVERRIDES__HOTMAILB2B__HELLO_NAME: my.proxy2.com       # Optionally override the HELO/EHLO name
      RCH__OVERRIDES__HOTMAILB2B__FROM_EMAIL: hello@my.proxy2.com # Optionally override the MAIL FROM email.
      # Worker config
      RCH__WORKER__ENABLE: false
    restart: always
```


# Reacher Configuration

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

* [Reacher Configuration (v0.10)](/advanced/migrations/reacher-configuration-v0.10)
* [Docker Environment Variables (v0.7)](/advanced/migrations/docker-environment-variables).
  {% 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](#examples-with-docker "mention").

```toml
# Backend configuration.

# Name to identify the backend.
#
# Env variable: RCH__BACKEND_NAME
backend_name = "backend-dev"

# Host to bind the backend to.
#
# Env variable: RCH__HTTP_HOST
http_host = "127.0.0.1"

# Port for the backend.
#
# Env variable: RCH__HTTP_PORT
http_port = 8080

# Name to use during the EHLO/HELO command in the SMTP conversation.
# Ideally, this should match the reverse DNS of the server's IP address.
#
# Env variable: RCH__HELLO_NAME
hello_name = "localhost"

# Email to use during the MAIL FROM command in the SMTP conversation.
# Ideally, the domain of this email should match the "hello_name" above.
#
# Env variable: RCH__FROM_EMAIL
from_email = "hello@localhost"

# Timeout for each SMTP connection, in seconds. Leaving it commented out will
# not set a timeout, i.e. the connection will wait indefinitely. If using a
# proxy, this timeout includes both the time to connect to the proxy and the
# time to connect to perform the whole SMTP verification. Also see:
# `proxy.timeout_ms`.
#
# Env variable: RCH__SMTP_TIMEOUT
# smtp_timeout = 45

# Shared secret between a trusted client and the backend, required in the
# `x-reacher-secret` header of all incoming requests.
#
# Env variable: RCH__HEADER_SECRET
# header_secret = "my-secret"

# Optional Sentry DSN. If set, all errors will be sent to Sentry.
#
# Env variable: RCH__SENTRY_DSN
# sentry_dsn = "<PASTE_YOUR_DSN_HERE>"

# Address of the Chrome WebDriver server for headless email verifications.
#
# Env variable: RCH__WEBDRIVER_ADDR
webdriver_addr = "http://localhost:9515"

# Uncomment the line `[proxy]` below to route all SMTP verification requests
# through a specified proxy.
# [proxy]

# The proxy host and port. The proxy must be a SOCKS5 proxy to work with the
# SMTP protocol. This proxy will not be used for headless verifications.
#
# Env variables:
# - RCH__PROXY__HOST
# - RCH__PROXY__PORT
#
# Uncomment the two lines below if the `[proxy]` section is uncommented.
# host = "my.proxy.com"
# port = 1080

# Username and password for the proxy. These are optional and only needed if
# the proxy requires authentication.
#
# Env variables:
# - RCH__PROXY__USERNAME
# - RCH__PROXY__PASSWORD
#
# Uncomment the two lines below if needed.
# username = "my-username"
# password = "my-password"

# This is the timeout for the proxy connection, in milliseconds. Please note
# that this is not the timeout for the SMTP connection itself, but rather the
# timeout for the connection to the proxy server only. As such, it can be kept
# quite low, for example 5000-10000ms. For a full timeout of the SMTP
# connection, please use the `smtp_timeout` field above.
#
# Env variable: RCH__PROXY__TIMEOUT_MS
#
# Uncomment the line below if needed.
# timeout_ms = 10000

[webdriver]
# Path to the Chrome binary. If not set, the default system Chrome will be used.
#
# Env variable: RCH__WEBDRIVER__BINARY
# binary = "/usr/bin/google-chrome"

# Override verification method to use for each email provider. Each email provider can
# be verified using one of the following methods:
# - Gmail: smtp
# - Hotmail B2B: smtp
# - Hotmail B2C: headless or smtp
# - Yahoo: headless or smtp
# - Mimecast: smtp
# - Proofpoint: smtp
#
# For the email providers you choose to verify using the "smtp" method, you
# may add additional configuration, such as hello_name, from_email, and
# whether to use a proxy or not.
#
# If using proxies, the list of proxies must be defined in the "proxies"
# section below, with a unique name for each proxy such as "proxy1", "proxy2",
# etc. Then, in the email provider's SMTP configuration, set the value to the
# name of the proxy to use. To use the proxy defined the the top-level "proxy"
# section, set the value to "default".
[overrides]
# Use the "proxies" configuration below to route SMTP verification requests
# through a specified proxy.
#
# Reacher allows you to configure multiple proxies, each with a unique name.
# We recommend simply using "proxy1", "proxy2", etc. as the proxy names.
#
# In the `overrides` section below, you can specify which proxy to use for
# each email provider. For example, to use "proxy1" for Gmail and "proxy2" for
# Yahoo, set the `gmail` field to "proxy1" and the `yahoo` field to "proxy2".
[overrides.proxies]
# Uncomment the lines below to configure a proxy. The username and password are
# optional and only needed if the proxy requires authentication.
#
# Env variables:
# - RCH__OVERRIDES__PROXIES__PROXY1__HOST
# - RCH__OVERRIDES__PROXIES__PROXY1__PORT
# - RCH__OVERRIDES__PROXIES__PROXY1__USERNAME
# - RCH__OVERRIDES__PROXIES__PROXY1__PASSWORD
# proxy1 = { host = "my.proxy1.com", port = 1080, username = "my-username1", password = "my-password1" }
# proxy2 = { host = "my.proxy2.com", port = 1081 }

# Set overrides for Gmail. If uncommented, make sure to uncomment all fields.
# [overrides.gmail]
# type = "smtp"
# proxy = "proxy1"
# hello_name = "my-domain.com"
# from_email = "hello@my-domain.com"

# For each email provider, you can override the verification method and set
# additional configuration. The available fields are the same as for the
# "gmail" section above.

# [overrides.hotmailb2b]

# [overrides.hotmailb2c]

# [overrides.mimecast]

# [overrides.proofpoint]

# [overrides.yahoo]

# Throttle the maximum number of requests per second, per minute, per hour, and
# per day for this worker.
# All fields are optional; comment them out to disable the limit.
#
# We however recommend setting the throttle for at least the per-minute and
# per-day limits to prevent the IPs from being blocked by the email providers.
# The default values are set to 60 requests per minute and 10,000 requests per
# day.
#
# Important: these throttle configurations only apply to /v1/* endpoints, and
# not to the previous /v0/check_email endpoint. The latter endpoint always
# executes the verification immediately, regardless of the throttle settings.
#
# Env variables:
# - RCH__THROTTLE__MAX_REQUESTS_PER_SECOND
# - RCH__THROTTLE__MAX_REQUESTS_PER_MINUTE
# - RCH__THROTTLE__MAX_REQUESTS_PER_HOUR
# - RCH__THROTTLE__MAX_REQUESTS_PER_DAY
[throttle]
# max_requests_per_second = 20
# max_requests_per_minute = 60
# max_requests_per_hour = 1000
# max_requests_per_day = 10000

# Configuration for a queue-based architecture for Reacher. This feature is
# currently in **beta**. The queue-based architecture allows Reacher to scale
# horizontally by running multiple workers that consume emails from a RabbitMQ
# queue.
#
# To enable the queue-based architecture, set the "enable" field to "true" and
# configure the RabbitMQ connection below. The "concurrency" field specifies
# the number of concurrent emails to verify for this worker.
#
# For more information, see the documentation at:
# https://docs.reacher.email/self-hosting/scaling-for-production
[worker]
# Enable the worker to consume emails from the RabbitMQ queues. If set, the
# RabbitMQ configuration below must be set as well.
#
# Env variable: RCH__WORKER__ENABLE
enable = false

# RabbitMQ configuration.
[worker.rabbitmq]
# Env variable: RCH__WORKER__RABBITMQ__URL
url = "amqp://guest:guest@localhost:5672"

# Number of concurrent emails to verify for this worker.
#
# Env variable: RCH__WORKER__RABBITMQ__CONCURRENCY
concurrency = 5

# Below are the configurations for the storage of the email verification
# results. We currently support the following storage backends:
# - Postgres
#
# Uncomment the following line to configure the storage to use Postgres.
# [storage.postgres]

# # URL to connect to the Postgres database.
#
# Env variable: RCH__STORAGE__0__POSTGRES__DB_URL
# db_url = "postgresql://localhost/reacherdb"
#
# If you wish to store additional data along with the verification results,
# you can add a JSON object to the "extra" field. This object will be stored
# as a JSONB column in the database. This is for example useful to track who
# initiated the verification request in a multi-tenant system.
# 
# Env variable: RCH__STORAGE__0__POSTGRES__TABLE_NAME
# extra = { "my_custom_key" = "my_custom_value" }
```

## 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`](https://github.com/reacherhq/check-if-email-exists/blob/master/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.


# 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](mailto:undefined) 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](/self-hosting/proxies).&#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>

```bash
* About to connect() to alt1.gmail-smtp-in.l.google.com port 25 (#0)
*   Trying 142.250.153.26...
* Connected to alt1.gmail-smtp-in.l.google.com (142.250.153.26) port 25 (#0)
< 220 mx.google.com ESMTP he11-20020a1709073d8b00b006e862100d5bsi2937572ejc.396 - gsmtp
> EHLO reacher
< 250-mx.google.com at your service, [176.31.197.159]
< 250-SIZE 157286400
< 250-8BITMIME
< 250-STARTTLS
< 250-ENHANCEDSTATUSCODES
< 250-PIPELINING
< 250-CHUNKING
< 250 SMTPUTF8
> STARTTLS
< 220 2.0.0 Ready to start TLS
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* 	subject: CN=mx.google.com
* 	start date: May 04 17:12:30 2022 GMT
* 	expire date: Jul 27 17:12:29 2022 GMT
* 	common name: mx.google.com
* 	issuer: CN=GTS CA 1C3,O=Google Trust Services LLC,C=US
> EHLO reacher
< 250-mx.google.com at your service, [176.31.197.159]
< 250-SIZE 157286400
< 250-8BITMIME
< 250-ENHANCEDSTATUSCODES
< 250-PIPELINING
< 250-CHUNKING
< 250 SMTPUTF8
> MAIL FROM:<test@gmail.com>
< 250 2.1.0 OK he11-20020a1709073d8b00b006e862100d5bsi2937572ejc.396 - gsmtp
> RCPT TO:<test@gmail.c>
< 550-5.1.1 The email account that you tried to reach does not exist. Please try
< 550-5.1.1 double-checking the recipient's email address for typos or
< 550-5.1.1 unnecessary spaces. Learn more at
< 550 5.1.1  https://support.google.com/mail/?p=NoSuchUser he11-20020a1709073d8b00b006e862100d5bsi2937572ejc.396 - gsmtp
* RCPT failed: 550
> QUIT
< 221 2.0.0 closing connection he11-20020a1709073d8b00b006e862100d5bsi2937572ejc.396 - gsmtp
* Closing connection 0
curl: (55) RCPT failed: 55
```

</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](mailto:undefined).


# OpenAPI

* [/v0/check\_email](/advanced/openapi/v0-check_email)
* [/v1/check\_email](/advanced/openapi/v1-check_email)
* [/v1/bulk](/advanced/openapi/v1-bulk)


# /v0/check\_email

{% openapi 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>
{% endopenapi %}


# /v1/check\_email

{% openapi 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>
{% endopenapi %}


# /v1/bulk

{% openapi 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>
{% endopenapi %}

{% openapi 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>
{% endopenapi %}

{% openapi 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>
{% endopenapi %}


# Run your own Proxy

Reacher integrates seamlessy with [Proxies](/self-hosting/proxies), 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](mailto:undefined).


# Migrations

* [Migrating from 0.7 to 0.10](/advanced/migrations/migrating-from-0.7-to-0.10-beta)


# 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](#examples-with-docker "mention").

```toml
# Backend configuration.

# Name to identify the backend.
#
# Env variable: RCH__BACKEND_NAME
backend_name = "backend-dev"

# Host to bind the backend to.
#
# Env variable: RCH__HTTP_HOST
http_host = "127.0.0.1"

# Port for the backend.
#
# Env variable: RCH__HTTP_PORT
http_port = 8080

# Shared secret between a trusted client and the backend, required in the
# `x-reacher-secret` header of all incoming requests.
#
# Env variable: RCH__HEADER_SECRET
# header_secret = "my-secret"

# Name to use during the EHLO/HELO command in the SMTP conversation.
# Ideally, this should match the reverse DNS of the server's IP address.
#
# Env variable: RCH__HELLO_NAME
hello_name = "localhost"

# Email to use during the MAIL FROM command in the SMTP conversation.
# Ideally, the domain of this email should match the "hello_name" above.
#
# Env variable: RCH__FROM_EMAIL
from_email = "hello@localhost"

# Address of the Chrome WebDriver server for headless email verifications.
#
# Env variable: RCH__WEBDRIVER_ADDR
webdriver_addr = "http://localhost:9515"

# Timeout for each SMTP connection, in seconds. Leaving it commented out will
# not set a timeout, i.e. the connection will wait indefinitely.
#
# Env variable: RCH__SMTP_TIMEOUT
# smtp_timeout = 45

# Optional Sentry DSN. If set, all errors will be sent to Sentry.
#
# Env variable: RCH__SENTRY_DSN
# sentry_dsn = "<PASTE_YOUR_DSN_NOW>"

# Uncomment the lines below to route all SMTP verification requests
# through a specified proxy. Note that the proxy must be a SOCKS5 proxy to work
# with the SMTP protocol. This proxy will not be used for headless
# verifications.
#
# The username and password are optional and only needed if the proxy requires
# authentication.
#
# Env variables:
# - RCH__PROXY__HOST
# - RCH__PROXY__PORT
# - RCH__PROXY__USERNAME
# - RCH__PROXY__PASSWORD
#
# [proxy]
# host = "my.proxy.com"
# port = 1080
# username = "my-username"
# password = "my-password"

# Verification method to use for each email provider. Available methods are:
# "smtp", "headless", and "api". Note that not all methods are supported by
# all email providers.
[verif_method]
# Gmail currently only supports the "smtp" method.
#
# Env variable: RCH__VERIF_METHOD__GMAIL
gmail = "smtp"
# Hotmail B2B currently only supports the "smtp" method.
#
# Env variable: RCH__VERIF_METHOD__HOTMAILB2B
hotmailb2b = "smtp"
# Hotmail B2C supports both "headless" and "smtp" methods. The "headless"
# method is recommended.
hotmailb2c = "headless"
# Yahoo supports both "headless" and "smtp" methods. The "headless" method is
# recommended.
yahoo = "headless"

# Throttle the maximum number of requests per second, per minute, per hour, and
# per day for this worker.
# All fields are optional; comment them out to disable the limit.
#
# We however recommend setting the throttle for at least the per-minute and
# per-day limits to prevent the IPs from being blocked by the email providers.
# The default values are set to 60 requests per minute and 10,000 requests per
# day.
#
# Important: these throttle configurations only apply to /v1/* endpoints, and
# not to the previous /v0/check_email endpoint. The latter endpoint always
# executes the verification immediately, regardless of the throttle settings.
#
# Env variables:
# - RCH__THROTTLE__MAX_REQUESTS_PER_SECOND
# - RCH__THROTTLE__MAX_REQUESTS_PER_MINUTE
# - RCH__THROTTLE__MAX_REQUESTS_PER_HOUR
# - RCH__THROTTLE__MAX_REQUESTS_PER_DAY
[throttle]
# max_requests_per_second = 20
max_requests_per_minute = 60
# max_requests_per_hour = 1000
max_requests_per_day = 10000

# Configuration for a queue-based architecture for Reacher. This feature is
# currently in **beta**. The queue-based architecture allows Reacher to scale
# horizontally by running multiple workers that consume emails from a RabbitMQ
# queue.
#
# To enable the queue-based architecture, set the "enable" field to "true" and
# configure the RabbitMQ connection below. The "concurrency" field specifies
# the number of concurrent emails to verify for this worker.
#
# For more information, see the documentation at:
# https://docs.reacher.email/self-hosting/scaling-for-production
[worker]
# Enable the worker to consume emails from the RabbitMQ queues. If set, the
# RabbitMQ configuration below must be set as well.
#
# Env variable: RCH__WORKER__ENABLE
enable = false

# RabbitMQ configuration.
[worker.rabbitmq]
# Env variable: RCH__WORKER__RABBITMQ__URL
url = "amqp://guest:guest@localhost:5672"

# Number of concurrent emails to verify for this worker.
#
# Env variable: RCH__WORKER__RABBITMQ__CONCURRENCY
concurrency = 5

# Below are the configurations for the storage of the email verification
# results. We currently support the following storage backends:
# - Postgres
#
# Uncomment the following line to configure the storage to use Postgres.
# [storage.postgres]

# # URL to connect to the Postgres database.
#
# Env variable: RCH__STORAGE__POSTGRES__DB_URL
# db_url = "postgresql://localhost/reacherdb"
#
# If you wish to store additional data along with the verification results,
# you can add a JSON object to the "extra" field. This object will be stored
# as a JSONB column in the database. This is for example useful to track who
# initiated the verification request in a multi-tenant system.
# 
# Env variable: RCH__STORAGE__0__POSTGRES__TABLE_NAME
# extra = { "my_custom_key" = "my_custom_value" }
```

## 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`](https://github.com/reacherhq/check-if-email-exists/blob/master/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.


# 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](/self-hosting/reacher-configuration-v0.10).
* `/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](/self-hosting/reacher-configuration-v0.10), 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.


# 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 Reacher in 20min](/self-hosting/install).
* 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](mailto:undefined).


# 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](/self-hosting/reacher-configuration-v0.10).
{% 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>


