check-if-email-exists

by amaurymartiny

Check if an email address exists without sending any email, written in Rust.

232 Stars 45 Forks Last release: 27 days ago (v0.8.14) Other 680 Commits 32 Releases

Available items

Custom Feature

Developer services
$500.00

Custom feature

Contact me before purchase

Bug Fix

Developer services
$300.00

Bug Fix

Fast resolution

Contact me before purchase

1 Support Hour

Developer services
$100.00

Email/Chat Support

Ask me anything

Coding not included

Crate Docs Actions Status Travis Appveyor Github Sponsor




check-if-email-exists

Check if an email address exists without sending any email.




πŸ‘‰ Live Demo: https://reacher.email

You can also: Deploy

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 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 address? |
smtp.is_catch_all
| | βœ… | Role account validation | Is the email address a well-known role account? |
misc.is_role_account
| | πŸ”œ | Free email provider check | Is the email address bound to a known free email provider? | Issue #89 | | πŸ”œ | Syntax validation, provider-specific | According to the syntactic rules of the target mail provider, is the address syntactically valid? | Issue #90 | | πŸ”œ | Honeypot detection | Does email address under test hide a honeypot? | Issue #91 | | πŸ”œ | Gravatar | Does this email address have a Gravatar profile picture? | Issue #92 | | πŸ”œ | Have I Been Pwned? | Has this email been compromised in a data breach? | Issue #289 |

πŸ€” 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

This library has a dual license, a commercial one suitable for closed-source commercial projects and an AGPL-3.0 license that can be used in open-source software. See the LICENSE file for more info.

Try It Yourself

There are 5 ways you can try

check-if-email-exists
.

1. Use the Hosted Version: https://reacher.email πŸ₯‡

Reacher is a simple SaaS using this library, also open-source!

If you would like a high free tier to test Reacher, consider sponsoring me! You'll get 8000 free email verifications every month, and a this contribution would mean A WHOLE LOT to me.

2. Deploy to Heroku

Deploy

Heroku's servers have SMTP port 25 open, and have static IPs able to connect to most email providers (unless if you start heavily spamming these providers).

3. Use Docker

The Docker image is hosted on Docker Hub: https://hub.docker.com/r/amaurymartiny/check-if-email-exists.

To run it, run the following command:

docker run -p 3000:3000 amaurymartiny/check-if-email-exists

You can then send a POST request with the following body to

http://localhost:3000
to test multiple emails at once:
{
    "to_emails": ["[email protected]"]
}

Here's the equivalent

curl
command:
curl -X POST -d'{"to_emails":["[email protected]"]}' http://localhost:3000

Optionally, you can also pass in

from_email
and
hello_name
fields into the JSON object, see the help message below to understand their meanings.

4. Download the Binary

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

Head to the releases page and download the binary for your platform. Make sure you have

openssl
installed on your local machine.

> $ check_if_email_exists --help
check_if_email_exists 0.8.14
Check if an email address exists without sending any email.

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

FLAGS: --http Runs a HTTP server. -h, --help Prints help information -V, --version Prints version information

OPTIONS: --from-email The email to use in the MAIL FROM: SMTP command. [default: [email protected]] --hello-name The name to use in the EHLO: SMTP command. [default: localhost] --http-host Sets the host IP address on which the HTTP server should bind. Only used when --http flag is on. [default: 127.0.0.1] --http-port Sets the port on which the HTTP server should bind. Only used when --http flag is on. If not set, then it will use $PORT, or default to 3000. --proxy-host Use the specified SOCKS5 proxy host to perform email verification. --proxy-port Use the specified SOCKS5 proxy port to perform email verification. Only used when --proxy-host flag is set. [default: 1080] --yahoo-use-api For Yahoo email addresses, use Yahoo's API instead of connecting directly to their SMTP servers. [default: true]

ARGS: The email to check.

If you run with the

--http
flag,
check-if-email-exists
will serve a HTTP server on
http://localhost:3000
. You can then send a POST request with the following body to test multiple emails at once:
{
    "to_emails": ["[email protected]"]
}

Here's the equivalent

curl
command:
curl -X POST -d'{"to_emails":["[email protected]"]}' http://localhost:3000

Optionally, you can also pass in

from_email
and
hello_name
fields into the JSON object, see the help message above to understand their meanings.

πŸ’‘ PRO TIP: To show debug logs when running the binary, run:

RUST_LOG=debug check_if_email_exists [FLAGS] [OPTIONS] [TO_EMAIL]

5. Usage as a Rust Library

In your own Rust project, you can add

check-if-email-exists
in your
Cargo.toml
:
[dependencies]
check-if-email-exists = "0.8"

And use it in your code as follows:

use check_if_email_exists::{check_email, CheckEmailInput};

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

// Optionally, we can also tweak the configuration parameters used in the
// verification.
input
    .from_email("[email protected]".into()) // Used in the `MAIL FROM:` command
    .hello_name("example.org".into()); // Used in the `EHLO` command

// Verify this input, 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.

✈️ JSON Output

The output will be a JSON with the below format, the fields should be self-explanatory. For

[email protected]
(note that it is disabled by Gmail), here's the exact output:
{
    "input": "[email protected]",
    "is_reachable": "invalid",
    "misc": {
        "is_disposable": false,
        "is_role_account": false
    },
    "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"
    }
}

You can also take a look at the documentation of this JSON object.

❓ FAQ

What does
is_reachable: "unknown"
mean?

This means that the server does not allow real-time verification of an email right now. It may happen for multiple reasons: your IP is blacklisted, the SMTP port 25 is blocked, the email account is momentarily receiving too many emails (spam protection)... or the email provider simply does not allow real-time verification at all. The details of this

"unknown"
case can be found in the
smtp.error
and
mx.error
fields.

The library hangs/takes a long time/doesn't show anything after 1 minute.

Most ISPs block outgoing SMTP requests through port 25, to prevent spam.

check-if-email-exists
needs to have this port open to make a connection to the email's SMTP server, so won't work behind these ISPs, and will instead hang until it times out. There's unfortunately no easy workaround for this problem, see for example this StackOverflow thread. One solution is to rent a Linux cloud server with a static IP and no blocked ports, see for example our Deploy to Heroku section.

To see in details what the binary is doing behind the scenes, run it in verbose mode to see the logs.

The output shows
"connection refused"
in the
smtp.error
field.

This also happens when your ISP block SMTP ports, see the above answer.

πŸ”¨ Build From Source

First, install Rust; you'll need Rust 1.37.0 or later. Then, run the following commands:

# Download the code
$ git clone https://github.com/amaurymartiny/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 which made a telnet call. If you would like to use that simpler version, have a look at the

legacy
branch. The reasons for porting the bash script to the current codebase are explained in issue #4.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.