Commit f138ae593a for wordpress.org

commit f138ae593ab926880d3ea3f298f13538d167cc78
Author: johnbillion <johnbillion@git.wordpress.org>
Date:   Thu Sep 10 13:59:53 2026 +0000

    Application Passwords: Send email notification when an application password is added.

    This introduces a filterable email notification so users get alerted when an application password is added to their account.

    The email can be filtered via the `wp_application_password_created_email` filter and disabled via the `wp_send_application_password_created_email` filter.

    Props prasadkarmalkar, johnbillion, audrasjb.

    Developed in https://github.com/WordPress/wordpress-develop/pull/9795

    Fixes #63927

    Built from https://develop.svn.wordpress.org/trunk@63582


    git-svn-id: http://core.svn.wordpress.org/trunk@62758 1a063a9b-81f0-0310-95a4-ce76da25c4cd

diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php
index a839ef9296..025a371781 100644
--- a/wp-includes/default-filters.php
+++ b/wp-includes/default-filters.php
@@ -345,6 +345,9 @@ add_action( 'application_password_did_authenticate', 'rest_application_password_
 add_filter( 'rest_authentication_errors', 'rest_application_password_check_errors', 90 );
 add_filter( 'rest_authentication_errors', 'rest_cookie_check_errors', 100 );

+// Application password notifications.
+add_action( 'wp_create_application_password', 'wp_application_password_created_notification', 10, 2 );
+
 // Actions.
 add_action( 'wp_head', '_wp_render_title_tag', 1 );
 add_action( 'wp_head', 'wp_enqueue_scripts', 1 );
diff --git a/wp-includes/functions.php b/wp-includes/functions.php
index 4c32381299..4f5916a322 100644
--- a/wp-includes/functions.php
+++ b/wp-includes/functions.php
@@ -9464,3 +9464,118 @@ function wp_verify_fast_hash(

 	return hash_equals( $hash, wp_fast_hash( $message ) );
 }
+
+/**
+ * Sends an email to the user when a new application password is created.
+ *
+ * @since 7.2.0
+ *
+ * @param int   $user_id  The user ID.
+ * @param array $new_item The application password details.
+ */
+function wp_application_password_created_notification( $user_id, $new_item ) {
+	$send = true;
+
+	// Get current user data.
+	$user = get_userdata( $user_id );
+
+	if ( ! $user ) {
+		return;
+	}
+
+	if ( ! is_email( $user->user_email ) ) {
+		return;
+	}
+
+	// Validate that the application password has a name.
+	if ( empty( $new_item['name'] ) ) {
+		return;
+	}
+
+	/**
+	 * Filters whether to send the application password created notification email.
+	 *
+	 * @since 7.2.0
+	 *
+	 * @param bool    $send  Whether to send the email notification.
+	 * @param WP_User $user  The user object.
+	 * @param array   $new_item The application password details.
+	 */
+	$send = apply_filters( 'wp_send_application_password_created_email', $send, $user, $new_item );
+
+	if ( ! $send ) {
+		return;
+	}
+
+	/* translators: Do not translate USERNAME, APPLICATION_PASSWORD_NAME, SITENAME, SITEURL, EMAIL: those are placeholders. */
+	$application_password_create_text = __(
+		'Hi ###USERNAME###,
+
+A new application password was added to your account on ###SITENAME###. This password allows access to your account via the REST API.
+
+If you did not expect this, please contact the Site Administrator at
+###ADMIN_EMAIL###
+
+Application password name: ###APPLICATION_PASSWORD_NAME###
+Site: ###SITEURL###
+
+You can manage your application passwords in your account settings.
+
+This email has been sent to ###EMAIL###
+
+Regards,
+All at ###SITENAME###
+###SITEURL###'
+	);
+
+	$email = array(
+		'to'      => $user->user_email,
+		/* translators: Application password creation email subject. %s: Site title. */
+		'subject' => __( '[%s] Application Password Created' ),
+		'message' => $application_password_create_text,
+		'headers' => '',
+	);
+
+	// Get site name.
+	$site_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
+
+	/**
+	 * Filters the contents of the email notification sent to a user when a new application password is created.
+	 *
+	 * @since 7.2.0
+	 *
+	 * @param array   $email {
+	 *     Used to build wp_mail().
+	 *
+	 *     @type string $to      The email address of the intended recipient.
+	 *     @type string $subject The subject of the email.
+	 *     @type string $message The content of the email.
+	 *         The following strings have a special meaning and will get replaced dynamically:
+	 *          - `###USERNAME###`                  The user's display name.
+	 *          - `###APPLICATION_PASSWORD_NAME###` The name of the application password.
+	 *          - `###EMAIL###`                     The user's email address.
+	 *          - `###SITENAME###`                  The name of the site.
+	 *          - `###SITEURL###`                   The URL to the site.
+	 *     @type string $headers Headers.
+	 * }
+	 * @param WP_User $user     The user object.
+	 * @param array   $new_item The application password details.
+	 */
+	$email = apply_filters( 'wp_application_password_created_email', $email, $user, $new_item );
+
+	$email['message'] = str_replace( '###USERNAME###', $user->display_name, $email['message'] );
+	$email['message'] = str_replace( '###APPLICATION_PASSWORD_NAME###', $new_item['name'], $email['message'] );
+	$email['message'] = str_replace( '###EMAIL###', $user->user_email, $email['message'] );
+	$email['message'] = str_replace( '###SITENAME###', $site_name, $email['message'] );
+	$email['message'] = str_replace( '###SITEURL###', home_url(), $email['message'] );
+
+	wp_mail(
+		$email['to'],
+		sprintf(
+			$email['subject'],
+			$site_name
+		),
+		$email['message'],
+		$email['headers']
+	);
+}
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 9799dc2459..4c27aa2d61 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '7.2-alpha-63581';
+$wp_version = '7.2-alpha-63582';

 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.