=== Blueforce Spam Protect ===
Contributors: worshipper
Tags: spam, anti-spam, honeypot, contact form, comments
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Blocks form and comment spam without captcha. All checks run on your own server, your visitors' messages never go to an external service.

== Description ==

Blueforce Spam Protect checks every submission of your forms and comments on your own server. There is no captcha, no puzzle and, unless you switch it on yourself, no external service. Visitors do not notice anything.

**What it is, and what it is not.** The plugin reduces spam from bots. It cannot guarantee that every spam submission is stopped, and a real submission can occasionally look suspicious. That is why only clear spam is rejected, and everything that merely looks suspicious is still delivered and written to the log.

= Why another anti-spam plugin =

Many spam plugins either send every submission to a cloud service or put a captcha in front of your visitors. This plugin does neither.

* **Everything stays on your server.** Out of the box nothing is sent to an external service, and there is no spam service to name in your privacy policy. Two optional functions use StopForumSpam, a check of the sender's IP address and the reporting of bots. Both are off by default, and the message of a form is never sent in either case.
* **No captcha.** Real visitors fill in the form as usual.
* **No real enquiry gets lost.** Only clear spam is rejected. Anything in between is delivered and written to the log, so you can see why it looked suspicious.
* **Works with page caches.** The fields are added by a small script in the browser, the token is only requested when a visitor starts filling in a form.

= How it decides =

Each submission collects points from several independent checks:

* A hidden field that only bots fill in.
* A signed token that proves a real browser loaded the page. The server measures how long filling in the form took, the browser cannot fake it.
* A small computing task that the browser solves in the background while the visitor fills in the form (proof of work). Visitors do not notice it, a bot has to pay for it with computing time on every submission. A token can only be used a few times.
* Whether the visitor used mouse, keyboard or touch, and whether the browser is remote-controlled.
* Missing browser language, script user agents.
* Links, stop words and text in an unexpected script.
* Advertising in the name or signature: a web address in the name field, or a text that ends with a link carrying the sender's own name.
* Whether the e-mail domain exists at all (DNS lookup, only when it can change the decision).
* Too many submissions from the same address in a short time.

Below the suspicion threshold a submission is accepted. Suspicious submissions are delivered and written to the log. Only from the block threshold on is a submission rejected, with a clear message to the visitor.

The plugin protects from the moment you activate it, there is nothing to switch on. If the log ever shows a real enquiry among the blocked ones, allow the sender with one click or raise the block threshold.

= Features =

* WordPress comments: blocked comments go to the spam folder, suspicious ones to moderation. Commenters who already have an approved comment get a bonus, so regulars are not held back
* Pingbacks and trackbacks are checked as well, without the browser checks they cannot pass. Pingbacks from your own site are left alone
* Elementor Pro forms
* Fluent Forms
* Contact Form 7
* Ninja Forms
* Booking Calendar (the booking form of the plugin "Booking Calendar")
* WPForms
* Forminator
* MetForm
* Jetpack contact form
* Gravity Forms (built against its documented hooks, not yet verified on a live installation)
* WordPress registration (`wp-login.php?action=register`, on multisite `wp-signup.php`): a blocked registration creates no account, a suspicious one is created and logged
* WooCommerce registration on the My account page, with the same rules. The checkout is left alone on purpose
* Mailchimp for WordPress (MC4WP) sign-up forms: a blocked sign-up is not sent to Mailchimp. Unsubscribing is never blocked
* MailerLite sign-up forms created in the official MailerLite plugin: a blocked sign-up is not sent to MailerLite. Forms and pop-ups that MailerLite serves from its own servers cannot be checked by any plugin on your site
* Protects right after activation, with adjustable thresholds
* Log of suspicious and blocked submissions with the reasons, counters for the last 30 days
* Your own stop words, an allowlist and a block list for IP addresses, ranges and e-mail domains. An allowed IP address always passes. An allowed e-mail domain only passes when a real browser sent the form and the hidden field is empty, because anyone can type a domain
* Allow or block a sender with one click in the log. IP addresses from these buttons expire after 30 days, free mail domains are never allowed as a whole
* Optional: check the IP address of the sender at StopForumSpam. Off by default, only the IP address is sent, and it can only be switched on together with a confirmation that your privacy policy mentions it
* Optional: report bots that fill in the hidden field to StopForumSpam, with your own API key. Off by default, a separate switch with its own confirmation. A report contains IP address, e-mail address and name, never the message
* The admin bar shows administrators how many submissions were blocked in the last 30 days. Can be switched off in the settings
* Dashboard widget with the numbers of the last 30 days and a small chart of blocked submissions per day
* Site Health tests: is the protection active, are there forms it does not protect
* Optional quarantine: keeps blocked submissions for 14 days on your own server, so no genuine enquiry is lost when the check gets it wrong. Off by default, needs your confirmation that the privacy policy mentions it. At most 200 submissions are kept. Fields that look like passwords, payment details or uploads are left out, recognised by their name, their type and their value. Switching it off or deactivating the plugin deletes what is stored. Works with the personal data export and erasure tools of WordPress
* Suggested text for your privacy policy
* Translation-ready. German is included for Germany (informal and formal) and for Switzerland (formal and informal)
* Removes all its data when you delete it

