> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Email Verification Warnings

> Reference for every Email Verification risk code: BREACHED_EMAIL_DETECTED, DISPOSABLE_EMAIL_DETECTED, UNDELIVERABLE_EMAIL_DETECTED, blocklist, and OTP caps.

export const WarningTypes = () => <div style={{
  display: "flex",
  flexDirection: "column",
  gap: "12px",
  margin: "16px 0"
}}>
    {WARNING_TYPES.map(w => <div key={w.type} style={{
  display: "flex",
  alignItems: "flex-start",
  gap: "12px",
  padding: "12px 16px",
  borderRadius: "8px",
  background: w.bg
}}>
        <span style={{
  fontSize: "16px",
  lineHeight: "24px"
}}>{w.icon}</span>
        <div>
          <div style={{
  fontWeight: 600,
  color: w.color,
  marginBottom: "2px"
}}>
            <code style={{
  background: "transparent",
  color: w.color,
  fontWeight: 600,
  padding: 0
}}>
              {w.type}
            </code>
          </div>
          <div style={{
  fontSize: "14px",
  lineHeight: "20px",
  color: "#374151"
}}>
            {w.description}
          </div>
        </div>
      </div>)}
  </div>;

The Email Verification feature emits **warnings** whenever a risk signal fires on the OTP flow or the address itself: a known data breach, a disposable provider, an undeliverable mailbox, an OTP attempt cap, or a hit against your blocklist or another approved verification. This page lists every code, what triggers it, and how to configure the workflow response.

## Overview

