WordPress Email + Contact Form Anti‑Spam (All‑Free) Playbook

Stack: Brevo (Free) + FluentSMTP (Free) + WPForms Lite (Free) + Cloudflare Turnstile (Free)

Goal: Reliable outbound email delivery (form notifications, password resets) + strong inbound spam protection, using only free tools.


0) What you’re building (mental model)

Flow

  1. Visitor submits your WPForms Lite contact form
  2. Turnstile blocks bots / verifies humans
  3. WPForms triggers email notifications using WordPress wp_mail()
  4. FluentSMTP intercepts wp_mail() and sends via Brevo Email API (v3) (not “basic SMTP login”)
  5. Brevo delivers mail with your domain authenticated (SPF/DKIM/DMARC)

Why this stack

  • No Google Workspace app passwords stored in WordPress (API key instead)
  • Brevo Free supports transactional emails and includes 300 email sends/day (daily reset, no rollover)
  • FluentSMTP includes Email Logs (useful for troubleshooting and keeping a local “copy” of notifications)

Sources: Brevo free limits/transactional access (https://help.brevo.com/hc/en-us/articles/208580669-FAQs-What-are-the-limits-of-the-Free-plan), Brevo plans overview (https://help.brevo.com/hc/en-us/articles/208589409-About-Brevo-s-pricing-plans), FluentSMTP email logs (https://fluentsmtp.com/docs/fluentsmtp-email-logs-feature/)


1) Prereqs (do these first)

You need

  • Admin access to WordPress
  • Access to your domain’s DNS records (where you manage TXT/CNAME)
  • A dedicated sender address you’ll use for WordPress, recommended:
    • wordpress@yourdomain.com or noreply@yourdomain.com
  • A place to store secrets (password manager)
  • Enable 2FA on WordPress admin accounts
  • Enable 2FA on Brevo
  • Use an admin email that isn’t public

2) Brevo setup (account → domain auth → sender → API key)

2.1 Create your Brevo account

  1. Sign up for Brevo
  2. Verify your email
  3. Turn on 2FA (recommended)

2.2 Authenticate your domain in Brevo (SPF + DKIM + DMARC)

This is the deliverability “make-or-break” step.

  1. In Brevo, go to Settings → Senders, Domains & Dedicated IPs → Domains
  2. Click Add a domain
  3. Brevo will show you DNS records to add, typically:
    • Brevo code (TXT) — domain ownership verification
    • DKIM records (CNAME/TXT depending on DNS provider) — email signing
    • DMARC record (TXT) — policy + reporting

Follow Brevo’s official “Authenticate your domain” guide for your DNS provider UI:
https://help.brevo.com/hc/en-us/articles/12163873383186-Authenticate-your-domain-with-Brevo-Brevo-code-DKIM-DMARC

DNS nuance: SPF “one record only” (merge, don’t add a second)

Correct approach: merge Brevo’s SPF include into your existing SPF record.
Brevo will show you the exact include to use (commonly include:spf.brevo.com, but copy what Brevo gives you).

Example (if you use Workspace + Brevo):

v=spf1 include:_spf.google.com include:spf.brevo.com ~all

(Your real record may differ; always use the include Brevo provides.)

Extra SPF guidance: multiple SPF records fail SPF checks and should be merged into one (https://mailtrap.io/blog/multiple-spf-records/)

DNS nuance: DMARC “one record per domain/subdomain”

Keep one DMARC record per domain/subdomain; do not create duplicates (or DMARC can break).
Example guidance: https://dmarcly.com/blog/can-i-have-multiple-dmarc-records-on-my-domain

Practical DMARC best practice (safe rollout):

  • Start with p=none (monitoring) and review reports before tightening later.

Note: Brevo will provide a DMARC record value; if you already have DMARC, you’ll need to combine reporting addresses (rua) into the single record instead of creating a second DMARC record.

2.3 Verify a Sender email in Brevo (“From Email”)

Brevo expects you to send “From” an email identity you’ve set up.

  1. In Brevo go to Settings → Senders, Domains & Dedicated IPs → Senders
  2. Add a sender:
    • From email: wordpress@yourdomain.com
    • From name: Your brand name
  3. Complete the email verification step (Brevo sends a verification email)

2.4 Create a Brevo API key (v3) for WordPress

  1. In Brevo: Settings → SMTP & API → API Keys
  2. Click Generate a new API key
  3. Name it something obvious:
    • wp-prod-fluentsmtp
  4. Copy it and store it in your password manager

Brevo API key guide: https://help.brevo.com/hc/en-us/articles/209467485-Create-and-manage-your-API-keys
Brevo API auth concept (header is api-key): https://developers.brevo.com/docs/how-it-works

Security best practices

  • One key per integration (so you can rotate/revoke safely)
  • If compromised: deactivate the key immediately (Brevo supports deactivate/reactivate)

3) WordPress setup (plugins + sending + logging)

