PHP code example of willvincent / laravel-email-verifier

1. Go to this page and download the library: Download willvincent/laravel-email-verifier library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

willvincent / laravel-email-verifier example snippets


return [
    // Minimum acceptable score (0-100)
    'min_score' => env('EMAIL_VERIFIER_MIN_SCORE', 70),

    // Require MX records (strict mode)
    'mx_strict' => env('EMAIL_VERIFIER_MX_STRICT', true),

    // Normalization settings
    'normalize' => [
        'enabled' => true,
        'lowercase_local' => false,  // Most providers are case-sensitive
    ],

    // Disposable domain detection
    'disposable' => [
        'file' => storage_path('app/disposable_email_domains.txt'),
        'source_url' => 'https://raw.githubusercontent.com/disposable/disposable-email-domains/master/domains.txt',
        'extra_domains' => [],
        'timeout_seconds' => 10,
        'max_bytes' => 2_000_000,
    ],

    // External verification provider
    'external' => [
        'driver' => env('EMAIL_VERIFIER_EXTERNAL_DRIVER'), // abstract, bouncer, emailable, kickbox, neverbounce, quickemailverification, verifiedemail, zerobounce
        'timeout_seconds' => 5,

        'bouncer' => [
            'api_key' => env('BOUNCER_API_KEY'),
            'endpoint' => 'https://api.usebouncer.com/v1.1/email/verify',
        ],

        // ... other providers
    ],
];

use WillVincent\EmailVerifier\Facades\EmailVerifier;

$result = EmailVerifier::verify('[email protected]');

if ($result->accepted) {
    echo "Email is valid! Score: {$result->score}";
} else {
    echo "Email rejected: " . implode(', ', $result->reasons);
}

use WillVincent\EmailVerifier\Validation\VerifiedEmail;

