Node.js and TypeScript power modern SaaS authentication flows, Next.js App Router applications, and serverless API gateways. Adding real-time email verification at the point of capture blocks disposable burner signups that drain AI token budgets, prevents typo bounces, and keeps your transactional sender reputation spotless at just $0.0002 to $0.00059 per check.
1. TypeScript Interfaces & Native fetch Client
In Node.js 20+ and Next.js 15, you do not need heavy third-party HTTP dependencies like axios or node-fetch. Built-in Undici-backed fetch paired with AbortSignal.timeout(3500) guarantees that a slow downstream DNS or MX lookup never blocks your Node.js event loop or delays a customer registration request.
MailVeri returns 7 explicit verification statuses (VALID, INVALID, DISPOSABLE, ROLE_ACCOUNT, CATCH_ALL, FULL_INBOX, and UNKNOWN) along with boolean flags for disposable providers, role aliases, and catch-all servers—and automatically refunds 100% of credits whenever a check returns UNKNOWN:
export type MailVeriStatus =
| 'VALID'
| 'INVALID'
| 'DISPOSABLE'
| 'ROLE_ACCOUNT'
| 'CATCH_ALL'
| 'FULL_INBOX'
| 'UNKNOWN';
export interface MailVeriResponse {
email: string;
status: MailVeriStatus;
is_disposable: boolean;
is_role_account: boolean;
is_catch_all: boolean;
mx_found: boolean;
credits_used: number;
}
export async function verifyEmail(email: string): Promise<MailVeriResponse> {
const response = await fetch('https://api.mailveri.com/v1/verify-mail/', {
method: 'POST',
headers: {
'X-Api-Key': process.env.MAILVERI_API_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify({ email: email.trim().toLowerCase() }),
signal: AbortSignal.timeout(3500),
});
if (!response.ok) {
throw new Error(`MailVeri API error: ${response.status}`);
}
return (await response.json()) as MailVeriResponse;
}Example JSON payload returned by the MailVeri API when a user attempts to sign up with a disposable burner address:
{
"email": "[email protected]",
"status": "DISPOSABLE",
"is_disposable": true,
"is_role_account": false,
"is_catch_all": false,
"mx_found": true,
"credits_used": 1
}2. Express.js Registration Guard Middleware
If your backend runs on Express or Fastify, attach a lightweight verification middleware to your registration and lead-capture routes. Notice how the middleware gracefully fails open if an external network timeout occurs, flagging the user for mandatory email link verification rather than dropping legitimate traffic:
import type { Request, Response, NextFunction } from 'express';
import { verifyEmail } from './lib/mailveri';
export async function requireDeliverableEmail(
req: Request,
res: Response,
next: NextFunction
) {
const email = req.body?.email;
if (!email || typeof email !== 'string') {
return res.status(400).json({ error: 'A valid email address is required.' });
}
try {
const result = await verifyEmail(email);
if (result.status === 'DISPOSABLE' || result.is_disposable) {
return res.status(422).json({
error: 'Temporary or disposable email addresses are not permitted.',
code: 'DISPOSABLE_EMAIL_BLOCKED',
});
}
if (result.status === 'INVALID' || result.status === 'FULL_INBOX') {
return res.status(422).json({
error: 'This email address cannot receive mail. Please check for typos.',
code: 'UNDELIVERABLE_EMAIL',
});
}
res.locals.emailVerification = result;
return next();
} catch (error) {
// Fail-open on timeout so signup conversion is never blocked
res.locals.emailVerification = { status: 'UNKNOWN', failOpen: true };
return next();
}
}3. Next.js 15 App Router Server Action Integration
In Next.js App Router applications (including Supabase Auth and Clerk signup flows), run email verification inside a Server Action. Your MAILVERI_API_KEY remains 100% server-side with zero client-side JavaScript bundle impact:
'use server';
import { verifyEmail } from '@/lib/mailveri';
export async function submitTrialSignup(formData: FormData) {
const rawEmail = String(formData.get('email') ?? '').trim();
if (!rawEmail.includes('@')) {
return { ok: false, message: 'Please enter a valid email address.' };
}
try {
const check = await verifyEmail(rawEmail);
if (check.status === 'INVALID' || check.status === 'DISPOSABLE') {
return {
ok: false,
message: 'Please use an active work or personal email (no burner domains).',
};
}
} catch {
// Graceful fallback if timeout occurs
}
// Proceed to create user in Supabase / Clerk / Prisma
return { ok: true, message: 'Check your inbox to confirm your account!' };
}4. Node.js Implementation Patterns Compared
| Integration Pattern | Best For | Recommended Timeout | Fallback Strategy |
|---|---|---|---|
| Next.js Server Action | SaaS trial signups, gated content forms | 3,000 – 3,500 ms | Fail-open + require email confirmation link |
| Express / Fastify Middleware | REST APIs, mobile app auth backends | 3,500 – 4,000 ms | Attach UNKNOWN flag & withhold trial AI quota until email link is verified |
| BullMQ / Background Worker | CRM webhook ingestion, CSV imports | 10,000 ms | Exponential backoff retry on HTTP 429/503 |
Explore full request and webhook specifications in the MailVeri API Documentation, and review production integration patterns in our Email Verification API Integration Guide.