3.1 Install the plugins

In WordPress Admin → Plugins → Add New:

  • Install + Activate WPForms Lite
  • Install + Activate FluentSMTP

3.2 Configure FluentSMTP → Brevo connection (API method)

  1. WordPress Admin → FluentSMTP → Settings
  2. Add Connection → choose Brevo
  3. Fill the fields:
  4. Save
  5. Send a Test Email from FluentSMTP

Why: it gives you a local record of outgoing emails and delivery status (helpful for troubleshooting and as a “copy” of contact submissions).

  • FluentSMTP → Email Logs (or Settings → enable logging depending on version)
  • Confirm you can see test emails in the log

Docs: https://fluentsmtp.com/docs/fluentsmtp-email-logs-feature/

Privacy note: email logs can contain message content (names/emails/messages).
Only admins should have access.


4) WPForms Lite setup (form + notifications + “store a copy” options)

4.1 Create your contact form

WPForms → Add New

  • Choose “Simple Contact Form” template (or blank)
  • Recommended fields:
    • Name
    • Email
    • Message
    • Optional: “Company”, “Phone” (only if you need them)

4.2 Notification email settings (critical deliverability best practice)

WPForms → your form → Settings → Notifications

Set:

  • Send To Email Address: your receiving inbox (e.g., hello@yourdomain.com)
  • From Name: your brand name
  • From Email: wordpress@yourdomain.com ✅ (same verified sender)
  • Reply-To: the visitor’s email field (so you can reply directly)

Why this matters:

  • If you set “From Email” to the visitor’s email, many systems will fail DMARC alignment and your mail may be rejected or spam-filtered.

4.3 “Store a copy” of submissions on the WordPress site (free options)

WPForms Lite does not store entries in your WordPress database by default; WPForms explains you can back them up remotely using Lite Connect, but restoring/viewing entries requires upgrading.
https://wpforms.com/docs/how-to-use-lite-connect-for-wpforms/

So, free “copy” strategies:

  • Ensure your WPForms notification email includes the submitted fields
  • FluentSMTP will log the email contents and status (success/failed)
  • This is often “good enough” for small sites

Docs: https://fluentsmtp.com/docs/fluentsmtp-email-logs-feature/

Option B: enable WPForms Lite Connect Entry Backups (off-site safety net)

WPForms → Settings → General

Reality check: this is not “view entries inside WP for free.” It’s a backup/restore path.


5) Anti‑spam: Cloudflare Turnstile (free, low-friction)

5.1 Create a Cloudflare account (Turnstile does NOT require moving your DNS)

You can use Turnstile even if your DNS isn’t on Cloudflare.

5.2 Create a Turnstile widget + keys in Cloudflare

In Cloudflare dashboard → Turnstile → Add widget

  • Widget name: contact-form
  • Hostnames: add both if you use both:
    • yourdomain.com
    • www.yourdomain.com
  • Mode: Managed (recommended)
  • Save and copy:
    • Site Key
    • Secret Key

5.3 Add the Turnstile keys to WPForms

WPForms doc path:

5.4 Enable Turnstile on your form

In WPForms form builder:

  • Either add the Turnstile field, or
  • Form Settings → Spam Protection and Security → enable Turnstile (UI varies by version)

5.5 Add extra anti‑spam layers (still free)

  • Enable WPForms honeypot / modern anti-spam (usually on by default)
  • Enable a minimum time to submit (helps against bots)
  • Avoid auto-replies to the submitter unless you truly need them (spammers exploit them)

