Developer Integration Guide 2026

Next.js Email Verification

Build real-time email verification into Next.js signup forms, checkout pages, and API routes. 25ms API response time means zero UX friction while blocking 94% of fake signups, catching typos, and preventing disposable emails from entering your database.

25ms
API Response Time
94%
Fake Signups Blocked
99.9%
Validation Accuracy

The Cost of Unverified Signup Forms

Every signup form without email validation is an open door for fake accounts, spam submissions, and data that degrades your entire system. The impact compounds with scale.

12%
Invalid Emails at Signup
94%
Fake Accounts Blocked
7%
Leads Lost to Typos
73%
Support Tickets from Bad Data

What Happens Without Signup Form Validation

Without Email Verification

  • Fake accounts proliferate—disposable emails bypass signup walls, inflating user counts
  • Welcome emails bounce—12% of signups never receive onboarding or verification emails
  • CRM data rots—invalid emails contaminate your contact database and downstream workflows
  • Support burden grows—73% of "didn't receive email" tickets trace back to bad signups

With Real-Time Verification

  • Clean user database—every account has a verified, deliverable email address
  • 99.4% delivery rate—welcome and transactional emails consistently reach inboxes
  • Typo recovery—7% more leads captured through auto-correction suggestions
  • 87% fewer support tickets—eliminates the "never got my email" category entirely

No Email Verification

Monthly Signups10,000
Invalid / Fake Emails1,200 (12%)
Disposable Email Signups480 (4.8%)
Lost Typos (Unrecoverable)700 (7%)
Valid Users Gained7,620

With Real-Time Verification

Monthly Signups10,000
Invalid Emails Blocked1,140 (before submission)
Disposables Blocked480 (100%)
Typos Recovered700 (auto-corrected)
Valid Users Gained9,080

Why Email Verification Belongs in Your Next.js App

A signup form without email verification accepts 12% invalid addresses—disposable emails, typos, and fabricated entries that pollute your database, inflate user counts, and break your email sequences. Real-time verification at the form level catches these problems before submission, with 25ms API response time that adds zero perceived delay to the user experience.

What Gets Validated (And Why It Matters)

Email verification isn't a single check—it's a pipeline of validations that progressively confirms an email is real, deliverable, and safe to accept. Each layer catches a different type of bad data:

The 6-Layer Validation Pipeline

1
RFC 5322 Syntax Check

Validates the email conforms to the Internet message format standard—correct structure, allowed characters, proper domain format. Catches entries like "user@" or "@domain.com"

2
DNS & MX Record Verification

Confirms the email domain exists and has mail exchange (MX) records configured. Catches entries like "user@nonexistent-domain.xyz"

3
SMTP Mailbox Verification

Connects to the recipient's mail server and verifies the mailbox exists—without sending an email. Catches "john.doe@gmail.com" when the account has been deleted

4
Disposable Email Detection

Checks against a database of 5,000+ temporary email services (Mailinator, Guerrilla Mail, 10minutemail). Blocks fake signups at the source

5
Typo Detection & Correction

Fuzzy matching identifies common misspellings: gmial.com, gmai.com, yaho.com, hotmal.com. Returns a suggestion for one-click correction

6
Risk Scoring

Combines all signals into a risk score (0-100). Free providers, catch-all domains, and role-based addresses get higher risk scores for downstream filtering

Setting Up Email Verification in Next.js

There are three integration patterns for Next.js apps, depending on where validation happens. Each has trade-offs between security, performance, and user experience.

Pattern 1: Next.js API Route (Server-Side Validation)

The most secure approach. Validation runs on your server before data reaches your database. The email never leaves your infrastructure until it's confirmed valid. Use this for signup form submissions, checkout forms, and any data that gets persisted.

// app/api/validate/route.ts
import { NextRequest, NextResponse } from 'next/server';

interface ValidationResponse {
  email: string;
  status: 'deliverable' | 'undeliverable' | 'unknown' | 'accept_all';
  suggestion?: string;
  disposable: boolean;
  roleBased: boolean;
  freeProvider: boolean;
  mxRecords: boolean;
  smtpCheck: boolean;
  riskScore: number;
}