= For developers =

* `bf_spam_signals` receives all signals before scoring, for example to add a block list.
* `bf_spam_checked` fires after every decision, with the result, the form and the IP address.
* `bf_spam_trusted_proxies` (or the constant `BF_SPAM_TRUSTED_PROXIES`) adds your own proxies or load balancers, as addresses or ranges. Cloudflare and private addresses are trusted already.
* `bf_spam_client_ip` overrides the visitor address as a last resort.
* `bf_spam_skip_selector` leaves forms matching a CSS selector alone.
* `bf_spam_mail_domain_lookup` replaces the DNS lookup, for example in tests.
* `bf_spam_registration_message` changes the message shown when a registration is blocked.
* `bf_spam_signup_message` changes the answer sent when a newsletter sign-up is blocked.
* `bf_spam_pow_bits` sets the difficulty of the computing task in bits (default 19, 0 switches it off, each bit doubles the work).
* `bf_spam_sfs_min_frequency` sets from how many reports at StopForumSpam an address counts as known (default 3).
* `bf_spam_sfs_report` has the last word on whether a sender is reported to StopForumSpam. Return false to prevent it.
* Add `data-bf-spam-skip` to a form to leave it out.

This plugin is an independent project by Blueforce Digital Solutions. It is not affiliated with Elementor, Fluent Forms, Contact Form 7, Ninja Forms, Booking Calendar, WPForms, Forminator, MetForm, Jetpack, Gravity Forms, WooCommerce, Mailchimp, Mailchimp for WordPress or MailerLite. Product names are used only to describe compatibility.

== Installation ==

1. Upload the plugin folder to `/wp-content/plugins/` or install it through the Plugins screen.
2. Activate the plugin.
3. That is all. The plugin protects right away. Under Settings, Spam Protect you find the log and the settings.

== Frequently Asked Questions ==

= Does it stop all spam? =

No plugin does. Blueforce Spam Protect stops the usual bot spam. Bots that control a full, disguised browser can get through, and so can a script whose author is willing to spend computing time on every submission. Spam written by humans is only caught by the content checks.

= A visitor without JavaScript cannot send the form? =

They can. A missing script alone only counts as a suspicion. The submission is delivered and logged.

= Does it work with plugins that combine or minify scripts? =

Yes. WP-Optimize, Autoptimize, WP Rocket and LiteSpeed may merge the script of this plugin into a combined file. The script then reads its settings from a small meta tag in the head of the page. Clear the page cache once after installing or updating.

= Does it work with Cloudflare or a proxy? =

Yes. Behind Cloudflare the plugin uses the visitor address that Cloudflare passes on, but only when the request really comes from a Cloudflare address. Behind a load balancer or proxy on a private address it reads `X-Forwarded-For` from the right. For a proxy on a public address, add it with the `bf_spam_trusted_proxies` filter or the `BF_SPAM_TRUSTED_PROXIES` constant. Headers sent by anyone else are ignored, so a bot cannot pick its own address.

= Does it protect the WooCommerce checkout? =

No, on purpose. A false alarm at the checkout would cost an order. The script leaves checkout and cart forms alone, and accounts created during checkout are not checked. Only the registration form on the My account page is protected.

= My form plugin is not in the list. =