6) Testing & Verification (how to prove it’s all working)

6.1 The “smoke test” sequence (10 minutes)

Do these in order:

  1. Brevo domain status
    • Brevo → Domains → your domain shows Authenticated / Verified
  2. Brevo sender status
    • Brevo → Senders → wordpress@yourdomain.com shows Verified
  3. FluentSMTP connection
    • FluentSMTP → Settings shows Brevo connection as active
  4. FluentSMTP test email
    • FluentSMTP → send test to your personal inbox
  5. WPForms live submission
    • Submit your contact form from the live page (incognito)
  6. Turnstile verification
    • Confirm you see Turnstile challenge (or “managed” invisible pass)
  7. Email delivery confirmation
    • Confirm you received the WPForms notification
  8. Email header authentication
    • In Gmail: “Show original” → confirm SPF/DKIM/DMARC = PASS
  9. FluentSMTP log confirmation
    • FluentSMTP → Email Logs → your test + notification show Success

6.2 Where to check “truth” for each layer

  • WordPress / FluentSMTP: Email Logs + test email results
  • Brevo: Transactional email activity / events (delivery, bounce, blocked)
  • Mailbox: Email headers show actual SPF/DKIM/DMARC results

6.3 How to read headers (Gmail example)

Open the received email → “More” menu → Show original.

Look for lines similar to:

  • SPF: PASS
  • DKIM: PASS
  • DMARC: PASS

If DMARC fails but SPF/DKIM pass, it’s often a From identity alignment problem (see troubleshooting).


7) Troubleshooting Playbook (symptoms → diagnosis → fixes)

Use this section like a decision tree. Start with your symptom and follow the steps.

7.1 Symptom: Emails don’t send at all (no notification, no test email)

Step 1 — Confirm WP is triggering email

  • Submit the form once
  • Check FluentSMTP → Email Logs
    • If there’s no log entry, WPForms may not be firing a notification (or caching is serving a stale form page)

Step 2 — Confirm FluentSMTP is configured

  • FluentSMTP → Settings:
    • Brevo connection exists
    • “From Email” matches your verified sender

Step 3 — Confirm the Brevo API key

  • Re-copy the API key from Brevo and paste it again
  • Ensure the key wasn’t revoked

Step 4 — Test again

  • Send FluentSMTP test email

Common fixes

  • Wrong API key pasted (extra spaces)
  • Using a “From Email” that is not verified in Brevo
  • Plugin conflict: another SMTP plugin is active (disable other mailer plugins)

7.2 Symptom: FluentSMTP test email works, but WPForms notification doesn’t send

Step 1 — Check WPForms notifications are enabled

  • WPForms → form → Settings → Notifications
  • Ensure notifications are ON and “Send To Email” is correct

Step 2 — Submit the form

  • If no log entry appears in FluentSMTP, WPForms isn’t triggering wp_mail()

Likely causes

  • Form isn’t actually embedded on the page you’re testing
  • Caching / page builder saved old shortcode/module
  • You’re testing a different form than the one you configured

Fix

  • Re-embed the form
  • Clear cache (WP cache plugin + host cache)
  • Test in an incognito window

7.3 Symptom: Emails send but never arrive (missing) or arrive late

Step 1 — Check Brevo events

  • Look for “Delivered” vs “Blocked” vs “Bounced”

Step 2 — Check spam / promotions tabs

  • Gmail: Spam + Promotions
  • Microsoft: Junk + Other

Step 3 — Check your recipient domain

  • Some org mail systems quarantine automated contact emails

Fix

  • Ensure domain auth is complete (SPF/DKIM/DMARC)
  • Use a consistent From identity (wordpress@…)
  • Add a subject prefix like “[Website]” so you can filter reliably

7.4 Symptom: Emails land in spam

Step 1 — Confirm domain auth

  • Brevo → your domain shows authenticated
  • Headers show SPF/DKIM/DMARC PASS

Step 2 — Ensure “From” is your domain

  • WPForms notification “From Email” should be wordpress@yourdomain.com
  • Visitor email must be Reply-To, not From

Step 3 — Reduce spam-trigger content

  • Avoid “free”, “urgent”, excessive links
  • Keep notification template plain text or simple HTML