export async function POST(request: NextRequest) {
  const { email } = await request.json();

  if (!email || typeof email !== 'string') {
    return NextResponse.json(
      { error: 'Email is required' },
      { status: 400 }
    );
  }

  const response = await fetch(
    'https://api.email-check.app/v1/validate',
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.EMAIL_CHECK_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ email })
    }
  );

  const result: ValidationResponse = await response.json();

  // Block disposable and role-based emails at submission
  if (result.disposable || result.roleBased) {
    return NextResponse.json({
      valid: false,
      reason: result.disposable
        ? 'disposable_email'
        : 'role_based_email'
    });
  }

  // Allow catch-all and accept_all with a warning
  if (result.status === 'accept_all' || result.status === 'unknown') {
    return NextResponse.json({
      valid: true,
      email: result.suggestion || email,
      warning: 'delivery_not_guaranteed',
      riskScore: result.riskScore
    });
  }

  return NextResponse.json({
    valid: result.status === 'deliverable',
    email: result.suggestion || email,
    riskScore: result.riskScore
  });
}

Pattern 2: Client-Side with Debounced Validation

Real-time feedback as users type. Validates on each typing pause (debounced at 400ms) and shows inline results: green checkmark for valid, error for invalid, and suggestion button for typos. This pattern provides the best UX but requires exposing your API key through a server proxy.

// components/email-verification-input.tsx
'use client';
import { useState, useCallback, useRef } from 'react';

interface ValidationResult {
  valid: boolean;
  email: string;
  suggestion?: string;
  warning?: string;
  reason?: string;
}

export function EmailVerificationInput({
  value,
  onChange,
  onSubmit
}: {
  value: string;
  onChange: (email: string) => void;
  onSubmit: () => void;
}) {
  const [status, setStatus] = useState<
    'idle' | 'validating' | 'valid' | 'invalid' | 'warning'
  >('idle');
  const [suggestion, setSuggestion] = useState('');
  const [message, setMessage] = useState('');
  const debounceRef = useRef<NodeJS.Timeout>();

  const validate = useCallback(async (email: string) => {
    if (!email.includes('@')) {
      setStatus('idle');
      return;
    }

    setStatus('validating');

    try {
      const response = await fetch('/api/validate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email })
      });

      const result: ValidationResult = await response.json();

      if (result.valid) {
        if (result.warning) {
          setStatus('warning');
          setMessage('This mailbox may not receive all emails');
        } else {
          setStatus('valid');
          setMessage('');
        }
      } else {
        setStatus('invalid');
        if (result.reason === 'disposable_email') {
          setMessage('Please use a permanent email address');
        } else if (result.reason === 'role_based_email') {
          setMessage('Please use a personal email address');
        } else {
          setMessage('Please enter a valid email address');
        }
      }

      if (result.suggestion) {
        setSuggestion(result.suggestion);
      }
    } catch {
      setStatus('idle');
    }
  }, []);

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const email = e.target.value;
    onChange(email);
    setSuggestion('');

    clearTimeout(debounceRef.current);
    debounceRef.current = setTimeout(
      () => validate(email),
      400
    );
  };

  const acceptSuggestion = () => {
    onChange(suggestion);
    setSuggestion('');
    validate(suggestion);
  };

  return (
    <div className="space-y-2">
      <div className="relative">
        <input
          type="email"
          value={value}
          onChange={handleChange}
          placeholder="you@example.com"
          className="w-full px-4 py-3 border rounded-lg
            focus:outline-none focus:ring-2"
        />
        {status === 'validating' && (
          <span className="absolute right-3 top-3
            loading loading-spinner loading-sm" />
        )}
      </div>

      {suggestion && (
        <button
          type="button"
          onClick={acceptSuggestion}
          className="text-sm text-blue-600 hover:underline"
        >
          Did you mean {suggestion}?
        </button>
      )}

      {message && status === 'invalid' && (
        <p className="text-sm text-red-600">{message}</p>
      )}
      {message && status === 'warning' && (
        <p className="text-sm text-amber-600">{message}</p>
      )}
    </div>
  );
}

Pattern 3: React Hook Form Integration

For forms managed by React Hook Form (used in production apps), integrate validation as an async validator on the email field. This keeps validation logic alongside other form validation and provides consistent error handling.

// app/(auth)/signup/_components/signup-form.tsx
'use client';
import { useForm } from 'react-hook-form';
import { EmailVerificationInput } from
  '@/components/email-verification-input';

interface SignupFormData {
  name: string;
  email: string;
  password: string;
  company?: string;
}

async function validateEmail(email: string): Promise<boolean> {
  const response = await fetch('/api/validate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email })
  });
  const result = await response.json();
  return result.valid;
}

