Skip to content

Refuse WordPress signups whose address cannot receive mail

Integration Forms and websites

Add a must-use plugin to WordPress that checks each new registration with PricklyMails and refuses the account when its address cannot receive mail.

No connector needed: at each signup, WordPress calls the PricklyMails API from the registration_errors filter, and an address that cannot receive mail is refused before the account exists.

Verify for free

Step by step

Check each signup in four steps

Before you start

Access to your site files, to edit wp-config.php and add a file to wp-content: a must-use plugin is uploaded as a file, not installed from the dashboard.

  1. In PricklyMails

    Create an API key in PricklyMails

    1. In the dashboard, open API Keys and click New key.
    2. Under Environment, pick Test first: the key starts with pm_test_, answers from canned results, bills nothing and contacts no mail server.
    3. Copy the key as soon as it shows: it is shown only once.

    Tip

    The Free plan holds one key: once everything works, revoke the test key, then create the one under Live.

  2. In WordPress

    Store the key and add the plugin to WordPress

    The key goes in wp-config.php as a constant, and the code in a must-use plugin, which WordPress runs without activation and which cannot be turned off from the dashboard.

    1. Open wp-config.php, at the root of your WordPress files.
    2. Above the That's all, stop editing! line, add define( 'PRICKLYMAILS_KEY', 'pm_test_your_key' );, with your test key as the value.
    3. In wp-content, create a mu-plugins folder, unless it already exists.
    4. Save the code below in it as pricklymails-signup-check.php.

    The code asks PricklyMails to answer within a few seconds (Prefer: wait) and stops waiting soon after, so a signup never hangs on the answer. It refuses the signup only when the recommendation is remove, and lets it through otherwise: a risky address, no answer in time, an error.

    wp-content/mu-plugins/pricklymails-signup-check.php
    <?php
    /**
     * Plugin Name: PricklyMails signup check
     */
    
    defined( 'ABSPATH' ) || exit;
    
    function pricklymails_refusal() {
        return __( 'This email address cannot receive mail.', 'pricklymails' ) . ' '
            . __( 'Check it for a typo, or use another one.', 'pricklymails' );
    }
    
    // The person waits at the form: wait 4 for the answer, give up at 5.
    function pricklymails_recommendation( $email ) {
        $response = wp_remote_post(
            'https://api.pricklymails.com/api/verify',
            array(
                'timeout' => 5,
                'headers' => array(
                    'Authorization' => 'Bearer ' . PRICKLYMAILS_KEY,
                    'Content-Type' => 'application/json',
                    'Prefer' => 'wait=4',
                ),
                'body' => wp_json_encode( array( 'email' => $email ) ),
            )
        );
        if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
            return null;
        }
        $result = json_decode( wp_remote_retrieve_body( $response ), true );
    
        return $result['verification']['recommendation'] ?? null;
    }
    
    function pricklymails_check_signup( $errors, $user_login, $user_email ) {
        // A signup WordPress already refused costs no verification.
        if ( $errors->has_errors() || ! defined( 'PRICKLYMAILS_KEY' ) ) {
            return $errors;
        }
        if ( 'remove' === pricklymails_recommendation( $user_email ) ) {
            $errors->add( 'user_email', pricklymails_refusal() );
        }
    
        return $errors;
    }
    add_filter( 'registration_errors', 'pricklymails_check_signup', 10, 3 );
    
    How the API answers in one call

    Warning

    If wp-config.php sets WP_HTTP_BLOCK_EXTERNAL to true, WordPress only sends requests to your own site and to the hosts listed in WP_ACCESSIBLE_HOSTS: add api.pricklymails.com to that list, or the code never reaches PricklyMails and lets every signup through.

    Note

    Keep the file directly in mu-plugins: WordPress does not load the files in its subfolders.

    SourceWordPress's official help center
  3. In WordPress

    Open registration in WordPress

    A must-use plugin needs no activation: WordPress runs it as soon as the file is in place. What is left is to let visitors create an account, and to check that WordPress sees the plugin.

    1. In the dashboard, open Settings then General.
    2. Under Membership, check Anyone can register.
    3. Click Save Changes.
    4. Open Plugins and click Must-Use, above the list.
    5. Check that PricklyMails signup check is listed.

    Tip

    The registration form is at wp-login.php?action=register on your site: that is where to try the next step.

    SourceWordPress's official help center
  4. In WordPress

    Try it with the test key

    1. Sign up with an address that starts with invalid, such as invalid@example.com: the test key answers remove, and the signup is refused.
    2. Sign up with another address, such as valid@example.com: the account is created.
    3. Where you stored the key, replace it with a key created under Live, which starts with pm_live_: from then on, each signup is verified for real and billed like any verification.

What each signup gets

The code reads the recommendation the API gives the address, the same one a list's report gives.

Remove

Refused: the address does not exist, its domain cannot receive mail, or it is disposable.

WordPress creates no account and shows the registration form again, with the message in an error notice above it. A plugin that changes the notices above the login form through the login_errors filter changes this one too, since the registration form shares that page.

Review

Let through: a domain that accepts any address, a generic address such as contact@, or a server that did not answer. The address may work.

Send

Let through: the address is valid, or hosted by a large provider that accepts every address.

No answer in time
WordPress waits for the filter before it creates the account, with no time limit of its own, while the person waits at the form. The code asks PricklyMails to answer within 4 seconds, stops waiting after 5, the timeout of its request, and then lets the signup through.
SourceWordPress's official help center

Frequently asked questions

Does it check the signups made through WooCommerce?

Not as is: WordPress runs registration_errors only for its own registration form, and WooCommerce's forms run their own filter, woocommerce_registration_errors, which its Checkout block supports too. To check those signups as well, add this line at the end of the file: add_filter( 'woocommerce_registration_errors', 'pricklymails_check_signup', 10, 3 );.

Does it work on a multisite network?

With one more filter. On a network, signups go through wp-signup.php, which validates them with the wpmu_validate_user_signup filter instead, and the file in mu-plugins runs on every site. Hook to that filter a function that passes the array's errors, user_name and user_email to pricklymails_check_signup, then returns the array: the message shows under the address field, since the code files it under user_email. To open registration, go to Network Admin then Settings and, under Allow new registrations, choose User accounts may be registered.

SourceWordPress's official help center

Does a signup WordPress refuses on its own cost a verification?

No. WordPress checks the username and the address before it runs the filter, and the code returns without calling PricklyMails when one of those checks failed: an empty or malformed address, or an address or a username already registered.

SourceWordPress's official help center

Is there a PricklyMails extension for WordPress?

No, and there is nothing to install: the code above calls the PricklyMails API with your key.

These trademarks belong to their respective owners. Naming them implies no partnership.

Check your list before your next send.

1,000 tokens free when you sign up, no credit card. After that, you only pay for answers.