How to prevent disposable emails registration in your Drupal website using Generative AI
Here we are discussing how to effectively prevent disposable emails getting registered on your Drupal website.
Many marketers are using users’ emails for various marketing campaigns. Availability of many temporary emails services like mailinator, yopmail etc. prevents marketers from communicating to potential customers.
How to prevent it in a traditional way
The most common way to identify and prevent is keeping a local database table of all disposable domains and validate user provided email with these disposable domain tables. You can get all disposable email domains on the internet for ex: this page has a list of disposable domains.
Same approach is done by some of the contributed modules(https://www.drupal.org/project/dea_blocker)
But the problem here is we cannot completely rely on this list. Since new domains are constantly coming to the market.
Large Language Model (LLM) approach to identify disposable domains
Disposable email domains are constantly evolving, making a static list approach less effective over time. Using a Large Language Model (LLM) is a better approach because:
Adaptability – LLMs can recognize patterns and infer disposable domains even if they are new.
Context Awareness – They can analyze domain structures, common disposable email trends, and user intent.
Less Maintenance – No need to constantly update a blocklist of disposable domains.
How to prevent disposable email registration in Drupal
Here we are using LLM to identify disposable email domains.
Install Drupal AI module.https://www.drupal.org/project/ai
Install dependent module like keys , this will be asked during installation.
We have to enable the three modules AI Core, AI API explorer and AI logging.

Here we are using Open AI LLM model.
Install Open AI provider module – https://www.drupal.org/project/ai_provider_openai

Create your API key in Open AI. The API Key Can be found on https://platform.openai.com/.
Configure Keys
Go to Configuration -> System -> Keys
Path -/admin/config/system/keys
Click on Add key.

Provide a key name, here I am using open-ai as the key name. You can give any readable name.
Provide all other fields as default value like Key type – Authentication , provider settings -configurations
In the key field provide the key you copied from the Open AI dashboard.

Then save the key.
Then Follow below steps.
Configure Provider
Go to Configuration-> AI -> Provider Settings select Open AI authentication.
Path – /admin/config/ai/providers/openai
Select the key we have created in the previous step and save the configuration.

Navigate to Configuration -> AI -> AI Default settings.
Path – /admin/config/ai/settings
In this configuration you can see all the default configurations for each functionality. Here we are using Chat, so make sure you have selected Open AI and which LLM model you are using. Here we have selected gpt-4o.

You can select models for other functionalities also. Then save the configuration.
We have done all the configurations.
In the next step we are going to create a custom module to alter the register hook and check for disposable domains with the help of open AI LLM.
Register form alter hook
We are going to implement our custom hook in a custom module dn_register.
Import below classes on top of dn_register.module file.
use Drupal\ai\OperationType\Chat\ChatInput;
use Drupal\ai\OperationType\Chat\ChatMessage;
Below provided our form registration hook.
function dn_register_form_user_register_form_alter(&$form, $form_state, $form_id) {
$form['#validate'][] = 'dn_register_validate';
}
Inside dn_register_validate we are going to implement our logic to validate email domains.
First create the dn_register_validate function and get the email value.
function dn_register_validate(&$form, $form_state) {
$mail = $mail = $form_state->getValue('mail');
}
In the next step we are going to call LLM. So for that get the service provider first using below functions.
$sets = \Drupal::service('ai.provider')->getDefaultProviderForOperationType('chat');
$service = \Drupal::service('ai.provider');
$provider = $service->createInstance($sets['provider_id']);
Next prepare your chat input as below.
$messages = new ChatInput([
new chatMessage('system', 'You are an expert email verification assistant. Your task is to determine whether a given email address belongs to a disposable email provider.
Disposable email providers offer temporary, anonymous, or single-use email addresses, often used to bypass registrations. These emails are typically from domains associated with known temporary mail services.
**Instructions:**
- If the email is from a known disposable email provider (e.g., mailinator.com, tempmail.com, guerrillamail.com), return: `"Disposable Email"`.
- If the email is from a well-known legitimate provider (e.g., gmail.com, yahoo.com, outlook.com, corporate domains), return: `"Not a Disposable Email"`.
- If the email domain is unknown but follows common disposable email patterns (randomized domains, unusual TLDs, etc.), return `"Likely Disposable Email"`.
- If uncertain, return `"Unknown"` and do not guess.
Respond **only** with one of the following:
- 0 for "Disposable Email"
- 1 for "Not a Disposable Email"
- 2 for "Likely Disposable Email"
- 3 for "Unknown".
Do not return explanations, just the number.
'),
new chatMessage('user', $mail),
]);
As you can see, the Chat input class is being initialized with two chat messages. One is for system prompt and other is with email provided by the user.
$messages = new ChatInput([
new chatMessage('system', 'Your prompt'),
new chatMessage('user', $mail),
]);
Send the messages to the provider.
$message = $provider->chat($messages, $sets['model_id'])->getNormalized();
So if LLM returns 0 or 2, we have to prevent the registration as below.
if($message->getText() == '0'){
$form_state->setErrorByName('mail', 'Email is disposable mail! Use a real mail');
}else if($message->getText() == '2'){
$form_state->setErrorByName('mail', 'Email is Likely Disposable Email! Use a real mail');
}
So the complete implementation of ‘dn_register_validate’ function will be as below.
function dn_register_validate(&$form, $form_state) {
$mail = $mail = $form_state->getValue('mail');
//=====call to LLM
// Find the default selected LLM
$sets = \Drupal::service('ai.provider')->getDefaultProviderForOperationType('chat');
$service = \Drupal::service('ai.provider');
$provider = $service->createInstance($sets['provider_id']);
$messages = new ChatInput([
new chatMessage('system', 'You are an expert email verification assistant. Your task is to determine whether a given email address belongs to a disposable email provider.
Disposable email providers offer temporary, anonymous, or single-use email addresses, often used to bypass registrations. These emails are typically from domains associated with known temporary mail services.
**Instructions:**
- If the email is from a known disposable email provider (e.g., mailinator.com, tempmail.com, guerrillamail.com), return: `"Disposable Email"`.
- If the email is from a well-known legitimate provider (e.g., gmail.com, yahoo.com, outlook.com, corporate domains), return: `"Not a Disposable Email"`.
- If the email domain is unknown but follows common disposable email patterns (randomized domains, unusual TLDs, etc.), return `"Likely Disposable Email"`.
- If uncertain, return `"Unknown"` and do not guess.
Respond **only** with one of the following:
- 0 for "Disposable Email"
- 1 for "Not a Disposable Email"
- 2 for "Likely Disposable Email"
- 3 for "Unknown".
Do not return explanations, just the number.
'),
new chatMessage('user', $mail),
]);
$message = $provider->chat($messages, $sets['model_id'])->getNormalized();
//echo $message->getText();exit;
if($message->getText() == '0'){
$form_state->setErrorByName('mail', 'Email is disposable mail! Use a real mail');
}else if($message->getText() == '2'){
$form_state->setErrorByName('mail', 'Email is Likely Disposable Email! Use a real mail');
}
//=====call to LLM
}
Enable the custom module and clear the cache.
You can see registration prevents disposable domains and allows only actual mail id’s.

You can download this sample module here.