9

I wondered if someone here might be able to help.

Basically, I've created a custom registration form that when validated, inserts a user to the user table.

function _new_user($data) {

    // Separate Data
    $default_newuser = array(
        'user_pass' =>  wp_hash_password( $data['user_pass']),
        'user_login' => $data['user_login'],
        'user_email' => $data['user_email'],
        'first_name' => $data['first_name'],
        'last_name' => $data['last_name'],
        'role' => 'pending'
    );

    wp_insert_user($default_newuser);
} 

Now, what I need it to do is rather than sent the confirmation e-mail which I know I can do with the following code.

wp_new_user_notification($user_id, $data['user_pass']);

I want to send a user activation e-mail instead. I've tried a few things but I cant seem to be able to find anything concrete. Hoping someone might have had this problem before.

9

To accomplish user activation process you need to do following steps:

  1. after create new user add a custom user field which indicates that this user has to activate his account
  2. send an email with activation code, provide a link in this email to a page where user will be activated
  3. implement activation page
  4. when user attempts to log in check if that custom user field exists or not. If it exists then do not log him in and show activation error message instead.

Add custom field and send email:

function _new_user($data) {

    // Separate Data
    $default_newuser = array(
        'user_pass' =>  wp_hash_password( $data['user_pass']),
        'user_login' => $data['user_login'],
        'user_email' => $data['user_email'],
        'first_name' => $data['first_name'],
        'last_name' => $data['last_name'],
        'role' => 'pending'
    );

    $user_id = wp_insert_user($default_newuser);
    if ( $user_id && !is_wp_error( $user_id ) ) {
        $code = sha1( $user_id . time() );
        $activation_link = add_query_arg( array( 'key' => $code, 'user' => $user_id ), get_permalink( /* YOUR ACTIVATION PAGE ID HERE */ ));
        add_user_meta( $user_id, 'has_to_be_activated', $code, true );
        wp_mail( $data['user_email'], 'ACTIVATION SUBJECT', 'CONGRATS BLA BLA BLA. HERE IS YOUR ACTIVATION LINK: ' . $activation_link );
    }
}

Check user activation on login:

// override core function
if ( !function_exists('wp_authenticate') ) :
function wp_authenticate($username, $password) {
    $username = sanitize_user($username);
    $password = trim($password);

    $user = apply_filters('authenticate', null, $username, $password);

    if ( $user == null ) {
        // TODO what should the error message be? (Or would these even happen?)
        // Only needed if all authentication handlers fail to return anything.
        $user = new WP_Error('authentication_failed', __('<strong>ERROR</strong>: Invalid username or incorrect password.'));
    } elseif ( get_user_meta( $user->ID, 'has_to_be_activated', true ) != false ) {
        $user = new WP_Error('activation_failed', __('<strong>ERROR</strong>: User is not activated.'));
    }

    $ignore_codes = array('empty_username', 'empty_password');

    if (is_wp_error($user) && !in_array($user->get_error_code(), $ignore_codes) ) {
        do_action('wp_login_failed', $username);
    }

    return $user;
}
endif;

Activation page:

add_action( 'template_redirect', 'wpse8170_activate_user' );
function wpse8170_activate_user() {
    if ( is_page() && get_the_ID() == /* YOUR ACTIVATION PAGE ID HERE */ ) {
        $user_id = filter_input( INPUT_GET, 'user', FILTER_VALIDATE_INT, array( 'options' => array( 'min_range' => 1 ) ) );
        if ( $user_id ) {
            // get user meta activation hash field
            $code = get_user_meta( $user_id, 'has_to_be_activated', true );
            if ( $code == filter_input( INPUT_GET, 'key' ) ) {
                delete_user_meta( $user_id, 'has_to_be_activated' );
            }
        }
    }
}

This is your starting point, go ahead and adjust it for your needs.

  • Good post. But I think you missed one thing. When you prevent un-authorized users from logging in, how are you able to get the user_id from get_current_user_id() on the activation page? – s1lv3r Oct 11 '13 at 14:05
  • 1
    damn... :) good point, will fix it in a minute :) – Eugene Manuilov Oct 11 '13 at 14:06
  • Thanks for this fantastic information. I was seeing if there was any core solution to just trigger the sending of an activation e-mail since you can 'resend activation' in the admin panel. I thought that by inserting a user as pending an activation code might be generated and inserted into the database, but upon further inspection I discovered that 'obviously' no such luck :) Anyway. It all makes sense and thanks again. – Joe Buckle Oct 11 '13 at 14:07
  • @JoeBuckle That's strange. You shouldn't have a resend activation-link at all on a vanilla install. Do you happen to already have a plugin installed for this? Also BuddyPress comes with a user activation functionality out of the box. – s1lv3r Oct 11 '13 at 14:09
  • @s1lv3r Could it have something to do with Theme-My-Login? – Joe Buckle Oct 11 '13 at 14:10
1

Two options to choose from:

  1. Use a plugin, for example User activation email or New User Approve

  2. Code this yourself.

Some functions that should get you started:

  • wp_mail() to send the email,
  • add_user_meta() to save a activation key for the user,
  • generate a link containing the key and place it in the email, create a page in wordpress which catches your key-param (for example using add_shortcode()),
  • use get_user_meta() to check the activation key against the one stored in the db, place another user meta key to mark this user as activated if successfull,
  • add a function to the authenticate filter to prevent any user which is not activated from logging in.
0

You can get the user_id by doing this while authentication:

$username='user email provided by the user at login panel.';
$results = $wpdb->get_row( "SELECT ID FROM wp_users WHERE user_email='".$username."'");
   $activation_id = $results->ID;
   $activation_key =  get_user_meta( $activation_id, 'has_to_be_activated', true );
 if($activation_key != false )
 {
  echo '<h4 class="error">Your account has not been activated yet.<br /> To activate it check your email and clik on the activation link.</h4>';
 }
else{
//authenticate your user login here...
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.