I get a lot of spam mails through the public available forms. I use the honypot field but looks like spam-bots are too clever to get trapped.
Also I want to avoid using google captcha as long as there are other autmated solutons.
After some search for best-practice I came across two ideas for detecting form spam:
The first one uses a hidden field with a timestamp and and compares the submitted timestamp with the current time. if the delta is below a certain time it´s likley that there was no human involved. I guess this is something which has to be implemented in the plugin itself.
Spam-bots want to share URLs. All of the spam-mails i have in the inbox contain an URL in the message-field. But it doesn´t make sense to write about URLs in my forms, so I thought about adding a validation.pattern that checks for URL-strings. Basically checking for “http://” would be enough.
For this approach I need some help. How would a validation pattern look like, that is falsey when a URL is included?
@daubneyi, I needed a solution myself for my own ContactForm plugin because someone was having a blast last night filling my mailbox which a few thousand of spam messages…
The solution mentioned above, seems to be failing when surrounding the pattern with a /. And without the /s, the pattern will fail when ‘message’ contains newlines.
So here is a rough abstract of the solution I was working on. It requires a custom plugin, but isn’t that difficult to create. It allows you to add as many patterns and messages as you like.
Create a plugin using $ bin/plugin devtools new-plugin
Let’s assume you named it ‘nospam’.
In ‘/user/plugins/nospam/nospam.yaml’ add the following:
enabled: true
fields:
name: []
email: []
phone: []
message:
- pattern: '/<br\/?>/i'
message: 'HTML is not allowed'
- pattern: '/https?:\/\//i'
message: 'URL is not allowed'
onSpam: notify # die|notify (default)
In file ‘/user/plugins/nospam/nospam.php’:
Alter function ‘onPluginsInitialized’ into:
public function onPluginsInitialized(): void
{
// Don't proceed if we are in the admin plugin
if ($this->isAdmin()) {
return;
}
// Enable the main events we are interested in
$this->enable([
// Put your main events here
'onFormPrepareValidation' => ['onFormPrepareValidation', 0],
]);
}
Create a new function to validate the fields
public function onFormPrepareValidation(Event $event)
{
/** @var Form */
$form = $event['form'];
$values = $form->value();
$fields = array_keys($form->getFields());
$onSpam = $this->config->get("plugins.nospam.onSpam", 'notify');
$messages = [];
foreach($fields as $field) {
$patterns = $this->config->get("plugins.nospam.fields.$field", []);
foreach($patterns as $pattern) {
if (preg_match($pattern['pattern'], $values[$field]) === 1) {
if ($onSpam === 'die') {
die();
}
if (!isset($messages[$field])) {
$messages[$field] = [];
}
$messages[$field][] = "Field '$field': {$pattern['message']}";
}
}
}
if (count($messages) > 0) {
$exception = new ValidationException('');
$exception->setMessages($messages);
throw $exception;
}
}
Result:
Notes:
Multiple notifications per field.
Multiple validation checks per field.
onSpam: notify: show validation message in page.
onSpam: die: stop processing when spam detected.
nospam.yaml: Only add fields that need testing for spam.