=== Email Validation for Forms (email-validation.org) ===
Tags: email validation, email verification, contact form 7, wpforms, woocommerce
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 8.1
Stable tag: 1.0.0
License: MIT
License URI: https://opensource.org/licenses/MIT

Check the email address in your forms before it is accepted: stop addresses that cannot receive mail and throwaway inboxes.

== Description ==

This plugin checks the email address a visitor submits with the [email-validation.org](https://email-validation.org/) API and stops the results you choose, with your own message. It works with:

* WPForms
* Contact Form 7
* Gravity Forms
* Elementor forms (Elementor Pro)
* WooCommerce checkout (the classic checkout and the Checkout block) and registration

Every check returns one of five statuses: `valid`, `invalid`, `catch_all`, `unknown` or `disposable`. By default the plugin stops `invalid` (the address cannot receive mail) and `disposable` (a throwaway inbox) on forms, only `invalid` at WooCommerce checkout, and lets everything else through. You choose which statuses to stop.

* **Your API key stays on your server.** It is kept in your site's settings (or in `wp-config.php`), never shown again on the settings page and never sent to a visitor's browser.
* **Runs after the form's own field checks.** An empty or malformed address gets the form's usual message and costs nothing. WPForms is checked after its spam checks too; Contact Form 7, Gravity Forms and Elementor check fields before their spam filters, so give your key a daily credit cap.
* **One check per address.** The same address in another case, or a form sent again within an hour, is not checked (or charged) again. An `unknown` result is asked again next time (it is free).
* **Never stops a visitor because of us.** If a check cannot be done (no credits left, the API out of reach), the form goes through. You can choose to stop it instead.
* **Suggests a fix for a likely typo** ("Did you mean jane@gmail.com?"), if you want.
* **EU data residency:** choose the EU endpoint to have checks validated and stored in the EU.

= WooCommerce checkout =

The billing email is checked when the order is placed, on the classic checkout and the Checkout block, with its own settings:

* **Stops 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).
* **Never loses an order because of us.** A check that times out or cannot be done lets the order through, unless you choose to stop it.
* **Your own message** at the checkout (empty: the forms' message).
* **A retried checkout is not charged again:** the result is remembered for an hour under a hash of the address.
* **An optional private order note** with the result (the status and reason), off by default. The address is never stored in the note, the logs or anywhere else.
* **Compatible with WooCommerce's High-Performance Order Storage (HPOS)** and the Cart and Checkout blocks.

You need an email-validation.org account and an API key. A check uses one credit; `unknown` results, errors and [test addresses](https://email-validation.org/docs/test-addresses/) are free ([credits and billing](https://email-validation.org/docs/credits-and-billing/)).

== Installation ==

1. Install and activate the plugin.
2. In your email-validation.org dashboard, create an API key with the permission "Validate addresses" (add "Read balance and usage" to see your balance in WordPress), and give it a daily credit cap.
3. In WordPress, open **Settings → Email validation**, paste the key and save. Or add `define( 'EVORG_API_KEY', 'ev_live_…' );` to `wp-config.php`.
4. Click **Check the connection**: it checks a free test address, then shows your credit balance if the key may read it.
5. Choose the statuses to stop and the forms to check.
6. Try a form with `no_mailbox@sandbox.email-validation.org` (stopped) and `accepted@sandbox.email-validation.org` (passes). Test addresses cost nothing.

== Frequently Asked Questions ==

= Which form fields are checked? =

Email fields: the email field of WPForms, Contact Form 7 (`email` and `email*`), Gravity Forms and Elementor forms, the billing email at WooCommerce checkout (classic checkout and Checkout block), and the email of a WooCommerce registration.

= What does the plugin log? =

At WooCommerce checkout, a stopped order and a check that could not be done are written to **WooCommerce → Status → Logs** (source `email-validation-org`) with the status, reason or error code. The address is never logged.

= What happens when my credits run out? =

The forms keep working and addresses are not checked. A notice in your WordPress admin says why, until a check works again or you check the connection.

= Does the plugin store the address? =

No. The plugin sends the address to the API in the body of an HTTPS request and never logs it. It remembers the result (its status and reason only) for an hour under a hash of the address, so a form sent again is not charged again. For the per-visitor limit it 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 IP address itself. What the API keeps is described in the [privacy policy](https://email-validation.org/legal/privacy/).

= Can a script or spam bot spend my credits? =

Only within limits. One visitor (one IP address) can cause at most 20 paid checks an hour; after that the form is treated as if the check could not be done, so your "when a check fails" setting decides, and nothing is charged. The daily credit cap on your API key bounds the total. The filter `evorg_visitor_limit` changes the number (0 turns it off; administrators are never limited). Behind a reverse proxy or CDN that WordPress does not see through, all visitors may share the proxy's address: return the real visitor address from the filter `evorg_visitor_ip`.

= Can I change the decision in code? =

Yes: the filter `evorg_blocked_message` receives the message (or `null` when the address passes), the API's result (or a `WP_Error`), the address and the form (`woo_checkout` at WooCommerce checkout). Return a message to stop the form, or `null` to let it through.

== External services ==

This plugin sends the email address a visitor submits to the email-validation.org API to check it:

* **What is sent:** the email address, and your API key in the request header. Nothing else about the visitor.
* **When:** when a visitor submits a form the plugin checks (see the settings), and when you click **Check the connection** (a test address and your API key).
* **Where:** `https://api.email-validation.org`, or `https://api-eu.email-validation.org` when you choose EU data residency.

The service is provided by email-validation.org: [Terms of Service](https://email-validation.org/legal/terms/), [Privacy Policy](https://email-validation.org/legal/privacy/).

== Changelog ==

= 1.0.0 =
* First release.
