Uniform spam problem

There is a uniform contact form on one of my pages that keeps receiving spam, even though I implemented the required code.
Since there is even another form on the same website - the only difference is that it is not called a contact form - I am honestly clueless about what the problem might be. The plugin folder is intact and Honeypot and CSRF are drawn correctly on the website - that is, they are actually there.

I’d post some code, but I have no idea where the problem could be to begin with.
Is there anything I am missing? Do I have to implement something more?

The honeypot doesn’t prevent spam in general, it only aims to prevent auto-filling of forms by bots etc. that fill in any field and thus go into the trap. So if it is real people filling the form, there is no real way to prevent that unless they are coming from an IP range you could generally block. And more clever bots probably won’t go into the honeypot either…

Check if you really need the form. Do you get real messages through the form at all? If not, remove the form.

You could of course implement Captchas or quizzes, to discourage people to fill in the forms (might also stop real contact from filling in the form though).

Or analyze the spam messages:

  • are they very short? (=> implement minimum character count)
  • do they contain typical words (=> check content for words)

I’ve also noticed an increasing amount of spam on sites with Uniform and its honeypot for a few months. I think spam bots have become a tiny bit smarter, and only fill required fields. As a honeypot field can’t be required, this approach doesn’t seem to really help anymore.
So I’m also looking for another approach, but also try to avoid captchas as I find them ugly and annoying. I haven’t found any magic solution so far.

I am seeing this too. I might introduce a simple math problem to the form but I would really rather not. I guess you could detect key presses to know its a real person because a bot probably pastes it in, but I don’t how foolproof that would be.

You also risk to mark as spam people who use browser autocomplete or other ways to fill in the content.

Sure but you could just do it on a “your message” textarea field that is going to be unique. The other route is to block access from the spam bots them selves through .htaccess.

I looked into the new ReCAPTCHA version which seems to be completely straightforward: just mark the box, and there you go. I also read that they are going to implement a completely invisible version of it, which just checks for user behavior on the contact form. I will use ReCAPTCHA I think.

I like the captcha they have on GitHub when you create a new account.

Just for the record, Uniform also supports the calc and reCAPTCHA guards which can be enabled instead of or in addition to the honeypot. The reCAPTCHA still needs to be updated for Kirby 3, though.

I’d like to revive this thread because a client has been getting empty form messages. These incorporate the ‘required’ form fields (I can see this because I’ve written surrounding text to make the email more ‘conversational’.

I’m using the honeypot and the calcGuard captcha.

It seems the spammers may be bypassing the form altogether and using the script actions to send mail directly. Neither ‘required’ fields nor spam traps will stop this, will they?

Is there a way of preventing this activity? I’ve just suggested Texnixe’s answer to the client… removing the form altogether. Which is a shame. I just don’t think I have the coding skill to fix it.

Kirby 3, Uniform v4

@Hugh: Are you doing form validation for the required fields on the server?

Even if they directly post to the script from a software, server-side validation should still kick in…

Does the client actually receive desired mail from the contact form?

@texnixe I’m guessing that if I don’t know the answer I’m probably out of my depth.

Controller code is as follows.

I’ve used HTML5 required fields for everything but the email address.

and in answer to your question, yes, the client does receive the mail from the form:

use Uniform\Form;

return function ($kirby)
$form = new Form([
  'name' => [],
  'surname' => [],
  'email' => [
    'rules' => ['required', 'email'],
    'message' => 'We need to be able to contact you',
    'mobile' => [],
    'date' => [],
    'droptime' => [],
    'captcha' => [],
    'date2' => [],
    'message' => [],

if ($kirby->request()->is('POST')) {

$form->sessionStoreAction(['name' => 'booking-form']);

  'to' => $form->data('email'),
  'from' => 'sender@domain.com',
  'subject' => 'Your booking enquiry',
  'template' => 'booking',

	if ($form->success()) {
return compact('form');

@Hugh The only required field in your controller is the email address… What you put into your HTML form field is sort of pretty irrelevant (or is only an additonal layer, but everything you want in your form needs to be validated serverside in addition to everything you do on the frontend).

@texnixe I guess my naive assumption (if I’d thought about this at all) would have been that Kirby Uniform or Kirby itself would take care of this. It sounds as though I need some serious help.

@Hugh The Uniform plugin in fact makes it pretty comfortable, because all you have to do is set up the required rules for the other required fields like you did for the email field, the rest is then taken care of by the plugin.

@texnixe Thank you. Your messages have helped a lot of things fall into place. Have now added simple ‘required’ rules for more fields, and used the example code (from the docs) in the form itself for validation, rather than front end HTML5 validation with a bit of Javascript for custom messaging. (I had been having problems with getting my Uniform form to work, which is why I had stripped everything out, but that must have been caused by my bad coding.)

I didn’t really understand that front and back end validation were different, and that Uniform would take care of this if I followed the pattern in the examples. This has been very helpful. (You’re probably shaking your head in disbelief.)

@Hugh, trust me, I don’t. Forms are hard if you want to do them right. We come across badly implemented forms every day, from forms that don’t work as expected, to form that are not accessible for different kinds of users and forms that require so much stuff that is not needed for the task and that poses a privacy issue.

HTML5 has made forms easier with different types of inputs and client-side validation, but not every browser support all features, and as you have experienced, it is very easy to bypass, e.g. by using a tool that automatically sends emails without a browser.

That’s why server-side validation is so important.

Glad you have sorted it out now :slightly_smiling_face:.

OK, well, much time has gone by and this one form on the website is still attracting spam messages.

  • I’ve used HTML5 validation for the required fields, and added validation rules in Uniform for those fields, but the spammers fill in these fields as per the rules.

(e.g. ‘name’ => [
‘rules’ => [‘required’, ‘match’ => ‘/[A-Za-z- ]{2,20}/’],
‘message’ => ‘Please let us know what to call you’,

  • I’ve blocked the whole world from seeing this form, apart from the country I’m and the nearby country.

  • I’ve supposedly limited the amount of text that can be entered in the textarea, using ‘maxlength=“250”’ in the HTML, but still receive messages much longer than this.

What could be going on? Am I just in an arms race that I cannot win?

The first question I’d try to answer is if the form is really needed, if not, remove it.

Fighting spam is hard. I guess you have the honeypot implemented? But of course, it’s easy to bypass. Also, spam protection probably protects against bot spam, but not the myriads of people who probably don’t have other stuff to do then fill in forms. I’m not really convinced it’s all bots. You could of course test if you are more successful by implementing either Google reCAPTCHA or another botguard, like math guard or whatever.

Thanks, @texnixe. I know the client is pretty keen on keeping it. Perhaps I can persuade him to do without the textfield. I’ll see.

What puzzles me is that the form seems to be being filled in by someone in a geo-blocked zone, and that that someone is able to bypass the 250 character limit. Does this indicate that they’re able to operate the form script independently of the form? And if so, can I move or rename that script to try to outwit them?