EmailVerify LogoEmailVerify

WooCommerce

Email checker for WooCommerce. Verify emails at checkout and in WordPress forms.

Add email verification to your WooCommerce store to reduce failed deliveries, prevent fraud, and improve customer communication.

Integration Methods

MethodBest ForComplexity
PluginQuick setupLow
Checkout HookReal-time verificationMedium
Order ProcessingBackground verificationMedium
REST APICustom solutionsHigh

Method 1: WordPress Plugin

If you've already set up the EmailVerify WordPress plugin, WooCommerce integration is automatic.

Enable WooCommerce Support

  1. Go to SettingsEmailVerify
  2. Check Enable WooCommerce Integration
  3. Configure options:
    • ✓ Verify at checkout
    • ✓ Block disposable emails
    • ✓ Show verification status in orders

Method 2: Checkout Validation

Add email verification to the WooCommerce checkout process.

Server-Side Validation

<?php
// functions.php or custom plugin

/**
 * Verify email at WooCommerce checkout
 */
add_action('woocommerce_checkout_process', 'emailverify_checkout_validation');

function emailverify_checkout_validation() {
    $email = sanitize_email($_POST['billing_email']);

    if (empty($email)) {
        return;
    }

    $result = emailverify_verify_email($email);

    if (!$result['success']) {
        // API error - allow checkout to proceed
        return;
    }

    $data = $result['data'];

    // Block invalid emails
    if ($data['status'] === 'invalid') {
        wc_add_notice(
            __('Please enter a valid email address to complete your order.', 'your-theme'),
            'error'
        );
    }

    // Block disposable emails (optional)
    if (get_option('emailverify_block_disposable', true)) {
        if ($data['result']['disposable'] ?? false) {
            wc_add_notice(
                __('Temporary email addresses are not accepted. Please use a permanent email.', 'your-theme'),
                'error'
            );
        }
    }
}

/**
 * EmailVerify API call helper
 */
function emailverify_verify_email($email) {
    $api_key = get_option('emailverify_api_key');

    // Check cache first
    $cache_key = 'bv_email_' . md5($email);
    $cached = get_transient($cache_key);

    if ($cached !== false) {
        return $cached;
    }

    $response = wp_remote_post('https://api.emailverify.ai/v1/verify', [
        'headers' => [
            'Authorization' => 'Bearer ' . $api_key,
            'Content-Type' => 'application/json',
        ],
        'body' => json_encode(['email' => $email]),
        'timeout' => 10,
    ]);

    if (is_wp_error($response)) {
        return ['success' => false, 'error' => $response->get_error_message()];
    }

    $body = json_decode(wp_remote_retrieve_body($response), true);
    $result = ['success' => true, 'data' => $body];

    // Cache for 24 hours
    set_transient($cache_key, $result, DAY_IN_SECONDS);

    return $result;
}

Real-Time AJAX Validation

Add instant feedback as customers type their email.

<?php
// Enqueue scripts
add_action('wp_enqueue_scripts', 'emailverify_wc_scripts');

function emailverify_wc_scripts() {
    if (!is_checkout()) {
        return;
    }

    wp_enqueue_script(
        'emailverify-checkout',
        get_template_directory_uri() . '/js/emailverify-checkout.js',
        ['jquery'],
        '1.0.0',
        true
    );

    wp_localize_script('emailverify-checkout', 'bv_checkout', [
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('emailverify_checkout'),
    ]);
}

// AJAX handler
add_action('wp_ajax_verify_checkout_email', 'emailverify_ajax_checkout_verify');
add_action('wp_ajax_nopriv_verify_checkout_email', 'emailverify_ajax_checkout_verify');

