Are you getting way too many spammy comments?

We created a module you can use on different projects to prevent fake registrations. Darko Zaric, our experienced Drupal developer, explains how to build the module and use it.

Spammers and sploggers pose a grave risk to online communities and without some protection in place, your fledgling community is in danger of being overrun by spammers trying to sell fake Uggs and Oakleys.

Fake users can easily make up to 98% of all new account requests.

That’s a huge number, so it’s useful (read: crucial) to have a game plan for stopping or decreasing the number of fake registrations.

How?

In Drupal, by default, there’s an option that automatically blocks all new users after registration, and the site administrator needs to activate their accounts.

This option works great leaving no room for someone to register on the site and post spammy comments.

However, even with this option, you can still encounter a problem, as we did working on one of our projects.

What seems to be the problem?

Spammers are added to the list of accounts that needs to be approved by the administrator, but you might not know who the real user is.

That’s the problem.

The project we worked on was a closed system used for file sharing between users on the site and soon after the project went live, the spam bots found the site address and started spamming every day.

Moreover, we sometimes saw several hundreds of registrations per day, and administrators had to spend a lot of time filtrating the real users from the fake ones.

We applied several solutions (captcha, hidden field that had to be empty, and more), the number of spam users was reduced, but the problem remained.

We decided to create and apply our custom solution using email verification.

How does email verification work? 

  • A user comes to a registration page, inserts an email address and clicks on the button “get the verification code.”
  • An email with a unique code for registration is sent to the user’s email address
  • The unique code is to be entered into a provided field on the registration page
  • When the user tries to register with the code, the inserted code is checked
  • If the code is valid, the user can register
  • If the code is invalid, an error appears on the screen

It’s a simple, yet efficient way to stop having spammers and sploggers create fake accounts and to prevent fraudulent registrations.

Read on to see how we made the module. I will explain in details, so if you follow these steps, you can apply the module efficiently on your project to prevent fake registrations.

#1 Step – Alter the registration form

To add a button for sending the verification code to an email, you need to alter the registration form.

The registration form should have Ajax submit button and a text field for the code to be inserted. Besides the new field, it’s necessary to add a new function for the verification process. You can do this by forming alter function code as shown below:

 
 * Implements hook_form_alter.
 */
function custom_mail_verification_form_alter(&$form, &$form_state, $form_id)
{
  switch ($form_id) {
    case 'user_register_form':
      $form['account']['get_code'] = array(
        '#type' => 'button',
        '#value' => 'Get Verification Code',
        '#limit_validation_errors' => array(),
        '#suffix' => '<div>'.t('Enter the email address and click on the button to get your verification code').'</div><div id="mess"></div>',
        '#ajax' => array(
          'callback' => 'custom_mail_verification_form_ajax_submit',
          'wrapper' => 'mess',
          'effect' => 'fade',
        ),
      );
      $form['account']['verification_code'] = array(
        '#type' => 'textfield',
        '#title' => t('Verification code'),
        '#required' => 1,
      );
      $form['#validate'][] = 'custom_mail_verification_register_validate';
      break;
  }
}

After you perform hook_form_alter, new elements will appear on the registration form as shown in the image bellow:

Prevent Fake Registrations In Drupal - Registration form#2 Step – Create a new table in the database

In a module.install file, create a new table in the database using hook_shema. The new table will contain the ID, an email address, and a verification code.

 
function custom_mail_verification_schema(){
  $schema['verification_code'] = array(
    'fields' => array(
      'id' => array(
        'description' => 'Primary ID',
        'type' => 'serial',
        'not null' => TRUE,
      ),
      'mail' => array(
        'description' => t('Email address'),
        'type' => 'varchar',
        'length' => 255,
        'not null' => true,
      ),
      'code' => array(
        'description' => t('Verification code'),
        'type' => 'varchar',
        'length' => 32,
        'not null' => true,
      ),
    ),
    'primary key' => array('id'),
  );
  return $schema;
}

//Clear cache on module instalation
function custom_mail_verification_install(){
  drupal_flush_all_caches();
}

//Remove table from database on module uninstall
function custom_mail_verification_uninstall(){
  drupal_uninstall_schema('custom_verification');
}

#3 Step – Create AJAX submit function

You need to create Ajax submit function that checks whether the email is valid. After checking the email, the verification code is generated and inserted in the database. If there’s already a generated code for the inserted email, the code is simply updated.



function custom_mail_verification_form_ajax_submit(&$form, &$form_state) {
  //Checking if mail is valid
  $mail = $form_state['complete form']['account']['mail']['#value'];
  if (!valid_email_address($mail)) {
    return(t('The email address appears to be invalid.'));
  }

 //Generate verification code
  $verificationCode = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 5);

 //Check if this email address is already in the database.
  $vc_id = db_select('verification_code', 'vc')
    ->fields('vc', array('id'))
    ->condition('mail', $mail, '=')
    ->execute()
    ->fetchField();

 //If it's not than insert a new row
  if(!($vc_id) || $vc_id == '') {
    db_insert('verification_code')
    ->fields(array(
        'mail' => $mail,
        'code' => $verificationCode,
      ))
      ->execute();
  } else {
  //If it exist than update existing row
    db_update('verification_code')
    ->fields(array(
        'mail' => $mail,
        'code' => $verificationCode,
      ))
      ->condition('id', $vc_id, '=')
      ->execute();
  }

The next step is sending an email with the verification code to the user.


  //Define mail parameters 
 $to = $mail;
  $from = variable_get('site_mail', '');

  $variables = array(
    '@site_name' => variable_get('site_name'),
  );

  $params['subject'] = t('@site_name verification code', $variables);

  $params['body'] = t('Your body of the mail with verification code included', $verificationCode);

 //Send email
  $sent = drupal_mail('custom_mail_verification', 'key', $to, language_default(), $params, $from, TRUE);

  if($sent){
    return(t('Message about successful sent email'));
  } else {
    return(t('Error message'));
  }

#4 Step – Create a new function for validation

To check whether the valid code is inserted, you can create an additional function for the validation of the registration form.

If the code is not valid – it will report an error.


function custom_mail_verification_register_validate(&$form, &$form_state) {
  
  $mail = $form_state['complete form']['account']['mail']['#value'];

 //Get verification code for users email address
  $code = db_select('verification_code', 'vc')
    ->fields('vc', array('code'))
    ->condition('mail', $mail)
    ->orderBy('id', 'DESC')
    ->execute()
    ->fetchField();

 //If
   if($form_state['values']['verification_code'] !== $code) {
    form_set_error('verification_code', t('The verification code appears to be invalid.'));
  }

These steps you need to follow to create the module successfully.

We also wanted to make sure the administrators can use this module easily and more efficiently, so we created the admin page.

The page increases the flexibility of the module and helps administrators have better control over the accounts they approve or deny.

On the admin page, the site administrator can insert the text of an email message with a token, which is automatically changed with the verification code. Although the site administrator needs to add the text of an email, if he doesn’t, the default text that is previously created will be used instead.

After implementing this solution, we haven’t noticed a single successful attempt of spam bot registration on the projects we used this type of protection on.

You can use this module successfully on different projects to prevent fake registrations – that’s a great advantage of it, so when you try it, tell me what you think.

If you have any questions, post in the comments below.