Fix

  • Repair SPF/DKIM/DMARC
  • Align From identity
  • Add DMARC monitoring and tighten later after reports look good

7.5 Symptom: SPF fails / “permerror” / “too many DNS lookups”

What this means Your SPF record is invalid, duplicated, or has too many included lookups.

Diagnosis

  • You have multiple SPF records → must merge into one
  • You added too many include: mechanisms

Fix

  • Merge SPF into ONE record
  • Remove old/duplicate SPF TXT records
  • Prefer minimal SPF: only includes you truly use

7.6 Symptom: DKIM fails

Diagnosis

  • DKIM record not published correctly
  • Wrong record type (TXT vs CNAME) for your DNS provider
  • DNS record published at wrong hostname (common copy/paste error)

Fix

  • Re-add DKIM exactly as Brevo provides
  • Wait for DNS propagation (can be minutes to hours)
  • Verify the DKIM hostnames match what Brevo expects

7.7 Symptom: DMARC fails even though SPF & DKIM pass

Diagnosis Usually “alignment”:

  • The domain used in the visible From: header doesn’t align with the domain authenticated by SPF/DKIM.

Common cause in WordPress

  • WPForms set “From Email” to the visitor’s address → DMARC fails

Fix

  • Force From Email to your domain sender (wordpress@...)
  • Use Reply-To for the visitor

7.8 Symptom: Turnstile not showing, or form won’t submit

Diagnosis

  • Hostname mismatch (you used yourdomain.com but page is www.yourdomain.com)
  • Cached JS / minified scripts interfering
  • Conflicting CAPTCHA scripts (reCAPTCHA + Turnstile both injected)

Fix

  • In Cloudflare Turnstile widget settings, add BOTH hostnames
  • Clear all caches
  • Disable other CAPTCHA features/plugins for this form
  • Use WPForms “No-Conflict” mode if available in your version (WPForms docs cover this)

7.9 Symptom: You’re suddenly hitting Brevo 300/day limit

Diagnosis

  • Bot spam is triggering form submissions (even if you don’t see them)
  • Auto-replies might be doubling sends

Fix

  • Add Turnstile + minimum submit time
  • Disable any auto-reply to the submitter
  • Tighten WPForms spam settings
  • Consider adding a second filter (Akismet) if spam persists

8) Diagnostics Toolkit (quick checks you can do anytime)

8.1 Confirm DNS records exist (SPF/DKIM/DMARC)

Use your DNS provider’s UI, or a DNS lookup tool:

  • SPF: TXT at root domain
  • DMARC: TXT at _dmarc.yourdomain.com
  • DKIM: at hostnames Brevo provided

8.2 Confirm FluentSMTP is “owning” wp_mail()

  • Disable any other SMTP/mailer plugin
  • Send FluentSMTP test email
  • Check Email Logs for every send

8.3 Confirm form is the one you edited

  • WPForms → check Form ID
  • Confirm page embeds correct form ID/shortcode/module

9) Hardening checklist (quick wins)

Brevo

  • 2FA enabled
  • One API key per integration
  • Revoke keys you don’t use

WordPress

  • Unique admin username (not “admin”)
  • 2FA for admins
  • Keep plugins/themes updated
  • Limit admin users
  • Backups enabled
  • If you store email logs, restrict who can see them

Form

  • Turnstile enabled
  • Minimal fields (less data collected = less risk)
  • No autoresponder unless needed
  • From = your domain, Reply-To = submitter

10) “Known limitations” (so you don’t get surprised)

  • WPForms Lite does not provide an on-site entries dashboard by default; Lite Connect backs up entries for later restore on upgrade.
    https://wpforms.com/docs/how-to-use-lite-connect-for-wpforms/
  • FluentSMTP email logging is the best free “on-site copy” workaround, but it means form content is stored in your WordPress database.

Appendix A — Copy/paste templates

  • From Name: Your Brand
  • From Email: wordpress@yourdomain.com
  • Reply-To: {visitor_email_field}

SPF example (Workspace + Brevo)

v=spf1 include:_spf.google.com include:spf.brevo.com ~all

Use Brevo’s provided include value.