function emailverify_ajax_checkout_verify() {
    check_ajax_referer('emailverify_checkout', 'nonce');

    $email = sanitize_email($_POST['email'] ?? '');

    if (empty($email)) {
        wp_send_json_error(['message' => 'Email is required']);
    }

    $result = emailverify_verify_email($email);

    if ($result['success']) {
        wp_send_json_success($result['data']);
    } else {
        wp_send_json_error(['message' => 'Verification failed']);
    }
}
// js/emailverify-checkout.js
jQuery(function($) {
    var $billingEmail = $('#billing_email');
    var verifyTimeout;
    var $status = $('<span class="bv-status"></span>');

    $billingEmail.after($status);

    $billingEmail.on('blur change', function() {
        var email = $(this).val();

        if (!email || !isValidEmailFormat(email)) {
            $status.html('').removeClass('valid invalid verifying');
            return;
        }

        clearTimeout(verifyTimeout);

        verifyTimeout = setTimeout(function() {
            verifyEmail(email);
        }, 500);
    });

    function verifyEmail(email) {
        $status.html('<span class="spinner"></span> Verifying...').addClass('verifying');

        $.ajax({
            url: bv_checkout.ajax_url,
            method: 'POST',
            data: {
                action: 'verify_checkout_email',
                nonce: bv_checkout.nonce,
                email: email
            },
            success: function(response) {
                $status.removeClass('verifying');

                if (response.success) {
                    var data = response.data;

                    if (data.status === 'valid') {
                        $status
                            .html('<span class="dashicons dashicons-yes"></span> Email verified')
                            .addClass('valid')
                            .removeClass('invalid');
                    } else if (data.status === 'invalid') {
                        $status
                            .html('<span class="dashicons dashicons-no"></span> Please enter a valid email')
                            .addClass('invalid')
                            .removeClass('valid');
                    } else if (data.result && data.result.disposable) {
                        $status
                            .html('<span class="dashicons dashicons-warning"></span> Please use a permanent email')
                            .addClass('invalid')
                            .removeClass('valid');
                    }
                }
            },
            error: function() {
                $status.html('').removeClass('verifying valid invalid');
            }
        });
    }

    function isValidEmailFormat(email) {
        return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
    }
});
/* style.css */
.bv-status {
    display: block;
    margin-top: 5px;
    font-size: 13px;
}

.bv-status.verifying {
    color: #666;
}

.bv-status.valid {
    color: #28a745;
}

.bv-status.invalid {
    color: #dc3545;
}

