user_email_verification.module in User email verification 7
Same filename and directory in other branches
This module allows you to have e-mail verification and in meanwhile allowing the users to type their own passwords. If they do not verify their accounts in a certain time interval the user will be blocked.
File
user_email_verification.moduleView source
<?php
/**
* @file
* This module allows you to have e-mail verification and in meanwhile allowing the users to type their own passwords.
* If they do not verify their accounts in a certain time interval the user will be blocked.
*/
// TODO: Build action for rules for e-mail verification e-mail send!
/**
* Implements hook_cron_queue_info().
*/
function user_email_verification_cron_queue_info() {
$queues['user_email_verification_tasks'] = array(
'worker callback' => 'user_email_verification_task',
'time' => 15,
);
$queues['user_email_verification_reminders'] = array(
'worker callback' => 'user_email_verification_reminder',
'time' => 15,
);
$queues['user_email_verification_extended'] = array(
'worker callback' => 'user_email_verification_delete_account',
'time' => 15,
);
return $queues;
}
/**
* Queue worker callback for running a single task.
*
* @param array $task
* The task to process.
*/
function user_email_verification_task($uid) {
// Block account if active
user_email_verification_block_account($uid);
}
/**
* Block user account if active and email user if extended verification is
* enabled
*/
function user_email_verification_block_account($uid) {
$account = user_load($uid);
// If the account is active, it shold be blocked
if ($account->status == 1) {
$account->status = 0;
user_save($account);
if (module_exists('rules')) {
// Invoke rules event
rules_invoke_event('user_email_verification_account_blocked', $account);
}
// If extended verification period is enabled, then send e-mail to user with
// a link which lets user to activate and verify the account within defined
// time period.
if (variable_get('user_email_verification_extended_enable', 0)) {
$params['account'] = $account;
$mail = drupal_mail('user_email_verification', 'verify_extended', $account->mail, $account->language, $params);
}
}
}
/**
* Queue worker callback for sending a single reminder.
*
* @param int $uid
* The user ID to process.
*/
function user_email_verification_reminder($uid) {
// Only send the reminder if the user is not verified yet and the number of
// reminders has not been reached yet.
$interval = variable_get('user_email_verification_validate_interval', 86400);
$num_reminders = variable_get('user_email_verification_num_reminders', 0);
$reminder_interval = $interval / ($num_reminders + 1);
$result = db_query("SELECT reminders FROM {user_email_verification} WHERE uid = :uid\n AND verified = 0 AND reminders < :num_reminders AND last_reminder < :reminder", array(
':uid' => $uid,
':num_reminders' => $num_reminders,
':reminder' => REQUEST_TIME - $reminder_interval,
))
->fetchField();
if ($result === FALSE) {
return;
}
$account = user_load($uid);
$params['account'] = $account;
$language = user_preferred_language($account);
drupal_mail('user_email_verification', 'verify', $account->mail, $language, $params);
if (module_exists('rules')) {
// Invoke rules event
rules_invoke_event('user_email_verification_account_reminded', $account);
}
// Always increase the reminder mail counter by one even if sending the mail
// failed. Some mail systems like Mandrill return FALSE if they cannot deliver
// the mail to an invalid address. We need to increase the counter to make
// sure the users get blocked at some point.
db_update('user_email_verification')
->condition('uid', $account->uid)
->expression('reminders', 'reminders + 1')
->fields(array(
'last_reminder' => REQUEST_TIME,
))
->execute();
}
/**
* Queue worker callback for running a single task. Delete user account when
* e-mail address has not been verified after extended verification period
* has passed.
*
* @param $uid
* User ID to be deleted
*/
function user_email_verification_delete_account($uid) {
// Load the account before canceling it
$account = user_load($uid);
if ($account) {
if (module_exists('rules')) {
// Invoke rules event
rules_invoke_event('user_email_verification_account_deleted', $account);
}
// Notify account about cancellation
$op = 'status_canceled';
_user_mail_notify($op, $account);
// Get the cancel method
$user_cancel_method = variable_get('user_cancel_method');
user_cancel(array(), $uid, $user_cancel_method);
// user_cancel() initiates a batch process. Run it manually.
$batch =& batch_get();
$batch['progressive'] = FALSE;
batch_process();
watchdog('user', 'User with uid %uid has been deleted due to e-mail address not being verified within extended verification period.', array(
'%uid' => $uid,
));
}
else {
watchdog('user', 'User with uid %uid could not be deleted because the uid does not exist anymore.', array(
'%uid' => $uid,
));
}
}
/**
* Implements hook_cron().
*/
function user_email_verification_cron() {
$interval = variable_get('user_email_verification_validate_interval', 86400);
$num_reminders = variable_get('user_email_verification_num_reminders', 0);
$reminder_interval = $interval / ($num_reminders + 1);
$skip_roles = variable_get('user_email_verification_roles', array());
$skip_roles = array_filter($skip_roles);
// Select those that need to be blocked.
$query = db_select('user_email_verification', 'uev');
$query
->join('users', 'u', 'uev.uid = u.uid');
if (!empty($skip_roles)) {
$query
->leftJoin('users_roles', 'ur', 'ur.uid = uev.uid');
$query
->distinct('uev.uid');
$or = db_or()
->condition('ur.rid', array_keys($skip_roles), 'NOT IN')
->isNull('ur.rid');
// normal registered users don't have an entry in the users_roles table.
$query
->condition($or);
}
$result = $query
->fields('u', array(
'uid',
))
->condition('uev.verified', 0, '=')
->condition('u.uid', 1, '>')
->condition('uev.last_reminder', REQUEST_TIME - $reminder_interval, '<')
->condition('uev.reminders', $num_reminders, '>=')
->execute();
$queue = DrupalQueue::get('user_email_verification_tasks');
foreach ($result as $account) {
$queue
->createItem($account->uid);
}
// Select those that need to be sent a reminder.
$query = db_select('user_email_verification', 'uev');
$query
->join('users', 'u', 'uev.uid = u.uid');
if (!empty($skip_roles)) {
$query
->leftJoin('users_roles', 'ur', 'ur.uid = uev.uid');
$query
->distinct('uev.uid');
$or = db_or()
->condition('ur.rid', array_keys($skip_roles), 'NOT IN')
->isNull('ur.rid');
// normal registered users don't have an entry in the users_roles table.
$query
->condition($or);
}
$result = $query
->fields('u', array(
'uid',
))
->condition('uev.verified', 0, '=')
->condition('u.uid', 1, '>')
->condition('uev.last_reminder', REQUEST_TIME - $reminder_interval, '<')
->condition('uev.reminders', $num_reminders, '<')
->execute();
$queue = DrupalQueue::get('user_email_verification_reminders');
foreach ($result as $account) {
$queue
->createItem($account->uid);
}
if (variable_get('user_email_verification_extended_enable', 0)) {
// Delete accounts which have not verified their e-mail addresses
// within extended time period. Similar to blocking users, but doesn't
// care about reminder settings.
$extended_interval = variable_get('user_email_verification_extended_validate_interval', 86400);
$skip_roles = variable_get('user_email_verification_roles', array());
$skip_roles = array_filter($skip_roles);
// Select those that need to be blocked.
$query = db_select('user_email_verification', 'uev');
$query
->join('users', 'u', 'uev.uid = u.uid');
if (!empty($skip_roles)) {
$query
->leftJoin('users_roles', 'ur', 'ur.uid = uev.uid');
$query
->distinct('uev.uid');
$or = db_or()
->condition('ur.rid', array_keys($skip_roles), 'NOT IN')
->isNull('ur.rid');
// normal registered users don't have an entry in the users_roles table.
$query
->condition($or);
}
$result = $query
->fields('u', array(
'uid',
))
->condition('uev.verified', 0, '=')
->condition('u.uid', 1, '>')
->condition('uev.last_reminder', REQUEST_TIME - $extended_interval, '<')
->execute();
$queue = DrupalQueue::get('user_email_verification_extended');
foreach ($result as $account) {
$queue
->createItem($account->uid);
}
}
}
/**
* Implements hook_menu().
*/
function user_email_verification_menu() {
$items['user/verify'] = array(
'title' => 'Request new e-mail verification',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'user_email_verification_request',
),
'access callback' => TRUE,
'type' => MENU_LOCAL_TASK,
'file' => 'user_email_verification.admin.inc',
);
$items['user/email-verify/%/%/%'] = array(
'title' => 'Verify user e-mail',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'user_email_verification_verify',
2,
3,
4,
),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
'file' => 'user_email_verification.admin.inc',
);
$items['user/email-verify-extended/%/%/%'] = array(
'title' => 'Verify user e-mail',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'user_email_verification_verify_extended',
2,
3,
4,
),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
'file' => 'user_email_verification.admin.inc',
);
return $items;
}
/**
* Implements of hook_form_FORM_ID_alter().
*/
function user_email_verification_form_user_admin_settings_alter(&$form, &$form_state, $form_id) {
$form['user_email_verification'] = array(
'#type' => 'fieldset',
'#title' => t('User e-mail verification'),
);
$roles = array_map('check_plain', user_roles(TRUE));
unset($roles[DRUPAL_AUTHENTICATED_RID]);
$form['user_email_verification']['user_email_verification_roles'] = array(
'#type' => 'checkboxes',
'#title' => t('Roles'),
'#default_value' => variable_get('user_email_verification_roles', array()),
'#options' => $roles,
'#access' => !empty($roles) && user_access('administer permissions'),
'#description' => t('Select the roles for which we should not verify the e-mail address!'),
);
$form['user_email_verification']['user_email_verification_validate_interval'] = array(
'#type' => 'textfield',
'#title' => t('Verification time interval'),
'#required' => TRUE,
'#default_value' => variable_get('user_email_verification_validate_interval', 86400),
'#description' => t('Enter the time interval in seconds in which the user must validate his/her e-mail.'),
'#element_validate' => array(
'element_validate_number',
),
);
$form['user_email_verification']['user_email_verification_num_reminders'] = array(
'#type' => 'select',
'#title' => t('Send reminder'),
'#options' => array(
0 => '- never -',
1 => 'Once',
2 => 'Twice',
3 => 'Three times',
),
'#required' => TRUE,
'#default_value' => variable_get('user_email_verification_num_reminders', 0),
'#description' => t('Select the number of reminders to be sent spread equally through the time interval in which the user must validate his/her e-mail.'),
);
$form['user_email_verification']['user_email_verification_subject'] = array(
'#type' => 'textfield',
'#title' => t('Verification mail subject'),
'#default_value' => variable_get('user_email_verification_subject', t('Verification e-mail')),
'#maxlength' => 180,
'#description' => t('Subject for e-mail when user is requesting a new verification link at /user/verify. <strong>On registration user will receive the core\'s "Welcome (no approval required)" message.</strong>'),
);
$form['user_email_verification']['user_email_verification_body'] = array(
'#type' => 'textarea',
'#title' => t('Verification mail body'),
'#default_value' => variable_get('user_email_verification_body', t('Please verify your e-mail by following the link: [user:verify-email]')),
'#rows' => 10,
'#description' => t('Among other tokens, [user:verify-email] can be used to display the link to e-mail verification.'),
);
$form['user_email_verification']['user_email_verification_extended_enable'] = array(
'#type' => 'checkbox',
'#title' => t('Enable extended verification period'),
'#default_value' => variable_get('user_email_verification_extended_enable', 0),
'#description' => t('Extended verification period allows you to define another time period when the account can be still verified even after being blocked.'),
);
$form['user_email_verification']['extended'] = array(
'#type' => 'fieldset',
'#title' => t('Extended verification period'),
// Hide the extended settings when disabled.
'#states' => array(
'invisible' => array(
'input[name="user_email_verification_extended_enable"]' => array(
'checked' => FALSE,
),
),
),
);
$form['user_email_verification']['extended']['user_email_verification_extended_validate_interval'] = array(
'#type' => 'textfield',
'#title' => t('Extended verification time interval'),
'#required' => FALSE,
'#default_value' => variable_get('user_email_verification_extended_validate_interval', 604800),
'#description' => t('Enter the extended time interval in seconds in which the user must validate his/her e-mail before the account gets deleted completely.'),
'#element_validate' => array(
'element_validate_number',
),
);
$form['user_email_verification']['extended']['user_email_verification_extended_subject'] = array(
'#type' => 'textfield',
'#title' => t('Mail subject'),
'#default_value' => variable_get('user_email_verification_extended_subject', t('Account blocked, please verify e-mail address')),
'#maxlength' => 180,
'#description' => t('Subject for e-mail when an account is blocked after not being verified.'),
);
$form['user_email_verification']['extended']['user_email_verification_extended_body'] = array(
'#type' => 'textarea',
'#title' => t('Mail body'),
'#default_value' => variable_get('user_email_verification_extended_body', t('Your account is now blocked. Your e-mail may still be verified by following the link: [user:verify-email-extended]')),
'#rows' => 10,
'#description' => t('Among other tokens, [user:verify-email-extended] can be used to display the link to e-mail verification.'),
);
}
/**
* Implements hook_user_delete().
*/
function user_email_verification_user_delete($account) {
db_delete('user_email_verification')
->condition('uid', $account->uid)
->execute();
}
/**
* Implements hook_user_insert().
*/
function user_email_verification_user_insert(&$edit, $account, $category) {
db_insert('user_email_verification')
->fields(array(
'uid' => $account->uid,
'verified' => 0,
'last_reminder' => REQUEST_TIME,
'reminders' => 0,
))
->execute();
}
/**
* Implements hook_mail_alter().
*/
function user_email_verification_mail_alter(&$message) {
if ($message['module'] == 'user' || $message['module'] == 'user_email_verification') {
$language = $message['language'];
$params = $message['params'];
$account = $params['account'];
if (!empty($account)) {
if (!empty($message['subject'])) {
$message['subject'] = token_replace($message['subject'], array(
'user' => $account,
), array(
'language' => $language,
'sanitize' => FALSE,
'clear' => TRUE,
));
}
if (!empty($message['body'])) {
foreach ($message['body'] as &$body) {
$body = token_replace($body, array(
'user' => $account,
), array(
'language' => $language,
'sanitize' => FALSE,
'clear' => TRUE,
));
}
}
}
}
}
/**
* Implements hook_mail().
*/
function user_email_verification_mail($key, &$message, $params) {
$language = $message['language'];
if ($key == 'verify') {
$subject = t(variable_get('user_email_verification_subject', 'Verification e-mail'), [], [
'langcode' => $language->language,
]);
$body = t(variable_get('user_email_verification_body', 'Please verify your e-mail by following the link: [user:verify-email]'), [], [
'langcode' => $language->language,
]);
if (module_exists('i18n_variable')) {
// If i18n_variable module is used: get the text variables directly and
// not from the cache, because the language might not match the current
// $language here.
$subject_translated = i18n_variable_get('user_email_verification_subject', $language->language, NULL);
// i18n_variable_get returns nothing if the realm is not set.
if (!is_null($subject_translated)) {
// Use translated value.
$subject = $subject_translated;
}
$body_translated = i18n_variable_get('user_email_verification_body', $language->language, NULL);
// i18n_variable_get returns nothing if the realm is not set.
if (!is_null($body_translated)) {
// Use translated value.
$body = $body_translated;
}
}
$message['subject'] .= $subject;
$message['body'][] = $body;
}
if ($key == 'verify_blocked') {
$account = $params['account'];
$message['subject'] .= t('A blocked account verified his e-mail.');
$message['body'][] = t('A blocked account ID: @AID verified his e-mail. If the account is not blocked for other reason, please unblock the account.');
}
if ($key == 'verify_extended') {
$account = $params['account'];
$message['subject'] .= variable_get('user_email_verification_extended_subject', t('Account blocked, please verify e-mail address'));
$message['body'][] = variable_get('user_email_verification_extended_body', t('Your account is now blocked. Your e-mail may still be verified by following the link: [user:verify-email-extended]'));
}
}
/**
* Implements hook_variable_info().
*
* Makes the user_email_verification mail translatable.
*/
function user_email_verification_variable_info($options) {
$variables['user_email_verification_[mail_part]'] = [
'type' => 'user_mail',
'title' => t('User email verification', [], $options),
'description' => t('Customize verification e-mail messages to verify email address.', [], $options),
'group' => 'user_mails',
];
return $variables;
}
/**
* Send e-mail to user when they request a new verification link
*/
function user_email_verification_mail_notify($op, $account, $language = NULL) {
$params['account'] = $account;
$language = $language ? $language : user_preferred_language($account);
$mail = drupal_mail('user_email_verification', 'verify', $account->mail, $language, $params);
return empty($mail) ? NULL : $mail['result'];
}
/**
* Generate the
* @param unknown $account
* @return string
*/
function user_email_verification_url($account) {
$timestamp = REQUEST_TIME;
$hmac = user_email_verification_hmac($account->uid, $timestamp);
$language = user_preferred_language($account);
return url("user/email-verify/{$account->uid}/{$timestamp}/" . $hmac, array(
'absolute' => TRUE,
'language' => $language,
));
}
/**
* Generate the
* @param unknown $account
* @return string
*/
function user_email_verification_extended_url($account) {
$timestamp = REQUEST_TIME;
$hmac = user_email_verification_hmac($account->uid, $timestamp);
return url("user/email-verify-extended/{$account->uid}/{$timestamp}/" . $hmac, array(
'query' => array(
'language' => $account->language,
),
'absolute' => TRUE,
));
}
/**
* Generate HMAC.
* @param unknown $uid
* @param unknown $timestamp
* @return string
*/
function user_email_verification_hmac($uid, $timestamp) {
$string = drupal_get_hash_salt() . $uid . variable_get('user_email_verification_salt', 'salt');
return drupal_hmac_base64($timestamp . $uid, $string);
}
/**
* Return the verified flag
* @param int $uid
* @return bool
*/
function user_email_verification_load_verify_flag($uid) {
$result = db_select('user_email_verification')
->fields('user_email_verification', array(
'verified',
))
->condition('uid', $uid, '=')
->execute()
->fetchAssoc();
if (!empty($result)) {
return (bool) $result['verified'];
}
return FALSE;
}
/**
* Implements hook_user_view().
*/
function user_email_verification_user_view($account, $view_mode, $langcode) {
// Present the information if a user has a verified account.
if ($view_mode == "full" && user_access('administer users')) {
$account->content['user_email_verification'] = array(
'#type' => 'user_profile_category',
'#attributes' => array(
'class' => array(
'user-email-verified',
),
),
'#title' => t('User email verification'),
);
$account->content['user_email_verification']['verified'] = array(
'#type' => 'user_profile_item',
'#title' => t('Verified account'),
'#markup' => user_email_verification_load_verify_flag($account->uid) ? t("Verified") : t("Not verified"),
);
}
}
/**
* Implements hook_views_api().
*/
function user_email_verification_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'user_email_verification') . '/views',
);
}
/**
* Implements hook_user_presave().
*/
function user_email_verification_user_presave(&$edit, $account, $category) {
// An admin user activated a user account
if (user_access('administer users') && (isset($edit['status']) && $edit['status'] == 1) && (isset($account->original, $account->original->status) && $account->original->status == 0)) {
// Mark user as verified
db_update('user_email_verification')
->fields(array(
'verified' => 1,
))
->condition('uid', $account->uid, '=')
->execute();
}
}