咳咳,大家好!今天老夫就来给大家扒一扒 WordPress 密码修改通知邮件的内裤…不是,是源码! 咱们细细地解剖一下 wp_password_change_notification()
函数,看看它到底是怎么把密码修改的“喜讯”传递给用户的。
开场白:为啥要知道这个?
你可能会问:“密码修改通知邮件而已,知道它干嘛?WordPress 自己搞定不就好了?” 嗯,没错,默认情况下是这样。但是,如果你想:
- 自定义邮件内容: 想让邮件更个性化,更符合你的品牌调性。
- 添加额外信息: 比如,显示修改密码的 IP 地址,提醒用户注意安全。
- 更换邮件发送方式: 不用 WordPress 自带的
wp_mail()
函数,而是用更专业的 SMTP 服务。 - Debug 邮件问题: 邮件发送失败了,你想知道哪里出了问题。
那么,了解 wp_password_change_notification()
的源码就非常有必要了。
正餐:wp_password_change_notification()
函数解剖
这个函数定义在 wp-includes/pluggable.php
文件中。我们来一步步分析它的源码:
/**
* Notifies the user of a password change.
*
* @since 3.6.0
*
* @param WP_User $user User object.
*/
function wp_password_change_notification( $user ) {
/**
* Fires after a user's password has been changed.
*
* @since 3.6.0
*
* @param WP_User $user User object.
*/
do_action( 'password_changed', $user );
$blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
$message = sprintf(
/* translators: 1: Site name, 2: Username */
__( 'Hi %1$s,' ) . "rnrn" .
__( 'This notice confirms that the password for your account on %2$s has been changed.' ) . "rnrn" .
__( 'If you did not change your password, please contact the Site Administrator immediately.' ) . "rnrn" .
__( 'Regards,' ) . "rn" .
__( 'All at %2$s' ) . "rn" .
__( 'https://wordpress.org/' ),
wp_specialchars_decode( $user->display_name ),
$blogname
);
wp_mail( $user->user_email, sprintf( __( '[%s] Password Changed' ), $blogname ), $message );
}
让我们拆解一下:
-
函数声明和文档注释:
/** * Notifies the user of a password change. * * @since 3.6.0 * * @param WP_User $user User object. */ function wp_password_change_notification( $user ) {
@since 3.6.0
:说明这个函数是从 WordPress 3.6 版本开始引入的。@param WP_User $user
:说明这个函数接收一个WP_User
类型的参数,也就是用户对象。
-
do_action( 'password_changed', $user );
do_action( 'password_changed', $user );
- 这是一个非常重要的 Hook! 它允许开发者在密码修改后执行自定义操作。 例如,你可以在这里记录密码修改日志,或者发送短信通知。
do_action()
函数是 WordPress 的核心 Hook 机制的一部分。 它会触发所有绑定到password_changed
这个 action 上的函数。
-
$blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
$blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
- 获取网站名称 (
blogname
),并进行解码。get_option( 'blogname' )
从 WordPress 的选项表中获取网站名称。wp_specialchars_decode()
用于解码 HTML 实体,确保网站名称显示正确。ENT_QUOTES
参数表示同时解码单引号和双引号。
- 获取网站名称 (
-
邮件内容构建 (重点!):
$message = sprintf( /* translators: 1: Site name, 2: Username */ __( 'Hi %1$s,' ) . "rnrn" . __( 'This notice confirms that the password for your account on %2$s has been changed.' ) . "rnrn" . __( 'If you did not change your password, please contact the Site Administrator immediately.' ) . "rnrn" . __( 'Regards,' ) . "rn" . __( 'All at %2$s' ) . "rn" . __( 'https://wordpress.org/' ), wp_specialchars_decode( $user->display_name ), $blogname );
- 这里使用
sprintf()
函数格式化邮件内容。 __( '...' )
是 WordPress 的国际化函数,用于翻译字符串。%1$s
和%2$s
是占位符,分别会被wp_specialchars_decode( $user->display_name )
(用户显示名称) 和$blogname
(网站名称) 替换。rn
是换行符。- 注意: 邮件内容是纯文本的。
- 这里使用
-
发送邮件:
wp_mail( $user->user_email, sprintf( __( '[%s] Password Changed' ), $blogname ), $message );
wp_mail()
函数是 WordPress 中用于发送邮件的核心函数。$user->user_email
:收件人邮箱地址。sprintf( __( '[%s] Password Changed' ), $blogname )
:邮件主题,同样包含了网站名称。$message
:邮件内容。
wp_mail()
函数的幕后英雄
wp_mail()
函数本身也值得我们深入了解。 它位于 wp-includes/pluggable.php
文件中。 简单来说,wp_mail()
会:
- 构建邮件头部: 包括发件人地址、回复地址、Content-Type 等。
- 应用过滤器: 允许开发者修改邮件的各个方面,例如
wp_mail_from
(发件人地址),wp_mail_from_name
(发件人名称),wp_mail_content_type
(内容类型),wp_mail_charset
(字符集),wp_mail_headers
(邮件头部),wp_mail
(整个邮件数组)。 - 调用
wp_mail()
实现发送: 最终依赖于 PHP 的mail()
函数,或者通过 SMTP 等方式发送邮件(如果配置了相应的插件)。
表格总结:核心步骤
步骤 | 描述 | 涉及的函数/变量 |
---|---|---|
1. 触发 Action | 允许开发者在密码修改后执行自定义操作。 | do_action( 'password_changed', $user ) |
2. 获取网站名称 | 获取网站名称并解码。 | get_option( 'blogname' ) , wp_specialchars_decode() |
3. 构建邮件内容 | 使用 sprintf() 和国际化函数 __() 构建邮件内容。 |
sprintf() , __() , $user->display_name |
4. 发送邮件 | 使用 wp_mail() 函数发送邮件。 |
wp_mail() , $user->user_email |
如何定制密码修改通知邮件?
了解了 wp_password_change_notification()
的源码,我们就可以开始定制邮件了。 主要有两种方法:
-
使用
password_changed
Action:这是最推荐的方法,因为它不会直接修改 WordPress 的核心代码。
add_action( 'password_changed', 'my_custom_password_notification', 10, 1 ); function my_custom_password_notification( $user ) { // 构建自定义邮件内容 $subject = sprintf( '[%s] 密码已修改', get_option( 'blogname' ) ); $message = sprintf( '尊敬的 %s:' . "rnrn" . '您的密码已成功修改。' . "rnrn" . '如果您没有修改密码,请立即联系我们!' . "rnrn" . '祝您愉快!', $user->display_name ); // 发送邮件 wp_mail( $user->user_email, $subject, $message ); }
add_action( 'password_changed', 'my_custom_password_notification', 10, 1 )
:将my_custom_password_notification
函数绑定到password_changed
action 上。10
是优先级,1
是接收的参数数量(这里是$user
对象)。- 在
my_custom_password_notification
函数中,你可以构建自己的邮件内容,并使用wp_mail()
函数发送。 -
注意: 为了避免发送两封邮件,你需要在
my_custom_password_notification
函数中移除 WordPress 默认的wp_password_change_notification
函数。 可以使用remove_action()
函数:remove_action( 'password_changed', 'wp_password_change_notification' );
完整的代码如下:
add_action( 'password_changed', 'my_custom_password_notification', 10, 1 ); function my_custom_password_notification( $user ) { // 移除默认的密码修改通知邮件 remove_action( 'password_changed', 'wp_password_change_notification' ); // 构建自定义邮件内容 $subject = sprintf( '[%s] 密码已修改', get_option( 'blogname' ) ); $message = sprintf( '尊敬的 %s:' . "rnrn" . '您的密码已成功修改。' . "rnrn" . '如果您没有修改密码,请立即联系我们!' . "rnrn" . '祝您愉快!', $user->display_name ); // 发送邮件 wp_mail( $user->user_email, $subject, $message ); }
-
使用
wp_mail
过滤器:这种方法可以让你修改
wp_mail()
函数的参数,例如邮件头部、内容类型等。add_filter( 'wp_mail', 'my_custom_wp_mail' ); function my_custom_wp_mail( $args ) { // 只修改密码修改通知邮件 if ( strpos( $args['subject'], 'Password Changed' ) !== false ) { // 修改邮件主题 $args['subject'] = sprintf( '[%s] 您的密码已修改', get_option( 'blogname' ) ); // 修改邮件内容 $args['message'] = sprintf( '尊敬的 %s:' . "rnrn" . '我们检测到您的密码已成功修改。' . "rnrn" . '如果您没有进行此操作,请立即联系我们!' . "rnrn" . '祝您愉快!', wp_get_current_user()->display_name ); // 修改邮件头部,例如设置 Content-Type 为 HTML $args['headers'] = array( 'Content-Type: text/html; charset=UTF-8' ); } return $args; }
add_filter( 'wp_mail', 'my_custom_wp_mail' )
:将my_custom_wp_mail
函数绑定到wp_mail
filter 上。$args
是一个数组,包含了wp_mail()
函数的所有参数,例如to
(收件人),subject
(主题),message
(内容),headers
(头部),attachments
(附件)。- 在
my_custom_wp_mail
函数中,你可以修改这些参数,然后返回修改后的$args
数组。 - 注意: 你需要判断当前邮件是否是密码修改通知邮件,可以使用
strpos( $args['subject'], 'Password Changed' ) !== false
来判断。 否则,你的修改会影响到所有使用wp_mail()
函数发送的邮件。
更高级的玩法:使用 SMTP
WordPress 默认使用 PHP 的 mail()
函数发送邮件,但这种方式不太可靠,容易被标记为垃圾邮件。 更推荐的做法是使用 SMTP (Simple Mail Transfer Protocol) 服务器。
有很多 WordPress 插件可以让你配置 SMTP,例如:
- WP Mail SMTP by WPForms: 非常流行且易于使用的 SMTP 插件。
- Easy WP SMTP: 另一个简单易用的 SMTP 插件。
- Post SMTP Mailer/Email Log: 功能更强大的 SMTP 插件,支持邮件日志。
安装并配置好 SMTP 插件后,WordPress 就会通过 SMTP 服务器发送邮件,而不是使用 PHP 的 mail()
函数,从而提高邮件的送达率。
代码示例:添加修改密码的 IP 地址
这是一个更高级的定制示例,我们将在密码修改通知邮件中添加修改密码的 IP 地址。
add_action( 'password_changed', 'my_custom_password_notification_with_ip', 10, 1 );
function my_custom_password_notification_with_ip( $user ) {
// 移除默认的密码修改通知邮件
remove_action( 'password_changed', 'wp_password_change_notification' );
// 获取用户 IP 地址
$ip_address = $_SERVER['REMOTE_ADDR'];
// 构建自定义邮件内容
$subject = sprintf( '[%s] 密码已修改', get_option( 'blogname' ) );
$message = sprintf(
'尊敬的 %s:' . "rnrn" .
'您的密码已于 %s 修改。' . "rnrn" .
'修改密码的 IP 地址为:%s' . "rnrn" .
'如果您没有修改密码,请立即联系我们!' . "rnrn" .
'祝您愉快!',
$user->display_name,
date( 'Y-m-d H:i:s' ),
$ip_address
);
// 发送邮件
wp_mail( $user->user_email, $subject, $message );
}
$_SERVER['REMOTE_ADDR']
:获取客户端 IP 地址。 注意: 这种方式获取的 IP 地址可能不准确,特别是当用户使用了代理服务器时。 更可靠的方法是使用一些 IP 地址检测服务。date( 'Y-m-d H:i:s' )
:获取当前时间,并格式化为YYYY-MM-DD HH:MM:SS
格式。
总结:定制邮件,掌握主动权
wp_password_change_notification()
函数虽然简单,但它却是密码安全的重要一环。 通过理解它的源码,我们可以定制邮件内容、添加额外信息、更换邮件发送方式,从而更好地保障用户的账户安全,提升用户体验。
记住,定制邮件的关键在于使用 WordPress 的 Hook 机制,避免直接修改核心代码。 同时,选择合适的 SMTP 服务,可以提高邮件的送达率。
好了,今天的讲座就到这里。 希望大家以后也能像解剖 wp_password_change_notification()
一样,勇敢地探索 WordPress 的源码,掌握更多的主动权!