Skip to Content
GuidesValidate Email

Validate Email

This guide covers best practices for integrating VerifNow’s email validation into your application — from simple form validation to advanced use cases.


Basic email validation

Send a POST request to /api/v1/validate/email with the value to validate:

POST https://api.verifnow.io/api/v1/validate/email X-API-KEY: your_api_key_here Content-Type: application/json { "value": "user@example.com" }

Example response

{ "valid": true, "message": "Email address is valid but has risk factors", "normalizedValue": "user@example.com", "originalValue": "user@example.com", "validationLevel": "PREMIUM", "emailDetails": { "signals": { "syntax_valid": true, "mx_valid": true, "typo_detected": false, "suggested_domain": null, "disposable": false, "role_based": false, "free_provider": false, "domain_age_days": 11554, "mx_provider": "google", "mx_quality_score": 0.9 }, "risk_score": 30, "risk_level": "MEDIUM", "deliverability": "RISKY", "applied_level": "PREMIUM" } }

Understanding the email signals

syntax_valid

Validates the email against standard syntax rules. An invalid syntax will result in valid: false.

mx_valid

Checks whether the email domain has valid MX (mail exchange) DNS records. Without MX records, the domain cannot receive email.

disposable

Detects whether the address is from a known disposable/temporary email provider (e.g., Mailinator, Guerrilla Mail, 10MinuteMail).

// Example: disposable email detected { "valid": true, "emailDetails": { "signals": { "disposable": true }, "risk_level": "HIGH" } }

role_based

Flags email addresses that are typically shared by multiple people or auto-generated:

  • info@, admin@, support@
  • noreply@, no-reply@
  • postmaster@, webmaster@

typo_detected & suggested_domain

If VerifNow detects a likely typo (e.g., gmal.com instead of gmail.com), typo_detected is true and suggested_domain contains the correction:

{ "valid": false, "emailDetails": { "signals": { "typo_detected": true, "suggested_domain": "gmail.com" } } }

Use this to prompt users to correct their email before submitting.

domain_age_days

The age of the email domain in days. Very young domains may indicate spam or fraud.

mx_provider & mx_quality_score

Identifies the mail provider (e.g., google, apple, microsoft) and assigns a quality score between 0 and 1.

risk_score & risk_level

A 0–100 risk score and a categorical risk level (LOW, MEDIUM, HIGH). Lower scores mean less risk.

deliverability

An overall deliverability assessment: DELIVERABLE, RISKY, UNDELIVERABLE, or UNKNOWN.


Acceptance strategy

Choose the right acceptance strategy based on your use case:

Strict — Block any risky or undeliverable email:

function isEmailAccepted(result) { return result.valid && result.emailDetails.deliverability === 'DELIVERABLE' && !result.emailDetails.signals.disposable && !result.emailDetails.signals.role_based }

Best for: paid signups, enterprise SaaS, financial services


Integration examples

React form validation

import { useState } from 'react' async function validateEmail(email: string) { const response = await fetch('/api/validate-email', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ value: email }), }) return response.json() } export function SignupForm() { const [email, setEmail] = useState('') const [error, setError] = useState('') const [suggestion, setSuggestion] = useState('') const [loading, setLoading] = useState(false) async function handleSubmit(e: React.FormEvent) { e.preventDefault() setLoading(true) setError('') setSuggestion('') const result = await validateEmail(email) if (result.emailDetails?.signals?.typo_detected && result.emailDetails?.signals?.suggested_domain) { const [local] = email.split('@') setSuggestion(`Did you mean ${local}@${result.emailDetails.signals.suggested_domain}?`) } if (!result.valid) { setError('Please enter a valid, reachable email address.') setLoading(false) return } // Continue with form submission... setLoading(false) } return ( <form onSubmit={handleSubmit}> <input type="email" value={email} onChange={e => setEmail(e.target.value)} placeholder="your@email.com" /> {suggestion && <p className="text-yellow-600">{suggestion}</p>} {error && <p className="text-red-600">{error}</p>} <button type="submit" disabled={loading}> {loading ? 'Validating...' : 'Sign Up'} </button> </form> ) }

Next.js API route (server-side proxy)

// app/api/validate-email/route.ts import { NextRequest, NextResponse } from 'next/server' export async function POST(req: NextRequest) { const body = await req.json() const { value } = body if (!value) { return NextResponse.json({ error: 'value is required' }, { status: 400 }) } const response = await fetch('https://api.verifnow.io/api/v1/validate/email', { method: 'POST', headers: { 'X-API-KEY': process.env.VERIFNOW_API_KEY!, 'Content-Type': 'application/json', }, body: JSON.stringify({ value }), }) const data = await response.json() return NextResponse.json(data) }

Security tip: Always proxy API calls through your backend to keep your API key secret. Never call the VerifNow API directly from client-side JavaScript.

Last updated on