When building a website that requires user registration, you may want to ensure that users sign up with their professional or personal domain rather than free email services like Gmail or Yahoo. Blocking registrations from these domains can help businesses avoid spam, ensure higher user quality, or restrict access to specific organizational users.
In this post, we’ll walk through how to implement this restriction in your Next.js application using Zod, a popular schema validation library, alongside TypeScript. This approach allows you to validate user input with custom logic, helping you prevent sign-ups from free email providers.
Why Block Free Email Providers?
Free email services such as Gmail, Yahoo, or ProtonMail are convenient for most users, but there are several scenarios where you might want to block them:
- Spam Prevention: Free email addresses are often associated with spam accounts.
- Business Context: You may want to allow only corporate email addresses.
- Security Concerns: Disposable or free email accounts may be used for malicious activities.
Step-by-Step Guide to Block Free Email Providers Using Zod
Let’s start by setting up the validation schema.
Set Up Zod in Your Next.js Project
First, install Zod in your Next.js project if you haven’t already:
npm install zod
Create a List of Blocked Email Providers
To block free email providers, we need a list of common domains used by these services. You can customize this list to suit your requirements:
const blockedDomains = [
'gmail.com',
'yahoo.com',
'protonmail.com',
'rediffmail.com',
'outlook.com',
'hotmail.com',
'icloud.com',
'aol.com',
'zoho.com',
'mail.com',
'gmx.com',
'yandex.com',
'inbox.com',
'lycos.com',
'fastmail.com',
'hushmail.com',
'tutanota.com',
'mail.ru',
'163.com',
'qq.com'
];
Validate Email Addresses Using Zod
We can use Zod’s .refine()
method to validate the email input and ensure the domain is not one of the blocked providers.
Here’s the full schema:
import { z } from 'zod';
// Custom email validation schema
const emailSchema = z.string().email().refine((email) => {
const domain = email.split('@')[1];
return !blockedDomains.includes(domain);
}, {
message: 'Please use a company or personal domain email, not a free email provider.',
});
// Example of using the schema in a user registration form
const userSchema = z.object({
email: emailSchema,
});
// Testing with a sample email
const result = userSchema.safeParse({ email: 'user@gmail.com' });
if (!result.success) {
console.log(result.error.errors); // Shows validation error if blocked
} else {
console.log('Email is valid!');
}
Using the Schema in Your Next.js Form
You can integrate the userSchema
into your Next.js forms or API routes to validate email addresses before user registration. Here’s an example of how you might use it in an API route:
// pages/api/register.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { z } from 'zod';
// User registration handler
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const userSchema = z.object({
email: emailSchema,
});
const validationResult = userSchema.safeParse(req.body);
if (!validationResult.success) {
return res.status(400).json({
error: validationResult.error.errors,
});
}
// Continue with registration process...
res.status(200).json({ message: 'Registration successful!' });
}
Customize the Blocked Domain List
This list can be expanded based on your requirements. Common free email providers include:
- Popular providers: Gmail, Yahoo, Outlook
- Privacy-focused providers: ProtonMail, Tutanota, Hushmail
- Regional providers: Mail.ru, QQ.com, 163.com (commonly used in Russia and China)
Feel free to add or remove providers as needed.
Conclusion
By blocking free email providers in your Next.js application using Zod and TypeScript, you can create a more secure and professional registration system. Whether you’re trying to ensure higher-quality users or restrict access to company users only, this approach provides a flexible, customizable solution.
With Zod’s powerful validation system, you can easily refine and adjust your validation logic to suit any use case.
Have you implemented a similar solution in your app? Let us know in the comments!