export function SignupForm() {
  const {
    register,
    handleSubmit,
    setValue,
    watch,
    formState: { errors, isSubmitting }
  } = useForm<SignupFormData>({
    defaultValues: {
      name: '',
      email: '',
      password: '',
      company: ''
    }
  });

  const emailValue = watch('email');

  const onSubmit = async (data: SignupFormData) => {
    // Double-check server-side before creating account
    const isValid = await validateEmail(data.email);
    if (!isValid) {
      throw new Error('Invalid email address');
    }
    await createAccount(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
      {/* Name field */}
      <input
        {...register('name', { required: 'Name is required' })}
        placeholder="Full name"
      />

      {/* Email with real-time verification */}
      <div>
        <input
          {...register('email', {
            required: 'Email is required',
            pattern: {
              value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
              message: 'Enter a valid email format'
            },
            validate: validateEmail
          })}
          placeholder="you@example.com"
        />
        {errors.email && (
          <p className="text-red-600 text-sm">
            {errors.email.message}
          </p>
        )}
      </div>

      {/* Password field */}
      <input
        {...register('password', {
          required: 'Password is required',
          minLength: {
            value: 8,
            message: 'Password must be at least 8 characters'
          }
        })}
        type="password"
        placeholder="Create a password"
      />

      <button
        type="submit"
        disabled={isSubmitting}
        className="w-full bg-blue-600 text-white py-3
          rounded-lg font-semibold disabled:opacity-50"
      >
        {isSubmitting ? 'Creating account...' : 'Create Account'}
      </button>
    </form>
  );
}

Understanding the API Response

The Email-Check.app API returns structured data you can use to make granular decisions about each email address. Here's a typical response:

API Response Structure

{ "email": "user@gmial.com", "status": "undeliverable", "suggestion": "user@gmail.com", "disposable": false, "roleBased": false, "freeProvider": true, "mxRecords": false, "smtpCheck": false, "riskScore": 92, "didYouMean": "user@gmail.com", "formatValid": true, "domain": "gmial.com" }

Decision logic for your app:

  • status: "deliverable" — Accept the email, proceed with signup
  • status: "undeliverable" — Block submission, show error
  • suggestion present — Show "Did you mean?" with one-click correction
  • disposable: true — Block with message "Use a permanent email address"
  • roleBased: true — Block or warn (depends on your use case)
  • status: "accept_all" — Accept with warning (catch-all domain)

Bulk Validation for Existing Data

If you already have a user database with unverified emails, run a bulk validation pass before your next campaign. Email-Check.app supports CSV upload with results you can download and import directly:

// Bulk validation via API for existing user lists
// Pass emails as an array for batch processing

const response = await fetch(
  'https://api.email-check.app/v1/validate/bulk',
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.EMAIL_CHECK_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      emails: [
        'user1@example.com',
        'user2@gmial.com',
        'user3@company.com',
        'test@10minutemail.com'
      ]
    })
  }
);

const results = await response.json();

// results.status contains breakdown:
// - deliverable:  emails confirmed valid
// - undeliverable: emails that bounce
// - disposable:    temporary email services
// - accept_all:    catch-all domains
// - unknown:       could not verify

// Download cleaned list from the dashboard:
// 1. Upload your CSV (name, email columns)
// 2. Choose validation checks to run
// 3. Download results with columns:
//    email, status, suggestion, riskScore, disposable
// 4. Import cleaned list back to your CRM/database

UX Patterns That Preserve Conversion

Aggressive validation hurts signup conversion if implemented poorly. Follow these patterns to protect data quality without friction:

UX Rules for Signup Form Verification

  1. Validate on blur, confirm on submit—check the email when the user leaves the field, but only block submission for hard failures
  2. Debounce at 400ms—validate after typing pauses, not on every keystroke, to avoid unnecessary API calls
  3. Show loading states—a subtle spinner during the 25ms API call builds trust that something is happening
  4. Use positive messaging—"Did you mean gmail.com?" instead of "Invalid email" reduces form abandonment
  5. Never clear other form fields—validation should only affect the email input, never wipe name or password fields
  6. Soft block catch-alls, hard block disposables—warn for uncertain domains but absolutely block temporary email services

Environment Configuration

Store your API key in environment variables and access it through Next.js built-in env support:

// .env.local (never commit this file)
EMAIL_CHECK_API_KEY=your_production_api_key_here

// For Next.js App Router, the key is automatically
// available in server components and API routes
// via process.env.EMAIL_CHECK_API_KEY

// .env.example (commit this)
EMAIL_CHECK_API_KEY=your_api_key_here

// next.config.ts - if using the key in client code
// (not recommended - use API route proxy instead)
// next.config.ts
const nextConfig = {
  env: {
    NEXT_PUBLIC_API_URL: process.env.EMAIL_CHECK_API_URL
  }
};