Warnings are tagged with feature `EMAIL`. They appear on the report under `email_verifications[].warnings[]` and follow the standard [warning object](/reference/data-models#warning-object) shape (`feature`, `risk`, `additional_data`, `log_type`, `short_description`, `long_description`, `node_id`). Each warning is also routed into the per-session log so it surfaces in the Business Console under the Email section.

Some warnings are **hard auto-decline** triggers — they always set the feature status to `Declined` and carry `log_type: "error"`. The others map to a **configurable action** (`DECLINE`, `REVIEW`, or the default `NO_ACTION`) defined per workflow node or per API call, so the same risk code may decline one workflow while only flagging another. The configured action also sets the severity: `DECLINE` → `error`, `REVIEW` → `warning`, `NO_ACTION` → `information`.

## Auto-decline conditions

The following warnings always decline the Email Verification step regardless of configuration:

* `EMAIL_CODE_ATTEMPTS_EXCEEDED` — the user exhausted the OTP budget: 2 wrong code entries (`email_max_check_attempts`) or 2 OTP sends — the initial send plus one resend (`email_max_retries`) — by default.
* `EMAIL_IN_BLOCKLIST` — the address is in a blocklist managed via the [Lists API](/management-api/lists/overview), or matched a previously approved email verification that was blocklisted.
* `UNDELIVERABLE_EMAIL_DETECTED` — the address cannot receive mail: invalid syntax, a non-existent domain, missing DNS (MX) records, or the OTP email could not be delivered. The step finalizes as `Declined` immediately — no code check ever runs. Exception: when the user typed the address themselves (it was not pre-filled at session creation), an undeliverable send returns an inline error so they can retry with a different address instead of being declined.

## Configurable risks

Each of the following risks maps to a setting (per workflow node, or per call on the standalone [check endpoint](/standalone-apis/email-check)) you can configure to `DECLINE`, `REVIEW`, or `NO_ACTION`:

| Setting                   | Risk code                   | Default behavior                                                                                    |
| ------------------------- | --------------------------- | --------------------------------------------------------------------------------------------------- |
| `breached_email_action`   | `BREACHED_EMAIL_DETECTED`   | `NO_ACTION` — surface breach details at `information` level without changing the status.            |
| `disposable_email_action` | `DISPOSABLE_EMAIL_DETECTED` | `NO_ACTION` — flag the throwaway provider at `information` level without changing the status.       |
| `duplicated_email_action` | `DUPLICATED_EMAIL`          | `NO_ACTION` — record the duplicate at `information` level. Skipped when the address is allowlisted. |

Duplicate detection only considers **previously approved** email verifications in the same application, grouped by `vendor_data` — verifications sharing the same `vendor_data` are treated as one end-user and excluded. Leave `vendor_data` empty and every session is treated as a distinct user. If the address is on your email allowlist, the duplicate action is skipped and `EMAIL_IN_ALLOWLIST` is emitted instead.

## Verification attempt limits

The Email Verification feature applies a hard cap on OTP attempts to prevent abuse:

* **Code-entry attempts** — `email_max_check_attempts`, default **2**: the second wrong (or expired) code finalizes the step.
* **Send attempts** — `email_max_retries`, default **2** sends in total (the initial send plus one resend): a further resend request finalizes the step.

Exceeding either cap raises `EMAIL_CODE_ATTEMPTS_EXCEEDED` and auto-declines. You can tune both caps per workflow node.

## Warnings produced

| Tag                            | Severity                                                 | Description                                                                                                                                                                                                                                                                                            |
| ------------------------------ | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `EMAIL_CODE_ATTEMPTS_EXCEEDED` | `error`                                                  | The user exceeded the code-entry or send cap. Auto-declines.                                                                                                                                                                                                                                           |
| `EMAIL_IN_BLOCKLIST`           | `error`                                                  | The address is present in a blocklist created via the [Lists API](/management-api/lists/overview), or matched a blocklisted approved verification. Auto-declines. `additional_data` carries `blocklisted_session_id`, `blocklisted_session_number` and `api_service` (all `null` for a pure list hit). |
| `EMAIL_IN_ALLOWLIST`           | `information`                                            | The address matched an allowlist created via the [Lists API](/management-api/lists/overview), so the duplicate-email action was skipped.                                                                                                                                                               |
| `BREACHED_EMAIL_DETECTED`      | Per `breached_email_action` (`information` by default)   | The address was found in one or more known data breaches. The `breaches[]` array on the report carries the breached service, date and data classes.                                                                                                                                                    |
| `DISPOSABLE_EMAIL_DETECTED`    | Per `disposable_email_action` (`information` by default) | The domain is a known disposable / throwaway provider often used to evade traceability.                                                                                                                                                                                                                |
| `UNDELIVERABLE_EMAIL_DETECTED` | `error`                                                  | The address cannot receive mail (invalid syntax, non-existent domain, missing MX records, or failed delivery). Auto-declines.                                                                                                                                                                          |
| `DUPLICATED_EMAIL`             | Per `duplicated_email_action` (`information` by default) | The address matches a previously approved email verification belonging to a different end-user (grouped by `vendor_data`). `additional_data` carries `duplicated_session_id`, `duplicated_session_number` and `api_service`.                                                                           |

At most one of `EMAIL_IN_BLOCKLIST`, `DUPLICATED_EMAIL` and `EMAIL_IN_ALLOWLIST` fires per attempt — blocklist takes precedence over duplicate, which takes precedence over allowlist.

## Cross-session matches

When an address is detected on previously approved email verifications or on your blocklist, those hits also appear under `email_verifications[].matches[]` (capped at 5 entries). Each match carries `session_id`, `session_number`, `vendor_data`, `verification_date`, `email`, `status`, `is_blocklisted`, `api_service`, and a `source` of `session` (another approved verification) or `list_entry` (a blocklist entry). If the current address is on your email allowlist, Didit keeps the match evidence but emits `EMAIL_IN_ALLOWLIST` instead of applying the duplicate-email action. See the [Email Verification report](/core-technology/email-verification/report-email-verification#cross-session-matches) for the full match schema.

## Example

```json theme={null}
{
  "warnings": [
    {
      "feature": "EMAIL",
      "risk": "EMAIL_IN_BLOCKLIST",
      "additional_data": {
        "blocklisted_session_id": null,
        "blocklisted_session_number": null,
        "api_service": null
      },
      "log_type": "error",
      "short_description": "Email in blocklist",
      "long_description": "The system detected that the email is in the blocklist, which is not allowed.",
      "node_id": "feature_email_1"
    },
    {
      "feature": "EMAIL",
      "risk": "DISPOSABLE_EMAIL_DETECTED",
      "additional_data": null,
      "log_type": "information",
      "short_description": "Disposable email detected",
      "long_description": "The system detected that the email is disposable, which is not allowed.",
      "node_id": "feature_email_1"
    }
  ]
}
```

## Warning types

Each risk is assigned a severity based on your application's configuration. Severities fall into three categories:

<WarningTypes />

## Related

* [Email Verification overview](/core-technology/email-verification/overview) — feature behavior and pricing.
* [Email Verification report](/core-technology/email-verification/report-email-verification) — full response shape including `lifecycle[]` and `matches[]`.
* [Data models — email verification](/reference/data-models#email-verification) — canonical field-by-field schema.
* [Management API — Lists](/management-api/lists/overview) — manage the email blocklist used by `EMAIL_IN_BLOCKLIST`.