Site Health tells you when an active form plugin is not supported. Its forms are then not checked.

= Can I read what was blocked? =

Not by default: the plugin stores no message texts. If you switch on the optional quarantine, blocked submissions are kept for 14 days and shown in the log, so you can answer a genuine enquiry that was blocked by mistake. Blocked comments are always in the spam folder of WordPress.

= What happens to the data when I delete the plugin? =

Deleting the plugin removes its settings (including the API key), its four tables (log, counters, quarantine and short-lived counters), its scheduled task, its cached values and the review notice choices, on every site of a multisite network. Comments it moved to spam or moderation stay where they are, they belong to your site.

== Privacy ==

By default nothing a visitor writes leaves your server. The only outside request is a DNS lookup of the e-mail domain (not the address), through the name server of your hosting, and only when the result can change the decision. For suspicious and blocked submissions the IP address and the domain of the e-mail address are stored for up to 30 days, then deleted automatically, also on sites where WP-Cron rarely runs. If you allow or block a sender with a button in the log, the IP address is kept for a further 30 days and an allowed e-mail domain until you remove it. Message texts, names and full e-mail addresses are not stored, unless you switch on the optional quarantine: it keeps blocked submissions on your own server for 14 days, so you can read them in the log. A suggested text for your privacy policy is added under Settings, Privacy.

If you switch on the optional StopForumSpam check, the IP address of the sender is sent to stopforumspam.com when a form is submitted. If you switch on the optional reporting, the IP address, the e-mail address and the name of a bot that filled in the hidden field are sent to stopforumspam.com and published there. The message of a form is never sent. See External services below.

== External services ==

This plugin can connect to StopForumSpam (https://www.stopforumspam.com), a service that collects the addresses of known spammers. There are two separate functions. Both are optional and off by default, and each can only be switched on in the settings together with its own confirmation that your privacy policy mentions it.

**1. Checking the sender.** When it is switched on, the plugin sends the IP address of the sender to `https://api.stopforumspam.org/api` each time a protected form or comment is submitted, to learn whether the address has been reported as a spammer. Nothing else is sent: no message, no name, no e-mail address. The answer is remembered for one day, so the same address is not sent again within that time. Nothing is sent for page views, for senders on your allowlist, or when a submission is already blocked for another reason. If the service does not answer, the submission is treated as if the check were off.

**2. Reporting spammers.** When it is switched on and you have entered your own API key from StopForumSpam, the plugin sends a report to `https://www.stopforumspam.com/add` when a submission is blocked because the hidden field was filled in, a field that human visitors never see, and the submission shows at least one more sign of a bot (for example no JavaScript, no interaction or a remote-controlled browser). The second sign is required because an autofill tool could fill the hidden field for a real visitor: that submission is blocked, but not reported. The report contains the IP address, the e-mail address and the name or user name entered in the form, a fixed sentence as evidence, and your API key. StopForumSpam requires these three details for a report and publishes reported entries in its database. The message is never sent. Nothing is reported for a mere suspicion, for senders on your allowlist, for logged-in users, for private addresses, or when the form has no name or no e-mail address. Each address is reported at most once a day. The plugin does not store the reported name or e-mail address. When you open the settings page with a key entered, the plugin asks StopForumSpam once whether the key is valid. That request contains only the key, and the result is shown as a green or red light next to the key field.

The data belongs to StopForumSpam and is used under its terms: [usage terms](https://www.stopforumspam.com/usage), [license](https://www.stopforumspam.com/license), [privacy policy](https://www.stopforumspam.com/privacy).

== Screenshots ==

1. Settings: counters of the last 30 days, thresholds and the forms that are checked.
2. The log shows why a submission looked suspicious or was blocked, with one-click buttons to allow or block the sender. Message texts are only stored if you switch on the optional quarantine.
3. Site Health confirms that the protection is active and tells you whether forms are left unprotected.
4. Allowlist, block list and the optional StopForumSpam functions. They are off by default and need your confirmation that the privacy policy mentions them.
5. Dashboard widget and admin bar: how many spam submissions were blocked in the last 30 days, with a chart per day.

== Changelog ==

= 1.0.0 =
* Initial release.

== Upgrade Notice ==

= 1.0.0 =
Initial release.
