diff --git a/src/wp-includes/ms-functions.php b/src/wp-includes/ms-functions.php
index 03c376836a..53da005cf9 100644
--- a/src/wp-includes/ms-functions.php
+++ b/src/wp-includes/ms-functions.php
@@ -2602,6 +2602,84 @@ function get_subdirectory_reserved_names() {
return apply_filters( 'subdirectory_reserved_names', $names );
}
+/**
+ * Send a confirmation request email when a change of network admin email address is attempted.
+ *
+ * The new network admin address will not become active until confirmed.
+ *
+ * @since 4.9.0
+ *
+ * @param string $old_value The old network admin email address.
+ * @param string $value The proposed new network admin email address.
+ */
+function update_network_option_new_admin_email( $old_value, $value ) {
+ if ( $value == get_site_option( 'admin_email' ) || ! is_email( $value ) ) {
+ return;
+ }
+
+ $hash = md5( $value . time() . mt_rand() );
+ $new_admin_email = array(
+ 'hash' => $hash,
+ 'newemail' => $value,
+ );
+ update_site_option( 'network_admin_hash', $new_admin_email );
+
+ $switched_locale = switch_to_locale( get_user_locale() );
+
+ /* translators: Do not translate USERNAME, ADMIN_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */
+ $email_text = __( 'Howdy ###USERNAME###,
+
+You recently requested to have the network admin email address on
+your network 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###' );
+
+ /**
+ * Filters the text of the email sent when a change of network admin email address is attempted.
+ *
+ * The following strings have a special meaning and will get replaced dynamically:
+ * ###USERNAME### The current user's username.
+ * ###ADMIN_URL### The link to click on to confirm the email change.
+ * ###EMAIL### The proposed new network admin email address.
+ * ###SITENAME### The name of the network.
+ * ###SITEURL### The URL to the network.
+ *
+ * @since 4.9.0
+ *
+ * @param string $email_text Text in the email.
+ * @param array $new_admin_email {
+ * Data relating to the new network admin email address.
+ *
+ * @type string $hash The secure hash used in the confirmation link URL.
+ * @type string $newemail The proposed new network admin email address.
+ * }
+ */
+ $content = apply_filters( 'new_network_admin_email_content', $email_text, $new_admin_email );
+
+ $current_user = wp_get_current_user();
+ $content = str_replace( '###USERNAME###', $current_user->user_login, $content );
+ $content = str_replace( '###ADMIN_URL###', esc_url( network_admin_url( 'settings.php?network_admin_hash=' . $hash ) ), $content );
+ $content = str_replace( '###EMAIL###', $value, $content );
+ $content = str_replace( '###SITENAME###', wp_specialchars_decode( get_site_option( 'site_name' ), ENT_QUOTES ), $content );
+ $content = str_replace( '###SITEURL###', network_home_url(), $content );
+
+ wp_mail( $value, sprintf( __( '[%s] New Network Admin Email Address' ), wp_specialchars_decode( get_site_option( 'site_name' ), ENT_QUOTES ) ), $content );
+
+ if ( $switched_locale ) {
+ restore_previous_locale();
+ }
+}
+
/**
* Send an email to the old network admin email address when the network admin email address changes.
*