Engineering12 min read

JSON Schema Validation for Email Fields: Complete Guide

Use json schema validation email fields correctly: validate format, handle empty values, add custom rules, and know when to verify deliverability.

B
The Bounceable Team
JSON document passing a validation gate before an email deliverability check

json schema validation email fields is the right first layer for API safety. It tells you whether the payload contains a string that looks like an email address. It does not tell you whether that address can receive mail.

How JSON Schema validates email fields

JSON Schema validates email fields by checking that a value is a string and, if enabled, that it matches the schema’s email format.

The common pattern is:

{
  "type": "object",
  "properties": {
    "email": {
      "type": "string",
      "format": "email"
    }
  },
  "required": ["email"]
}

That gives you two checks:

  • type: "string" rejects numbers, booleans, arrays, objects, and null.
  • format: "email" asks the validator to check email-like syntax.

This is the usual json schema email format pattern. You will also see it described as json schema format email or JSON schema email validation.

But the important limit is this:

JSON Schema checks structure. It does not prove that a mailbox exists, accepts mail, or belongs to a real user.

For example, this can pass JSON Schema validation:

nobody@example.com

It has a valid shape. But it may not be a real mailbox. The domain may not accept mail. The mailbox may not exist. The address may be disposable. The receiving server may accept all addresses and bounce later.

Validator behavior also differs. In some JSON Schema libraries, format is an annotation by default. In others, it can be enforced, disabled, or moved into a separate plugin. You must check your validator and configuration before you rely on it.

Do not assume format: "email" runs in production just because your schema contains it. Write a failing test with an invalid email and confirm your validator rejects it.

Basic JSON Schema examples for email fields

You can model most API email fields with a small set of schema patterns.

Required email field

Use this for signup forms, account creation, checkout accounts, and any payload where email is mandatory.

{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "email": {
      "type": "string",
      "format": "email",
      "maxLength": 254
    }
  },
  "required": ["email"]
}

maxLength: 254 is a practical guardrail. It matches the commonly accepted maximum length for email addresses and prevents oversized input from reaching your application code.

Optional email field

Use this when the field can be absent.

{
  "type": "object",
  "properties": {
    "email": {
      "type": "string",
      "format": "email",
      "maxLength": 254
    }
  }
}

Here, email is valid if omitted. If present, it must be a string in email format.

Nullable email field

If your API uses null to mean “no email,” allow it explicitly.

{
  "type": "object",
  "properties": {
    "email": {
      "type": ["string", "null"],
      "format": "email",
      "maxLength": 254
    }
  }
}

Be careful here. Some validators only apply format when the value is a string. That is usually what you want.

Empty string email field

Avoid empty strings if you control the API. Prefer omitted fields or null.

If you must support empty strings from a legacy form, model them clearly:

{
  "type": "object",
  "properties": {
    "email": {
      "anyOf": [
        {
          "type": "string",
          "format": "email",
          "maxLength": 254
        },
        {
          "const": ""
        }
      ]
    }
  }
}

This makes the behavior explicit. An empty string is allowed, but only because you chose to allow it.

Array of email addresses

Use an array for invites, recipients, approvers, or notification settings.

{
  "type": "object",
  "properties": {
    "recipients": {
      "type": "array",
      "minItems": 1,
      "maxItems": 50,
      "uniqueItems": true,
      "items": {
        "type": "string",
        "format": "email",
        "maxLength": 254
      }
    }
  },
  "required": ["recipients"]
}

uniqueItems: true helps, but it is exact-value matching. It will not treat User@Example.com and user@example.com as duplicates unless you normalize before validation or before storage.

Common API payload patterns

For a signup form, keep the schema strict:

{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "email": { "type": "string", "format": "email", "maxLength": 254 },
    "password": { "type": "string", "minLength": 12 }
  },
  "required": ["email", "password"]
}

For an invite form, validate the sender and recipients:

{
  "type": "object",
  "properties": {
    "fromEmail": { "type": "string", "format": "email" },
    "invitees": {
      "type": "array",
      "items": { "type": "string", "format": "email" },
      "minItems": 1,
      "maxItems": 100
    }
  },
  "required": ["fromEmail", "invitees"]
}

For a lead form, email may be required, while phone and company remain optional:

{
  "type": "object",
  "properties": {
    "email": { "type": "string", "format": "email" },
    "company": { "type": "string", "maxLength": 120 },
    "source": { "type": "string", "maxLength": 80 }
  },
  "required": ["email"]
}

These examples validate payload shape. They do not validate business quality or deliverability.

Common mistakes with JSON Schema email validation

Most production issues come from treating syntax validation as complete email validation.

Relying on regex alone

Email regexes look simple until they fail real users.

A basic regex may reject valid addresses with plus tags, subdomains, longer TLDs, quoted local parts, or internationalized domains. A very loose regex may accept obvious junk.

This is the practical difference in email regex vs JSON schema:

