Email Validation API for JavaScript: Real-Time Signup Protection
Learn how to integrate email validation into JavaScript applications. Covers React form validation, vanilla JS, and Node.js with the MailOdds TypeScript SDK.
Contents
Invalid email signups cost businesses money and damage deliverability. Every hard bounce chips away at your sender reputation, pushing legitimate emails into the spam folder. According to data published by HubSpot, the average email list decays by 22.5% annually, making real-time validation at the point of entry a technical necessity rather than a nice-to-have.
Most JavaScript developers start with a regex pattern in their signup form and call it a day. The problem: regex can only check whether a string looks like an email address. It cannot tell you whether the mailbox actually exists, whether the domain is a disposable email provider, or whether the server is a catch-all that accepts everything. API-based validation solves all of these problems by checking the actual mail server in real time.
This guide walks through three integration patterns: vanilla JavaScript for static sites, React with TypeScript for modern SPAs, and server-side Node.js for API routes. Each example is production-ready and follows the fail-open principle so your signup flow never breaks.
Why Not Just Use Regex?
The email address format defined in RFC 5322 is notoriously complex. According to RFC 5322 Section 3.4, valid email addresses can include quoted strings, comments, and domain literals, making comprehensive regex validation practically impossible. A regex pattern that correctly handles every valid address would span thousands of characters and still miss edge cases.
Beyond format, regex cannot answer the questions that actually matter for deliverability:
- Does the mailbox actually exist on the receiving server?
- Is the domain a disposable email provider like Mailinator or Guerrilla Mail?
- Is the server configured as catch-all, accepting mail for any address regardless of whether it exists?
- Is the address a role account (info@, support@) that typically has lower engagement?
An API-based validator performs syntax checks, DNS lookups, and SMTP mailbox verification in a single call, returning a structured response you can act on. For more on the five levels of validation, see the email validation rules guide.
Step 1: Install the MailOdds TypeScript SDK
The MailOdds TypeScript SDK works in Node.js, Deno, and browser environments. Install it from npm:
npm install mailoddsConfigure the client with your API key:
import { MailOdds } from 'mailodds';
const client = new MailOdds({
apiKey: process.env.MAILODDS_API_KEY,
baseUrl: 'https://api.mailodds.com'
});Get your API key from the dashboard. The free tier includes 50 validations per month with no credit card required.
Step 2: Vanilla JavaScript Form Validation
For static sites, marketing landing pages, or any project without a framework, you can call the MailOdds API directly from a form submit handler. This example validates the email before allowing the form to proceed.
<form id="signup-form">
<input type="email" id="email" placeholder="you@company.com" />
<span id="email-status"></span>
<button type="submit">Sign Up</button>
</form>const form = document.getElementById('signup-form');
const emailInput = document.getElementById('email');
const status = document.getElementById('email-status');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const email = emailInput.value.trim();
status.textContent = 'Validating...';
try {
const response = await fetch('https://api.mailodds.com/v1/validate', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ email })
});
const result = await response.json();
if (result.action === 'reject') {
status.textContent = 'This email appears to be invalid.';
status.style.color = 'red';
} else if (result.action === 'flag') {
status.textContent = 'This email may have issues. Please verify.';
status.style.color = 'orange';
} else {
status.textContent = 'Email verified!';
status.style.color = 'green';
form.submit();
}
} catch (error) {
// Fail open: allow signup if validation service is unreachable
form.submit();
}
});Fail-open pattern
If the validation API is unreachable due to a network issue or timeout, the catch block allows the signup to proceed. This ensures your registration flow never breaks, even during an outage. You can clean invalid addresses later with bulk validation.
Step 3: React Form Validation with TypeScript
In React applications, you can wrap the validation logic in a
component with state management. This example uses the
MailOdds TypeScript SDK and highlights the did_you_mean field, which suggests corrections for common typos like
"gmial.com" or "yaho.com".
import { useState } from 'react';
import { MailOdds } from 'mailodds';
const client = new MailOdds({
apiKey: process.env.NEXT_PUBLIC_MAILODDS_KEY!,
baseUrl: 'https://api.mailodds.com'
});
interface ValidationResult {
status: string;
action: string;
sub_status: string;
did_you_mean: string | null;
}
export function SignupForm() {
const [email, setEmail] = useState('');
const [validating, setValidating] = useState(false);
const [result, setResult] = useState<ValidationResult | null>(null);
const handleValidate = async () => {
if (!email) return;
setValidating(true);
try {
const res = await client.validate({ email });
setResult(res);
} catch {
// Fail open
setResult({ status: 'unknown', action: 'accept',
sub_status: '', did_you_mean: null });
} finally {
setValidating(false);
}
};
return (
<form onSubmit={(e) => { e.preventDefault(); handleValidate(); }}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="you@company.com"
/>
{result?.did_you_mean && (
<p>Did you mean {result.did_you_mean}?
<button type="button"
onClick={() => setEmail(result.did_you_mean!)}>
Use suggestion
</button>
</p>
)}
{result?.action === 'reject' && (
<p style={{ color: 'red' }}>
Invalid email: {result.sub_status.replace(/_/g, ' ')}
</p>
)}
<button type="submit" disabled={validating}>
{validating ? 'Validating...' : 'Sign Up'}
</button>
</form>
);
}The did_you_mean field is one of the most impactful features for signup
conversion. When a user types "jane@gmial.com", the API
returns a suggestion of "jane@gmail.com". Displaying this
suggestion inline prevents a valid user from being blocked by
a simple typo, and reduces support tickets from users who
never received their confirmation email.
Step 4: Server-Side Validation with Node.js
For production applications, server-side validation is the recommended approach. Your API key stays on the server and is never exposed to the browser. This is especially important if you want to block disposable email addresses, since a determined user could bypass client-side checks.
import express from 'express';
import { MailOdds } from 'mailodds';
const app = express();
const client = new MailOdds({
apiKey: process.env.MAILODDS_API_KEY!,
baseUrl: 'https://api.mailodds.com'
});
app.post('/api/signup', async (req, res) => {
const { email, name } = req.body;
// Server-side validation (API key stays secret)
const validation = await client.validate({ email });
if (validation.action === 'reject') {
return res.status(400).json({
error: 'Invalid email address',
reason: validation.sub_status
});
}
if (validation.disposable) {
return res.status(400).json({
error: 'Disposable email addresses are not allowed'
});
}
// Proceed with user registration
// ...
res.json({ success: true });
});This pattern works with any Node.js framework: Express, Fastify, Next.js API routes, or Hono. The key principle is the same: validate on the server, reject before writing to your database. See the full TypeScript SDK documentation for additional methods including bulk validation and webhook setup.
Handling Edge Cases
Production email validation involves several edge cases that are easy to overlook during initial integration. Here are the most common scenarios and how to handle them:
Catch-all domains
Some mail servers accept mail for any address at their
domain, making it impossible to confirm whether a specific
mailbox exists. The API returns a catch_all status for these. Treat them as a flag rather than a hard
reject, since many legitimate business domains use catch-all
configurations.
Rate limiting
MailOdds returns a 429 status code with a Retry-After header when you exceed your plan's rate limit. The TypeScript
SDK handles retries automatically. If you are calling the API
directly, read the header value and wait before retrying.
Timeouts
Set a reasonable timeout of 5 seconds for validation requests. If the request times out, follow the fail-open pattern: allow the signup and validate the address asynchronously later. A slow SMTP server should not block your user from completing registration.
Disposable emails
Whether to block disposable email addresses depends on
your use case. SaaS signup forms typically block them to
prevent abuse. Newsletter signups may accept them since the
cost of a disposable subscriber is low. The disposable boolean in the response gives you the flexibility to decide.
Google and Yahoo Sender Requirements
According to Google's 2024 Bulk Sender Guidelines and Yahoo's corresponding requirements, senders processing more than 5,000 emails per day must maintain bounce rates below 0.3% and implement one-click unsubscribe. Violating these thresholds results in throttling or outright blocking of your sending domain.
Validating email addresses before they enter your system is the most effective way to meet these requirements. A single validation call at signup prevents hard bounces from ever reaching your sending infrastructure. Combined with proper authentication (SPF, DKIM, DMARC), real-time validation forms the foundation of a healthy sender reputation.
For a deeper look at building and maintaining sender reputation, see the email deliverability guide.
Related Resources
Start validating emails in JavaScript
Install the MailOdds TypeScript SDK and validate your first email in under 2 minutes. 50 free validations per month, no credit card required.