FR
Copied
Modules

Email verification

Email verification

The verify_emails module checks whether the addresses of a list can receive mail. It checks syntax, spots obvious typos, resolves MX records, opens a probe against the receiving server, and filters out disposable domains and suspect prefixes (test@, noreply@, abuse@ and similar).

Reduced functionality during the alpha, for technical cost reasons. Syntax, typo, disposable-domain, suspect-prefix and MX checks run for every address. The mailbox probe (SMTP) runs from our server with retries, catch-all and greylisting detection. Large consumer mail providers (Gmail, Outlook, Yahoo, Orange, Free, SFR, La Poste, iCloud and others) refuse such probes: their addresses come back as skipped. Some receiving servers do not answer our server clearly, which gives unknown rows. If the probe port is closed on our side, the job switches to MX-only mode and marks the rows unknown with the mx_only category.

It runs after an enrichment step that produced emails, or against an imported list. The job is parallel: it does not consume a slot on the multi-proxy queue and can run alongside extraction jobs.

Disposable domains are detected, while privacy alias services (Apple, DuckDuckGo, Proton) are recognised as real mailboxes and never rejected as disposable. Catch-all domains are surfaced as cases where acceptance is not a guarantee.

Inputs

Field Required Source
email yes from a previous emails job, or imported
nom no passed through to the output
telephone no passed through
site_web no passed through

needs: ['email']. Items missing an @ are discarded at job creation. Duplicates are deduplicated on the lowercased address. The job accepts between 1 and 10000 items per call.

source_job_id is optional and points to the emails job whose output is being verified. The UI surfaces this picker as from_jobs_of_type: 'emails'.

Outputs

The job produces a verification report. Each row carries the verified address and the verdict; the input columns are kept.

Column Type Meaning
email string Lowercased address as submitted
status string Deliverability verdict (see values below)
category string How the verdict was reached: smtp, syntax, disposable, suspect, big_provider, no_mx, mx_only, error
reason string Human-readable explanation of the verdict
suggested_fix string Suggested correction for an obvious typo, when detected (optional)
smtp_code string Raw SMTP response code from the probe, when an SMTP check ran
catch_all string yes, no or unknown: whether the domain accepts any address
nom string Passed through from input
telephone string Passed through from input
site_web string Passed through from input

status takes one of:

Value Meaning
valid The receiving server accepted the address
valid_catch_all Accepted, but the domain is catch-all so acceptance is not a guarantee
invalid The server rejected the address
greylisted Temporarily deferred by the server; can be retried later
unknown Could not be determined (timeout, blocked probe, MX-only mode)
filtered Rejected before the SMTP step: bad syntax, disposable, suspect prefix or no MX (see category)
skipped Large consumer mail provider (Gmail, Outlook, Orange, and so on) that refuses probes: the mailbox cannot be checked

The signal columns (status, category) are declared in the module registry under produces. They are the columns downstream filter and sort nodes branch on.

Lifecycle

Standard job states. See Jobs lifecycle. Progress is reported per email (progress_unit: 'emails').

Pipeline

The module declares the following contract:

Property Value
needs email
produces status, category
category verify
pipelinable true
supports_veille false

In a pipeline, verify_emails accepts any upstream node that emits email (typically emails or import). Its verified output can be wired into a downstream filter or sort node: filter on status to keep only accepted rows (for example status in valid, valid_catch_all). The pipeline builder does not accept enrichment nodes after verify_emails.

Endpoints

Create a job

POST /api/jobs/verify-emails

Body:

{
  "items": [
    { "email": "alex@example.com", "nom": "Alex", "site_web": "https://example.com" },
    { "email": "contact@example.org" }
  ],
  "source_job_id": "f3c2…"
}

source_job_id is optional. items is required, with at least one record and at most 10000.

Response: JobPublic (the standard job envelope).

Read a job

The standard job endpoints apply:

GET  /api/jobs/{id}
GET  /api/jobs/{id}/events     # SSE stream
GET  /api/jobs/{id}/download   # CSV

For per-job and per-account caps, see Limits. Throughput is capped at 15 verifications per second across 4 workers, with up to 3 SMTP attempts per address, so the outbound IP does not get flagged by mail providers. In MX-only mode (no SMTP probe) the cap rises to 80 per second. Concurrency: the job runs on the parallel worker pool, so a verify_emails job never blocks a scraping job and is never blocked by one.

Errors

Code Condition
400 Aucun email valide dans la liste: items empty, every entry missing @, or all entries are duplicates
400 Quota dépassé: estimated cost exceeds MAX_EF_PER_JOB
401 Caller is not an active user
422 Payload does not match VerifyEmailsJobCreateRequest

Per-item failures (timeout on MX, refused SMTP probe, etc.) do not fail the job. The row is written with status = unknown and the job advances.

What's next