ApproachGood forWeakness
Custom regexSimple UI hintsEasy to make too strict or too loose
JSON Schema format: "email"Standard API shape validationValidator behavior varies
Email verificationDeliverability and risk decisionsRequires a network/API check

Use JSON Schema for structure. Avoid inventing a complex regex unless you have a narrow internal requirement.

Assuming format: "email" is always enforced

This mistake is common with JavaScript validators.

Some validators require a formats package. Some treat format as metadata. Some let you disable strict format checking for performance or compatibility.

Add tests like these:

[
  { "email": "not-an-email" },
  { "email": "@example.com" },
  { "email": "user@" },
  { "email": "user@example.com" }
]

The first three should fail. The last one should pass schema validation.

Rejecting valid addresses with overly strict rules

Do not block addresses just because they include:

  • A + tag, such as alex+trial@example.com
  • A subdomain, such as alex@mail.example.co.uk
  • A newer or longer top-level domain
  • Uppercase characters
  • A hyphen in the domain

You can normalize case for comparison, but do not over-normalize the local part. Domain names are case-insensitive. Local parts are technically case-sensitive, even though most major providers treat them as case-insensitive.

Accepting syntactically valid but undeliverable emails

This address can pass format: "email":

made-up-mailbox@real-company-domain.com

It may still bounce. JSON Schema does not check MX records. It does not ask the receiving mail server whether the mailbox exists. It does not detect catch-all behavior. It does not know whether the domain is disposable.

That gap matters when you send password resets, onboarding emails, sales sequences, invoices, or product invites.

Forgetting normalization and typo handling

Normalize before you validate and store:

  • Trim leading and trailing whitespace.
  • Convert the domain to lowercase.
  • Convert obvious Unicode domain input to a consistent representation if your stack supports it.
  • Deduplicate after normalization.
  • Suggest fixes for common domain typos, such as gmial.com to gmail.com.

Typo handling is not the same as validation. Treat it as a correction step. Ask the user to confirm the fixed address.

Using JSON Schema email validation with Ajv and other validators

With Ajv, email format validation usually requires adding the formats package and enabling format checks.

For Ajv v7 and v8, install ajv-formats:

npm install ajv ajv-formats

Then configure validation:


const ajv = new Ajv({ allErrors: true });
addFormats(ajv);

const schema = {
  type: "object",
  additionalProperties: false,
  properties: {
    email: {
      type: "string",
      format: "email",
      maxLength: 254
    }
  },
  required: ["email"]
};

const validate = ajv.compile(schema);

console.log(validate({ email: "user@example.com" })); // true
console.log(validate({ email: "not-an-email" })); // false
console.log(validate.errors);

That is the core of Ajv email format validation.

If you use another validator, check three things:

  1. Does it support the JSON Schema draft you use?
  2. Does it enforce format: "email" by default?
  3. Does it use the same email format behavior in frontend and backend code?

Server-side validation should be the source of truth. Frontend validation improves UX, but users can bypass it. Mobile clients can lag behind. Browser extensions can alter requests. Your API must reject invalid payloads on its own.

For consistent validation between frontend and backend:

  • Share schema files where practical.
  • Pin validator versions.
  • Run the same test cases in both environments.
  • Avoid adding stricter frontend-only email rules.
  • Return machine-readable error codes from the API.

Test edge cases before shipping:

valid:
user@example.com
user.name+tag@example.co.uk
USER@EXAMPLE.COM

invalid:
plainaddress
user@
@example.com
user example@example.com
user@example

You do not need to accept every obscure RFC-valid address. You do need predictable behavior that matches your product requirements.

JSON Schema vs real email verification

JSON Schema validation and real email verification answer different questions.

JSON Schema asks: “Does this field look like an email address in a valid payload?”

Email verification asks: “Should I trust this address enough to send to it?”

CheckJSON Schema format: "email"Email verification
Field is presentYes, with requiredNo
Value is a stringYesNo
Email-like syntaxYes, if format is enforcedYes
Domain has mail recordsNoYes
Mailbox appears reachableNoOften, via SMTP probing
Disposable domain detectionNoYes
Catch-all detectionNoYes
Role account detectionNoOften
Typo suggestionsNoOften
Bounce risk scoringNoYes

A valid JSON Schema email can still bounce because deliverability depends on systems outside your payload:

  • The domain may not have valid MX records.
  • The mailbox may not exist.
  • The domain may accept all recipients and later drop or bounce mail.
  • The address may be disposable.
  • The recipient server may reject mail from your sending infrastructure.
  • The user may have mistyped a real domain.

Call an email field validation API after schema validation when the email affects revenue, authentication, sender reputation, or workflow quality.

Good places to verify:

  • During signup, before sending a confirmation email
  • Before creating sales leads
  • Before sending product invites
  • Before importing a CSV into your CRM or ESP
  • Before launching a lifecycle or cold outreach campaign

