CheckDisposable Emailcheckdisposable.email
← All guidesLaravel guide · PHP

Block disposable email signups in Laravel

Add a custom rule class. The rule runs as part of Laravel's validator, so disposable emails surface as standard form errors with no extra plumbing.

The code

<?php
// app/Rules/NotDisposable.php
namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class NotDisposable implements ValidationRule
{
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        try {
            $res = Http::withToken(config('services.cde.key'))
                ->timeout(3)
                ->get('https://api.checkdisposable.email/v1/check', ['email' => $value]);
            if ($res->successful() && $res->json('is_disposable') === true) {
                $fail('Please use a real email address.');
            }
        } catch (\Throwable $e) {
            Log::warning('CDE unreachable, failing open', ['error' => $e->getMessage()]);
        }
    }
}

// app/Http/Controllers/Auth/RegisteredUserController.php
public function store(Request $request)
{
    $request->validate([
        'email' => ['required', 'email', new \App\Rules\NotDisposable],
        'password' => ['required', 'min:8'],
    ]);
    // ...create user
}

Notes

config/services.php
Add `'cde' => ['key' => env('CDE_KEY')]` so the rule reads through Laravel's typed config rather than hitting env() at runtime.
Fortify / Breeze / Jetstream
For Fortify, add the rule via the `Fortify::createUsersUsing` action. For Breeze and Jetstream, the rule drops into the existing Validator config without further work.
Inertia + Vue
Failed validation surfaces in the inertia errors bag, so the disposable message renders alongside other field errors without special handling on the frontend.

Get a free API key

500 checks/month, no credit card. No credit card. 30 seconds.

Sign up free →