Prevent spam with contact form


#1

Hi,

I have a form with modelless forms and receive spam and I am working on prevent this spam.

I have made the following:

Contactcontroller

<?php
namespace App\Controller;

use App\Controller\AppController;
use App\Form\ContactForm;
use Cake\Core\Configure;

class ContactController extends AppController
{
    
    public function initialize()
    {
        parent::initialize();
        $this->Auth->allow(['index']);
    } 
    
    public function index()
    {
        $contact = new ContactForm();
        if ($this->request->is('post')) {
            if ($contact->execute($this->request->getData())) {
                $this->Flash->success('We will get back to you soon.');
                $this->redirect($this->referer());
            } else {
                $this->Flash->error('There was a problem submitting your form.');
            }
        }
        $this->set('contact', $contact);
        $this->set('recaptcha', Configure::read('Users.reCaptcha.key'));
    }
}
?>

Then contactform.php

<?php 
namespace App\Form;

use Cake\Form\Form;
use Cake\Form\Schema;
use Cake\Mailer\Email;
use Cake\Validation\Validator;
use CakeDC\Users\Controller\Traits\ReCaptchaTrait;

class ContactForm extends Form
{
    use ReCaptchaTrait;
    
    protected function _buildSchema(Schema $schema)
    {
        return $schema->addField('name', 'string')
        ->addField('email', ['type' => 'string'])
        ->addField('body', ['type' => 'text']);
    }
    
    protected function _buildValidator(Validator $validator)
    
    {
         
        $validator->add('name', 'length', [
            'rule' => ['minLength', 10],
            'message' => 'A name is required'
        ])->add('email', 'format', [
            'rule' => 'email',
            'message' => 'A valid email address is required',
        ])->add('body', 'length', [
            'rule' => ['minlength', 20], 
            'message' => 'Message can not be empty'
        ])->add('g-recaptcha-response', 'custom', [
            'rule' => function ($value, $context) {
                if (!$value) {
                    return false;
                }
                if (!$this->validateReCaptcha($value,env('REMOTE_ADDR'))){
                    return false;
                }
                return true;
            },
                'message' => 'Need to use the recaptcha'
        ]);
        
        return $validator;
    }
    
    protected function _execute(array $data)
    {
        $email = new Email('default');
        $email->setFrom(['sales@website.com' => 'My Site'])
        ->setTo('sales@website.com')
        ->setSubject('Website')
        ->send('Ip: '.env('REMOTE_ADDR').', Name: '.$data['name'].', Email: '.$data['email'].' Message: '. $data['body']);
        return true;
    }
}
?>

I believe someone is submitting the form without going through the validation. Posting it directly? Am I doing something wrong here. I basicly used the Cakedc/Users RecaptchaTrait


#2

This should just work fine as far as I can tell.
Are you sure somebody didn’t just get your email from somewhere else?


#3

It was coming through the website. I will check if it still persists.

The form works when I use it through a browser, but somehow I was still receiving spam.


#4

hm… odd… Maybe the spammer has some human clicking on the captcha?


#5

I’ve had excellent success blocking spam simply by including a hidden “website” input in the form. Bots can’t tell it’s hidden, and eagerly fill it in, but browsers don’t show it so humans don’t provide any data there. If you get a form with that field set, you know it’s spam.


#6

This will be my next step if it continues. Seems to have stopped for now.


#7

Check the logs of the webserver or ask your provider to do so - typically the client software is being logged so you can at least identify wether the input comes from a browser or some kind of script.

Also, you can try to limit the number of requests to that action on an IP basis (either in your webserver or via cakephp) or use geoIP blocking mechanisms if the spam originates in specific countries…

Hope this helps…


#8

Zuluru has sugested something you should look into which is the CSRF, which creates a session token and add it into your website as a hidden field which cake will validate once the post request has been made.

https://book.cakephp.org/3.0/en/controllers/components/csrf.html

let me know if this help and happy coding