.bv-status .spinner {
    display: inline-block;
    width: 12px;
    height: 12px;
    border: 2px solid #ccc;
    border-top-color: #333;
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

Method 3: Order Processing

Verify emails after order placement and store results.

Save Verification Data

<?php
/**
 * Verify email after order is created
 */
add_action('woocommerce_checkout_order_created', 'emailverify_verify_order_email');

function emailverify_verify_order_email($order) {
    $email = $order->get_billing_email();

    if (empty($email)) {
        return;
    }

    $result = emailverify_verify_email($email);

    if ($result['success']) {
        $data = $result['data'];

        // Store verification data as order meta
        $order->update_meta_data('_email_verification_status', $data['status']);
        $order->update_meta_data('_email_verification_score', $data['score'] ?? '');
        $order->update_meta_data('_email_is_disposable', $data['result']['disposable'] ? 'yes' : 'no');
        $order->update_meta_data('_email_verified_at', current_time('mysql'));
        $order->save();

        // Add order note
        if ($data['status'] === 'invalid') {
            $order->add_order_note(
                sprintf(
                    __('Warning: Customer email %s failed verification (Status: %s)', 'your-theme'),
                    $email,
                    $data['status']
                )
            );
        }
    }
}

/**
 * Display verification status in order details
 */
add_action('woocommerce_admin_order_data_after_billing_address', 'emailverify_show_order_email_status');

function emailverify_show_order_email_status($order) {
    $status = $order->get_meta('_email_verification_status');

    if (empty($status)) {
        return;
    }

    $score = $order->get_meta('_email_verification_score');
    $disposable = $order->get_meta('_email_is_disposable');

    $status_class = $status === 'valid' ? 'status-completed' : 'status-on-hold';

    echo '<div class="email-verification-status">';
    echo '<h3>' . __('Email Verification', 'your-theme') . '</h3>';
    echo '<p><strong>' . __('Status:', 'your-theme') . '</strong> ';
    echo '<mark class="order-status ' . esc_attr($status_class) . '">' . esc_html(ucfirst($status)) . '</mark></p>';

    if ($score) {
        echo '<p><strong>' . __('Score:', 'your-theme') . '</strong> ' . esc_html($score) . '</p>';
    }

    if ($disposable === 'yes') {
        echo '<p><span class="dashicons dashicons-warning" style="color: #d63638;"></span> ';
        echo __('Disposable email detected', 'your-theme') . '</p>';
    }

    echo '</div>';
}

Add Order List Column

<?php
/**
 * Add email status column to orders list
 */
add_filter('manage_edit-shop_order_columns', 'emailverify_orders_column');

function emailverify_orders_column($columns) {
    $new_columns = [];

    foreach ($columns as $key => $value) {
        $new_columns[$key] = $value;

        if ($key === 'order_status') {
            $new_columns['email_status'] = __('Email', 'your-theme');
        }
    }

    return $new_columns;
}

add_action('manage_shop_order_posts_custom_column', 'emailverify_orders_column_content', 10, 2);

function emailverify_orders_column_content($column, $post_id) {
    if ($column !== 'email_status') {
        return;
    }

    $order = wc_get_order($post_id);
    $status = $order->get_meta('_email_verification_status');

    if (empty($status)) {
        echo '<span class="dashicons dashicons-minus" title="Not verified"></span>';
        return;
    }

    if ($status === 'valid') {
        echo '<span class="dashicons dashicons-yes-alt" style="color: #28a745;" title="Valid"></span>';
    } else {
        echo '<span class="dashicons dashicons-dismiss" style="color: #dc3545;" title="Invalid"></span>';
    }

    $disposable = $order->get_meta('_email_is_disposable');
    if ($disposable === 'yes') {
        echo '<span class="dashicons dashicons-warning" style="color: #d63638;" title="Disposable"></span>';
    }
}

Method 4: REST API Integration

For headless WooCommerce or custom checkout flows.

Custom REST Endpoint

<?php
/**
 * Register REST API endpoint for email verification
 */
add_action('rest_api_init', 'emailverify_register_wc_endpoint');

function emailverify_register_wc_endpoint() {
    register_rest_route('emailverify/v1', '/verify-checkout', [
        'methods' => 'POST',
        'callback' => 'emailverify_rest_verify_checkout',
        'permission_callback' => '__return_true',
        'args' => [
            'email' => [
                'required' => true,
                'type' => 'string',
                'format' => 'email',
                'sanitize_callback' => 'sanitize_email',
            ],
        ],
    ]);
}

function emailverify_rest_verify_checkout($request) {
    $email = $request->get_param('email');

    // Rate limiting
    $ip = $_SERVER['REMOTE_ADDR'];
    $rate_key = 'bv_rate_' . md5($ip);
    $rate_count = get_transient($rate_key) ?: 0;

    if ($rate_count >= 20) {
        return new WP_Error(
            'rate_limited',
            'Too many verification requests',
            ['status' => 429]
        );
    }

    set_transient($rate_key, $rate_count + 1, MINUTE_IN_SECONDS);

    // Verify email
    $result = emailverify_verify_email($email);

    if (!$result['success']) {
        return new WP_Error(
            'verification_failed',
            'Email verification failed',
            ['status' => 503]
        );
    }

    $data = $result['data'];

    return new WP_REST_Response([
        'valid' => $data['status'] === 'valid',
        'status' => $data['status'],
        'disposable' => $data['result']['disposable'] ?? false,
        'score' => $data['score'] ?? null,
    ], 200);
}

Frontend Usage

// Headless checkout verification
async function verifyCheckoutEmail(email) {
    const response = await fetch('/wp-json/emailverify/v1/verify-checkout', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({ email }),
    });

    if (!response.ok) {
        if (response.status === 429) {
            throw new Error('Too many requests. Please wait.');
        }
        throw new Error('Verification failed');
    }

    return response.json();
}

// Usage
try {
    const result = await verifyCheckoutEmail('customer@example.com');

    if (!result.valid) {
        showError('Please enter a valid email address');
    } else if (result.disposable) {
        showError('Please use a permanent email address');
    } else {
        proceedToPayment();
    }
} catch (error) {
    // Allow checkout on error
    proceedToPayment();
}

Bulk Customer Verification

Verify existing customers in your database.

WP-CLI Command

<?php
/**
 * WP-CLI command for bulk customer verification
 */
