Требуется подтверждение при изменении электронной почты
Мне просто интересно, почему wordpress не отправляет письмо с подтверждением каждый раз, когда пользователь меняет свой адрес электронной почты.
Как мы узнаем, что адрес электронной почты не является поддельным или набранным с ошибкой?
Так может ли кто-нибудь дать мне какой-нибудь фрагмент для реализации этой функции?
Обновление:
Вот в чем идея.
- пользователь меняет свою почту
- Мы отправляем подтверждение по электронной почте.
- Если пользователь подтвердит это электронное письмо в течение X дней, нажав кнопку подтверждение ссылка, затем адрес электронной почты должен быть изменен. В противном случае мы должны использовать существующую электронную почту.
4 answers
Как и SickHippie, эта функция является родной для WordPress, но только для настройки на нескольких сайтах, поэтому вот две функции, которые вам нужны, чтобы заставить это работать на одном сайте, которые в основном являются кодом один к одному из ядра /wp-admin/user-edit.php file
function custom_send_confirmation_on_profile_email() {
global $errors, $wpdb;
$current_user = wp_get_current_user();
if ( ! is_object($errors) )
$errors = new WP_Error();
if ( $current_user->ID != $_POST['user_id'] )
return false;
if ( $current_user->user_email != $_POST['email'] ) {
if ( !is_email( $_POST['email'] ) ) {
$errors->add( 'user_email', __( "<strong>ERROR</strong>: The e-mail address isn't correct." ), array( 'form-field' => 'email' ) );
return;
}
if ( email_exists( $_POST['email'] ) ) {
$errors->add( 'user_email', __( "<strong>ERROR</strong>: The e-mail address is already used." ), array( 'form-field' => 'email' ) );
delete_user_meta( $current_user->ID . '_new_email' );
return;
}
$hash = md5( $_POST['email'] . time() . mt_rand() );
$new_user_email = array(
'hash' => $hash,
'newemail' => $_POST['email']
);
update_user_meta( $current_user->ID . '_new_email', $new_user_email );
$content = apply_filters( 'new_user_email_content', __( "Dear user,
You recently requested to have the email address on your account changed.
If this is correct, please click on the following link to change it:
###ADMIN_URL###
You can safely ignore and delete this email if you do not want to
take this action.
This email has been sent to ###EMAIL###
Regards,
All at ###SITENAME###
###SITEURL###" ), $new_user_email );
$content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'profile.php?newuseremail='.$hash ) ), $content );
$content = str_replace( '###EMAIL###', $_POST['email'], $content);
$content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content );
$content = str_replace( '###SITEURL###', home_url(), $content );
wp_mail( $_POST['email'], sprintf( __( '[%s] New Email Address' ), get_option( 'blogname' ) ), $content );
$_POST['email'] = $current_user->user_email;
}
}
add_action( 'personal_options_update', 'custom_send_confirmation_on_profile_email' );
// Execute confirmed email change. See send_confirmation_on_profile_email().
function verify_email_change(){
global $errors, $wpdb;
$current_user = wp_get_current_user();
if (in_array($GLOBALS['pagenow'], array('profile.php')) && $current_user->ID > 0) {
if (isset( $_GET[ 'newuseremail' ] ) && $current_user->ID ) {
$new_email = get_user_meta( $current_user->ID . '_new_email' );
if ( $new_email[ 'hash' ] == $_GET[ 'newuseremail' ] ) {
$user->ID = $current_user->ID;
$user->user_email = esc_html( trim( $new_email[ 'newemail' ] ) );
if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_login FROM {$wpdb->users} WHERE user_login = %s", $current_user->user_login ) ) )
$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->users} SET user_email = %s WHERE user_login = %s", $user->user_email, $current_user->user_login ) );
wp_update_user( get_object_vars( $user ) );
delete_user_meta( $current_user->ID . '_new_email' );
wp_redirect( add_query_arg( array('updated' => 'true'), self_admin_url( 'profile.php' ) ) );
die();
}
} elseif ( !empty( $_GET['dismiss'] ) && $current_user->ID . '_new_email' == $_GET['dismiss'] ) {
delete_user_meta( $current_user->ID . '_new_email' );
wp_redirect( add_query_arg( array('updated' => 'true'), self_admin_url( 'profile.php' ) ) );
die();
}
}
}
add_action('plugins_loaded','verify_email_change');
Это странная "особенность". Функция на самом деле доступна внутри WordPress (WordPress.com включена ли она для их службы управляемых блогов), но она ограничена несколькими сайтами. Если вы посмотрите в /wp-admin/includes/ms.php
, вы найдете функцию, которая обрабатывает эту строку 239 send_confirmation_on_profile_email()
.
Предположительно, вы могли бы переместить эту функцию в свой functions.php или в плагин, чтобы получить эту функциональность, возможно, с небольшой настройкой, чтобы заставить его работать правильно. Это не отвечает на вопрос "почему", но и не есть ли билет trac по этому вопросу здесь.
ETA: При дальнейшем рассмотрении этого вопроса вам также может потребоваться дублировать несколько других функций - new_user_email_admin_notice()
и update_option_new_admin_email()
выскакивают по мере необходимости.
Ответ Гири не сработал для меня. Мне пришлось настроить свой, чтобы он работал (Wordpress 3.5)
function cleanup_verify_email_change()
{
global $errors, $wpdb;
$current_user = wp_get_current_user();
// don't execute this if they're trying to dismiss a pending email change
if (in_array($GLOBALS['pagenow'], array('profile.php')) && $current_user->ID > 0 & !isset($_GET["dismiss"]))
{
if (isset( $_POST[ 'email' ] ) && ($current_user->user_email != $_POST['email']) )
{
$user->ID = $current_user->ID;
$user->user_email = esc_html( trim( $_POST[ 'email' ] ) );
if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_login FROM {$wpdb->users} WHERE user_login = %s", $current_user->user_login ) ) ) {
$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->users} SET user_email = %s WHERE user_login = %s", $user->user_email, $current_user->user_login ) );
}
wp_update_user( get_object_vars( $user ) );
wp_redirect( add_query_arg( array('updated' => 'true', 'multisite_cleanup' => 'true'), self_admin_url( 'profile.php' ) ) );
die();
}
elseif ( !empty( $_GET['dismiss'] ) && $current_user->ID . '_new_email' == $_GET['dismiss'] )
{
delete_user_meta( $current_user->ID . '_new_email' );
wp_redirect( add_query_arg( array('updated' => 'true', 'multisite_cleanup' => 'true'), self_admin_url( 'profile.php' ) ) );
die();
}
}
}
add_action('plugins_loaded','cleanup_verify_email_change');
Я изменил код Giri, чтобы он работал на моем wordpress (версия 4.8.1+)
Перед:
update_user_meta( $current_user->ID . '_new_email', $new_user_email );
После:
update_user_meta( $current_user->ID, '_new_email', $new_user_email );
Запятая должна заменить точку.
Также:
$new_email['hash'];
$new_email['newemail'];
Стал
$new_email[0]['hash'];
$new_email[0]['newemail'];
Следовательно:
function custom_send_confirmation_on_profile_email() {
global $errors, $wpdb;
$current_user = wp_get_current_user();
if ( ! is_object($errors) )
$errors = new WP_Error();
if ( $current_user->ID != $_POST['user_id'] )
return false;
if ( $current_user->user_email != $_POST['email'] ) {
if ( !is_email( $_POST['email'] ) ) {
$errors->add( 'user_email', __( "<strong>ERROR</strong>: The e-mail address isn't correct." ), array( 'form-field' => 'email' ) );
return;
}
if ( email_exists( $_POST['email'] ) ) {
$errors->add( 'user_email', __( "<strong>ERROR</strong>: The e-mail address is already used." ), array( 'form-field' => 'email' ) );
delete_user_meta( $current_user->ID, '_new_email' );
return;
}
$hash = md5( $_POST['email'] . time() . mt_rand() );
$new_user_email = array(
'hash' => $hash,
'newemail' => $_POST['email']
);
update_user_meta( $current_user->ID, '_new_email', $new_user_email );
$content = apply_filters( 'new_user_email_content', __( "Dear user,
You recently requested to have the email address on your account changed.
If this is correct, please click on the following link to change it:
###ADMIN_URL###
You can safely ignore and delete this email if you do not want to
take this action.
This email has been sent to ###EMAIL###
Regards,
All at ###SITENAME###
###SITEURL###" ), $new_user_email );
$content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'profile.php?newuseremail='.$hash ) ), $content );
$content = str_replace( '###EMAIL###', $_POST['email'], $content);
$content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content );
$content = str_replace( '###SITEURL###', home_url(), $content );
wp_mail( $_POST['email'], sprintf( __( '[%s] New Email Address' ), get_option( 'blogname' ) ), $content );
$_POST['email'] = $current_user->user_email;
}
}
add_action( 'personal_options_update', 'custom_send_confirmation_on_profile_email' );
// Execute confirmed email change. See send_confirmation_on_profile_email().
function verify_email_change(){
global $errors, $wpdb;
$current_user = wp_get_current_user();
if (in_array($GLOBALS['pagenow'], array('profile.php')) && $current_user->ID > 0) {
if (isset( $_GET[ 'newuseremail' ] ) && $current_user->ID ) {
$new_email = get_user_meta( $current_user->ID, '_new_email' );
if ( $new_email[0]['hash'] == $_GET[ 'newuseremail' ] ) {
$user->ID = $current_user->ID;
$user->user_email = esc_html( trim( $new_email[0][ 'newemail' ] ) );
if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_login FROM {$wpdb->users} WHERE user_login = %s", $current_user->user_login ) ) )
$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->users} SET user_email = %s WHERE user_login = %s", $user->user_email, $current_user->user_login ) );
wp_update_user( get_object_vars( $user ) );
delete_user_meta( $current_user->ID, '_new_email' );
wp_redirect( add_query_arg( array('updated' => 'true'), self_admin_url( 'profile.php' ) ) );
die();
}
} elseif ( !empty( $_GET['dismiss'] ) && $current_user->ID . '_new_email' == $_GET['dismiss'] ) {
delete_user_meta( $current_user->ID, '_new_email' );
wp_redirect( add_query_arg( array('updated' => 'true'), self_admin_url( 'profile.php' ) ) );
die();
}
}
}
add_action('after_setup_theme','verify_email_change');
Ваше здоровье.