Users: enable admins to send users a reset password link.
Add a feature so Admins can send users a 'password reset' email. This doesn't change the password or force a password change. It only emails the user the password reset link. The feature appears in several places: * A "Send Reset Link" button on user profile screen. * A "Send password reset" option in the user list bulk action dropdown. * A "Send password reset" quick action when hovering over a username in the user list. Props Ipstenu, DrewAPicture, eventualo, wonderboymusic, knutsp, ericlewis, afercia, JoshuaWold, johnbillion, paaljoachim, hedgefield. Fixes #34281. Built from https://develop.svn.wordpress.org/trunk@50129 git-svn-id: http://core.svn.wordpress.org/trunk@49808 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
68c6e9982b
commit
315b1c185d
|
@ -140,6 +140,7 @@ $core_actions_post = array(
|
|||
'health-check-loopback-requests',
|
||||
'health-check-get-sizes',
|
||||
'toggle-auto-updates',
|
||||
'send-password-reset',
|
||||
);
|
||||
|
||||
// Deprecated.
|
||||
|
|
|
@ -5398,3 +5398,33 @@ function wp_ajax_toggle_auto_updates() {
|
|||
|
||||
wp_send_json_success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax handler sends a password reset link.
|
||||
*
|
||||
* @since 5.7.0
|
||||
*/
|
||||
function wp_ajax_send_password_reset() {
|
||||
|
||||
// Validate the nonce for this action.
|
||||
$user_id = isset( $_POST['user_id'] ) ? (int) $_POST['user_id'] : 0;
|
||||
check_ajax_referer( 'reset-password-for-' . $user_id, 'nonce' );
|
||||
|
||||
// Verify user capabilities.
|
||||
if ( ! current_user_can( 'edit_user', $user_id ) ) {
|
||||
wp_send_json_error( __( 'Cannot send password reset, permission denied.' ) );
|
||||
}
|
||||
|
||||
// Send the password reset link.
|
||||
$user = get_userdata( $user_id );
|
||||
$results = retrieve_password( $user->user_login );
|
||||
|
||||
if ( true === $results ) {
|
||||
wp_send_json_success(
|
||||
/* translators: 1: User's display name. */
|
||||
sprintf( __( 'A password reset link was emailed to %s.' ), $user->display_name )
|
||||
);
|
||||
} else {
|
||||
wp_send_json_error( $results );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -274,6 +274,11 @@ class WP_Users_List_Table extends WP_List_Table {
|
|||
}
|
||||
}
|
||||
|
||||
// Add a password reset link to the bulk actions dropdown.
|
||||
if ( current_user_can( 'edit_users' ) ) {
|
||||
$actions['resetpassword'] = __( 'Send password reset' );
|
||||
}
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
|
@ -469,6 +474,11 @@ class WP_Users_List_Table extends WP_List_Table {
|
|||
);
|
||||
}
|
||||
|
||||
// Add a link to send the user a reset password link by email.
|
||||
if ( get_current_user_id() !== $user_object->ID && current_user_can( 'edit_user', $user_object->ID ) ) {
|
||||
$actions['resetpassword'] = "<a class='resetpassword' href='" . wp_nonce_url( "users.php?action=resetpassword&users=$user_object->ID", 'bulk-users' ) . "'>" . __( 'Send password reset' ) . '</a>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the action links displayed under each user in the Users list table.
|
||||
*
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* @output wp-admin/js/user-profile.js
|
||||
*/
|
||||
|
||||
/* global ajaxurl, pwsL10n */
|
||||
/* global ajaxurl, pwsL10n, userProfileL10n */
|
||||
(function($) {
|
||||
var updateLock = false,
|
||||
__ = wp.i18n.__,
|
||||
|
@ -91,6 +91,68 @@
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the password reset button. Sets up an ajax callback to trigger sending
|
||||
* a password reset email.
|
||||
*/
|
||||
function bindPasswordRestLink() {
|
||||
$( '#generate-reset-link' ).on( 'click', function() {
|
||||
var $this = $(this),
|
||||
data = {
|
||||
'user_id': userProfileL10n.user_id, // The user to send a reset to.
|
||||
'nonce': userProfileL10n.nonce // Nonce to validate the action.
|
||||
};
|
||||
|
||||
// Remove any previous error messages.
|
||||
$this.parent().find( '.notice-error' ).remove();
|
||||
|
||||
// Send the reset request.
|
||||
var resetAction = wp.ajax.post( 'send-password-reset', data );
|
||||
|
||||
// Handle reset success.
|
||||
resetAction.done( function( response ) {
|
||||
addInlineNotice( $this, true, response );
|
||||
} );
|
||||
|
||||
// Handle reset failure.
|
||||
resetAction.fail( function( response ) {
|
||||
addInlineNotice( $this, false, response );
|
||||
} );
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to insert an inline notice of success or failure.
|
||||
*
|
||||
* @param {jQuery Object} $this The button element: the message will be inserted
|
||||
* above this button
|
||||
* @param {bool} success Whether the message is a success message.
|
||||
* @param {string} message The message to insert.
|
||||
*/
|
||||
function addInlineNotice( $this, success, message ) {
|
||||
var resultDiv = $( '<div />' );
|
||||
|
||||
// Set up the notice div.
|
||||
resultDiv.addClass( 'notice inline' );
|
||||
|
||||
// Add a class indicating success or failure.
|
||||
resultDiv.addClass( 'notice-' + ( success ? 'success' : 'error' ) );
|
||||
|
||||
// Add the message, wrapping in a p tag, with a fadein to highlight each message.
|
||||
resultDiv.text( $( $.parseHTML( message ) ).text() ).wrapInner( '<p />');
|
||||
|
||||
// Disable the button when the callback has succeeded.
|
||||
$this.prop( 'disabled', success );
|
||||
|
||||
// Remove any previous notices.
|
||||
$this.siblings( '.notice' ).remove();
|
||||
|
||||
// Insert the notice.
|
||||
$this.before( resultDiv );
|
||||
}
|
||||
|
||||
function bindPasswordForm() {
|
||||
var $generateButton,
|
||||
$cancelButton;
|
||||
|
@ -369,6 +431,7 @@
|
|||
});
|
||||
|
||||
bindPasswordForm();
|
||||
bindPasswordRestLink();
|
||||
});
|
||||
|
||||
$( '#destroy-sessions' ).on( 'click', function( e ) {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -609,6 +609,27 @@ endif;
|
|||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
// Allow admins to send reset password link
|
||||
if ( ! IS_PROFILE_PAGE ) :
|
||||
?>
|
||||
<tr class="user-sessions-wrap hide-if-no-js">
|
||||
<th><?php _e( 'Password Reset' ); ?></th>
|
||||
<td>
|
||||
<div class="generate-reset-link">
|
||||
<button type="button" class="button button-secondary" id="generate-reset-link">
|
||||
<?php _e( 'Send Reset Link' ); ?>
|
||||
</button>
|
||||
</div>
|
||||
<p class="description">
|
||||
<?php
|
||||
/* translators: 1: User's display name. */
|
||||
printf( __( 'Send %s a link to reset their password. This will not change their password, nor will it force a change.' ), esc_html( $profileuser->display_name ) );
|
||||
?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
/**
|
||||
|
|
|
@ -208,6 +208,46 @@ switch ( $wp_list_table->current_action() ) {
|
|||
wp_redirect( $redirect );
|
||||
exit;
|
||||
|
||||
case 'resetpassword':
|
||||
check_admin_referer( 'bulk-users' );
|
||||
if ( ! current_user_can( 'edit_users' ) ) {
|
||||
$errors = new WP_Error( 'edit_users', __( 'You can’t edit users.' ) );
|
||||
}
|
||||
if ( empty( $_REQUEST['users'] ) ) {
|
||||
wp_redirect( $redirect );
|
||||
exit();
|
||||
}
|
||||
$userids = array_map( 'intval', (array) $_REQUEST['users'] );
|
||||
|
||||
$reset_count = 0;
|
||||
|
||||
foreach ( $userids as $id ) {
|
||||
if ( ! current_user_can( 'edit_user', $id ) ) {
|
||||
wp_die( __( 'You can’t edit that user.' ) );
|
||||
}
|
||||
|
||||
if ( $id === $current_user->ID ) {
|
||||
$update = 'err_admin_reset';
|
||||
continue;
|
||||
}
|
||||
|
||||
// Send the password reset link.
|
||||
$user = get_userdata( $id );
|
||||
if ( retrieve_password( $user->user_login ) ) {
|
||||
++$reset_count;
|
||||
}
|
||||
}
|
||||
|
||||
$redirect = add_query_arg(
|
||||
array(
|
||||
'reset_count' => $reset_count,
|
||||
'update' => 'resetpassword',
|
||||
),
|
||||
$redirect
|
||||
);
|
||||
wp_redirect( $redirect );
|
||||
exit;
|
||||
|
||||
case 'delete':
|
||||
if ( is_multisite() ) {
|
||||
wp_die( __( 'User deletion is not allowed from this screen.' ), 400 );
|
||||
|
@ -504,6 +544,16 @@ switch ( $wp_list_table->current_action() ) {
|
|||
);
|
||||
}
|
||||
|
||||
$messages[] = '<div id="message" class="updated notice is-dismissible"><p>' . $message . '</p></div>';
|
||||
break;
|
||||
case 'resetpassword':
|
||||
$reset_count = isset( $_GET['reset_count'] ) ? (int) $_GET['reset_count'] : 0;
|
||||
if ( 1 === $reset_count ) {
|
||||
$message = __( 'Password reset link sent.' );
|
||||
} else {
|
||||
/* translators: %s: Number of users. */
|
||||
$message = sprintf( __( 'Password reset links sent to %s users.' ), $reset_count );
|
||||
}
|
||||
$messages[] = '<div id="message" class="updated notice is-dismissible"><p>' . $message . '</p></div>';
|
||||
break;
|
||||
case 'promote':
|
||||
|
|
|
@ -7781,3 +7781,172 @@ function is_php_version_compatible( $required ) {
|
|||
function wp_fuzzy_number_match( $expected, $actual, $precision = 1 ) {
|
||||
return abs( (float) $expected - (float) $actual ) <= $precision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles sending a password retrieval email to a user.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @since 5.7.0 Added `$user_login` parameter.
|
||||
*
|
||||
* Note: prior to 5.7.0 this function was in wp_login.php.
|
||||
*
|
||||
* @global wpdb $wpdb WordPress database abstraction object.
|
||||
* @global PasswordHash $wp_hasher Portable PHP password hashing framework.
|
||||
*
|
||||
* @param string $user_login Optional user_login, default null. Uses
|
||||
* `$_POST['user_login']` if `$user_login` not set.
|
||||
* @return true|WP_Error True when finished, WP_Error object on error.
|
||||
*/
|
||||
function retrieve_password( $user_login = null ) {
|
||||
$errors = new WP_Error();
|
||||
$user_data = false;
|
||||
|
||||
// Use the passed $user_login if available, otherwise use $_POST['user_login'].
|
||||
if ( ! $user_login && ! empty( $_POST['user_login'] ) ) {
|
||||
$user_login = $_POST['user_login'];
|
||||
}
|
||||
|
||||
if ( empty( $user_login ) ) {
|
||||
$errors->add( 'empty_username', __( '<strong>Error</strong>: Please enter a username or email address.' ) );
|
||||
} elseif ( strpos( $user_login, '@' ) ) {
|
||||
$user_data = get_user_by( 'email', trim( wp_unslash( $user_login ) ) );
|
||||
if ( empty( $user_data ) ) {
|
||||
$errors->add( 'invalid_email', __( '<strong>Error</strong>: There is no account with that username or email address.' ) );
|
||||
}
|
||||
} else {
|
||||
$user_data = get_user_by( 'login', trim( wp_unslash( $user_login ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the user data during a password reset request.
|
||||
*
|
||||
* Allows, for example, custom validation using data other than username or email address.
|
||||
*
|
||||
* @since 5.7.0
|
||||
*
|
||||
* @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
|
||||
* @param WP_Error $errors A WP_Error object containing any errors generated
|
||||
* by using invalid credentials.
|
||||
*/
|
||||
$user_data = apply_filters( 'lostpassword_user_data', $user_data, $errors );
|
||||
|
||||
/**
|
||||
* Fires before errors are returned from a password reset request.
|
||||
*
|
||||
* @since 2.1.0
|
||||
* @since 4.4.0 Added the `$errors` parameter.
|
||||
* @since 5.4.0 Added the `$user_data` parameter.
|
||||
*
|
||||
* @param WP_Error $errors A WP_Error object containing any errors generated
|
||||
* by using invalid credentials.
|
||||
* @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
|
||||
*/
|
||||
do_action( 'lostpassword_post', $errors, $user_data );
|
||||
|
||||
/**
|
||||
* Filters the errors encountered on a password reset request.
|
||||
*
|
||||
* The filtered WP_Error object may, for example, contain errors for an invalid
|
||||
* username or email address. A WP_Error object should always be returned,
|
||||
* but may or may not contain errors.
|
||||
*
|
||||
* If any errors are present in $errors, this will abort the password reset request.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @param WP_Error $errors A WP_Error object containing any errors generated
|
||||
* by using invalid credentials.
|
||||
* @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
|
||||
*/
|
||||
$errors = apply_filters( 'lostpassword_errors', $errors, $user_data );
|
||||
|
||||
if ( $errors->has_errors() ) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
if ( ! $user_data ) {
|
||||
$errors->add( 'invalidcombo', __( '<strong>Error</strong>: There is no account with that username or email address.' ) );
|
||||
return $errors;
|
||||
}
|
||||
|
||||
// Redefining user_login ensures we return the right case in the email.
|
||||
$user_login = $user_data->user_login;
|
||||
$user_email = $user_data->user_email;
|
||||
$key = get_password_reset_key( $user_data );
|
||||
|
||||
if ( is_wp_error( $key ) ) {
|
||||
return $key;
|
||||
}
|
||||
|
||||
if ( is_multisite() ) {
|
||||
$site_name = get_network()->site_name;
|
||||
} else {
|
||||
/*
|
||||
* The blogname option is escaped with esc_html on the way into the database
|
||||
* in sanitize_option. We want to reverse this for the plain text arena of emails.
|
||||
*/
|
||||
$site_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
|
||||
}
|
||||
|
||||
$message = __( 'Someone has requested a password reset for the following account:' ) . "\r\n\r\n";
|
||||
/* translators: %s: Site name. */
|
||||
$message .= sprintf( __( 'Site Name: %s' ), $site_name ) . "\r\n\r\n";
|
||||
/* translators: %s: User login. */
|
||||
$message .= sprintf( __( 'Username: %s' ), $user_login ) . "\r\n\r\n";
|
||||
$message .= __( 'If this was a mistake, ignore this email and nothing will happen.' ) . "\r\n\r\n";
|
||||
$message .= __( 'To reset your password, visit the following address:' ) . "\r\n\r\n";
|
||||
$message .= network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . "\r\n\r\n";
|
||||
|
||||
$requester_ip = $_SERVER['REMOTE_ADDR'];
|
||||
if ( $requester_ip ) {
|
||||
$message .= sprintf(
|
||||
/* translators: %s: IP address of password reset requester. */
|
||||
__( 'This password reset request originated from the IP address %s.' ),
|
||||
$requester_ip
|
||||
) . "\r\n";
|
||||
}
|
||||
|
||||
/* translators: Password reset notification email subject. %s: Site title. */
|
||||
$title = sprintf( __( '[%s] Password Reset' ), $site_name );
|
||||
|
||||
/**
|
||||
* Filters the subject of the password reset email.
|
||||
*
|
||||
* @since 2.8.0
|
||||
* @since 4.4.0 Added the `$user_login` and `$user_data` parameters.
|
||||
*
|
||||
* @param string $title Email subject.
|
||||
* @param string $user_login The username for the user.
|
||||
* @param WP_User $user_data WP_User object.
|
||||
*/
|
||||
$title = apply_filters( 'retrieve_password_title', $title, $user_login, $user_data );
|
||||
|
||||
/**
|
||||
* Filters the message body of the password reset mail.
|
||||
*
|
||||
* If the filtered message is empty, the password reset email will not be sent.
|
||||
*
|
||||
* @since 2.8.0
|
||||
* @since 4.1.0 Added `$user_login` and `$user_data` parameters.
|
||||
*
|
||||
* @param string $message Email message.
|
||||
* @param string $key The activation key.
|
||||
* @param string $user_login The username for the user.
|
||||
* @param WP_User $user_data WP_User object.
|
||||
*/
|
||||
$message = apply_filters( 'retrieve_password_message', $message, $key, $user_login, $user_data );
|
||||
|
||||
if ( $message && ! wp_mail( $user_email, wp_specialchars_decode( $title ), $message ) ) {
|
||||
$errors->add(
|
||||
'retrieve_password_email_failure',
|
||||
sprintf(
|
||||
/* translators: %s: Documentation URL. */
|
||||
__( '<strong>Error</strong>: The email could not be sent. Your site may not be correctly configured to send emails. <a href="%s">Get support for resetting your password</a>.' ),
|
||||
esc_url( __( 'https://wordpress.org/support/article/resetting-your-password/' ) )
|
||||
)
|
||||
);
|
||||
return $errors;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1078,6 +1078,15 @@ function wp_default_scripts( $scripts ) {
|
|||
|
||||
$scripts->add( 'user-profile', "/wp-admin/js/user-profile$suffix.js", array( 'jquery', 'password-strength-meter', 'wp-util' ), false, 1 );
|
||||
$scripts->set_translations( 'user-profile' );
|
||||
$user_id = isset( $_GET['user_id'] ) ? (int) $_GET['user_id'] : 0;
|
||||
did_action( 'init' ) && $scripts->localize(
|
||||
'user-profile',
|
||||
'userProfileL10n',
|
||||
array(
|
||||
'user_id' => $user_id,
|
||||
'nonce' => wp_create_nonce( 'reset-password-for-' . $user_id ),
|
||||
)
|
||||
);
|
||||
|
||||
$scripts->add( 'language-chooser', "/wp-admin/js/language-chooser$suffix.js", array( 'jquery' ), false, 1 );
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* @global string $wp_version
|
||||
*/
|
||||
$wp_version = '5.7-alpha-50128';
|
||||
$wp_version = '5.7-alpha-50129';
|
||||
|
||||
/**
|
||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||
|
|
157
wp-login.php
157
wp-login.php
|
@ -360,163 +360,6 @@ function wp_login_viewport_meta() {
|
|||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles sending a password retrieval email to a user.
|
||||
*
|
||||
* @since 2.5.0
|
||||
*
|
||||
* @return true|WP_Error True when finished, WP_Error object on error.
|
||||
*/
|
||||
function retrieve_password() {
|
||||
$errors = new WP_Error();
|
||||
$user_data = false;
|
||||
|
||||
if ( empty( $_POST['user_login'] ) || ! is_string( $_POST['user_login'] ) ) {
|
||||
$errors->add( 'empty_username', __( '<strong>Error</strong>: Please enter a username or email address.' ) );
|
||||
} elseif ( strpos( $_POST['user_login'], '@' ) ) {
|
||||
$user_data = get_user_by( 'email', trim( wp_unslash( $_POST['user_login'] ) ) );
|
||||
if ( empty( $user_data ) ) {
|
||||
$errors->add( 'invalid_email', __( '<strong>Error</strong>: There is no account with that username or email address.' ) );
|
||||
}
|
||||
} else {
|
||||
$login = trim( wp_unslash( $_POST['user_login'] ) );
|
||||
$user_data = get_user_by( 'login', $login );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the user data during a password reset request.
|
||||
*
|
||||
* Allows, for example, custom validation using data other than username or email address.
|
||||
*
|
||||
* @since 5.7.0
|
||||
*
|
||||
* @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
|
||||
* @param WP_Error $errors A WP_Error object containing any errors generated
|
||||
* by using invalid credentials.
|
||||
*/
|
||||
$user_data = apply_filters( 'lostpassword_user_data', $user_data, $errors );
|
||||
|
||||
/**
|
||||
* Fires before errors are returned from a password reset request.
|
||||
*
|
||||
* @since 2.1.0
|
||||
* @since 4.4.0 Added the `$errors` parameter.
|
||||
* @since 5.4.0 Added the `$user_data` parameter.
|
||||
*
|
||||
* @param WP_Error $errors A WP_Error object containing any errors generated
|
||||
* by using invalid credentials.
|
||||
* @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
|
||||
*/
|
||||
do_action( 'lostpassword_post', $errors, $user_data );
|
||||
|
||||
/**
|
||||
* Filters the errors encountered on a password reset request.
|
||||
*
|
||||
* The filtered WP_Error object may, for example, contain errors for an invalid
|
||||
* username or email address. A WP_Error object should always be returned,
|
||||
* but may or may not contain errors.
|
||||
*
|
||||
* If any errors are present in $errors, this will abort the password reset request.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @param WP_Error $errors A WP_Error object containing any errors generated
|
||||
* by using invalid credentials.
|
||||
* @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
|
||||
*/
|
||||
$errors = apply_filters( 'lostpassword_errors', $errors, $user_data );
|
||||
|
||||
if ( $errors->has_errors() ) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
if ( ! $user_data ) {
|
||||
$errors->add( 'invalidcombo', __( '<strong>Error</strong>: There is no account with that username or email address.' ) );
|
||||
return $errors;
|
||||
}
|
||||
|
||||
// Redefining user_login ensures we return the right case in the email.
|
||||
$user_login = $user_data->user_login;
|
||||
$user_email = $user_data->user_email;
|
||||
$key = get_password_reset_key( $user_data );
|
||||
|
||||
if ( is_wp_error( $key ) ) {
|
||||
return $key;
|
||||
}
|
||||
|
||||
if ( is_multisite() ) {
|
||||
$site_name = get_network()->site_name;
|
||||
} else {
|
||||
/*
|
||||
* The blogname option is escaped with esc_html on the way into the database
|
||||
* in sanitize_option. We want to reverse this for the plain text arena of emails.
|
||||
*/
|
||||
$site_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
|
||||
}
|
||||
|
||||
$message = __( 'Someone has requested a password reset for the following account:' ) . "\r\n\r\n";
|
||||
/* translators: %s: Site name. */
|
||||
$message .= sprintf( __( 'Site Name: %s' ), $site_name ) . "\r\n\r\n";
|
||||
/* translators: %s: User login. */
|
||||
$message .= sprintf( __( 'Username: %s' ), $user_login ) . "\r\n\r\n";
|
||||
$message .= __( 'If this was a mistake, ignore this email and nothing will happen.' ) . "\r\n\r\n";
|
||||
$message .= __( 'To reset your password, visit the following address:' ) . "\r\n\r\n";
|
||||
$message .= network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . "\r\n\r\n";
|
||||
|
||||
$requester_ip = $_SERVER['REMOTE_ADDR'];
|
||||
if ( $requester_ip ) {
|
||||
$message .= sprintf(
|
||||
/* translators: %s: IP address of password reset requester. */
|
||||
__( 'This password reset request originated from the IP address %s.' ),
|
||||
$requester_ip
|
||||
) . "\r\n";
|
||||
}
|
||||
|
||||
/* translators: Password reset notification email subject. %s: Site title. */
|
||||
$title = sprintf( __( '[%s] Password Reset' ), $site_name );
|
||||
|
||||
/**
|
||||
* Filters the subject of the password reset email.
|
||||
*
|
||||
* @since 2.8.0
|
||||
* @since 4.4.0 Added the `$user_login` and `$user_data` parameters.
|
||||
*
|
||||
* @param string $title Email subject.
|
||||
* @param string $user_login The username for the user.
|
||||
* @param WP_User $user_data WP_User object.
|
||||
*/
|
||||
$title = apply_filters( 'retrieve_password_title', $title, $user_login, $user_data );
|
||||
|
||||
/**
|
||||
* Filters the message body of the password reset mail.
|
||||
*
|
||||
* If the filtered message is empty, the password reset email will not be sent.
|
||||
*
|
||||
* @since 2.8.0
|
||||
* @since 4.1.0 Added `$user_login` and `$user_data` parameters.
|
||||
*
|
||||
* @param string $message Email message.
|
||||
* @param string $key The activation key.
|
||||
* @param string $user_login The username for the user.
|
||||
* @param WP_User $user_data WP_User object.
|
||||
*/
|
||||
$message = apply_filters( 'retrieve_password_message', $message, $key, $user_login, $user_data );
|
||||
|
||||
if ( $message && ! wp_mail( $user_email, wp_specialchars_decode( $title ), $message ) ) {
|
||||
$errors->add(
|
||||
'retrieve_password_email_failure',
|
||||
sprintf(
|
||||
/* translators: %s: Documentation URL. */
|
||||
__( '<strong>Error</strong>: The email could not be sent. Your site may not be correctly configured to send emails. <a href="%s">Get support for resetting your password</a>.' ),
|
||||
esc_url( __( 'https://wordpress.org/support/article/resetting-your-password/' ) )
|
||||
)
|
||||
);
|
||||
return $errors;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Main.
|
||||
//
|
||||
|
|
Loading…
Reference in New Issue