if (defined('WP_CLI') && WP_CLI) {
    WP_CLI::add_command('emailverify verify-customers', function($args, $assoc_args) {
        $batch_size = $assoc_args['batch'] ?? 100;
        $dry_run = isset($assoc_args['dry-run']);

        global $wpdb;

        // Get customers without verification status
        $customers = $wpdb->get_results("
            SELECT DISTINCT pm.meta_value as email, pm.post_id as order_id
            FROM {$wpdb->postmeta} pm
            LEFT JOIN {$wpdb->postmeta} pm2 ON pm.post_id = pm2.post_id
                AND pm2.meta_key = '_email_verification_status'
            WHERE pm.meta_key = '_billing_email'
            AND pm.meta_value != ''
            AND pm2.meta_id IS NULL
            LIMIT {$batch_size}
        ");

        if (empty($customers)) {
            WP_CLI::success('All customers are verified!');
            return;
        }

        WP_CLI::log(sprintf('Found %d customers to verify', count($customers)));

        $progress = \WP_CLI\Utils\make_progress_bar('Verifying', count($customers));

        $stats = ['valid' => 0, 'invalid' => 0, 'error' => 0];

        foreach ($customers as $customer) {
            $result = emailverify_verify_email($customer->email);

            if ($result['success']) {
                $status = $result['data']['status'];
                $stats[$status === 'valid' ? 'valid' : 'invalid']++;

                if (!$dry_run) {
                    update_post_meta($customer->order_id, '_email_verification_status', $result['data']['status']);
                    update_post_meta($customer->order_id, '_email_verification_score', $result['data']['score'] ?? '');
                }
            } else {
                $stats['error']++;
            }

            $progress->tick();

            // Rate limiting
            usleep(100000); // 100ms delay
        }

        $progress->finish();

        WP_CLI::success(sprintf(
            'Verification complete: %d valid, %d invalid, %d errors',
            $stats['valid'],
            $stats['invalid'],
            $stats['error']
        ));
    });
}

Usage

# Verify 100 customers (default)
wp emailverify verify-customers

# Verify 500 customers
wp emailverify verify-customers --batch=500

# Dry run (no database changes)
wp emailverify verify-customers --dry-run

Fraud Prevention

Use email verification as part of fraud detection.

<?php
/**
 * Flag high-risk orders based on email verification
 */
add_action('woocommerce_checkout_order_processed', 'emailverify_fraud_check', 10, 3);

function emailverify_fraud_check($order_id, $posted_data, $order) {
    $risk_score = 0;
    $risk_reasons = [];

    $email = $order->get_billing_email();
    $result = emailverify_verify_email($email);

    if ($result['success']) {
        $data = $result['data'];

        // Invalid email = high risk
        if ($data['status'] === 'invalid') {
            $risk_score += 50;
            $risk_reasons[] = 'Invalid email address';
        }

        // Disposable email = high risk
        if ($data['result']['disposable'] ?? false) {
            $risk_score += 40;
            $risk_reasons[] = 'Disposable email detected';
        }

        // Low score = medium risk
        if (($data['score'] ?? 1) < 0.5) {
            $risk_score += 20;
            $risk_reasons[] = 'Low email score';
        }

        // Role-based email = slight risk
        if ($data['result']['role'] ?? false) {
            $risk_score += 10;
            $risk_reasons[] = 'Role-based email address';
        }
    }

    // Store risk assessment
    $order->update_meta_data('_fraud_risk_score', $risk_score);
    $order->update_meta_data('_fraud_risk_reasons', $risk_reasons);

    // Flag high-risk orders for manual review
    if ($risk_score >= 50) {
        $order->set_status('on-hold', __('High fraud risk - manual review required', 'your-theme'));

        // Notify admin
        $admin_email = get_option('admin_email');
        wp_mail(
            $admin_email,
            sprintf(__('High-Risk Order #%s Needs Review', 'your-theme'), $order_id),
            sprintf(
                __("Order #%s has been flagged as high risk.\n\nRisk Score: %d\nReasons:\n- %s\n\nPlease review the order.", 'your-theme'),
                $order_id,
                $risk_score,
                implode("\n- ", $risk_reasons)
            )
        );
    }

    $order->save();
}

Best Practices

1. Graceful Degradation

// Always allow checkout if API fails
$result = emailverify_verify_email($email);

if (!$result['success']) {
    error_log('EmailVerify API error: ' . ($result['error'] ?? 'Unknown'));
    return; // Don't block checkout
}

2. Cache Results

// Cache verification results to reduce API calls
$cache_key = 'bv_email_' . md5($email);
$cached = get_transient($cache_key);

if ($cached !== false) {
    return $cached;
}

// ... make API call ...

set_transient($cache_key, $result, DAY_IN_SECONDS);

3. Clear Error Messages

// Provide helpful, non-technical error messages
$messages = [
    'invalid' => __('This email address appears to be invalid. Please check and try again.', 'your-theme'),
    'disposable' => __('Temporary email addresses cannot be used for orders. Please use your regular email.', 'your-theme'),
];

On this page