WordPress 6.0 新增了两个和密码找回邮件相关的钩子:
send_retrieve_password_email可用于过滤是否发送找回密码邮件retrieve_password_notification_email可用于过滤发送给用户的重置密码通知邮件的内容。
为了与一些类似的过滤器(如send_password_change_email或 send_email_change_email)保持一致,并获得更大的灵活性,请将$user_login和$user_data参数直接传递给新的send_retrieve_password_email和retrieve_password_notification_email过滤器。
apply_filters( 'send_retrieve_password_email', true, $user_login, $user_data );
apply_filters( 'retrieve_password_notification_email', $defaults, $key, $user_login, $user_data );
禁用密码找回邮件
以下代码可以全局禁用发送密码找回邮件,也可以按照提示通过 $user_login, $user_data 两个参数来添加限制条件:
function wpdax_disable_retrieve_password_email( $user_login, $user_data ){// 如果你希望符合某类条件的才禁止发送,那你可以通过 $user_login, $user_data 这两个参数来做判断return false;}add_filter( 'send_retrieve_password_email', 'wpdax_disable_retrieve_password_email', 10, 2 );
修改密码找回邮件的内容
retrieve_password_notification_email 承接的 $defaults 内容包括邮件的收件人、标题、信息和Headers头部信息:
$defaults = array('to' => $user_email,'subject' => $title,'message' => $message,'headers' => '',);
所以,retrieve_password_notification_email 是可以直接修改以上四项内容的。代码范例如下
function wpdx_filter_retrieve_password_notification_email( $defaults, $key, $user_login, $user_data ){// 可以通过 $key, $user_login, $user_data 三个参数来获取和传递一些用户信息值// 收件人邮箱 to 不能修改,否则他会收不到// $defaults['title'] = '自定义标题';// $defaults['message'] = '自定义消息';// $defaults['headers'] = '自定义headers'; //一般情况下不需要修改return $defaults;}add_filter( 'retrieve_password_notification_email', 'wpdx_filter_retrieve_password_notification_email', 10, 4 );
在下面的函数代码中,我们可以看到还有两个钩子:
retrieve_password_title专门用于修改找回密码邮件的标题retrieve_password_message专门用于修改找回密码邮件的消息
所以,你可以根据实际需要,选择对应的钩子。
至于实际如何修改,可以参考WP内核的 /wp-includes/user.php 文件对应的下列函数(以下为 WordPress 6.0 版本):
/*** Handles sending a password retrieval email to a user.** @since 2.5.0* @since 5.7.0 Added `$user_login` parameter.** @global wpdb $wpdb WordPress database abstraction object.* @global PasswordHash $wp_hasher Portable PHP password hashing framework.** @param string $user_login Optional. Username to send a password retrieval email for.* Defaults to `$_POST['user_login']` if 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;}/*** Filters whether to send the retrieve password email.** Return false to disable sending the email.** @since 6.0.0** @param bool $send Whether to send the email.* @param string $user_login The username for the user.* @param WP_User $user_data WP_User object.*/if ( ! apply_filters( 'send_retrieve_password_email', true, $user_login, $user_data ) ) {return true;}// 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;}// Localize password reset message content for user.$locale = get_user_locale( $user_data );$switched_locale = switch_to_locale( $locale );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' ) . '&wp_lang=' . $locale . "\r\n\r\n";if ( ! is_user_logged_in() ) {$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 );// Short-circuit on falsey $message value for backwards compatibility.if ( ! $message ) {return true;}/** Wrap the single notification email arguments in an array* to pass them to the retrieve_password_notification_email filter.*/$defaults = array('to' => $user_email,'subject' => $title,'message' => $message,'headers' => '',);/*** Filters the contents of the reset password notification email sent to the user.** @since 6.0.0** @param array $defaults {* The default notification email arguments. Used to build wp_mail().** @type string $to The intended recipient - user email address.* @type string $subject The subject of the email.* @type string $message The body of the email.* @type string $headers The headers of the email.* }* @type string $key The activation key.* @type string $user_login The username for the user.* @type WP_User $user_data WP_User object.*/$notification_email = apply_filters( 'retrieve_password_notification_email', $defaults, $key, $user_login, $user_data );if ( $switched_locale ) {restore_previous_locale();}if ( is_array( $notification_email ) ) {// Force key order and merge defaults in case any value is missing in the filtered array.$notification_email = array_merge( $defaults, $notification_email );} else {$notification_email = $defaults;}list( $to, $subject, $message, $headers ) = array_values( $notification_email );$subject = wp_specialchars_decode( $subject );if ( ! wp_mail( $to, $subject, $message, $headers ) ) {$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" rel="external nofollow" >Get support for resetting your password</a>.' ),esc_url( __( 'https://wordpress.org/support/article/resetting-your-password/' ) )));return $errors;}return true;}

