# Validate Emails in WordPress

URL: https://email-validation.org/docs/guides/wordpress/
Updated: 2026-11-10

> Documentation index: https://email-validation.org/llms.txt

Our WordPress plugin checks the email address a visitor submits before the form is accepted, and stops the results
you choose with your own message. It works with WPForms, Contact Form 7, Gravity Forms, Elementor forms (Elementor
Pro), WooCommerce registration and the WooCommerce checkout, both the classic checkout and the Checkout block.

The plugin is not in the WordPress.org plugin directory yet. Until it is, you install it from the zip on this page.

## Before you start

- **WordPress 6.0 or newer, PHP 8.1 or newer**, and at least one of the form plugins above.
- **An API key for the site.** Create one on the [API keys page](https://email-validation.org/app/api-keys/) with the permission "Validate
  addresses" (add "Read balance and usage" to see your balance in WordPress), and give it a
  [daily credit cap](https://email-validation.org/docs/authentication/#limits), so a busy form or a wave of spam can never spend more than you
  expect.

## Install the plugin

1. Download [email-validation.zip](https://email-validation.org/downloads/wordpress/email-validation.zip). It is built from the plugin's tested
   source and holds only the files the plugin needs.
2. In WordPress, open **Plugins → Add New Plugin → Upload Plugin**, choose the zip and click **Install Now**, then
   **Activate**.
3. Open **Settings → Email validation**, paste your API key and save. The key is kept on your server and never shown
   again. You can instead add `define( 'EVORG_API_KEY', 'your key' );` to `wp-config.php`.
4. Click **Check the connection**. It checks a free [test address](https://email-validation.org/docs/test-addresses/), then shows your credit
   balance if the key may read it.

To update the plugin later, download the zip again and upload it the same way: WordPress offers to replace the
installed version, and your settings stay.

## Forms

On the settings page you choose:

- **The results to stop.** Each check returns one of the five [result statuses](https://email-validation.org/docs/statuses/). By default forms
  stop `invalid` (the address cannot receive mail) and `disposable` (a throwaway inbox), and let `valid`,
  `catch_all` and `unknown` through.
- **The forms to check:** WPForms, Contact Form 7, Gravity Forms, Elementor forms, WooCommerce checkout and WooCommerce
  registration, each on or off.
- **What happens when a check fails** (no credits left, the API out of reach): the form goes through by default. You
  can choose to stop it instead.
- **The message** a visitor sees, and whether to add a suggested fix for a likely typo ("Did you mean …?").
- **The region:** the default API, or the EU endpoint for [EU data residency](https://email-validation.org/docs/eu-data-residency/).

The plugin checks a field only after the form's own checks passed, so an empty or malformed address gets the form's
usual message and costs nothing. WPForms is checked after its spam checks. Contact Form 7, Gravity Forms and Elementor
check fields before their spam filters, so spam submissions there can use credits. Two limits bound that: one visitor
(one IP address) can cause at most 20 paid checks an hour, after which the form is treated as if the check could not
be done (your setting above decides), and the daily credit cap on the key bounds the total.

## WooCommerce checkout

The plugin checks the billing email when the customer places the order, on the classic checkout and on the Checkout
block. A stopped order shows your message at the checkout, and the customer can correct the address and place the
order again. The checkout has its own settings, in the **WooCommerce checkout** section of the settings page:

- **Stop the order for these results.** Only `invalid` by default. Stopping `disposable` is your choice. `catch_all`
  and `unknown` are never stopped unless you tick them: a real customer can get them, and a lost order costs more
  than an unchecked address.
- **When a check fails.** A check that times out or cannot be done (no credits, the API out of reach, a refused key)
  lets the order through by default. You can choose to stop the order instead.
- **Message.** What the customer sees when the order is stopped. Left empty, the checkout uses the forms' message.
- **Order note.** Off by default. When on, the order gets a private note with the result, such as *Email validation:
  the billing email is valid (accepted).*, or the error code of a check that could not be done.

The checkout is turned on or off with **WooCommerce checkout** under **Check these forms**. The plugin is compatible
with WooCommerce's High-Performance Order Storage (HPOS) and with the Cart and Checkout blocks.

## What is kept, and what is logged

- **The address is never stored by the plugin.** It is sent to the API in the body of an HTTPS request. The plugin
  remembers the result (its status and reason only) for an hour under a hash of the address, so a form sent again, or
  a checkout placed again after a declined payment, is not checked or charged again. An `unknown` result is asked
  again next time.
- **Logs never hold the address.** At checkout, a stopped order and a check that could not be done are written to
  **WooCommerce → Status → Logs** under the source *email-validation-org*, with the status and reason or the error
  code. A passing order is not logged.
- **The order note holds the status, never the address.**
- **The visitor limit keeps a salted hash of the visitor's IP address** (for IPv6, of its /64) with a count, for at
  most an hour; never the address itself.
- What the API keeps is in the [privacy policy](https://email-validation.org/legal/privacy/).

## Try it for free

Test addresses cost nothing and contact no mail server. With the default settings,
`no_mailbox@sandbox.email-validation.org` is stopped and `accepted@sandbox.email-validation.org` passes, on a form and at checkout;
`disposable@sandbox.email-validation.org` is stopped on a form but passes the checkout until you tick `disposable` there. The
[test addresses page](https://email-validation.org/docs/test-addresses/) lists them all.

## Costs

Each completed check costs 1 credit, as with any [validation request](https://email-validation.org/docs/api/validate/). `unknown` results,
errors and test addresses are free ([credits and billing](https://email-validation.org/docs/credits-and-billing/)). A form or a checkout sent
again with the same address within an hour is not charged again.

## For developers

A filter decides last. It receives the message (or null when the address passes), the API's result (or a WP_Error
when the check could not be done), the address and the form: the checkout is *woo_checkout*. Return a message to stop
the form or the order, or null to let it through. For example, to stop throwaway inboxes at checkout only:

```php
add_filter( 'evorg_blocked_message', function ( $message, $result, $email, $form ) {
	if ( 'woo_checkout' === $form && is_array( $result ) && 'disposable' === $result['status'] ) {
		return 'Please use an address you check: we send your receipt there.';
	}
	return $message;
}, 10, 4 );
```

The filter *evorg_visitor_limit* sets the paid checks one visitor may cause per hour (default 20; 0 turns the limit
off; administrators are never limited). Behind a reverse proxy or CDN that WordPress does not see through, every
visitor can appear with the proxy's address and share one limit: return the real visitor address from the filter
*evorg_visitor_ip* (only from a header your proxy sets and visitors cannot).
