Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/oliforge/oliforge-submission-guard-for-contact-form-7/archive/refs/heads/main.zipA local, transparent policy firewall for Contact Form 7: checks every submission against the rules of its form. No external services.
Description
OliForge Submission Guard for Contact Form 7 is a local, transparent policy firewall for Contact Form 7. It does not only look for spam: it checks that every submission follows the rules of the specific form it was sent through, entirely on your own server, before any mail is sent.
What makes it different
- Rules, not guesses. You decide what a valid submission looks like for each form: field lengths, no links or HTML where they do not belong, accepted countries, blocked email domains, a minimum time to fill in the form. A submission follows the rules or it does not, and the log shows which rule decided.
- Private by design. Everything runs locally in your WordPress. No message, name or email address is sent to any external service. By default the plugin does not store submitted names, email addresses or message contents.
- You stay in control. Every rule is configured per form. Newly discovered forms stay disabled until you enable them and map their fields. Monitor mode records what a rule would have blocked without rejecting anything, so you can test a rule on live traffic first.
- No subscription. No account, no API key and no monthly fee are needed to keep the protection working, and it does not depend on a vendor's reputation database or an AI service.
- Precise and predictable. The plugin enforces the exact rules of your form instead of competing on the size of a shared blacklist.
One layer in a layered defense
Contact Form 7 itself recommends combining several protections instead of relying on a single mechanism. Submission Guard is designed for that: it works alongside the anti-spam integrations built into Contact Form 7, such as Akismet, Cloudflare Turnstile and reCAPTCHA, and does not replace or disable them. Akismet and a CAPTCHA service judge who is sending, using external intelligence. Submission Guard judges what is being sent, by checking the submission against the rules of that form, locally and without sharing the content. Each check runs independently and a submission has to pass all of them.
What it can enforce
- Field length rules, and blocking of URLs, email-like content and HTML in text fields.
- Validation of native select values and, when OliForge Country Select for Contact Form 7 is active, of every country field on the form.
- Blocking of specific email domains, rate limiting by IP, a minimum completion time and detection of duplicate messages.
- Validation of a configured consent field.
- A hidden honeypot field that catches simple bots.
- Monitor mode, which records rule matches without rejecting the submission.
Logs are lightweight: they record the form (shown by its Contact Form 7 title), the rule that matched and the result, and are paginated in wp-admin. By default the plugin does not store submitted names, email addresses or message contents.
Extending the plugin
The plugin exposes hooks for add-ons such as OliForge Submission Guard Pro for Contact Form 7: extra panels in the Domains and Logging tabs, extra settings keys, additional email-domain checks, additional views on the Logs page, and an oliforge_cf7sg_submission_passed action fired after a submission passes all checks. An add-on that uses this action may store submission details; the free plugin itself does not.
Installation
- Install and activate Contact Form 7.
- Upload and activate OliForge Submission Guard for Contact Form 7.
- Open the "Submission Guard" menu in wp-admin, enable protection for the required CF7 forms, map their fields, and configure the shared rules.
Screenshots
- The dashboard: blocked and monitored submissions, the most triggered rules and recent activity.
- Content rules: block links, email patterns and HTML, and reject select values that are not one of the field's options.
- The log: which form, which rule and what result, without storing names, email addresses or message contents.
Changelog
0.4.6
- Renamed to "OliForge Submission Guard for Contact Form 7" and moved to the matching text domain and plugin file for the WordPress.org directory. Menu pages, settings and stored data are unchanged.
- Declared Contact Form 7 as a required plugin and the plugin author and license URIs in the plugin header.
- The admin logo is now a small bundled image.
- Updated the optional OliForge Country Select integration to the new Country Select plugin file name.
0.4.5
- Rewrote the plugin description: a local, transparent policy firewall that checks every submission against the rules of its form, with no external services, working alongside Akismet, Turnstile and reCAPTCHA.
- Listed the honeypot field in the feature list.
0.4.4
- Timing failures now log distinct rule codes:
too_fast(submitted before the minimum time),timing_missing,timing_invalidandtiming_expired. Previously every timing failure was logged astoo_fast, including a missing, altered or day-old timing token. - A missing, altered or expired timing token now shows a new editable "form expired" message asking the visitor to reload the page, instead of the "too quickly" message.
- Updated the translation template and the German, Spanish, French, Russian and Ukrainian translations.
0.4.3
- Added a "Get more with Submission Guard Pro" block at the bottom of the Dashboard, listing the Pro features with a button to the Pro page (hidden once Pro is active).
- Updated the translation template and the German, Spanish, French, Russian and Ukrainian translations: the new Pro strings plus previously untranslated strings (honeypot option, Logs tab, settings notices). Fixed the plural rules for Russian, Ukrainian and French.
0.4.2
- Database queries now pass table names through the
%iidentifier placeholder of$wpdb->prepare()instead of interpolating them into the SQL string (requires WordPress 6.2+, already the minimum). - Documented why the plugin's direct queries against its own log and rate-limit tables are intentional, and why submitted form values are read without a nonce (the request is handled by Contact Form 7).
uninstall.phpno longer defines global variables; it drops both custom tables through a prefixed function.- Cleared all Plugin Check findings except the discouraged
load_plugin_textdomain()call.
0.4.1
- Added an "Upgrade to Pro" link in the Plugins list (hidden once the Pro add-on is active).
- Added the Plugin URI header linking to the plugin page on oliforge.io.
- Fixed two Plugin Check errors: a missing translators comment and an unescaped attribute fragment on the settings page.
0.4.0
- Added extension hooks for optional log views and successful-submission processing used by compatible add-ons.
- Added a logging-panel extension point for add-on settings.
- Added paginated log views and human-readable Contact Form 7 form labels.
- Improved cache busting for edited admin CSS and JavaScript assets.
- Added a reliable fallback for the settings-saved admin notice.
- "Clear all logs" now removes only blocked/monitored entries; passed entries are kept.
0.3.0
- Admin settings UX: widened the "Field" column in the Logs table, gave the "Fields checked by content rules" block a proper section heading, and fixed the "Settings saved." notice never appearing after save (auto-dismisses after 5 seconds now).
- Every
country_selectfield on a form is now validated automatically — replaced the manual per-form "Country fields" checkbox toggle with auto-detection, and fixedcountry_selectfields slipping into the generic "Fields checked by content rules" list (only plainselectwas excluded before). - Added extension points for add-ons (e.g. OliForge Submission Guard Pro for Contact Form 7):
oliforge_cf7sg_domains_panelaction to render extra UI in the Domains tab,oliforge_cf7sg_sanitize_settingsfilter to persist extra settings keys, andoliforge_cf7sg_domain_checkfilter to add extra email-domain checks beyond the core blocklist.
0.2.5
- Moved textdomain loading from plugins_loaded to init: since WordPress 6.7, loading a plugin's textdomain before the init hook can trigger a "_load_textdomain_just_in_time was called incorrectly" notice. The plugin still ships and loads its own bundled translations (it isn't distributed through WordPress.org language packs), so load_plugin_textdomain() itself stays — only its timing changed.
0.2.4
- Fixed: unchecking every field in a form's "Country fields" list and saving had no effect — the previous selection was silently kept instead of being cleared, because unchecked checkboxes submit nothing and the save handler couldn't tell that apart from the panel not being shown at all.
- Country validation now uses OliForge Country Select for Contact Form 7's structured
get_country_context()API (3.2.7+) when available: an unresolvable list: (unknown/deleted slug, or Pro inactive) is now logged as its owncountry_list_unresolvedrule, distinct frominvalid_countryfor a genuinely bad submission — the visitor sees the same message either way, but the two are easy to tell apart in the Logs and dashboard rule breakdown. - Refreshed translation strings for the 0.2.3 country-field changes ("Country fields" checkbox group) across all 5 bundled locales, and fixed their Project-Id-Version header, which msgmerge doesn't update on its own.
0.2.3
- A country_select field is now always validated through OliForge Country Select for Contact Form 7's API — a leftover value in the (now-hidden) legacy allowed_countries setting could previously override a Pro list: option instead of the field's own configuration.
- A protected form can now have more than one country field (e.g. billing vs. shipping): every country_select field is protected by default, and each is checked independently. The single "Country field" dropdown per form is replaced with a "Country fields" checkbox group.
- country_select fields fail closed when Country Select itself can't resolve a list: option (unknown/deleted list, or Pro inactive): previously an unresolvable list silently fell back to accepting no value as invalid only if a legacy allowlist happened to also be empty; now it's always rejected.
0.2.2
- Country validation now uses OliForge Country Select for Contact Form 7's public
get_allowed_country_codes()API (3.2.5+) when available, instead of a no-op: it checks the submitted value against exactly the set that field's admin allowlist, include/exclude options, and Pro named lists allow, and logs a genuineinvalid_countryblock when it doesn't match.
0.2.1
- Validate native CF7 select values, including pipe-mapped and multiple values.
- Exclude select and dedicated email, country, and consent fields from generic content rules.
- Use an atomic fixed-window database rate limiter.
- Separate the plugin version from the database schema version.
- Refresh translation metadata and release packaging.
0.2.0
- Discover saved Contact Form 7 forms and their fields automatically.
- Add an independent protection profile for every form, including field mapping and length rules.
- Apply validation, timing tokens, rate limits, duplicate detection, and logs only to enabled forms.
- Keep newly discovered forms disabled until an administrator explicitly enables them.
0.1.3
- Record Monitor only rule matches as monitored instead of blocked and report them separately on the dashboard.
0.1.2
- Store duplicate-submission fingerprints only after Contact Form 7 successfully sends the message.
0.1.1
- Show country settings and run country validation only when OliForge Country Select for Contact Form 7 is active.
0.1.0
- Initial release.