Case Study: SaaS Platform Blocks 94% of Fake Signups

A B2B SaaS platform with 45,000 monthly signups integrated real-time email verification at their Next.js signup form using Pattern 2 (client-side with debounced validation). Results after 30 days:

Before Verification

  • • 45,000 monthly signups
  • • 5,400 invalid emails accepted (12%)
  • • 2,160 disposable email signups (4.8%)
  • • 3,150 typos with no correction (7%)
  • • 1,800 welcome emails bounced daily
  • • 73% of support tickets: email-related
  • • Sender reputation declining monthly

After Real-Time Verification

  • • 45,000 monthly attempts
  • • 1,080 invalid emails blocked (94% catch rate)
  • • 0 disposable signups (100% blocked)
  • • 2,940 typos auto-corrected (93% recovery)
  • • 180 welcome emails bounced daily (90% reduction)
  • • 8% of support tickets: email-related
  • • Sender reputation: stable "High"

Implementation detail: The team chose client-side debounced validation (Pattern 2) for immediate feedback during typing, combined with server-side re-validation at form submission for security. This dual approach catches both UX-level issues (typos) and programmatic abuse (bot submissions with fake emails) without adding visible latency.

Common Mistakes to Avoid

MistakeImpactFix
Only using regex validationAccepts fake@anything.comAdd SMTP + MX verification
Validating without debouncingExcessive API calls, slow formDebounce at 300-500ms
Exposing API key in client codeSecurity vulnerabilityUse API route as proxy
Blocking all catch-all domainsLoses 15% of B2B signupsAccept with warning
Only validating at signupExisting data degradesRun bulk validation monthly

Getting Started

Build email verification into your Next.js app in three steps:

  1. Create an API route proxy—never expose your API key in client-side code. Set up /api/validate as a secure proxy that forwards requests to the Email-Check.app API
  2. Add debounced validation to signup forms—validate on typing pause with inline feedback (valid, invalid, suggestion)
  3. Run bulk validation on existing users—upload your user CSV, download cleaned results, and import back to your database

Email-Check.app handles validation with 99.9% accuracy and 25ms average response time—fast enough for real-time form validation without any perceptible delay.

Start with 6,000 Free Validations

Professional plans start at $29/month with 6,000 validations. Set up your API key, add the validation route to your Next.js app, and block fake signups before your next deploy.

View Pricing Plans

Related guides: Learn about SaaS signup form protection strategies, real-time validation API for SaaS, and disposable email detection for fake signup prevention.

Built for Next.js Developers

The Email-Check.app API is designed for developer integration: REST endpoints, TypeScript SDK, and response times that work at every level of your Next.js app.

25ms Average Response

Sub-30ms response time means real-time form validation with zero UX impact. Debounce at 400ms and the API call completes before users notice.

🛡️

99.9% Accuracy

Multi-layer validation pipeline: syntax, DNS, MX records, SMTP mailbox check, disposable detection, and typo correction—all in a single API call.

📦

TypeScript SDK

Auto-generated TypeScript types from OpenAPI schema. Full type safety for request and response objects, with intellisense support in your IDE.

✏️

Typo Correction API

Returns suggested corrections for misspelled domains: gmial.com → gmail.com, yaho.com → yahoo.com. Recover 7% of leads lost to typos.

🚫

Disposable Email Database

5,000+ disposable email domains updated daily. Block temporary email services at signup—prevent fake accounts and spam form submissions.

📊

Risk Scoring Engine

Every email gets a 0-100 risk score combining domain reputation, account type, and deliverability signals. Use risk thresholds to build custom acceptance rules.

Next.js Integration Options Compared

FeatureAPI RouteClient-SideReact Hook Form
Security (Key Protection)✓ Server-sideNeeds proxy✓ Server-side
Real-Time FeedbackOn submit only✓ As-you-type✓ On blur/submit
Typo Correction UX✗ No inline✓ Suggestion buttonCustom needed
Form Library Compatibility✓ Any✓ Any✓ React Hook Form
Bot ProtectionPartial✗ BypassablePartial
Recommended ForCheckouts, secure formsSignup UX optimizationProduction signup forms

Block Fake Signups on Your Next.js App

Join 3,200+ businesses using Email-Check.app to protect signup forms, prevent fake accounts, and maintain a clean user database with 99.9% validation accuracy.

99.9%
Validation Accuracy
25ms
Average API Response Time
94%
Fake Signups Blocked

Professional plans starting at $29/month for 6,000 validations. No free tier. Enterprise pricing available.