$request->validate([
    'email' => ['dEmail(minScore: 90)],
]);

// Disable external verification for this validation
$request->validate([
    'email' => ['

$request->validate([
    'email' => '>validate([
    'email' => '->validate([
    'email' => '

$result = EmailVerifier::verify('[email protected]');

// Core properties
$result->accepted;         // bool: Overall pass/fail
$result->score;           // int: Quality score (0-100)
$result->normalizedEmail; // string: Normalized email address
$result->reasons;         // array: Reasons for score reduction/rejection
$result->meta;           // array: Additional metadata

// Common reasons
// - invalid_format
// - invalid_domain
// - no_mx_records
// - disposable_domain
// - role_based_local_part (info@, admin@, etc.)
// - plus_addressing (user+tag@)
// - external_rejected:*

namespace App\EmailVerification;

use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Illuminate\Http\Client\Factory as HttpFactory;
use WillVincent\EmailVerifier\Contracts\ExternalEmailVerifier;
use WillVincent\EmailVerifier\Results\EmailVerificationResult;

class CustomEmailVerifier implements ExternalEmailVerifier
{
    public function __construct(
        private HttpFactory $http,
        private ConfigRepository $config,
    ) {}

    public function verify(string $email): EmailVerificationResult
    {
        $apiKey = $this->config->get('email-verifier.external.custom.api_key', '');
        $endpoint = $this->config->get('email-verifier.external.custom.endpoint', '');
        $timeout = $this->config->get('email-verifier.external.timeout_seconds', 5);

        // Return accepted with reduced score if not configured
        if ($apiKey === '' || $endpoint === '') {
            return new EmailVerificationResult(
                accepted: true,
                score: 100,
                normalizedEmail: $email,
                reasons: [],
                meta: ['provider' => 'custom', 'configured' => false],
            );
        }

        try {
            $response = $this->http
                ->timeout($timeout)
                ->retry(1, 250)
                ->post($endpoint, [
                    'email' => $email,
                    'api_key' => $apiKey,
                ]);

            if (!$response->ok()) {
                // Fail-open: accept with reduced score
                return new EmailVerificationResult(
                    accepted: true,
                    score: 90,
                    normalizedEmail: $email,
                    reasons: ['external_provider_unavailable'],
                    meta: ['provider' => 'custom', 'http_status' => $response->status()],
                );
            }

            $data = $response->json() ?? [];
            $status = $data['status'] ?? 'unknown';

            // Map provider status to scores
            return match ($status) {
                'valid' => new EmailVerificationResult(
                    accepted: true,
                    score: 100,
                    normalizedEmail: $email,
                    meta: ['provider' => 'custom', 'status' => $status],
                ),
                'invalid' => new EmailVerificationResult(
                    accepted: false,
                    score: 0,
                    normalizedEmail: $email,
                    reasons: ['external_rejected:invalid'],
                    meta: ['provider' => 'custom', 'status' => $status],
                ),
                'risky' => new EmailVerificationResult(
                    accepted: true,
                    score: 75,
                    normalizedEmail: $email,
                    reasons: ['external_risky'],
                    meta: ['provider' => 'custom', 'status' => $status],
                ),
                default => new EmailVerificationResult(
                    accepted: true,
                    score: 80,
                    normalizedEmail: $email,
                    reasons: ['external_unknown'],
                    meta: ['provider' => 'custom', 'status' => $status],
                ),
            };
        } catch (\Throwable $e) {
            // Fail-open on exceptions
            return new EmailVerificationResult(
                accepted: true,
                score: 90,
                normalizedEmail: $email,
                reasons: ['external_exception'],
                meta: ['provider' => 'custom', 'error' => $e->getMessage()],
            );
        }
    }
}

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use WillVincent\EmailVerifier\External\ExternalEmailVerifierManager;
use App\EmailVerification\CustomEmailVerifier;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        $this->app->extend(ExternalEmailVerifierManager::class, function ($manager, $app) {
            $manager->extend('custom', function () use ($app) {
                return $app->make(CustomEmailVerifier::class);
            });

            return $manager;
        });
    }
}

'external' => [
    'driver' => env('EMAIL_VERIFIER_EXTERNAL_DRIVER'), // 'custom'

    'custom' => [
        'api_key' => env('CUSTOM_API_KEY'),
        'endpoint' => env('CUSTOM_ENDPOINT', 'https://api.example.com/verify'),
    ],
],

'disposable' => [
    'extra_domains' => [
        'tempmail.com',
        'throwaway.email',
    ],
],

use WillVincent\EmailVerifier\Contracts\EmailVerifierContract;

class UserController extends Controller
{
    public function __construct(
        private EmailVerifierContract $verifier
    ) {}

    public function store(Request $request)
    {
        $result = $this->verifier->verify($request->email);

        if ($result->score < 90) {
            return back()->withErrors([
                'email' => 'Please provide a high-quality email address.'
            ]);
        }

        // Proceed with user registration
    }
}

'custom' => [
    'email' => [
        'verified_email' => 'The :attribute address appears to be invalid or temporary.',
    ],
],

interface Rule
{
    public function apply(
        VerificationContext $ctx,
        EmailVerificationResult $result
    ): void;
}

use Illuminate\Support\Facades\Queue;
use WillVincent\EmailVerifier\Facades\EmailVerifier;

class RegisterController extends Controller
{
    public function store(Request $request)
    {
        // Quick validation without external provider (< 50ms)
        $request->validate([
            'email' => ['()->route('verify-email-notice');
    }
}

namespace App\Jobs;

use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use WillVincent\EmailVerifier\Facades\EmailVerifier;

class VerifyUserEmailJob implements ShouldQueue
{
    use Queueable;

    public function __construct(
        public User $user
    ) {}

    public function handle(): void
    {
        // Full verification with external provider
        $result = EmailVerifier::verify($this->user->email);

        if ($result->accepted && $result->score >= 80) {
            // Email looks good - allow user to proceed
            $this->user->update([
                'email_verification_score' => $result->score,
            ]);
        } else {
            // Email suspicious - 

// Fast validation (< 50ms) - perfect for forms
$request->validate([
    'email' => ['_email:70,no_external',
]);

class NewsletterSubscriptionRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            // Fast validation for most users
            'email' => ['

use Illuminate\Support\Facades\Cache;

public function verifyEmail(string $email): EmailVerificationResult
{
    return Cache::remember(
        "email_verification:{$email}",
        now()->addHours(24),
        fn () => EmailVerifier::verify($email)
    );
}

use Illuminate\Support\Collection;

Collection::chunk($emails, 100)->each(function ($chunk) {
    dispatch(new BulkVerifyEmailsJob($chunk));
});
bash
php artisan vendor:publish --tag=email-verifier-config
bash
php artisan vendor:publish --tag=email-verifier-lang
bash
php artisan email-verifier:fetch-disposable-domains
bash
# Custom source URL
php artisan email-verifier:fetch-disposable-domains --url=https://example.com/domains.txt

# Custom output path
php artisan email-verifier:fetch-disposable-domains --path=/custom/path.txt

# Force update even if unchanged
php artisan email-verifier:fetch-disposable-domains --force
bash
php artisan vendor:publish --tag=email-verifier-lang