DEV Community

Mohammed Samaan
Mohammed Samaan

Posted on

What an MX-only email check can and cannot tell you

Bad addresses at signup cost you bounces and sender reputation. Full mailbox verification services dial the recipient's mail server to ask whether the mailbox exists. This API does not, and that matters for how you use it. Here is what it returns and where it stops.

It sits next to two other APIs from the same account. The Disposable Email Checker is the list-only version (Stop Mailinator signups with one GET request), and Domain Trust Score judges the domain (Scoring an unknown domain 0 to 100). This one checks the address itself.

The shortest working call

curl --request GET \
  --url 'https://email-verifier38.p.rapidapi.com/v1/verify?email=test@gmail.com' \
  --header 'x-rapidapi-host: email-verifier38.p.rapidapi.com' \
  --header 'x-rapidapi-key: YOUR_RAPIDAPI_KEY'
Enter fullscreen mode Exit fullscreen mode

JavaScript (Node 18+):

const email = 'test@gmail.com';const res = await fetch(
  'https://email-verifier38.p.rapidapi.com/v1/verify?email=' + encodeURIComponent(email),
  {
    headers: {
      'x-rapidapi-host': 'email-verifier38.p.rapidapi.com',
      'x-rapidapi-key': process.env.RAPIDAPI_KEY,
    },
  }
);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
const reject = ['invalid', 'disposable'].includes(data.status);
console.log(reject ? 'reject' : 'accept', data.score);
Enter fullscreen mode Exit fullscreen mode

Python:

import os, requests

r = requests.get(
    "https://email-verifier38.p.rapidapi.com/v1/verify",
    params={"email": "test@gmail.com"},    headers={
        "x-rapidapi-host": "email-verifier38.p.rapidapi.com",
        "x-rapidapi-key": os.environ["RAPIDAPI_KEY"],
    },
    timeout=10,
)
r.raise_for_status()
d = r.json()
print("reject" if d["status"] in ("invalid", "disposable") else "accept", d["score"])
Enter fullscreen mode Exit fullscreen mode

The response, field by field

Captured from the live API on 7 Oct 2026 (HTTP 200, 607 bytes):

{
  "email": "test@gmail.com",  "status": "unknown",
  "score": 72,
  "reason": "mx_only_no_smtp",
  "reason_detail": "Domain accepts mail. This API is MX-only — the mailbox itself was not dialed (SMTP port 25 is blocked on serverless platforms).",
  "method": "mx",
  "syntax_valid": true,
  "domain": "gmail.com",
  "mx_found": true,
  "mx_host": "gmail-smtp-in.l.google.com",
  "is_disposable": false,
  "is_role": false,
  "is_free_provider": true,
  "has_tag": false,
  "base_email": "test@gmail.com",  "typo_suggestion": null,
  "domain_has_spf": true,
  "domain_has_dmarc": true,
  "checked_at": "2026-10-07T10:00:52.056Z",
  "duration_ms": 9,
  "meta": { "user": "..." }
}
Enter fullscreen mode Exit fullscreen mode
  • status is one of valid, invalid, disposable, risky or unknown. score runs from 0 to 100.
  • reason and reason_detail explain the verdict. Here the domain accepts mail but the mailbox was not contacted, so the answer is unknown, not valid.
  • syntax_valid, domain, mx_found and mx_host are the syntax and DNS checks.
  • is_disposable, is_role (such as info@) and is_free_provider are separate booleans. has_tag and base_email handle plus-addressing.
  • typo_suggestion offers a correction for misspelled domains, or null.
  • domain_has_spf and domain_has_dmarc describe the domain's DNS, not the mailbox.
  • duration_ms is the server-side time (9 ms here, from the response itself). The playground round trip was about 1.5 s.
  • meta.user holds the caller's account name, shown as "...".

Two more captures from the same day, with the same 21 keys. someone@mailinator.com returned status: "disposable", score: 5, reason: "disposable_domain", mx_found: false. not-an-email returned status: "invalid", score: 0, reason: "bad_syntax", syntax_valid: false and domain: null. Both were HTTP 200, so a bad address is a result and not an error status.

Using it at signup

Reject invalid and disposable, accept the rest, and confirm with a real confirmation email later. Do not reject unknown, because it is the normal answer for a good Gmail address.

What it does not do

  • It never contacts the mailbox. SMTP port 25 is blocked on serverless platforms, so this API cannot tell you a specific mailbox exists.
  • It does not detect catch-all domains.
  • It cannot promise an address will receive mail or will not bounce. valid means the checks it runs passed, nothing more.
  • A single GET checks one address. A POST to /v1/verify with an emails array checks a small batch, with a maximum of 10 per request.

Errors

A malformed address is a normal 200 with status: "invalid", as shown above. Gateway failures such as a missing or wrong key, or a used-up quota, return RapidAPI's own error before the request reaches the API. I did not re-run other error cases for this post, so check the listing's endpoint documentation for the current ones.

Status Meaning
200 The address was checked, whatever the verdict
Non-2xx Gateway or API failure. Throw, log, and let the user continue rather than blocking signup

Plan

The free Basic plan on the listing currently shows 300 requests per month. Pro is $19 per month for 3,000.

Listing and playground: https://rapidapi.com/samaanmohammed/api/email-verifier38

Top comments (0)