• Hi!

    I will share my use case scenario, a full example. Maybe someone finds it useful or give me some good suggestions.
    I don’t like mass mailings from core wp and woocommerce in the process of user registrations and changing passwords. Let’s take a look at what we have:

    1. User registration through woocommerce my-account form:

    • New user submitted (user)
    • Customer new account (user)
    • New user confirmed (user)
    • Password Reset (admin)

    Password reset is needed because of settings in WooCommerce->Settings->Accounts&Privacy->When creating an account, send the new user a link to set their password (checked).
    In this scenario, a user doesn’t know when someone trying to brake a password, but the admin knows.

    2. User registration through wp-login.php form:

    • New user submitted (user)
    • New user notification – welcome (user)
    • New user confirmed (user)
    • New user notification (admin)
    • Password Reset (admin)

    Password reset is needed because of default wp behavior, for new user registrations, you must enter a username and email.
    In this scenario, again a user doesn’t know when someone trying to brake a password, but the admin knows, and the admin knows that a new user is registered.
    I believe that the Automattic team really knows what are they doing, they rock, but for my taste, this behavior needs some changes.

    So, what are my small mods?
    Let’s see:

    • New user notification (admin) – disable
    • Password Reset email (admin) – disable
    • Customer new account email (user) – disable

    In my testing environments password change emails for users don’t works, so I added an action hook for ‘after_password_reset’ and send password change emails to the users, but don’t send them to the admin.
    Users know if someone tries to break their password, the admin is not bothered by that potential mass email notification.
    Also, I have added the logo to the missing templates, the sortable column in the user list table with the date registered, and Register IP’s plugin column with a link to the IP address checker.
    Some of the tweaks are collected from open-source projects.

    My User Verification settings:
    Email verification:
    Email verification -> Yes
    Choose verification page -> None
    Redirect after verification -> None
    Automatically login after -> Yes
    verification
    Required verification on email -> Yes
    change?
    Spam Protection:
    Enable username block -> Yes
    Blocked username -> www
    reCAPTCHA:
    Recaptcha version -> V2 – Checkbox
    All pages and forms -> Yes
    WooCommerce:
    Redirect after registration -> None
    Disable auto login on -> Yes
    registration
    Disable auto login on checkout -> Yes
    Redirect after payment -> None
    Tools:
    Delete unverified users -> Yes
    Delete interval unverified users -> Daily
    Mark all existing users as verified -> No
    Disable WordPress welcome -> Yes
    email

    WooCommerce->Settings->Accounts&Privacy:
    Allow customers to place orders without an account -> No
    Allow customers to log into an existing account during checkout ->Yes
    Account creation -> Yes to all 4 settings

    My code from functions.php is pasted below, I am using it in the Theme Customizations plugin template by WooThemes, so anytime can test without customization, just disable the plugin.
    Also, it’s good to know for advanced users that Spam Protection->Blocked username is PCRE regex, which can do well blocking with patterns.
    Hope that my use case scenario will someone find it useful.
    Thx for your excellent job with this plugin, and don’t be too strict with me, I am a PHP beginner.

    Regards

    add_action('init', 'custom_init');
    function custom_init()
    {
    
    	// display notices on myaccount priority workarround
    	// Early initialize customer session
    	if (isset(WC()->session) && !WC()->session->has_session()) {
    		WC()->session->set_customer_session_cookie(true);
    	}
    }
    
    
    // customize random password, carefully
    add_filter('random_password', 'filter_random_password', 10, 4);
    function filter_random_password($password, $length, $special_chars, $extra_special_chars)
    {
    	// custom mod, shorten passwords, but leave keys and tokens untouched
    	if (($length <= 24) && ($special_chars || $extra_special_chars)) $length = 12;
    
    	// do stuff to the password here, original wp_generate_password()
    	$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    	if ($special_chars) {
    		$chars .= '!@#$%^&*()';
    	}
    	if ($extra_special_chars) {
    		$chars .= '-_ []{}<>~`+=,.;:/?|';
    	}
    
    	$password = '';
    	for ($i = 0; $i < $length; $i++) {
    		$password .= substr($chars, wp_rand(0, strlen($chars) - 1), 1);
    	}
    	// perfectly clear which chars are allowed
    	return $password;
    };
    
    
    // redirect to password reset after user verification
    add_action('user_verification_email_verified', 'user_verification_email_verified_11012021');
    function user_verification_email_verified_11012021($args)
    {
    	$user_id = isset($args['user_id']) ? $args['user_id'] : '';
    	// get user by $user_id
    	$user = get_user_by('id', $user_id);
    
    	$is_login_page = (isset($_GET['is_login_page']) && ($_GET['is_login_page'] == 'true'));
    	$key = get_password_reset_key($user);
    	if (!is_wp_error($key)) {
    		if ($is_login_page) {
    			$action  = 'rp';
    			$url = wp_login_url() . "?action=$action&key=$key&login=" . rawurlencode($user->user_login);
    		} else {
    			$action  = 'newaccount';
    			$url = wc_get_account_endpoint_url('lost-password') . "?action=$action&key=$key&login=" . rawurlencode($user->user_login);
    		}
    	} else {
    		// Something went wrong while getting the key for new password URL, send customer to the generic password reset.
    		if ($is_login_page) {
    			$action  = 'lostpassword';
    			$url = wp_login_url() . "?action=$action";
    		} else {
    			$url = wc_get_account_endpoint_url('lost-password');
    		}
    	}
    	wp_safe_redirect($url);
    }
    
    
    // Disable woocommerce customer new account email.
    add_filter('woocommerce_email_enabled_customer_new_account', "__return_false", 10);
    // Disable password change notification email, admin.
    add_filter('woocommerce_disable_password_change_notification', '__return_true');
    // Disable new user welcome email admin
    add_filter('wp_send_new_user_notification_to_admin', '__return_false');
    // Disable new user welcome email user
    add_filter('wp_send_new_user_notification_to_user', '__return_false');
    // Send password change email, user.
    add_filter('send_password_change_email', '__return_false');
    
    // login logo url
    add_filter('login_headerurl', 'my_custom_login_url');
    function my_custom_login_url($url)
    {
    	return home_url();
    }
    
    // Customize login header text.
    add_filter('login_headertext', 'wpdoc_customize_login_headertext');
    function wpdoc_customize_login_headertext($headertext)
    {
    	$headertext = get_bloginfo('name') . ' | ' . get_bloginfo('description');
    	return $headertext;
    }
    
    function my_login_logo()
    { ?>
    	<style type="text/css">
    		#login h1 a,
    		.login h1 a {
    			background-image: url('<?php echo esc_url(wp_get_attachment_image_src(get_theme_mod('custom_logo'), 'full')[0]); ?>');
    			height: 60px;
    			width: 240px;
    			background-size: 235px 55px;
    			background-repeat: no-repeat;
    			padding-bottom: 20px;
    		}
    	</style>
    <?php }
    add_action('login_enqueue_scripts', 'my_login_logo');
    
    // register ips link to an ip checker
    // Plugin Register IP's
    function filter_ripm_show_ip($theip)
    {
    	$theip = '<a target="_blank"  . $theip . '">' . $theip . '</a>';
    	return $theip;
    }
    add_filter('ripm_show_ip', 'filter_ripm_show_ip');
    
    // add sortable user->registered column to all users admin table
    /*
     * Create a column. And maybe remove some of the default ones
     * @param array $columns Array of all user table columns {column ID} => {column Name} 
     */
    add_filter('manage_users_columns', 'rudr_modify_user_table');
    function rudr_modify_user_table($columns)
    {
    	// unset( $columns['posts'] ); // maybe you would like to remove default columns
    	$columns['registration_date'] = 'Registration date'; // add new
    	return $columns;
    }
    
    /*
     * Fill our new column with the registration dates of the users
     * @param string $row_output text/HTML output of a table cell
     * @param string $column_id_attr column ID
     * @param int $user user ID (in fact - table row ID)
     */
    add_filter('manage_users_custom_column', 'rudr_modify_user_table_row', 10, 3);
    function rudr_modify_user_table_row($row_output, $column_id_attr, $user)
    {
    	$date_format = 'j M, Y H:i';
    	switch ($column_id_attr) {
    		case 'registration_date':
    			return date($date_format, strtotime(get_the_author_meta('registered', $user)));
    			break;
    		default:
    	}
    	return $row_output;
    }
    
    /*
     * Make our "Registration date" column sortable
     * @param array $columns Array of all user sortable columns {column ID} => {orderby GET-param} 
     */
    add_filter('manage_users_sortable_columns', 'rudr_make_registered_column_sortable');
    function rudr_make_registered_column_sortable($columns)
    {
    	return wp_parse_args(array('registration_date' => 'registered'), $columns);
    }
    
    // logout redirect
    add_action('wp_logout', 'homepage_logout_redirect');
    function homepage_logout_redirect()
    {
    	wp_safe_redirect(home_url());
    	exit;
    }
    
    
    // wc notice and redirect after password reset
    remove_action('after_password_reset', 'wp_password_change_notification');
    add_action('after_password_reset', 'my_password_reset_redirect', 10, 2);
    // woocommerce after customer password reset
    add_action('woocommerce_customer_reset_password', 'my_password_reset_redirect', 10, 1);
    function my_password_reset_redirect($user, $new_pass = '')
    {
    	// Do whatever you want...
    	$user_obj = $user->to_array();
    
    	$blog_name = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
    
    	$send_password_change_email = true;
    	// $send_password_change_email = apply_filters('send_password_change_email', $send_password_change_email);
    
    
    	if (!empty($send_password_change_email)) {
    		/* translators: Do not translate USERNAME, ADMIN_EMAIL, EMAIL, SITENAME, SITEURL: those are placeholders. */
    		$pass_change_text = __(
    			'Hi ###USERNAME###,
    
    This notice confirms that your password was changed on ###SITENAME###.
    
    If you did not change your password, please contact the Site Administrator at
    ###ADMIN_EMAIL###
    
    This email has been sent to ###EMAIL###
    
    Regards,
    All at ###SITENAME###
    ###SITEURL###'
    		);
    
    		$pass_change_email = array(
    			'to'      => $user_obj['user_email'],
    			/* translators: Password change notification email subject. %s: Site title. */
    			'subject' => __('[%s] Password Changed'),
    			'message' => $pass_change_text,
    			'headers' => '',
    		);
    
    
    		$pass_change_email['message'] = str_replace('###USERNAME###', $user_obj['user_login'], $pass_change_email['message']);
    		$pass_change_email['message'] = str_replace('###ADMIN_EMAIL###', get_option('admin_email'), $pass_change_email['message']);
    		$pass_change_email['message'] = str_replace('###EMAIL###', $user_obj['user_email'], $pass_change_email['message']);
    		$pass_change_email['message'] = str_replace('###SITENAME###', $blog_name, $pass_change_email['message']);
    		$pass_change_email['message'] = str_replace('###SITEURL###', home_url(), $pass_change_email['message']);
    
    		wp_mail($pass_change_email['to'], sprintf($pass_change_email['subject'], $blog_name), $pass_change_email['message'], $pass_change_email['headers']);
    	}
    
    	wc_add_notice(__('Your password has been reset successfully.', 'woocommerce'), 'success');
    	wp_safe_redirect(site_url('/my-account'));
    	exit;
    }
    
    
    // set retrieve password email address to cookie
    // add logo to retrieve password email message
    add_filter('retrieve_password_notification_email', 'retrieve_password_notification_email_logo');
    function retrieve_password_notification_email_logo($defaults)
    {
    	// set user email
    	$user_email = rawurlencode($defaults['to']);
    	// set a cookie for 1 day
    	setcookie('user_email', $user_email, time() + 86400, "/");
    	// add custom logo to message
    	$logo = '';
    	// woocommerce email logo
    	if ($img = get_option('woocommerce_email_header_image')) {
    		$link = home_url();
    		$alt = get_bloginfo('name', 'display');
    		// one way of getting logo html
    		$logo = '<p style="margin-top:0;"><a target="_blank" href="' . esc_url($link) . '" class="custom-logo-link" rel="home" itemprop="url"><img src="' . esc_url($img) . '" alt="' . $alt . '" ></a></p>';
    	} elseif (function_exists('the_custom_logo') && has_custom_logo()) {
    		// custom logo
    		$custom_logo_id = get_theme_mod('custom_logo');
    		if ($custom_logo_id) {
    			$link = home_url();
    			$custom_logo_attr = array('class' => 'custom-logo', 'itemprop' => 'logo');
    			$image_alt = get_post_meta($custom_logo_id, '_wp_attachment_image_alt', true);
    			if (empty($image_alt)) {
    				$custom_logo_attr['alt'] = get_bloginfo('name', 'display');
    			}
    			// just another way of getting logo html
    			$logo = sprintf(
    				'<p style="margin-top:0;"><a target="_blank" href="%1$s" class="custom-logo-link" rel="home" itemprop="url">%2$s</a></p>',
    				esc_url($link),
    				wp_get_attachment_image($custom_logo_id, 'full', false, $custom_logo_attr)
    			);
    		}
    	}
    	// add logo to email message
    	if (!empty($logo)) {
    		// set headers
    		$defaults['headers'] = 'Content-Type: text/html; charset=UTF-8';
    		// add logo to message
    		$defaults['message'] = $logo . wpautop($defaults['message']);
    	}
    	return $defaults;
    }
    
    
    // redirect after retrieve password
    add_filter('lostpassword_redirect', 'my_lostpassword_redirect');
    function my_lostpassword_redirect($lostpassword_redirect)
    {
    	return site_url('/my-account');
    }
    
    
    // add wc notice after rettrieve password email sent
    add_action('wp_mail_succeeded', 'wp_mail_succeeded_action');
    /**
     * Function for wp_mail_succeeded action-hook.
     * 
     * @param array $mail_data An array containing the email recipient(s), subject, message, headers, and attachments.
     *
     * @return void
     */
    function wp_mail_succeeded_action($mail_data)
    {
    	// action...
    	$title = sprintf(__('[%s] Password Reset'), get_bloginfo('name'));
    	if ($mail_data['subject'] === $title) {
    		if (isset($_COOKIE['user_email']) && rawurldecode($_COOKIE['user_email'])  === $mail_data['to'][0]) {
    			wc_add_notice(__('A password reset email has been sent to the email address on file for your account, but may take several minutes to show up in your inbox. Please wait at least 10 minutes before attempting another reset.', 'woocommerce'), 'success');
    			setcookie('user_email', '', time() - 3600, "/");
    			// unset($_COOKIE['user_email']);
    		};
    	};
    };
    
    // add login page to verification url
    // true for standard wordpress wp-login
    add_filter('user_verification_mail_vars', 'user_verification_mail_vars_11012021', 10, 2);
    function user_verification_mail_vars_11012021($vars, $user_data)
    {
    	$is_login_page = is_login();
    	if ($is_login_page) {
    		$vars['{ac_activaton_url}'] .= "&is_login_page="  . var_export($is_login_page, true);
    	}
    
    	return $vars;
    }
    
  • The topic ‘User Verification, just one example’ is closed to new replies.