The Spaw Email Verification plugin connects a WordPress site to Spaw in two layers. In the browser it loads the Spaw form helper on the comment form, the registration form and the WooCommerce classic checkout, so a visitor who mistypes an address sees a "Did you mean …?" correction and a notice when the address cannot receive mail. On the server, with a secret key, it verifies the address again when the form is submitted and can refuse addresses Spaw reports as undeliverable, and it can look up the address the submission came from to refuse Tor, VPN or datacenter visitors. Nothing is sent to Spaw until you save a key.
The plugin has been submitted to the WordPress.org directory. Until the listing is live, install it from the plugin zip: ask [email protected] for the current build.
Install and configure
- Create a free account at https://spaw.co and open the API keys page.
- Create a publishable key locked to your site's domain. A publishable key is safe in page source: it can only run single lookups through the four browser endpoints (email, phone, IP and postal address), only from the domains you list, and this plugin uses it for email lookups. Add a Cloudflare Turnstile site key and secret to the key if your forms are open to the public, so bots cannot spend your credits.
- In WordPress, go to Plugins, choose Add New, then Upload Plugin, and upload the zip. Activate it.
- Open Settings, then Spaw. Paste the publishable key and tick the forms to verify: comments, registration, and WooCommerce checkout if WooCommerce is active. The "Extra email inputs" field takes a CSS selector for any other inputs, for example a newsletter form or the WooCommerce block checkout's email field.
- To also reject undeliverable addresses on the server, paste a secret key and tick "Block undeliverable addresses". Prefer the publishable key alone unless you need blocking; the secret key is stored in the WordPress options table like any other plugin setting.
- To refuse submissions from Tor exits, known VPN exits or datacenter ranges, tick the switches under "Visitor address check". Each is independent and off by default.
What happens on each form
The browser helper runs when a visitor leaves the email field. It never blocks a submission: it only renders a hint under the field, and every result is also emitted as a spaw:result event on the input in case your theme wants to do more.
The server check runs on preprocess_comment for comments, registration_errors for registrations, and woocommerce_checkout_process for the classic checkout. It posts the address to POST /api/v1/email with a five-second timeout, caches the verdict for seven days in a transient keyed by the hashed address, and rejects only verdicts on the blocked list. By default that list is undeliverable alone. If the API cannot be reached, answers an error, or is slow, the submission goes through as normal.
Block Tor, VPN and datacenter visitors
With the same secret key, the plugin can look up the address a comment, registration or checkout comes from through the IP lookup endpoint and refuse the submission when a flag you ticked is true: is_tor for Tor exit nodes, is_vpn for known VPN exits, is_datacenter for datacenter and cloud ranges, which is traffic that is not a person on a home connection. Visitors on iCloud Private Relay are never blocked, because relay users are ordinary Apple customers even though the aggregate lists mark the relay's egress as hosting. Answers are cached for six hours in a transient keyed by the hashed address, and a lookup that fails or is slow never blocks anyone. Each answered lookup costs one credit; reserved or private addresses and repeats within seven days are free.
The plugin reads REMOTE_ADDR. Behind a proxy or CDN that is the proxy's address, so map the real client address with the spaw_visitor_ip filter, for example from the header your CDN sets. Two more filters cover the rest: spaw_block_ip receives the matched flag and the answer and can veto a block, and spaw_blocked_ip_message rewrites the rejection text.
Adjust the behaviour with filters
Three filters cover the usual customisations. This example also refuses risky addresses, which covers disposable domains, role inboxes and catch-all domains, and rewrites the rejection message:
add_filter('spaw_blocked_verdicts', function (array $verdicts, string $email): array {
return ['undeliverable', 'risky'];
}, 10, 2);
add_filter('spaw_blocked_message', function (string $message): string {
return 'Please use a work email address that can receive mail.';
});
add_filter('spaw_email_selectors', function (array $selectors): array {
$selectors[] = '.newsletter-form input[type="email"]';
return $selectors;
});
Logged-in users are never checked on the comment form, because their address was verified when their account was created.
What to do with the verdict
Blocking undeliverable is safe: the address has invalid syntax, a domain with no working mail servers, or a mailbox the receiving server rejected. Blocking risky is a policy choice. It stops burner signups and shared inboxes, but it also refuses catch-all domains, which many companies use for perfectly good addresses. Read the reason values before widening the list.
Cost
Each answered email lookup costs one credit from your Spaw balance, and one credit covers five answered visitor address lookups. Unverified answers cost nothing, undeliverable answers cost nothing within a fair-use allowance, a repeat of the same address within seven days costs nothing, and the plugin's own seven-day cache means a returning visitor is not looked up twice. Every account gets 100 free credits a month; packs start at $9 for 1,000 credits.