Bandage for Craft CMS

Free · Pro $79 · Craft CMS 5

Your contact form has no memory

Craft's Contact Form plugin is deliberately tiny: it takes a POST, checks an email address, and sends one message. That is the whole plugin. So a site running it has no record of what it received, no defence against the spam a public form attracts inside a week, no way to tell the sender it arrived, no way to send an enquiry anywhere but one fixed address — and no way to recover the fortnight that vanished while the mail server was down. Bandage adds all of it without changing your form.

Bandage

One line, and it is the only one

Bandage never forks Contact Form. It attaches through the only three events Contact Form fires, so contact-form/send is still the action you post to, submission is still Contact Form's model, and getErrors() still behaves exactly as documented. Adopting it means adding a tag to a template you already have.

twig
<form method="post" accept-charset="UTF-8">
  {{ csrfInput() }}
  {{ actionInput('contact-form/send') }}
  {{ redirectInput('contact/thanks') }}

  {# This is the only line Bandage needs. #}
  {{ craft.bandage.form() }}

  <input type="email" name="fromEmail">
  <input type="text" name="message[Phone]">
  <textarea name="message[body]"></textarea>

  <button type="submit">Send</button>
</form>

{# Per-field errors, keyed by the label you already know #}
{% set errors = craft.bandage.errors(submission) %}
{{ errors.Phone ? errors.Phone|first }}

{# The reference, on the thank-you page #}
{{ craft.bandage.reference() }}   {# K4TP-9WQR #}

Features

Everything a contact form needs on the second day, once the first enquiry has already been lost.

Every message, and its files, kept

Submissions are Craft elements, so the index, search, exporter, trash, per-user permissions and a field layout are Craft's own rather than a second implementation of each. Uploads are copied into a volume instead of dying with the temporary file.

  • The field layout is where your team records what happened next
  • A short reference — K4TP-9WQR — somebody can read down a phone
  • Attachment records keep filename, size and kind after the volume is emptied

Spam that scores instead of vetoing

Honeypot, time trap, rate limit, word and pattern blocklists, sender and IP blocking, throwaway addresses, MX checks, link counting and CAPTCHA. Each contributes to a score; the threshold decides.

  • A password manager filling a hidden field is not a bot — one hit alone is forgivable
  • Quarantine, reject or flag, and all three store the message

Fields that actually get validated

Contact Form validates two things: that the sender's address is an email address, and that the message isn't empty. Every other field on your form is unchecked, and a visitor who mistypes a phone number finds out never.

  • Required, email, URL, number, whole number, pattern, length, allow and deny lists
  • Errors land under the name the input already has

Not always the same inbox

The most-asked-for thing Contact Form cannot do: its recipients come from one setting and are identical for every submission the site will ever take. Route To, Cc and Bcc on what the sender actually answered.

  • One condition per line — paste it, diff it, review it
  • A rule with no conditions matches everything: the catch-all Bcc

Everything after the send

A confirmation back to the sender with their own answers and their reference, and the same submission delivered to a signed JSON webhook, Slack or Microsoft Teams — all of it on the queue, so a dead endpoint never holds the visitor's browser open.

  • The autoresponder is rate limited per recipient — it is a relay aimed by the request body
  • X-Bandage-Signature: sha256=… is an HMAC over the exact bytes sent
  • Endpoints are http(s) only, because a file:// endpoint with a settings screen is a forgery primitive

Export, retention and the quiet week

CSV from the control panel and the console, each submitted field expanded into a column of its own. Retention deletes after N days, spam sooner, and can blank stored IPs while keeping the message.

  • Cells beginning = + - @ are neutralised. Every value in that file came from a stranger
  • The digest exists because a broken form looks exactly like a quiet week

Frequently Asked Questions

The questions worth answering before you install it.

One tag away

Install it, add the line, and the next enquiry your site receives is one you still have next year. Free for a single form; Pro is $79 when you need routing, rules and autoresponders.