A verification result might look like this:

{
  "email": "alex@example.com",
  "verdict": "risky",
  "riskScore": 62,
  "checks": {
    "syntax": true,
    "mx": true,
    "smtp": "unknown",
    "disposable": false,
    "catchAll": true,
    "role": false
  },
  "suggestion": null
}

That gives your application more than pass/fail. You can route risky addresses differently.

A production-ready email validation flow

A production flow should separate payload correctness from deliverability decisions.

Step 1: normalize input

Normalize before validation where safe:

function normalizeEmailInput(value) {
  if (typeof value !== "string") return value;

  const trimmed = value.trim();
  const at = trimmed.lastIndexOf("@");

  if (at === -1) return trimmed;

  const local = trimmed.slice(0, at);
  const domain = trimmed.slice(at + 1).toLowerCase();

  return `${local}@${domain}`;
}

Do not blindly lowercase the full address unless your business rules allow it. Lowercase the domain. Be cautious with the local part.

Step 2: validate JSON payload shape with JSON Schema

Run your schema validator next. Reject malformed payloads early.

This protects your application from bad types, missing fields, oversized strings, extra properties, and structurally invalid email fields.

Step 3: verify deliverability with an email verification API

After the schema passes, call email deliverability validation for addresses that matter.

This is where a service such as Bounceable fits. It can check deliverability signals, disposable domains, catch-all behavior, role accounts, typo suggestions, and bounce risk before you send.

Step 4: store verdicts and risk metadata

Store the verification result with the email record:

{
  "email": "alex@example.com",
  "emailStatus": "risky",
  "emailRiskScore": 62,
  "emailRiskReasons": ["catch_all"],
  "emailVerifiedAt": "2026-06-13T12:00:00Z"
}

This helps support, analytics, campaign routing, and auditability. It also prevents repeated verification calls for the same unchanged address.

Step 5: decide whether to accept, warn, block, or request correction

Do not treat every non-deliverable signal the same.

Use clear policy:

VerdictSuggested action
DeliverableAccept and proceed
RiskyAccept with warning, suppress from campaigns, or route for review
UndeliverableBlock or request a different email
UnknownAllow for low-risk flows; require confirmation for high-risk flows

A password reset flow should be strict. A newsletter preference form can be more forgiving. A bulk outbound campaign should be stricter because bounces affect sender reputation.

Different forms need different email validation rules. Use the same primitives, but change the policy.

Signup forms

For signup forms, validate in real time and suggest corrections.

Recommended rules:

  • Trim whitespace.
  • Validate with JSON Schema on the server.
  • Run real-time verification before sending confirmation mail.
  • Show typo suggestions for common domains.
  • Block clearly undeliverable or disposable addresses if they create abuse.
  • Let the user correct the address before account creation or before activation.

Keep the error copy specific:

This email address looks misspelled. Did you mean alex@gmail.com?

That works better than:

Invalid email.

Lead capture

For lead capture, avoid throwing away every risky address automatically.

Recommended rules:

  • Require a syntactically valid email.
  • Verify deliverability after submit.
  • Accept risky addresses, but route them differently.
  • Flag disposable, role, and free-provider addresses if sales quality matters.
  • Suppress undeliverable addresses from automated sequences.

A risky lead may still be useful. A catch-all corporate domain can hide a real buyer. Route based on risk instead of blocking too aggressively.

Invitations

For invitations, check deliverability before sending.

Recommended rules:

  • Validate every invitee address in the array.
  • Deduplicate normalized addresses.
  • Verify each recipient.
  • Block undeliverable recipients before sending.
  • Warn the sender about risky or catch-all recipients.
  • Log who invited whom and when.

This prevents wasted invites and confusing “I never got it” support tickets.

Bulk imports

For bulk imports, verify before campaigns.

Recommended rules:

  • Validate CSV shape first.
  • Normalize and deduplicate addresses.
  • Batch verify the list before adding it to active sending segments.
  • Suppress undeliverable and disposable addresses.
  • Segment risky and unknown addresses for lower-volume testing or manual review.
  • Store verification timestamps so you know when data went stale.

For large lists, validate syntax first. Then verify deliverability. You avoid spending verification calls on rows that fail basic schema or import rules.

Internal admin tools

For internal tools, optimize for clarity and traceability.

Recommended rules:

  • Use the same backend schema as public APIs.
  • Show exact validation errors.
  • Require confirmation before overriding risky or undeliverable results.
  • Log manual overrides.
  • Store the previous and new email values.
  • Re-verify when an admin changes an email address.

Admins need enough context to make safe exceptions. Give them verdicts, reasons, timestamps, and audit logs.

JSON Schema gives you the first reliable gate: the payload is shaped correctly, and the email field looks like an email address. Real verification gives you the second gate: the address is likely safe to send to. Use both, in that order.

Catch bad addresses before they bounce.
Verify your list free

Frequently asked questions

Keep reading