Index: wp-admin/includes/misc.php
===================================================================
--- wp-admin/includes/misc.php	(revision 47320)
+++ wp-admin/includes/misc.php	(working copy)
@@ -1302,66 +1302,52 @@
 
 	$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###,
+	/**
+	 * Filter removed
+	 *
+	 * $content = apply_filters( 'new_admin_email_content', $email_text, $new_admin_email );
+	 *
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
+	 *
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+	 *
+	 */
 
+	$wp_mail = array(
+		'id' => 'new_admin_email',
+		'group' => 'admin',
+
+		'to' => $value,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( '[{{SITENAME}}] New Admin Email Address' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => __(
+'{{HEADER}}
+
 You recently requested to have the administration email address on
 your site changed.
 
 If this is correct, please click on the following link to change it:
-###ADMIN_URL###
+{{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###
+This email has been sent to {{EMAIL}}
 
-Regards,
-All at ###SITENAME###
-###SITEURL###'
+{{FOOTER}}'
+		),
+		'replacements' => array(
+			'{{ADMIN_URL}}' => esc_url_raw( self_admin_url( 'options.php?adminhash=' . $hash ) ),
+			'{{EMAIL}}' => $value,
+		),
 	);
 
-	/**
-	 * Filters the text of the email sent when a change of site 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 site admin email address.
-	 * ###SITENAME###  The name of the site.
-	 * ###SITEURL###   The URL to the site.
-	 *
-	 * @since MU (3.0.0)
-	 * @since 4.9.0 This filter is no longer Multisite specific.
-	 *
-	 * @param string $email_text      Text in the email.
-	 * @param array  $new_admin_email {
-	 *     Data relating to the new site admin email address.
-	 *
-	 *     @type string $hash     The secure hash used in the confirmation link URL.
-	 *     @type string $newemail The proposed new site admin email address.
-	 * }
-	 */
-	$content = apply_filters( 'new_admin_email_content', $email_text, $new_admin_email );
+	$wp_mailer = WP_Mailer::getInstance();
+	$wp_mailer->send( $wp_mail );
 
-	$current_user = wp_get_current_user();
-	$content      = str_replace( '###USERNAME###', $current_user->user_login, $content );
-	$content      = str_replace( '###ADMIN_URL###', esc_url( self_admin_url( 'options.php?adminhash=' . $hash ) ), $content );
-	$content      = str_replace( '###EMAIL###', $value, $content );
-	$content      = str_replace( '###SITENAME###', wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), $content );
-	$content      = str_replace( '###SITEURL###', home_url(), $content );
-
-	wp_mail(
-		$value,
-		sprintf(
-			/* translators: New admin email address notification email subject. %s: Site title. */
-			__( '[%s] New Admin Email Address' ),
-			wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES )
-		),
-		$content
-	);
-
 	if ( $switched_locale ) {
 		restore_previous_locale();
 	}
Index: wp-admin/includes/privacy-tools.php
===================================================================
--- wp-admin/includes/privacy-tools.php	(revision 47320)
+++ wp-admin/includes/privacy-tools.php	(working copy)
@@ -556,137 +556,51 @@
 	$expiration      = apply_filters( 'wp_privacy_export_expiration', 3 * DAY_IN_SECONDS );
 	$expiration_date = date_i18n( get_option( 'date_format' ), time() + $expiration );
 
-	$export_file_url = get_post_meta( $request_id, '_export_file_url', true );
-	$site_name       = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
-	$site_url        = home_url();
-
 	/**
-	 * Filters the recipient of the personal data export email notification.
-	 * Should be used with great caution to avoid sending the data export link to wrong emails.
+	 * Filters removed
 	 *
-	 * @since 5.3.0
+	 * $request_email = apply_filters( 'wp_privacy_personal_data_email_to', $request->email, $request );
+	 * $subject = apply_filters( 'wp_privacy_personal_data_email_subject', $subject, $site_name, $email_data );
+	 * $content = apply_filters( 'wp_privacy_personal_data_email_content', $email_text, $request_id, $email_data );
+	 * $headers = apply_filters( 'wp_privacy_personal_data_email_headers', $headers, $subject, $content, $request_id, $email_data );
 	 *
-	 * @param string          $request_email The email address of the notification recipient.
-	 * @param WP_User_Request $request       The request that is initiating the notification.
-	 */
-	$request_email = apply_filters( 'wp_privacy_personal_data_email_to', $request->email, $request );
-
-	$email_data = array(
-		'request'           => $request,
-		'expiration'        => $expiration,
-		'expiration_date'   => $expiration_date,
-		'message_recipient' => $request_email,
-		'export_file_url'   => $export_file_url,
-		'sitename'          => $site_name,
-		'siteurl'           => $site_url,
-	);
-
-	/* translators: Personal data export notification email subject. %s: Site title. */
-	$subject = sprintf( __( '[%s] Personal Data Export' ), $site_name );
-
-	/**
-	 * Filters the subject of the email sent when an export request is completed.
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
 	 *
-	 * @since 5.3.0
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
 	 *
-	 * @param string $subject    The email subject.
-	 * @param string $sitename   The name of the site.
-	 * @param array  $email_data {
-	 *     Data relating to the account action email.
-	 *
-	 *     @type WP_User_Request $request           User request object.
-	 *     @type int             $expiration        The time in seconds until the export file expires.
-	 *     @type string          $expiration_date   The localized date and time when the export file expires.
-	 *     @type string          $message_recipient The address that the email will be sent to. Defaults
-	 *                                              to the value of `$request->email`, but can be changed
-	 *                                              by the `wp_privacy_personal_data_email_to` filter.
-	 *     @type string          $export_file_url   The export file URL.
-	 *     @type string          $sitename          The site name sending the mail.
-	 *     @type string          $siteurl           The site URL sending the mail.
-	 * }
 	 */
-	$subject = apply_filters( 'wp_privacy_personal_data_email_subject', $subject, $site_name, $email_data );
 
-	/* translators: Do not translate EXPIRATION, LINK, SITENAME, SITEURL: those are placeholders. */
-	$email_text = __(
-		'Howdy,
+	$wp_mail = array(
+		'id' => 'wp_privacy_personal_data',
+		'group' => 'privacy',
 
+		'to' => $request->email,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( '[{{SITENAME}}] Personal Data Export' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => __(
+'{{HEADER}}
+
 Your request for an export of personal data has been completed. You may
 download your personal data by clicking on the link below. For privacy
-and security, we will automatically delete the file on ###EXPIRATION###,
+and security, we will automatically delete the file on {{EXPIRATION}},
 so please download it before then.
 
-###LINK###
+{{EXPORTLINK}}
 
-Regards,
-All at ###SITENAME###
-###SITEURL###'
+{{FOOTER}}'
+		),
+		'replacements' => array(
+			'{{EXPIRATION}}' => $expiration_date,
+			'{{EXPORTLINK}}' => esc_url_raw( get_post_meta( $request_id, '_export_file_url', true ) ),
+		),
 	);
 
-	/**
-	 * Filters the text of the email sent with a personal data export file.
-	 *
-	 * The following strings have a special meaning and will get replaced dynamically:
-	 * ###EXPIRATION###         The date when the URL will be automatically deleted.
-	 * ###LINK###               URL of the personal data export file for the user.
-	 * ###SITENAME###           The name of the site.
-	 * ###SITEURL###            The URL to the site.
-	 *
-	 * @since 4.9.6
-	 * @since 5.3.0 Introduced the `$email_data` array.
-	 *
-	 * @param string $email_text Text in the email.
-	 * @param int    $request_id The request ID for this personal data export.
-	 * @param array  $email_data {
-	 *     Data relating to the account action email.
-	 *
-	 *     @type WP_User_Request $request           User request object.
-	 *     @type int             $expiration        The time in seconds until the export file expires.
-	 *     @type string          $expiration_date   The localized date and time when the export file expires.
-	 *     @type string          $message_recipient The address that the email will be sent to. Defaults
-	 *                                              to the value of `$request->email`, but can be changed
-	 *                                              by the `wp_privacy_personal_data_email_to` filter.
-	 *     @type string          $export_file_url   The export file URL.
-	 *     @type string          $sitename          The site name sending the mail.
-	 *     @type string          $siteurl           The site URL sending the mail.
-	 */
-	$content = apply_filters( 'wp_privacy_personal_data_email_content', $email_text, $request_id, $email_data );
+	$wp_mailer = WP_Mailer::getInstance();
+	$mail_success = $wp_mailer->send( $wp_mail );
 
-	$content = str_replace( '###EXPIRATION###', $expiration_date, $content );
-	$content = str_replace( '###LINK###', esc_url_raw( $export_file_url ), $content );
-	$content = str_replace( '###EMAIL###', $request_email, $content );
-	$content = str_replace( '###SITENAME###', $site_name, $content );
-	$content = str_replace( '###SITEURL###', esc_url_raw( $site_url ), $content );
-
-	$headers = '';
-
-	/**
-	 * Filters the headers of the email sent with a personal data export file.
-	 *
-	 * @since 5.4.0
-	 *
-	 * @param string|array $headers    The email headers.
-	 * @param string       $subject    The email subject.
-	 * @param string       $content    The email content.
-	 * @param int          $request_id The request ID.
-	 * @param array        $email_data {
-	 *     Data relating to the account action email.
-	 *
-	 *     @type WP_User_Request $request           User request object.
-	 *     @type int             $expiration        The time in seconds until the export file expires.
-	 *     @type string          $expiration_date   The localized date and time when the export file expires.
-	 *     @type string          $message_recipient The address that the email will be sent to. Defaults
-	 *                                              to the value of `$request->email`, but can be changed
-	 *                                              by the `wp_privacy_personal_data_email_to` filter.
-	 *     @type string          $export_file_url   The export file URL.
-	 *     @type string          $sitename          The site name sending the mail.
-	 *     @type string          $siteurl           The site URL sending the mail.
-	 * }
-	 */
-	$headers = apply_filters( 'wp_privacy_personal_data_email_headers', $headers, $subject, $content, $request_id, $email_data );
-
-	$mail_success = wp_mail( $request_email, $subject, $content, $headers );
-
 	if ( $switched_locale ) {
 		restore_previous_locale();
 	}
Index: wp-admin/includes/schema.php
===================================================================
--- wp-admin/includes/schema.php	(revision 47320)
+++ wp-admin/includes/schema.php	(working copy)
@@ -1178,22 +1178,23 @@
 		$site_admins = get_site_option( 'site_admins' );
 	}
 
-	/* translators: Do not translate USERNAME, SITE_NAME, BLOG_URL, PASSWORD: those are placeholders. */
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
 	$welcome_email = __(
-		'Howdy USERNAME,
+'{{HEADER}}
 
-Your new SITE_NAME site has been successfully set up at:
-BLOG_URL
+Your new {{SITENAME}} site has been successfully set up at:
+{{SITEURL}}
 
 You can log in to the administrator account with the following information:
 
-Username: USERNAME
-Password: PASSWORD
-Log in here: BLOG_URLwp-login.php
+Username: {{USERNAME}}
+Password: {{PASSWORD}}
 
-We hope you enjoy your new site. Thanks!
+Log in here: {{LOGINLINK}}
 
---The Team @ SITE_NAME'
+We hope you will enjoy your new site.
+
+{{FOOTER}}'
 	);
 
 	$misc_exts        = array(
Index: wp-admin/includes/upgrade.php
===================================================================
--- wp-admin/includes/upgrade.php	(revision 47320)
+++ wp-admin/includes/upgrade.php	(working copy)
@@ -603,32 +603,41 @@
 		$name      = $user->user_login;
 		$login_url = wp_login_url();
 
-		$message = sprintf(
-			/* translators: New site notification email. 1: New site URL, 2: User login, 3: User password or password reset link, 4: Login URL. */
-			__(
-				'Your new WordPress site has been successfully set up at:
+		$wp_mail = array(
+			'id' => 'install',
+			'group' => 'admin',
 
-%1$s
+			'to' => $user->user_email,
+			/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+			'subject' => __( '[{{SITENAME}}] New WordPress Site' ),
+			/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+			'message' => __(
+'Your new WordPress site has been successfully set up at:
 
+{{SITEURL}}
+
 You can log in to the administrator account with the following information:
 
-Username: %2$s
-Password: %3$s
-Log in here: %4$s
+Username: {{USERNAME}}
+Password: {{PASSWORD}}
 
+Log in here: {{LOGINLINK}}
+
 We hope you enjoy your new site. Thanks!
 
 --The WordPress Team
-https://wordpress.org/
-'
+https://wordpress.org/' ),
+			'replacements' => array(
+				'{{SITEURL}}' 	=> esc_url_raw( $blog_url ),
+				'{{SITENAME}}' 	=> $blog_title,
+				'{{USERNAME}}' 	=> $user->user_login,
+				'{{PASSWORD}}' 	=> $password,
+				'{{LOGINLINK}}'	=> esc_url_raw( wp_login_url() ),
 			),
-			$blog_url,
-			$name,
-			$password,
-			$login_url
 		);
 
-		wp_mail( $email, __( 'New WordPress Site' ), $message );
+		$wp_mailer = WP_Mailer::getInstance();
+		$wp_mailer->send( $wp_mail );
 	}
 endif;
 
Index: wp-admin/ms-delete-site.php
===================================================================
--- wp-admin/ms-delete-site.php	(revision 47320)
+++ wp-admin/ms-delete-site.php	(working copy)
@@ -52,48 +52,51 @@
 
 	$switched_locale = switch_to_locale( get_locale() );
 
-	/* translators: Do not translate USERNAME, URL_DELETE, SITE_NAME: those are placeholders. */
-	$content = __(
-		"Howdy ###USERNAME###,
+	/**
+	 * Filter removed
+	 *
+	 * $content = apply_filters( 'delete_site_email_content', $content );
+	 *
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
+	 *
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+	 *
+	 */
 
-You recently clicked the 'Delete Site' link on your site and filled in a
+	$wp_mail = array(
+		'id' => 'delete_site_email',
+		'group' => 'ms',
+
+		'to' => get_option( 'admin_email' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( '[{{SITENAME}}] Delete My Site' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => __(
+'{{HEADER}}
+
+As {{USERNAME}}, you recently clicked the \'Delete Site\' link on your site and filled in a
 form on that page.
 
 If you really want to delete your site, click the link below. You will not
 be asked to confirm again so only click this link if you are absolutely certain:
-###URL_DELETE###
+{{URL_DELETE}}
 
 If you delete your site, please consider opening a new site here
 some time in the future! (But remember your current site and username
 are gone forever.)
 
-Thanks for using the site,
-Webmaster
-###SITE_NAME###"
+{{FOOTER}}'
+		),
+		'replacements' => array(
+			'{{URL_DELETE}}' => esc_url_raw( admin_url( 'ms-delete-site.php?h=' . $hash ) )
+		),
 	);
-	/**
-	 * Filters the email content sent when a site in a Multisite network is deleted.
-	 *
-	 * @since 3.0.0
-	 *
-	 * @param string $content The email content that will be sent to the user who deleted a site in a Multisite network.
-	 */
-	$content = apply_filters( 'delete_site_email_content', $content );
 
-	$content = str_replace( '###USERNAME###', $user->user_login, $content );
-	$content = str_replace( '###URL_DELETE###', $url_delete, $content );
-	$content = str_replace( '###SITE_NAME###', get_network()->site_name, $content );
+	$wp_mailer = WP_Mailer::getInstance();
+	$wp_mailer->send( $wp_mail );
 
-	wp_mail(
-		get_option( 'admin_email' ),
-		sprintf(
-			/* translators: %s: Site title. */
-			__( '[%s] Delete My Site' ),
-			wp_specialchars_decode( get_option( 'blogname' ) )
-		),
-		$content
-	);
-
 	if ( $switched_locale ) {
 		restore_previous_locale();
 	}
Index: wp-admin/network/site-new.php
===================================================================
--- wp-admin/network/site-new.php	(revision 47320)
+++ wp-admin/network/site-new.php	(working copy)
@@ -144,31 +144,51 @@
 			update_user_option( $user_id, 'primary_blog', $id, true );
 		}
 
-		wp_mail(
-			get_site_option( 'admin_email' ),
-			sprintf(
-				/* translators: New site notification email subject. %s: Network title. */
-				__( '[%s] New Site Created' ),
-				get_network()->site_name
-			),
-			sprintf(
-				/* translators: New site notification email. 1: User login, 2: Site URL, 3: Site title. */
-				__(
-					'New site created by %1$s
+		$admin_email = get_site_option( 'admin_email' );
 
-Address: %2$s
-Name: %3$s'
-				),
-				$current_user->user_login,
-				get_site_url( $id ),
-				wp_unslash( $title )
+		/**
+		 *
+		 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
+		 *
+		 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+		 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+		 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+		 *
+		 */
+
+
+		$wp_mail = array(
+			'id' => 'site_new',
+			'group' => 'network',
+
+			'to' => get_site_option( 'admin_email' ),
+			/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+			'subject' => __( '[{{SITENAME}}] New Site Created' ),
+			/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+			'message' => __(
+'{{HEADER}}
+
+New site created by {{USERNAME}}
+
+Address: {{SITEURL}}
+Name: {{BLOGNAME}}
+
+{{FOOTER}}'
 			),
-			sprintf(
-				'From: "%1$s" <%2$s>',
-				_x( 'Site Admin', 'email "From" field' ),
-				get_site_option( 'admin_email' )
-			)
+			'headers' => array(
+				'From' => "{$admin_email} <{$admin_email}>",
+			),
+			'replacements' => array(
+				'{{SITENAME}}' => get_network()->site_name,
+				'{{SITEURL}}'  => esc_url_raw( get_site_url( $id ) ),
+				'{{USERNAME}}' => $current_user->user_login,
+				'{{BLOGNAME}}' => wp_unslash( $title ),
+			),
 		);
+
+		$wp_mailer = WP_Mailer::getInstance();
+		$wp_mailer->send( $wp_mail );
+
 		wpmu_welcome_notification( $id, $user_id, $password, $title, array( 'public' => 1 ) );
 		wp_redirect(
 			add_query_arg(
Index: wp-admin/user-new.php
===================================================================
--- wp-admin/user-new.php	(revision 47320)
+++ wp-admin/user-new.php	(working copy)
@@ -112,33 +112,46 @@
 
 			$switched_locale = switch_to_locale( get_user_locale( $user_details ) );
 
-			/* translators: 1: Site title, 2: Site URL, 3: User role, 4: Activation URL. */
-			$message = __(
-				'Hi,
+			/**
+			 * No filter removed
+			 *
+			 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
+			 *
+			 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+			 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );	
+			 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+			 *
+			 */
 
-You\'ve been invited to join \'%1$s\' at
-%2$s with the role of %3$s.
+			$wp_mail = array(
+				'id' => 'invite',
+				'group' => 'blog',
 
+				'to' => $new_user_email,
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				'subject' => __( '[{{SITENAME}}] Joining Confirmation' ),
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				'message' => __(
+'{{HEADER}}
+
+You have been invited to join "{{SITENAME}}" at
+{{SITEURL}} with the role of {{ROLE}}.
+
 Please click the following link to confirm the invite:
-%4$s'
-			);
+{{INVITE_URL}}
 
-			wp_mail(
-				$new_user_email,
-				sprintf(
-					/* translators: Joining confirmation notification email subject. %s: Site title. */
-					__( '[%s] Joining Confirmation' ),
-					wp_specialchars_decode( get_option( 'blogname' ) )
+{{FOOTER}}'
 				),
-				sprintf(
-					$message,
-					get_option( 'blogname' ),
-					home_url(),
-					wp_specialchars_decode( translate_user_role( $role['name'] ) ),
-					home_url( "/newbloguser/$newuser_key/" )
-				)
+				'replacements' => array(
+					'{{ROLE}}'	 => translate_user_role( $role['name'] ),
+					'{{INVITE_URL}}' => esc_url_raw( home_url( "/newbloguser/$newuser_key/" ) ),
+				),
 			);
 
+			$wp_mailer = WP_Mailer::getInstance();
+			$wp_mailer->send( $wp_mail );
+
+
 			if ( $switched_locale ) {
 				restore_previous_locale();
 			}
Index: wp-includes/class-wp-mailer.php
===================================================================
--- wp-includes/class-wp-mailer.php	(nonexistent)
+++ wp-includes/class-wp-mailer.php	(working copy)
@@ -0,0 +1,229 @@
+<?php
+/**
+ * API for easily sending customisable mails.
+ *
+ * @package WordPress
+ * @subpackage Mail
+ * @since 5.5.0
+ */
+
+class WP_Mailer{
+
+	/**
+	 * Unique class instance
+         *
+         * @static object
+	 */
+	private static $_instance = null;
+
+	/**
+	 * Stores generated mail ids for uniqueness
+	 *
+	 * @static array
+	 */
+	private static $_ids = array();
+
+	/**
+	 * The occurence of debug_backtrace to identify the caller
+         *
+         * @var array
+	 */
+	private $call = array();
+
+	/**
+	 * Constructor
+	 *
+	 * Constructor is private, use GLOBALS variable $wp_mailer or getInstance() static function instead
+	 */
+	private function __construct() {  
+	}
+ 
+	 /**
+	  * Returns class instance
+	  *
+	  * @return object Class instance.
+	  */
+	public static function getInstance() {
+ 
+		if ( is_null( self::$_instance ) ) {
+			self::$_instance = new self();
+		}
+
+		return self::$_instance;
+	}
+
+	/**
+	 * Sending using wp_mail.
+	 *
+	 * @param array $mail The mail parameters, an array with structured information to send mail
+	 *	to      : (string|array) the email recipient(s)
+	 *	subject : (string) mail subject
+	 *	message : (string) message content before replacements
+	 *	headers : (string|array) if an array, each item is a pair of ( Header => Value, )
+	 * 				 example 1 : array( 'From' => 'me@my.awesome.blog', )
+	 * 				 example 2 : array( 'X-Repeatable' => array( 'value1', 'value2', )
+	 * 	attachments : (string|array)
+	 *
+	 *	replacements : (array) each item is a pair of ( Text_to_replace => Text_replaced )
+	 *				 example : array( '{{MYEMAIL}}' => 'me@my.awesome.blog', )
+         *	id : (string) used to individualize filter
+         *
+ 	 * @return bool Whether the mail was sent successfully.
+	 */
+	public function send( $mail ) {
+
+		$this->get_called();
+
+		$current_user = wp_get_current_user();
+
+		$defaults = array(
+			'id' => $this->get_mail_id(),
+			'group' => 'wordpress',
+
+			'subject' => '',
+			'message' => '',
+			'headers' => array(),
+			'attachments' => array(),
+
+			/* make sure reserved words {{HEADER}} and {{FOOTER}} are first. */
+			'replacements' => array(
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				'{{HEADER}}'   => __( '{{SITENAME}}
+{{SITEURL}}
+
+Hello,' ),
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				'{{FOOTER}}'   => __( 'With gratitude' ),
+				'{{SITENAME}}' => wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ),
+				'{{SITEURL}}'  => esc_url_raw( home_url() ),
+				'{{USERNAME}}' => $current_user->user_login,
+			),
+		);
+
+		/**
+		 * Filters the default message components.
+		 *
+		 * @since 5.5
+		 *
+		 * @param array  $defaults   Default values of api.
+		 * @param array  $mail       Current values of api.
+		 * @param array  $call       Debug_backtrace occurence of api caller.
+		 */
+		$defaults = apply_filters( 'wp_mailer_defaults', $defaults, $mail, $this->call );
+
+		$mail = array_replace_recursive( $defaults, $mail );
+
+
+		/**
+		 * Filters the message components for a specific mail.
+		 *
+		 * @since 5.5
+		 *
+		 * @param array  $mail       Current values of api.
+		 * @param array  $call       Debug_backtrace occurence of api caller.
+		 */
+		$mail = apply_filters( "wp_mailer_{$mail['id']}", $mail, $this->call );
+                
+		/**
+		 * Filters the message components for a group of mails ( network, ms, admin, blog, privacy, ...)
+		 *
+		 * @since 5.5
+		 *
+		 * @param array  $mail       Current values of api.
+		 * @param array  $call       Debug_backtrace occurence of api caller.
+		 */
+		$mail = apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $this->call );
+
+		/**
+		 * Filters the message components.
+		 *
+		 * @since 5.5
+		 *
+		 * @param array  $mail       Current values of api.
+		 * @param array  $call       Debug_backtrace occurence of api caller.
+		 */
+		$mail = apply_filters( "wp_mailer_mail", $mail, $this->call );
+
+		$search = array_keys( $mail['replacements'] );
+		$mail['subject'] = str_replace( $search, $mail['replacements'], $mail['subject'] );
+		$mail['subject'] = wp_specialchars_decode( $mail['subject'], ENT_QUOTES );
+		$mail['message'] = str_replace( $search, $mail['replacements'], $mail['message'] );
+		$mail['message'] = wp_specialchars_decode( $mail['message'], ENT_QUOTES );
+
+		/* to can be an array */                
+                if ( !isset( $mail['to'] ) ) return false;
+		if ( !is_array( $mail['to'] ) ) $mail['to'] = array( $mail['to'] );
+		else $mail['to'] = array_unique( $mail['to'] );
+                
+		/* headers argument is mixed (string|array) in wp_mail */
+		if ( is_array( $mail['headers'] ) ) {
+			$headers = array();
+			foreach( $mail['headers'] as $key => $value ) {
+				if ( is_array( $value ) ) {         /* repeatable header */
+					foreach( $value as $v ) {
+						$headers[] = trim( $key ) . ': ' . trim( $v ) . "\n";
+					}
+				}
+				else
+				{
+					$headers[] = trim( $key ) . ': ' . trim( $value ) . "\n";
+				}
+			}
+		}
+		else
+		{
+			$headers = $mail['headers'];
+		}
+                
+		$return = true;
+
+		foreach( $mail['to'] as $to )
+		{
+			if ( ! $return ) break;
+			$return = wp_mail( 
+					$to, 
+					$mail['subject'], 
+					$mail['message'],
+					$headers,
+					$mail['attachments']
+			);
+		}
+
+		return $return;
+	}
+
+	/**
+	 * Generates a mail id based on caller and occurence
+	 *
+	 */
+	private function get_mail_id() {
+
+		if ( empty( $this->call ) ) return 'unknown';
+
+		$ids = array();
+		if ( isset( $this->call['class'] ) )    $ids[] = $this->call['class'];
+		if ( isset( $this->call['function'] ) ) $ids[] = $this->call['function'];
+		if ( empty( $ids ) && isset( $this->call['file'] ) ) $ids[] = substr( basename( $this->call['file'] ), 0, -4 );
+		$id = implode ( '_', $ids );
+		if ( isset( self::$_ids[$id] ) )  $ids[] = ++self::$_ids[$id];
+		else self::$_ids[$id] = 0;				
+
+		return implode ( '_', $ids );
+	}
+
+	/**
+	 * For filters and eventually mail id (caller and arguments)
+	 *
+	 */
+	private function get_called() {
+		$calls = debug_backtrace();
+		$call = array();
+                for( $i = 2; $i >= 0; $i-- ) {
+			if ( isset( $calls[$i] ) ) {
+				$call = $calls[$i];
+				break;
+			}
+                }
+		$this->call = $call;
+	}
+}
\ No newline at end of file
Index: wp-includes/functions.php
===================================================================
--- wp-includes/functions.php	(revision 47320)
+++ wp-includes/functions.php	(working copy)
@@ -7009,69 +7009,47 @@
 		return;
 	}
 
-	/* translators: Do not translate OLD_EMAIL, NEW_EMAIL, SITENAME, SITEURL: those are placeholders. */
-	$email_change_text = __(
-		'Hi,
-
-This notice confirms that the admin email address was changed on ###SITENAME###.
-
-The new admin email address is ###NEW_EMAIL###.
-
-This email has been sent to ###OLD_EMAIL###
-
-Regards,
-All at ###SITENAME###
-###SITEURL###'
-	);
-
-	$email_change_email = array(
-		'to'      => $old_email,
-		/* translators: Site admin email change notification email subject. %s: Site title. */
-		'subject' => __( '[%s] Admin Email Changed' ),
-		'message' => $email_change_text,
-		'headers' => '',
-	);
-
-	// Get site name.
-	$site_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
-
 	/**
-	 * Filters the contents of the email notification sent when the site admin email address is changed.
+	 * Filter removed
 	 *
-	 * @since 4.9.0
+	 * $email_change_email = apply_filters( 'site_admin_email_change_email', $email_change_email, $old_email, $new_email );
 	 *
-	 * @param array $email_change_email {
-	 *            Used to build wp_mail().
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
 	 *
-	 *            @type string $to      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:
-	 *                - ###OLD_EMAIL### The old site admin email address.
-	 *                - ###NEW_EMAIL### The new site admin email address.
-	 *                - ###SITENAME###  The name of the site.
-	 *                - ###SITEURL###   The URL to the site.
-	 *            @type string $headers Headers.
-	 *        }
-	 * @param string $old_email The old site admin email address.
-	 * @param string $new_email The new site admin email address.
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+	 *
 	 */
-	$email_change_email = apply_filters( 'site_admin_email_change_email', $email_change_email, $old_email, $new_email );
 
-	$email_change_email['message'] = str_replace( '###OLD_EMAIL###', $old_email, $email_change_email['message'] );
-	$email_change_email['message'] = str_replace( '###NEW_EMAIL###', $new_email, $email_change_email['message'] );
-	$email_change_email['message'] = str_replace( '###SITENAME###', $site_name, $email_change_email['message'] );
-	$email_change_email['message'] = str_replace( '###SITEURL###', home_url(), $email_change_email['message'] );
+	$wp_mail = array(
+		'id' => 'site_admin_email_change',
+		'group' => 'admin',
 
-	wp_mail(
-		$email_change_email['to'],
-		sprintf(
-			$email_change_email['subject'],
-			$site_name
+		'to' => $old_email,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( '[{{SITENAME}}] Admin Email Changed' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => __(
+'{{HEADER}}
+
+This notice confirms that the admin email address was changed on {{SITENAME}}.
+
+The new admin email address is {{NEW_EMAIL}}.
+
+This email has been sent to {{OLD_EMAIL}}.
+
+{{FOOTER}}'
 		),
-		$email_change_email['message'],
-		$email_change_email['headers']
+		'replacements' => array(
+			'{{OLD_EMAIL}}' => $old_email,
+			'{{NEW_EMAIL}}' => $new_email,
+
+		),
 	);
+
+	$wp_mailer = WP_Mailer::getInstance();
+	$wp_mailer->send( $wp_mail );
 }
 
 /**
Index: wp-includes/ms-functions.php
===================================================================
--- wp-includes/ms-functions.php	(revision 47320)
+++ wp-includes/ms-functions.php	(working copy)
@@ -903,10 +903,6 @@
  * Filter {@see 'wpmu_signup_blog_notification'} to bypass this function or
  * replace it with your own notification behavior.
  *
- * Filter {@see 'wpmu_signup_blog_notification_email'} and
- * {@see 'wpmu_signup_blog_notification_subject'} to change the content
- * and subject line of the email sent to newly registered users.
- *
  * @since MU (3.0.0)
  *
  * @param string $domain     The new blog domain.
@@ -949,77 +945,92 @@
 		$admin_email = 'support@' . $_SERVER['SERVER_NAME'];
 	}
 	$from_name       = get_site_option( 'site_name' ) == '' ? 'WordPress' : esc_html( get_site_option( 'site_name' ) );
-	$message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n";
 
 	$user            = get_user_by( 'login', $user_login );
+
+	$new_siteurl = is_ssl() ? 'https://' : 'http://';
+	$new_siteurl .= $domain . $path;
+
 	$switched_locale = switch_to_locale( get_user_locale( $user ) );
 
-	$message = sprintf(
-		/**
-		 * Filters the message content of the new blog notification email.
-		 *
-		 * Content should be formatted for transmission via wp_mail().
-		 *
-		 * @since MU (3.0.0)
-		 *
-		 * @param string $content    Content of the notification email.
-		 * @param string $domain     Site domain.
-		 * @param string $path       Site path.
-		 * @param string $title      Site title.
-		 * @param string $user_login User login name.
-		 * @param string $user_email User email address.
-		 * @param string $key        Activation key created in wpmu_signup_blog().
-		 * @param array  $meta       Signup meta data. By default, contains the requested privacy setting and lang_id.
-		 */
-		apply_filters(
-			'wpmu_signup_blog_notification_email',
-			/* translators: New site notification email. 1: Activation URL, 2: New site URL. */
-			__( "To activate your blog, please click the following link:\n\n%1\$s\n\nAfter you activate, you will receive *another email* with your login.\n\nAfter you activate, you can visit your site here:\n\n%2\$s" ),
-			$domain,
-			$path,
-			$title,
-			$user_login,
-			$user_email,
-			$key,
-			$meta
-		),
-		$activate_url,
-		esc_url( "http://{$domain}{$path}" ),
-		$key
-	);
 
-	$subject = sprintf(
-		/**
-		 * Filters the subject of the new blog notification email.
-		 *
-		 * @since MU (3.0.0)
-		 *
-		 * @param string $subject    Subject of the notification email.
-		 * @param string $domain     Site domain.
-		 * @param string $path       Site path.
-		 * @param string $title      Site title.
-		 * @param string $user_login User login name.
-		 * @param string $user_email User email address.
-		 * @param string $key        Activation key created in wpmu_signup_blog().
-		 * @param array  $meta       Signup meta data. By default, contains the requested privacy setting and lang_id.
-		 */
-		apply_filters(
-			'wpmu_signup_blog_notification_subject',
-			/* translators: New site notification email subject. 1: Network title, 2: New site URL. */
-			_x( '[%1$s] Activate %2$s', 'New site notification email subject' ),
-			$domain,
-			$path,
-			$title,
-			$user_login,
-			$user_email,
-			$key,
-			$meta
+	/**
+	 * Filters removed
+	 *
+	 * 	$message = sprintf(
+	 * 		apply_filters(
+	 * 			'wpmu_signup_blog_notification_email',
+	 * 			__( "To activate your blog, please click the following link:\n\n%1\$s\n\nAfter you activate, you will receive *another email* with your login.\n\nAfter you activate, you can visit your site here:\n\n%2\$s" ),
+	 * 			$domain,
+	 * 			$path,
+	 * 			$title,
+	 * 			$user_login,
+	 * 			$user_email,
+	 * 			$key,
+	 * 			$meta
+	 * 		),
+	 * 		$activate_url,
+	 * 		esc_url( "http://{$domain}{$path}" ),
+	 * 		$key
+	 * 	);
+	 * 
+	 * 	$subject = sprintf(
+	 * 		apply_filters(
+	 * 			'wpmu_signup_blog_notification_subject',
+	 * 			_x( '[%1$s] Activate %2$s', 'New site notification email subject' ),
+	 * 			$domain,
+	 * 			$path,
+	 * 			$title,
+	 * 			$user_login,
+	 * 			$user_email,
+	 * 			$key,
+	 * 			$meta
+	 * 		),
+	 * 		$from_name,
+	 * 		esc_url( 'http://' . $domain . $path )
+	 * 	);
+	 *
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
+	 *
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+	 *
+	 */
+
+	$wp_mail = array(
+		'id' => 'wpmu_signup_blog_notification',
+		'group' => 'ms',
+
+		'to' => $user_email,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( '[{{SITENAME}}] Activate {{NEW_SITEURL}}' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => __(
+'{{HEADER}}
+
+To activate your blog, please click the following link: {{ACTIVATE_URL}}
+
+After you activate, you will receive *another email* with your login
+
+and you will be able to visit your new site here: {{NEW_SITEURL}}
+
+{{FOOTER}}'
 		),
-		$from_name,
-		esc_url( 'http://' . $domain . $path )
+		'headers' => array(
+			'From' => "{$from_name} <{$admin_email}>",
+			'Content-Type' => 'text/plain; charset="' . get_option( 'blog_charset' ) . '"',
+		),
+		'replacements' => array(
+			'{{SITENAME}}'     => $from_name,
+			'{{USERNAME}}'     => $user_login,
+			'{{ACTIVATE_URL}}' => esc_url_raw( $activate_url ),
+			'{{NEW_SITEURL}}'  => esc_url_raw( $new_siteurl ),
+		),
 	);
 
-	wp_mail( $user_email, wp_specialchars_decode( $subject ), $message, $message_headers );
+	$wp_mailer = WP_Mailer::getInstance();
+	$wp_mailer->send( $wp_mail );
 
 	if ( $switched_locale ) {
 		restore_previous_locale();
@@ -1038,10 +1049,6 @@
  * Filter {@see 'wpmu_signup_user_notification'} to bypass this function or
  * replace it with your own notification behavior.
  *
- * Filter {@see 'wpmu_signup_user_notification_email'} and
- * {@see 'wpmu_signup_user_notification_subject'} to change the content
- * and subject line of the email sent to newly registered users.
- *
  * @since MU (3.0.0)
  *
  * @param string $user_login The user's login name.
@@ -1066,7 +1073,6 @@
 	}
 
 	$user            = get_user_by( 'login', $user_login );
-	$switched_locale = switch_to_locale( get_user_locale( $user ) );
 
 	// Send email with activation link.
 	$admin_email = get_site_option( 'admin_email' );
@@ -1074,59 +1080,75 @@
 		$admin_email = 'support@' . $_SERVER['SERVER_NAME'];
 	}
 	$from_name       = get_site_option( 'site_name' ) == '' ? 'WordPress' : esc_html( get_site_option( 'site_name' ) );
-	$message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n";
-	$message         = sprintf(
-		/**
-		 * Filters the content of the notification email for new user sign-up.
-		 *
-		 * Content should be formatted for transmission via wp_mail().
-		 *
-		 * @since MU (3.0.0)
-		 *
-		 * @param string $content    Content of the notification email.
-		 * @param string $user_login User login name.
-		 * @param string $user_email User email address.
-		 * @param string $key        Activation key created in wpmu_signup_user().
-		 * @param array  $meta       Signup meta data. Default empty array.
-		 */
-		apply_filters(
-			'wpmu_signup_user_notification_email',
-			/* translators: New user notification email. %s: Activation URL. */
-			__( "To activate your user, please click the following link:\n\n%s\n\nAfter you activate, you will receive *another email* with your login." ),
-			$user_login,
-			$user_email,
-			$key,
-			$meta
-		),
-		site_url( "wp-activate.php?key=$key" )
-	);
 
-	$subject = sprintf(
-		/**
-		 * Filters the subject of the notification email of new user signup.
-		 *
-		 * @since MU (3.0.0)
-		 *
-		 * @param string $subject    Subject of the notification email.
-		 * @param string $user_login User login name.
-		 * @param string $user_email User email address.
-		 * @param string $key        Activation key created in wpmu_signup_user().
-		 * @param array  $meta       Signup meta data. Default empty array.
-		 */
-		apply_filters(
-			'wpmu_signup_user_notification_subject',
-			/* translators: New user notification email subject. 1: Network title, 2: New user login. */
-			_x( '[%1$s] Activate %2$s', 'New user notification email subject' ),
-			$user_login,
-			$user_email,
-			$key,
-			$meta
+	$switched_locale = switch_to_locale( get_user_locale( $user ) );
+
+	/**
+	 * Filters removed
+	 *
+	 * $message         = sprintf(
+	 * 		apply_filters(
+	 * 			'wpmu_signup_user_notification_email',
+	 * 			__( "To activate your user, please click the following link:\n\n%s\n\nAfter you activate, you will receive *another email* with your login." ),
+	 * 			$user_login,
+	 * 			$user_email,
+	 * 			$key,
+	 * 			$meta
+	 * 		),
+	 * 		site_url( "wp-activate.php?key=$key" )
+	 * );
+	 * 
+	 * $subject = sprintf(
+	 * 		apply_filters(
+	 * 			'wpmu_signup_user_notification_subject',
+	 * 			_x( '[%1$s] Activate %2$s', 'New user notification email subject' ),
+	 * 			$user_login,
+	 * 			$user_email,
+	 * 			$key,
+	 * 			$meta
+	 * 		),
+	 * 		$from_name,
+	 * 		$user_login
+	 * );
+	 *
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
+	 *
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+	 *
+	 */
+
+	$wp_mail = array(
+		'id' => 'wpmu_signup_user_notification',
+		'group' => 'ms',
+
+		'to' => $user_email,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( '[{{SITENAME}}] Activate {{USERNAME}}' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => __(
+'{{HEADER}}
+
+To activate your user, please click the following link: {{ACTIVATE_URL}}
+
+After you activate, you will receive *another email* with your login.
+
+{{FOOTER}}'
 		),
-		$from_name,
-		$user_login
+		'headers' => array(
+			'From' => "{$from_name} <{$admin_email}>",
+			'Content-Type' => 'text/plain; charset="' . get_option( 'blog_charset' ) . '"',
+		),
+		'replacements' => array(
+			'{{SITENAME}}'     => $from_name,
+			'{{USERNAME}}'     => $user_login,
+			'{{ACTIVATE_URL}}' => esc_url_raw( site_url( "wp-activate.php?key={$key}" ) ),
+		),
 	);
 
-	wp_mail( $user_email, wp_specialchars_decode( $subject ), $message, $message_headers );
+	$wp_mailer = WP_Mailer::getInstance();
+	$wp_mailer->send( $wp_mail );
 
 	if ( $switched_locale ) {
 		restore_previous_locale();
@@ -1383,11 +1405,7 @@
 /**
  * Notifies the network admin that a new site has been activated.
  *
- * Filter {@see 'newblog_notify_siteadmin'} to change the content of
- * the notification email.
- *
  * @since MU (3.0.0)
- * @since 5.1.0 $blog_id now supports input from the {@see 'wp_initialize_site'} action.
  *
  * @param WP_Site|int $blog_id    The new site's object or ID.
  * @param string      $deprecated Not used.
@@ -1407,42 +1425,53 @@
 		return false;
 	}
 
-	$options_site_url = esc_url( network_admin_url( 'settings.php' ) );
-
 	switch_to_blog( $blog_id );
 	$blogname = get_option( 'blogname' );
 	$siteurl  = site_url();
 	restore_current_blog();
 
-	$msg = sprintf(
-		/* translators: New site notification email. 1: Site URL, 2: User IP address, 3: URL to Network Settings screen. */
-		__(
-			'New Site: %1$s
-URL: %2$s
-Remote IP address: %3$s
-
-Disable these notifications: %4$s'
-		),
-		$blogname,
-		$siteurl,
-		wp_unslash( $_SERVER['REMOTE_ADDR'] ),
-		$options_site_url
-	);
 	/**
-	 * Filters the message body of the new site activation email sent
-	 * to the network administrator.
+	 * Filter removed
 	 *
-	 * @since MU (3.0.0)
-	 * @since 5.4.0 The `$blog_id` parameter was added.
+	 * $msg = apply_filters( 'newblog_notify_siteadmin', $msg, $blog_id );
 	 *
-	 * @param string $msg     Email body.
-	 * @param int    $blog_id The new site's ID.
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
+	 *
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+	 *
 	 */
-	$msg = apply_filters( 'newblog_notify_siteadmin', $msg, $blog_id );
 
-	/* translators: New site notification email subject. %s: New site URL. */
-	wp_mail( $email, sprintf( __( 'New Site Registration: %s' ), $siteurl ), $msg );
+	$wp_mail = array(
+		'id' => 'newblog_notify_siteadmin',
+		'group' => 'network',
 
+		'to' => $email,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( 'New Site Registration: {{SITEURL}}' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => __(
+'{{HEADER}}
+
+New Site: {{SITENAME}}
+URL : {{SITEURL}}
+Remote IP address : {{REMOTEADDR}}
+
+Disable these notifications: {{ADMIN_URL}}
+
+{{FOOTER}}'
+		),
+		'replacements' => array(
+			'{{SITEURL}}'     => esc_url_raw( $siteurl ),
+			'{{REMOTEADDR}}'  => wp_unslash( $_SERVER['REMOTE_ADDR'] ),
+			'{{ADMIN_URL}}'   => esc_url_raw( network_admin_url( 'settings.php' ) ),
+		),
+	);
+
+	$wp_mailer = WP_Mailer::getInstance();
+	$wp_mailer->send( $wp_mail );
+
 	return true;
 }
 
@@ -1449,9 +1478,6 @@
 /**
  * Notifies the network admin that a new user has been activated.
  *
- * Filter {@see 'newuser_notify_siteadmin'} to change the content of
- * the notification email.
- *
  * @since MU (3.0.0)
  *
  * @param int $user_id The new user's ID.
@@ -1470,35 +1496,48 @@
 
 	$user = get_userdata( $user_id );
 
-	$options_site_url = esc_url( network_admin_url( 'settings.php' ) );
+	/**
+	 * Filter removed
+	 *
+	 * $msg = apply_filters( 'newuser_notify_siteadmin', $msg, $user );
+	 *
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
+	 *
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+	 *
+	 */
 
-	$msg = sprintf(
-		/* translators: New user notification email. 1: User login, 2: User IP address, 3: URL to Network Settings screen. */
-		__(
-			'New User: %1$s
-Remote IP address: %2$s
+	$wp_mail = array(
+		'id' => 'newuser_notify_siteadmin',
+		'group' => 'network',
 
-Disable these notifications: %3$s'
+		'to' => $email,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( 'New User Registration: {{USERNAME}}' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => __(
+'{{HEADER}}
+
+New User: {{USERNAME}}
+
+Remote IP address : {{REMOTEADDR}}
+
+Disable these notifications: {{ADMIN_URL}}
+
+{{FOOTER}}'
 		),
-		$user->user_login,
-		wp_unslash( $_SERVER['REMOTE_ADDR'] ),
-		$options_site_url
+		'replacements' => array(
+			'{{USERNAME}}'    => $user->user_login,
+			'{{REMOTEADDR}}'  => wp_unslash( $_SERVER['REMOTE_ADDR'] ),
+			'{{ADMIN_URL}}'   => esc_url_raw( network_admin_url( 'settings.php' ) ),
+		),
 	);
 
-	/**
-	 * Filters the message body of the new user activation email sent
-	 * to the network administrator.
-	 *
-	 * @since MU (3.0.0)
-	 *
-	 * @param string  $msg  Email body.
-	 * @param WP_User $user WP_User instance of the new user.
-	 */
-	$msg = apply_filters( 'newuser_notify_siteadmin', $msg, $user );
+	$wp_mailer = WP_Mailer::getInstance();
+	$wp_mailer->send( $wp_mail );
 
-	/* translators: New user notification email subject. %s: User login. */
-	wp_mail( $email, sprintf( __( 'New User Registration: %s' ), $user->user_login ), $msg );
-
 	return true;
 }
 
@@ -1552,9 +1591,6 @@
  *
  * Filter {@see 'wpmu_welcome_notification'} to disable or bypass.
  *
- * Filter {@see 'update_welcome_email'} and {@see 'update_welcome_subject'} to
- * modify the content and subject line of the notification email.
- *
  * @since MU (3.0.0)
  *
  * @param int    $blog_id  Blog ID.
@@ -1565,8 +1601,6 @@
  * @return bool
  */
 function wpmu_welcome_notification( $blog_id, $user_id, $password, $title, $meta = array() ) {
-	$current_network = get_network();
-
 	/**
 	 * Filters whether to bypass the welcome email after site activation.
 	 *
@@ -1584,82 +1618,92 @@
 		return false;
 	}
 
+	$current_network = get_network();
+	if ( empty( $current_network->site_name ) ) {
+		$current_network->site_name = 'WordPress';
+	}
+
 	$user = get_userdata( $user_id );
 
+	$admin_email   = get_site_option( 'admin_email' );
+
+	if ( '' == $admin_email ) {
+		$admin_email = 'support@' . $_SERVER['SERVER_NAME'];
+	}
+	$from_name       = get_site_option( 'site_name' ) == '' ? 'WordPress' : esc_html( get_site_option( 'site_name' ) );
+
+	$url       = get_blogaddress_by_id( $blog_id );
+	$login_url = $url . 'wp-login.php';
+
+	// Back-compat for pre-5.5.
+	$welcome_backward_compat = array( 'SITE_NAME' => '{{SITENAME}}', 'BLOG_URL' => '{{SITEURL}}', 'USERNAME' => '{{USERNAME}}', 'PASSWORD' => '{{PASSWORD}}', 'BLOG_URLwp-login.php' => '{{LOGINLINK}}', '{{{{' => '{{', '}}}}' => '}}', );
+	$welcome_search = array_keys( $welcome_backward_compat );
+	$welcome_email = get_site_option( 'welcome_email' );
+	$welcome_email = str_replace( $welcome_search, $welcome_backward_compat, $welcome_email );
+
 	$switched_locale = switch_to_locale( get_user_locale( $user ) );
 
-	$welcome_email = get_site_option( 'welcome_email' );
 	if ( false == $welcome_email ) {
-		/* translators: Do not translate USERNAME, SITE_NAME, BLOG_URL, PASSWORD: those are placeholders. */
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
 		$welcome_email = __(
-			'Howdy USERNAME,
+'{{HEADER}}
 
-Your new SITE_NAME site has been successfully set up at:
-BLOG_URL
+Your new {{SITENAME}} site has been successfully set up at:
+{{SITEURL}}
 
 You can log in to the administrator account with the following information:
 
-Username: USERNAME
-Password: PASSWORD
-Log in here: BLOG_URLwp-login.php
+Username: {{USERNAME}}
+Password: {{PASSWORD}}
 
-We hope you enjoy your new site. Thanks!
+Log in here: {{LOGINLINK}}
 
---The Team @ SITE_NAME'
+We hope you will enjoy your new site.
+
+{{FOOTER}}'
 		);
 	}
 
-	$url = get_blogaddress_by_id( $blog_id );
-
-	$welcome_email = str_replace( 'SITE_NAME', $current_network->site_name, $welcome_email );
-	$welcome_email = str_replace( 'BLOG_TITLE', $title, $welcome_email );
-	$welcome_email = str_replace( 'BLOG_URL', $url, $welcome_email );
-	$welcome_email = str_replace( 'USERNAME', $user->user_login, $welcome_email );
-	$welcome_email = str_replace( 'PASSWORD', $password, $welcome_email );
-
 	/**
-	 * Filters the content of the welcome email after site activation.
+	 * Filter removed
 	 *
-	 * Content should be formatted for transmission via wp_mail().
+	 * $welcome_email = apply_filters( 'update_welcome_email', $welcome_email, $blog_id, $user_id, $password, $title, $meta );
+	 * $subject = apply_filters( 'update_welcome_subject', sprintf( $subject, $current_network->site_name, wp_unslash( $title ) ) );
 	 *
-	 * @since MU (3.0.0)
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
 	 *
-	 * @param string $welcome_email Message body of the email.
-	 * @param int    $blog_id       Blog ID.
-	 * @param int    $user_id       User ID.
-	 * @param string $password      User password.
-	 * @param string $title         Site title.
-	 * @param array  $meta          Signup meta data. By default, contains the requested privacy setting and lang_id.
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+	 *
 	 */
-	$welcome_email = apply_filters( 'update_welcome_email', $welcome_email, $blog_id, $user_id, $password, $title, $meta );
-	$admin_email   = get_site_option( 'admin_email' );
 
-	if ( '' == $admin_email ) {
-		$admin_email = 'support@' . $_SERVER['SERVER_NAME'];
-	}
+	$wp_mail = array(
+		'id' => 'update_welcome',
+		'group' => 'ms',
 
-	$from_name       = get_site_option( 'site_name' ) == '' ? 'WordPress' : esc_html( get_site_option( 'site_name' ) );
-	$message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n";
-	$message         = $welcome_email;
+		'to' => $user->user_email,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( 'New {{SITENAME}} Site: {{BLOGNAME}}' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => $welcome_email,
+		'headers' => array(
+			'From' => "{$from_name} <{$admin_email}>",
+			'Content-Type' => 'text/plain; charset="' . get_option( 'blog_charset' ) . '"',
+		),
+		'replacements' => array(
+			'{{SITENAME}}' => $current_network->site_name,
+			'{{SITEURL}}'  => esc_url_raw( $url ),
+			'{{USERNAME}}' => $user->user_login,
+			'{{PASSWORD}}' => $password,
+			'{{LOGINLINK}}' => esc_url_raw( $login_url ),
+			'{{BLOGNAME}}' => wp_unslash( $title ),
+		),
+	);
 
-	if ( empty( $current_network->site_name ) ) {
-		$current_network->site_name = 'WordPress';
-	}
+	$wp_mailer = WP_Mailer::getInstance();
+	$wp_mailer->send( $wp_mail );
 
-	/* translators: New site notification email subject. 1: Network title, 2: New site title. */
-	$subject = __( 'New %1$s Site: %2$s' );
-
-	/**
-	 * Filters the subject of the welcome email after site activation.
-	 *
-	 * @since MU (3.0.0)
-	 *
-	 * @param string $subject Subject of the email.
-	 */
-	$subject = apply_filters( 'update_welcome_subject', sprintf( $subject, $current_network->site_name, wp_unslash( $title ) ) );
-
-	wp_mail( $user->user_email, wp_specialchars_decode( $subject ), $message, $message_headers );
-
 	if ( $switched_locale ) {
 		restore_previous_locale();
 	}
@@ -1683,8 +1727,6 @@
  * @return bool
  */
 function wpmu_welcome_user_notification( $user_id, $password, $meta = array() ) {
-	$current_network = get_network();
-
 	/**
 	 * Filters whether to bypass the welcome email after user activation.
 	 *
@@ -1700,58 +1742,83 @@
 		return false;
 	}
 
-	$welcome_email = get_site_option( 'welcome_user_email' );
+	$current_network = get_network();
+	if ( empty( $current_network->site_name ) ) {
+		$current_network->site_name = 'WordPress';
+	}
 
 	$user = get_userdata( $user_id );
 
-	$switched_locale = switch_to_locale( get_user_locale( $user ) );
-
-	/**
-	 * Filters the content of the welcome email after user activation.
-	 *
-	 * Content should be formatted for transmission via wp_mail().
-	 *
-	 * @since MU (3.0.0)
-	 *
-	 * @param string $welcome_email The message body of the account activation success email.
-	 * @param int    $user_id       User ID.
-	 * @param string $password      User password.
-	 * @param array  $meta          Signup meta data. Default empty array.
-	 */
-	$welcome_email = apply_filters( 'update_welcome_user_email', $welcome_email, $user_id, $password, $meta );
-	$welcome_email = str_replace( 'SITE_NAME', $current_network->site_name, $welcome_email );
-	$welcome_email = str_replace( 'USERNAME', $user->user_login, $welcome_email );
-	$welcome_email = str_replace( 'PASSWORD', $password, $welcome_email );
-	$welcome_email = str_replace( 'LOGINLINK', wp_login_url(), $welcome_email );
-
 	$admin_email = get_site_option( 'admin_email' );
-
 	if ( '' == $admin_email ) {
 		$admin_email = 'support@' . $_SERVER['SERVER_NAME'];
 	}
-
 	$from_name       = get_site_option( 'site_name' ) == '' ? 'WordPress' : esc_html( get_site_option( 'site_name' ) );
-	$message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n";
-	$message         = $welcome_email;
 
-	if ( empty( $current_network->site_name ) ) {
-		$current_network->site_name = 'WordPress';
+	// Back-compat for pre-5.5.
+	$welcome_backward_compat = array( 'SITE_NAME' => '{{SITENAME}}', 'USERNAME' => '{{USERNAME}}', 'PASSWORD' => '{{PASSWORD}}', 'LOGINLINK' => '{{LOGINLINK}}', '{{{{' => '{{', '}}}}' => '}}', );
+	$welcome_search = array_keys( $welcome_backward_compat );
+	$welcome_email = get_site_option( 'welcome_user_email' );
+	$welcome_email = str_replace( $welcome_search, $welcome_backward_compat, $welcome_email );
+
+	$switched_locale = switch_to_locale( get_user_locale( $user ) );
+
+	if ( false == $welcome_email ) {
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		$welcome_email = __(
+'{{HEADER}}
+
+As {{USERNAME}}, your new account is set up.
+
+You can log in with the following information:
+Username: {{USERNAME}}
+Password: {{PASSWORD}}
+
+Log in here: {{LOGINLINK}}
+
+
+{{FOOTER}}'
+		);
 	}
 
-	/* translators: New user notification email subject. 1: Network title, 2: New user login. */
-	$subject = __( 'New %1$s User: %2$s' );
-
 	/**
-	 * Filters the subject of the welcome email after user activation.
+	 * Filter removed
 	 *
-	 * @since MU (3.0.0)
+	 * $welcome_email = apply_filters( 'update_welcome_user_email', $welcome_email, $user_id, $password, $meta );
+	 * $subject = apply_filters( 'update_welcome_user_subject', sprintf( $subject, $current_network->site_name, $user->user_login ) );
 	 *
-	 * @param string $subject Subject of the email.
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
+	 *
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+	 *
 	 */
-	$subject = apply_filters( 'update_welcome_user_subject', sprintf( $subject, $current_network->site_name, $user->user_login ) );
 
-	wp_mail( $user->user_email, wp_specialchars_decode( $subject ), $message, $message_headers );
+	$wp_mail = array(
+		'id' => 'update_welcome_user',
+		'group' => 'ms',
 
+		'to' => $user->user_email,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( 'New {{SITENAME}} User: {{USERNAME}}' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => $welcome_email,
+		'headers' => array(
+			'From' => "{$from_name} <{$admin_email}>",
+			'Content-Type' => 'text/plain; charset="' . get_option( 'blog_charset' ) . '"',
+		),
+		'replacements' => array(
+			'{{SITENAME}}' => $current_network->site_name,
+			'{{USERNAME}}' => $user->user_login,
+			'{{PASSWORD}}' => $password,
+			'{{LOGINLINK}}' => esc_url_raw( wp_login_url() ),
+		),
+	);
+
+	$wp_mailer = WP_Mailer::getInstance();
+	$wp_mailer->send( $wp_mail );
+
 	if ( $switched_locale ) {
 		restore_previous_locale();
 	}
@@ -2276,20 +2343,20 @@
 	if ( ! $text ) {
 		remove_filter( 'site_option_welcome_user_email', 'welcome_user_msg_filter' );
 
-		/* translators: Do not translate USERNAME, PASSWORD, LOGINLINK, SITE_NAME: those are placeholders. */
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
 		$text = __(
-			'Howdy USERNAME,
+'{{HEADER}}
 
-Your new account is set up.
+As {{USERNAME}}, your new account is set up.
 
 You can log in with the following information:
-Username: USERNAME
-Password: PASSWORD
-LOGINLINK
+Username: {{USERNAME}}
+Password: {{PASSWORD}}
 
-Thanks!
+Log in here: {{LOGINLINK}}
 
---The Team @ SITE_NAME'
+
+{{FOOTER}}'
 		);
 		update_site_option( 'welcome_user_email', $text );
 	}
@@ -2672,65 +2739,54 @@
 
 	$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###,
+	/**
+	 * Filter removed
+	 *
+	 * $content = apply_filters( 'new_network_admin_email_content', $email_text, $new_admin_email );
+	 *
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
+	 *
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+	 *
+	 */
 
-You recently requested to have the network admin email address on
+	$wp_mail = array(
+		'id' => 'new_network_admin_email',
+		'group' => 'network',
+
+		'to' => $value,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( '[{{SITENAME}}] Network Admin Email Change Request' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => __(
+'{{HEADER}}
+
+As {{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###
+{{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###
+This email has been sent to {{EMAIL}}
 
-Regards,
-All at ###SITENAME###
-###SITEURL###'
+{{FOOTER}}'
+		),
+		'replacements' => array(
+			'{{SITENAME}}' => get_site_option( 'site_name' ),
+			'{{SITEURL}}'  => esc_url_raw( network_home_url() ),
+			'{{ADMIN_URL}}' => esc_url_raw( network_admin_url( 'settings.php?network_admin_hash=' . $hash ) ),
+			'{{EMAIL}}' => $value,
+		),
 	);
 
-	/**
-	 * 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 );
+	$wp_mailer = WP_Mailer::getInstance();
+	$wp_mailer->send( $wp_mail );
 
-	$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(
-			/* translators: Email change notification email subject. %s: Network title. */
-			__( '[%s] Network Admin Email Change Request' ),
-			wp_specialchars_decode( get_site_option( 'site_name' ), ENT_QUOTES )
-		),
-		$content
-	);
-
 	if ( $switched_locale ) {
 		restore_previous_locale();
 	}
@@ -2770,67 +2826,45 @@
 		return;
 	}
 
-	/* translators: Do not translate OLD_EMAIL, NEW_EMAIL, SITENAME, SITEURL: those are placeholders. */
-	$email_change_text = __(
-		'Hi,
-
-This notice confirms that the network admin email address was changed on ###SITENAME###.
-
-The new network admin email address is ###NEW_EMAIL###.
-
-This email has been sent to ###OLD_EMAIL###
-
-Regards,
-All at ###SITENAME###
-###SITEURL###'
-	);
-
-	$email_change_email = array(
-		'to'      => $old_email,
-		/* translators: Network admin email change notification email subject. %s: Network title. */
-		'subject' => __( '[%s] Network Admin Email Changed' ),
-		'message' => $email_change_text,
-		'headers' => '',
-	);
-	// Get network name.
-	$network_name = wp_specialchars_decode( get_site_option( 'site_name' ), ENT_QUOTES );
-
 	/**
-	 * Filters the contents of the email notification sent when the network admin email address is changed.
+	 * Filter removed
 	 *
-	 * @since 4.9.0
+	 * $email_change_email = apply_filters( 'network_admin_email_change_email', $email_change_email, $old_email, $new_email, $network_id );
 	 *
-	 * @param array $email_change_email {
-	 *            Used to build wp_mail().
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
 	 *
-	 *            @type string $to      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:
-	 *                - ###OLD_EMAIL### The old network admin email address.
-	 *                - ###NEW_EMAIL### The new network admin email address.
-	 *                - ###SITENAME###  The name of the network.
-	 *                - ###SITEURL###   The URL to the site.
-	 *            @type string $headers Headers.
-	 *        }
-	 * @param string $old_email  The old network admin email address.
-	 * @param string $new_email  The new network admin email address.
-	 * @param int    $network_id ID of the network.
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+	 *
 	 */
-	$email_change_email = apply_filters( 'network_admin_email_change_email', $email_change_email, $old_email, $new_email, $network_id );
 
-	$email_change_email['message'] = str_replace( '###OLD_EMAIL###', $old_email, $email_change_email['message'] );
-	$email_change_email['message'] = str_replace( '###NEW_EMAIL###', $new_email, $email_change_email['message'] );
-	$email_change_email['message'] = str_replace( '###SITENAME###', $network_name, $email_change_email['message'] );
-	$email_change_email['message'] = str_replace( '###SITEURL###', home_url(), $email_change_email['message'] );
+	$wp_mail = array(
+		'id' => 'network_admin_email_change',
+		'group' => 'network',
 
-	wp_mail(
-		$email_change_email['to'],
-		sprintf(
-			$email_change_email['subject'],
-			$network_name
+		'to' => $old_email,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( '[{{SITENAME}}] Network Admin Email Changed' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => __(
+'{{HEADER}}
+
+This notice confirms that the network admin email address was changed on {{SITENAME}}.
+
+The new network admin email address is {{NEW_EMAIL}}.
+
+This email has been sent to {{OLD_EMAIL}}.
+
+{{FOOTER}}'
 		),
-		$email_change_email['message'],
-		$email_change_email['headers']
+		'replacements' => array(
+			'{{SITENAME}}'  => get_site_option( 'site_name' ),
+			'{{NEW_EMAIL}}' => $new_email,
+			'{{OLD_EMAIL}}' => $old_email,
+		),
 	);
+
+	$wp_mailer = WP_Mailer::getInstance();
+	$wp_mailer->send( $wp_mail );
 }
Index: wp-includes/pluggable.php
===================================================================
--- wp-includes/pluggable.php	(revision 47320)
+++ wp-includes/pluggable.php	(working copy)
@@ -1560,141 +1560,166 @@
 			$emails = array_flip( $emails );
 		}
 
-		$switched_locale = switch_to_locale( get_locale() );
-
 		$comment_author_domain = '';
 		if ( WP_Http::is_ip_address( $comment->comment_author_IP ) ) {
 			$comment_author_domain = gethostbyaddr( $comment->comment_author_IP );
 		}
 
-		// 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.
-		$blogname        = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
-		$comment_content = wp_specialchars_decode( $comment->comment_content );
+		$from_email = 'wordpress@' . preg_replace( '#^www\.#', '', strtolower( $_SERVER['SERVER_NAME'] ) );
 
+		$switched_locale = switch_to_locale( get_locale() );
+
+		$notify_replacements = array (
+			'{{THE_TITLE}}' 	=> $post->post_title,
+
+			'{{COMMENT_TYPE}}' 	=> __( 'comment' ),
+
+			'{{COMMENT_AUTHOR}}' 	=> $comment->comment_author,
+			'{{REMOTEADDR}}' 	=> $comment->comment_author_IP,
+			'{{COMMENT_WEBSITE}}' 	=> esc_url_raw( $comment_author_domain ),
+			'{{COMMENT_URL}}' 	=> esc_url_raw( $comment->comment_author_url ),
+			'{{COMMENT_CONTENT}}' 	=> wp_specialchars_decode( $comment->comment_content ),
+			'{{COMMENTS_LINK}}' 	=> esc_url_raw( get_permalink( $comment->comment_post_ID ) . '#comments' ),
+			'{{COMMENT_LINK}}' 	=> esc_url_raw( get_comment_link( $comment ) ),
+
+			'{{APPROVELINK}}' 	=> esc_url_raw( admin_url( "comment.php?action=approve&c={$comment_id}#wpbody-content" ) ),
+			'{{SUPPRESSLINK}}' 	=> esc_url_raw( ( EMPTY_TRASH_DAYS ) ? admin_url( "comment.php?action=trash&c={$comment_id}#wpbody-content" ) : admin_url( "comment.php?action=delete&c={$comment_id}#wpbody-content" ) ),
+			'{{SPAMLINK}}' 		=> esc_url_raw( admin_url( "comment.php?action=spam&c={$comment_id}#wpbody-content" ) ),
+		);
+
+		$notify_message = array();
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		$notify_message[]  = __(
+'{{HEADER}}
+
+New {{COMMENT_TYPE}} on your post "{{THE_TITLE}}"
+
+Website: {{COMMENT_AUTHOR}} (IP address: {{REMOTEADDR}}, {{COMMENT_WEBSITE}})
+
+URL: {{COMMENT_URL}}
+
+Content: {{COMMENT_CONTENT}}' );
+
 		switch ( $comment->comment_type ) {
 			case 'trackback':
-				/* translators: %s: Post title. */
-				$notify_message = sprintf( __( 'New trackback on your post "%s"' ), $post->post_title ) . "\r\n";
-				/* translators: 1: Trackback/pingback website name, 2: Website IP address, 3: Website hostname. */
-				$notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
-				/* translators: %s: Trackback/pingback/comment author URL. */
-				$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
-				/* translators: %s: Comment text. */
-				$notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
-				$notify_message .= __( 'You can see all trackbacks on this post here:' ) . "\r\n";
-				/* translators: Trackback notification email subject. 1: Site title, 2: Post title. */
-				$subject = sprintf( __( '[%1$s] Trackback: "%2$s"' ), $blogname, $post->post_title );
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				$notify_subject = __( '[{{SITENAME}}] Trackback: "{{THE_TITLE}}"' );
+
+				$notify_message[] = '';
+				$notify_message[] = __( 'You can see all trackbacks on this post here:' );
+
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				$notify_replacements ['{{COMMENT_TYPE}}'] = __( 'trackback' );
 				break;
 
 			case 'pingback':
-				/* translators: %s: Post title. */
-				$notify_message = sprintf( __( 'New pingback on your post "%s"' ), $post->post_title ) . "\r\n";
-				/* translators: 1: Trackback/pingback website name, 2: Website IP address, 3: Website hostname. */
-				$notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
-				/* translators: %s: Trackback/pingback/comment author URL. */
-				$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
-				/* translators: %s: Comment text. */
-				$notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
-				$notify_message .= __( 'You can see all pingbacks on this post here:' ) . "\r\n";
-				/* translators: Pingback notification email subject. 1: Site title, 2: Post title. */
-				$subject = sprintf( __( '[%1$s] Pingback: "%2$s"' ), $blogname, $post->post_title );
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				$notify_subject = __( '[{{SITENAME}}] Pingback: "{{THE_TITLE}}"' );
+
+				$notify_message[] = '';
+				$notify_message[] = __( 'You can see all pingbacks on this post here:' );
+
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				$notify_replacements ['{{COMMENT_TYPE}}'] = __( 'pingback' );
 				break;
 
 			default: // Comments.
-				/* translators: %s: Post title. */
-				$notify_message = sprintf( __( 'New comment on your post "%s"' ), $post->post_title ) . "\r\n";
-				/* translators: 1: Comment author's name, 2: Comment author's IP address, 3: Comment author's hostname. */
-				$notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
-				/* translators: %s: Comment author email. */
-				$notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
-				/* translators: %s: Trackback/pingback/comment author URL. */
-				$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
 
-				if ( $comment->comment_parent && user_can( $post->post_author, 'edit_comment', $comment->comment_parent ) ) {
-					/* translators: Comment moderation. %s: Parent comment edit URL. */
-					$notify_message .= sprintf( __( 'In reply to: %s' ), admin_url( "comment.php?action=editcomment&c={$comment->comment_parent}#wpbody-content" ) ) . "\r\n";
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				$notify_subject = __( '[{{SITENAME}}] Comment: "{{THE_TITLE}}"' );
+
+				$notify_message = array();
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				$notify_message[]  = __(
+'{{HEADER}}
+
+New {{COMMENT_TYPE}} on your post "{{THE_TITLE}}"
+
+Website: {{COMMENT_AUTHOR}} (IP address: {{REMOTEADDR}}, {{COMMENT_WEBSITE}})
+
+Email: {{COMMENT_EMAIL}}
+URL: {{COMMENT_URL}}' );
+				$notify_replacements ['{{COMMENT_EMAIL}}'] = $comment->comment_author_email;
+
+				if ( $comment->comment_parent ) {
+					/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+					$notify_message[] =  __( 'In reply to: {{ADMINURL}}' );
+					$notify_replacements ['{{ADMINURL}}'] = esc_url_raw( admin_url( "comment.php?action=editcomment&c={$comment->comment_parent}#wpbody-content" ) );
 				}
 
-				/* translators: %s: Comment text. */
-				$notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
-				$notify_message .= __( 'You can see all comments on this post here:' ) . "\r\n";
-				/* translators: Comment notification email subject. 1: Site title, 2: Post title. */
-				$subject = sprintf( __( '[%1$s] Comment: "%2$s"' ), $blogname, $post->post_title );
+				$notify_message[] = '';
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				$notify_message[] = __( 'Comment: {{COMMENT_CONTENT}}' );
+				$notify_message[] = '';
+				$notify_message[] = __( 'You can see all comments on this post here:' );
 				break;
 		}
 
-		$notify_message .= get_permalink( $comment->comment_post_ID ) . "#comments\r\n\r\n";
-		/* translators: %s: Comment URL. */
-		$notify_message .= sprintf( __( 'Permalink: %s' ), get_comment_link( $comment ) ) . "\r\n";
 
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		$notify_message[] = '{{COMMENTS_LINK}}';
+		$notify_message[] = '';
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		$notify_message[] = __( 'Permalink: {{COMMENT_LINK}}' );
+
 		if ( user_can( $post->post_author, 'edit_comment', $comment->comment_ID ) ) {
+
 			if ( EMPTY_TRASH_DAYS ) {
-				/* translators: Comment moderation. %s: Comment action URL. */
-				$notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				$notify_message[] = __( 'Trash it: {{SUPPRESSLINK}}' );
 			} else {
-				/* translators: Comment moderation. %s: Comment action URL. */
-				$notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				$notify_message[] = __( 'Delete it: {{SUPPRESSLINK}}' );
 			}
-			/* translators: Comment moderation. %s: Comment action URL. */
-			$notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
-		}
 
-		$wp_email = 'wordpress@' . preg_replace( '#^www\.#', '', strtolower( $_SERVER['SERVER_NAME'] ) );
-
-		if ( '' == $comment->comment_author ) {
-			$from = "From: \"$blogname\" <$wp_email>";
-			if ( '' != $comment->comment_author_email ) {
-				$reply_to = "Reply-To: $comment->comment_author_email";
-			}
-		} else {
-			$from = "From: \"$comment->comment_author\" <$wp_email>";
-			if ( '' != $comment->comment_author_email ) {
-				$reply_to = "Reply-To: \"$comment->comment_author_email\" <$comment->comment_author_email>";
-			}
+			/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+			$notify_message[] = __( 'Spam it: {{SPAMLINK}}' );
 		}
 
-		$message_headers = "$from\n"
-		. 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n";
+		$notify_message[] = '';
+		$notify_message[] = '{{FOOTER}}';
 
-		if ( isset( $reply_to ) ) {
-			$message_headers .= $reply_to . "\n";
-		}
 
-		/**
-		 * Filters the comment notification email text.
-		 *
-		 * @since 1.5.2
-		 *
-		 * @param string $notify_message The comment notification email text.
-		 * @param int    $comment_id     Comment ID.
-		 */
-		$notify_message = apply_filters( 'comment_notification_text', $notify_message, $comment->comment_ID );
 
 		/**
-		 * Filters the comment notification email subject.
+		 * Filter removed
 		 *
-		 * @since 1.5.2
+		 * $notify_message = apply_filters( 'comment_notification_text', $notify_message, $comment->comment_ID );
+		 * $subject = apply_filters( 'comment_notification_subject', $subject, $comment->comment_ID );
+		 * $message_headers = apply_filters( 'comment_notification_headers', $message_headers, $comment->comment_ID );
 		 *
-		 * @param string $subject    The comment notification email subject.
-		 * @param int    $comment_id Comment ID.
-		 */
-		$subject = apply_filters( 'comment_notification_subject', $subject, $comment->comment_ID );
-
-		/**
-		 * Filters the comment notification email headers.
+		 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
 		 *
-		 * @since 1.5.2
+		 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+		 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+		 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
 		 *
-		 * @param string $message_headers Headers for the comment notification email.
-		 * @param int    $comment_id      Comment ID.
 		 */
-		$message_headers = apply_filters( 'comment_notification_headers', $message_headers, $comment->comment_ID );
 
-		foreach ( $emails as $email ) {
-			wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
+		$from_email = 'wordpress@' . preg_replace( '#^www\.#', '', strtolower( $_SERVER['SERVER_NAME'] ) );
+
+		$wp_mail = array(
+			'id' => 'comment_notification',
+			'group' => 'blog',
+
+			'to' => $emails,
+			/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+			'subject' => $notify_subject,
+			'message' => implode( "\r\n", $notify_message ),
+			'headers' => array(
+				'From' => ( '' == $comment->comment_author ) ? "{$blogname} <{$from_email}>" : "{$comment->comment_author} <{$from_email}>",
+				'Content-Type' => 'text/plain; charset="' . get_option( 'blog_charset' ) . '"',
+			),
+			'replacements' => $notify_replacements,
+		);
+
+		if ( '' != $comment->comment_author_email ) {
+                        $wp_mail['headers']['Reply-To'] =  "{$comment->comment_author_email} <{$comment->comment_author_email}>";
 		}
 
+		$wp_mailer = WP_Mailer::getInstance();
+		$wp_mailer->send( $wp_mail );
+
 		if ( $switched_locale ) {
 			restore_previous_locale();
 		}
@@ -1747,6 +1772,16 @@
 			}
 		}
 
+		/**
+		 * Filters the list of recipients for comment moderation emails.
+		 *
+		 * @since 3.7.0
+		 *
+		 * @param string[] $emails     List of email addresses to notify for comment moderation.
+		 * @param int      $comment_id Comment ID.
+		 */
+		$emails = apply_filters( 'comment_moderation_recipients', $emails, $comment_id );
+
 		$switched_locale = switch_to_locale( get_locale() );
 
 		$comment_author_domain = '';
@@ -1756,70 +1791,88 @@
 
 		$comments_waiting = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_approved = '0'" );
 
-		// 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.
-		$blogname        = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
-		$comment_content = wp_specialchars_decode( $comment->comment_content );
+		$notify_replacements = array (
+			'{{THE_TITLE}}' 	=> $post->post_title,
 
+			'{{COMMENT_TYPE}}' 	=> __( 'comment' ),
+
+			'{{COMMENT_AUTHOR}}' 	=> $comment->comment_author,
+			'{{REMOTEADDR}}' 	=> $comment->comment_author_IP,
+			'{{COMMENT_WEBSITE}}' 	=> esc_url_raw( $comment_author_domain ),
+			'{{COMMENT_URL}}' 	=> esc_url_raw( $comment->comment_author_url ),
+			'{{COMMENT_CONTENT}}' 	=> wp_specialchars_decode( $comment->comment_content ),
+			'{{COMMENT_LINK}}' 	=> esc_url_raw( get_permalink( $comment->comment_post_ID ) ),
+
+			'{{APPROVELINK}}' 	=> esc_url_raw( admin_url( "comment.php?action=approve&c={$comment_id}#wpbody-content" ) ),
+			'{{SUPPRESSLINK}}' 	=> esc_url_raw( ( EMPTY_TRASH_DAYS ) ? admin_url( "comment.php?action=trash&c={$comment_id}#wpbody-content" ) : admin_url( "comment.php?action=delete&c={$comment_id}#wpbody-content" ) ),
+			'{{SPAMLINK}}' 		=> esc_url_raw( admin_url( "comment.php?action=spam&c={$comment_id}#wpbody-content" ) ),
+		);
+
+		$notify_message = array();
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		$notify_message[]  = __(
+'{{HEADER}}
+
+A new {{COMMENT_TYPE}} on the post "{{THE_TITLE}}" is waiting for your approval
+{{COMMENT_LINK}}
+
+Website: {{COMMENT_AUTHOR}} (IP address: {{REMOTEADDR}}, {{COMMENT_WEBSITE}})
+
+URL: {{COMMENT_URL}}
+
+Content: {{COMMENT_CONTENT}}' );
+
 		switch ( $comment->comment_type ) {
 			case 'trackback':
-				/* translators: %s: Post title. */
-				$notify_message  = sprintf( __( 'A new trackback on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
-				$notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
-				/* translators: 1: Trackback/pingback website name, 2: Website IP address, 3: Website hostname. */
-				$notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
-				/* translators: %s: Trackback/pingback/comment author URL. */
-				$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
-				$notify_message .= __( 'Trackback excerpt: ' ) . "\r\n" . $comment_content . "\r\n\r\n";
+				$notify_replacements ['{{COMMENT_TYPE}}'] = __( 'trackback' );
 				break;
 
 			case 'pingback':
-				/* translators: %s: Post title. */
-				$notify_message  = sprintf( __( 'A new pingback on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
-				$notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
-				/* translators: 1: Trackback/pingback website name, 2: Website IP address, 3: Website hostname. */
-				$notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
-				/* translators: %s: Trackback/pingback/comment author URL. */
-				$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
-				$notify_message .= __( 'Pingback excerpt: ' ) . "\r\n" . $comment_content . "\r\n\r\n";
+				$notify_replacements ['{{COMMENT_TYPE}}'] = __( 'pingback' );
 				break;
 
 			default: // Comments.
-				/* translators: %s: Post title. */
-				$notify_message  = sprintf( __( 'A new comment on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
-				$notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
-				/* translators: 1: Comment author's name, 2: Comment author's IP address, 3: Comment author's hostname. */
-				$notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
-				/* translators: %s: Comment author email. */
-				$notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
-				/* translators: %s: Trackback/pingback/comment author URL. */
-				$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
+				$notify_message = array();
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				$notify_message[]  = __(
+'{{HEADER}}
 
+A new {{COMMENT_TYPE}} on the post "{{THE_TITLE}}" is waiting for your approval
+{{APPROVELINK}}
+
+Website: {{COMMENT_AUTHOR}} (IP address: {{REMOTEADDR}}, {{COMMENT_WEBSITE}})
+
+Email: {{COMMENT_EMAIL}}
+URL: {{COMMENT_URL}}' );
+				$notify_replacements ['{{COMMENT_EMAIL}}'] = $comment->comment_author_email;
+
 				if ( $comment->comment_parent ) {
-					/* translators: Comment moderation. %s: Parent comment edit URL. */
-					$notify_message .= sprintf( __( 'In reply to: %s' ), admin_url( "comment.php?action=editcomment&c={$comment->comment_parent}#wpbody-content" ) ) . "\r\n";
+					/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+					$notify_message[] =  __( 'In reply to: {{ADMINURL}}' ) . "\r\n";
+					$notify_replacements ['{{ADMINURL}}'] = esc_url_raw( admin_url( "comment.php?action=editcomment&c={$comment->comment_parent}#wpbody-content" ) );
 				}
 
-				/* translators: %s: Comment text. */
-				$notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				$notify_message[] = __( 'Comment: {{COMMENT_CONTENT}}' );
+				$notify_message[] = '';
 				break;
 		}
 
-		/* translators: Comment moderation. %s: Comment action URL. */
-		$notify_message .= sprintf( __( 'Approve it: %s' ), admin_url( "comment.php?action=approve&c={$comment_id}#wpbody-content" ) ) . "\r\n";
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		$notify_message[] = __( 'Approve it: {{APPROVELINK}}' );
 
 		if ( EMPTY_TRASH_DAYS ) {
-			/* translators: Comment moderation. %s: Comment action URL. */
-			$notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment_id}#wpbody-content" ) ) . "\r\n";
+			/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+			$notify_message[] = __( 'Trash it: {{SUPPRESSLINK}}' );
 		} else {
-			/* translators: Comment moderation. %s: Comment action URL. */
-			$notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment_id}#wpbody-content" ) ) . "\r\n";
+			/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+			$notify_message[] = __( 'Delete it: {{SUPPRESSLINK}}' );
 		}
 
-		/* translators: Comment moderation. %s: Comment action URL. */
-		$notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment_id}#wpbody-content" ) ) . "\r\n";
-
-		$notify_message .= sprintf(
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		$notify_message[] = __( 'Spam it: {{SPAMLINK}}' );
+		$notify_message[] = '';
+		$notify_message[] = sprintf(
 			/* translators: Comment moderation. %s: Number of comments awaiting approval. */
 			_n(
 				'Currently %s comment is waiting for approval. Please visit the moderation panel:',
@@ -1827,56 +1880,39 @@
 				$comments_waiting
 			),
 			number_format_i18n( $comments_waiting )
-		) . "\r\n";
-		$notify_message .= admin_url( 'edit-comments.php?comment_status=moderated#wpbody-content' ) . "\r\n";
-
-		/* translators: Comment moderation notification email subject. 1: Site title, 2: Post title. */
-		$subject         = sprintf( __( '[%1$s] Please moderate: "%2$s"' ), $blogname, $post->post_title );
-		$message_headers = '';
-
+		);
+		$notify_message[] = admin_url( 'edit-comments.php?comment_status=moderated#wpbody-content' );
+		$notify_message[] = '';
+		$notify_message[] = '{{FOOTER}}';
+		
 		/**
-		 * Filters the list of recipients for comment moderation emails.
+		 * Filters removed
 		 *
-		 * @since 3.7.0
+		 * $notify_message = apply_filters( 'comment_moderation_text', $notify_message, $comment_id );
+		 * $subject = apply_filters( 'comment_moderation_subject', $subject, $comment_id );
+		 * $message_headers = apply_filters( 'comment_moderation_headers', $message_headers, $comment_id );
 		 *
-		 * @param string[] $emails     List of email addresses to notify for comment moderation.
-		 * @param int      $comment_id Comment ID.
-		 */
-		$emails = apply_filters( 'comment_moderation_recipients', $emails, $comment_id );
-
-		/**
-		 * Filters the comment moderation email text.
+		 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
 		 *
-		 * @since 1.5.2
+		 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+		 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+		 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
 		 *
-		 * @param string $notify_message Text of the comment moderation email.
-		 * @param int    $comment_id     Comment ID.
 		 */
-		$notify_message = apply_filters( 'comment_moderation_text', $notify_message, $comment_id );
 
-		/**
-		 * Filters the comment moderation email subject.
-		 *
-		 * @since 1.5.2
-		 *
-		 * @param string $subject    Subject of the comment moderation email.
-		 * @param int    $comment_id Comment ID.
-		 */
-		$subject = apply_filters( 'comment_moderation_subject', $subject, $comment_id );
+		$wp_mail = array(
+			'id' => 'comment_moderation',
+			'group' => 'blog',
 
-		/**
-		 * Filters the comment moderation email headers.
-		 *
-		 * @since 2.8.0
-		 *
-		 * @param string $message_headers Headers for the comment moderation email.
-		 * @param int    $comment_id      Comment ID.
-		 */
-		$message_headers = apply_filters( 'comment_moderation_headers', $message_headers, $comment_id );
+			'to' => $emails,
+			/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+			'subject' => __( '[{{SITENAME}}] Please moderate: "{{THE_TITLE}}"' ),
+			'message' => implode( "\r\n", $notify_message ),
+			'replacements' => $notify_replacements,
+		);
 
-		foreach ( $emails as $email ) {
-			wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
-		}
+		$wp_mailer = WP_Mailer::getInstance();
+		$wp_mailer->send( $wp_mail );
 
 		if ( $switched_locale ) {
 			restore_previous_locale();
@@ -1898,44 +1934,43 @@
 		// Send a copy of password change notification to the admin,
 		// but check to see if it's the admin whose password we're changing, and skip this.
 		if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) ) {
-			/* translators: %s: User name. */
-			$message = sprintf( __( 'Password changed for user: %s' ), $user->user_login ) . "\r\n";
-			// 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.
-			$blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
-
-			$wp_password_change_notification_email = array(
-				'to'      => get_option( 'admin_email' ),
-				/* translators: Password change notification email subject. %s: Site title. */
-				'subject' => __( '[%s] Password Changed' ),
-				'message' => $message,
-				'headers' => '',
-			);
-
+			
 			/**
-			 * Filters the contents of the password change notification email sent to the site admin.
+			 * Filter removed
 			 *
-			 * @since 4.9.0
+			 * $wp_password_change_notification_email = apply_filters( 'wp_password_change_notification_email', $wp_password_change_notification_email, $user, $blogname );
 			 *
-			 * @param array   $wp_password_change_notification_email {
-			 *     Used to build wp_mail().
+			 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
 			 *
-			 *     @type string $to      The intended recipient - site admin 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.
-			 * }
-			 * @param WP_User $user     User object for user whose password was changed.
-			 * @param string  $blogname The site title.
+			 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+			 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+			 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+			 *
 			 */
-			$wp_password_change_notification_email = apply_filters( 'wp_password_change_notification_email', $wp_password_change_notification_email, $user, $blogname );
 
-			wp_mail(
-				$wp_password_change_notification_email['to'],
-				wp_specialchars_decode( sprintf( $wp_password_change_notification_email['subject'], $blogname ) ),
-				$wp_password_change_notification_email['message'],
-				$wp_password_change_notification_email['headers']
+			$wp_mail = array(
+				'id' => 'wp_password_change_notification',
+				'group' => 'admin',
+
+				'to' => get_option( 'admin_email' ),
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				'subject' => __( '[{{SITENAME}}] Password Changed' ),
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				'message' => __(
+'{{HEADER}}
+
+Password changed for user: {{USERNAME}}
+
+{{FOOTER}}'
+				),
+				'replacements' => array(
+					'{{USERNAME}}' => $user->user_login,
+				),
 			);
+
+			$wp_mailer = WP_Mailer::getInstance();
+			$wp_mailer->send( $wp_mail );
+
 		}
 	}
 endif;
@@ -1968,53 +2003,50 @@
 
 		$user = get_userdata( $user_id );
 
-		// 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.
-		$blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
-
 		if ( 'user' !== $notify ) {
 			$switched_locale = switch_to_locale( get_locale() );
 
-			/* translators: %s: Site title. */
-			$message = sprintf( __( 'New user registration on your site %s:' ), $blogname ) . "\r\n\r\n";
-			/* translators: %s: User login. */
-			$message .= sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
-			/* translators: %s: User email address. */
-			$message .= sprintf( __( 'Email: %s' ), $user->user_email ) . "\r\n";
-
-			$wp_new_user_notification_email_admin = array(
-				'to'      => get_option( 'admin_email' ),
-				/* translators: New user registration notification email subject. %s: Site title. */
-				'subject' => __( '[%s] New User Registration' ),
-				'message' => $message,
-				'headers' => '',
-			);
-
 			/**
-			 * Filters the contents of the new user notification email sent to the site admin.
+			 * Filter removed
 			 *
-			 * @since 4.9.0
+			 * $wp_new_user_notification_email_admin = apply_filters( 'wp_new_user_notification_email_admin', $wp_new_user_notification_email_admin, $user, $blogname );
 			 *
-			 * @param array   $wp_new_user_notification_email_admin {
-			 *     Used to build wp_mail().
+			 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
 			 *
-			 *     @type string $to      The intended recipient - site admin 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.
-			 * }
-			 * @param WP_User $user     User object for new user.
-			 * @param string  $blogname The site title.
+			 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+			 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+			 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+			 *
 			 */
-			$wp_new_user_notification_email_admin = apply_filters( 'wp_new_user_notification_email_admin', $wp_new_user_notification_email_admin, $user, $blogname );
 
-			wp_mail(
-				$wp_new_user_notification_email_admin['to'],
-				wp_specialchars_decode( sprintf( $wp_new_user_notification_email_admin['subject'], $blogname ) ),
-				$wp_new_user_notification_email_admin['message'],
-				$wp_new_user_notification_email_admin['headers']
+			$wp_mail = array(
+				'id' => 'new_user_notification',
+				'group' => 'admin',
+
+				'to' => get_option( 'admin_email' ),
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				'subject' => __( '[{{SITENAME}}] New User Registration' ),
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				'message' => __(
+'{{HEADER}}
+
+New user registration on your site {{SITENAME}}:
+
+Username: {{USERNAME}}
+
+Email: {{EMAIL}}
+
+{{FOOTER}}'
+				),
+				'replacements' => array(
+					'{{USERNAME}}' => $user->user_login,
+					'{{EMAIL}}' => $user->user_email,
+				),
 			);
 
+			$wp_mailer = WP_Mailer::getInstance();
+			$wp_mailer->send( $wp_mail );
+
 			if ( $switched_locale ) {
 				restore_previous_locale();
 			}
@@ -2031,47 +2063,49 @@
 		}
 
 		$switched_locale = switch_to_locale( get_user_locale( $user ) );
-
-		/* translators: %s: User login. */
-		$message  = sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
-		$message .= __( 'To set your password, visit the following address:' ) . "\r\n\r\n";
-		$message .= network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user->user_login ), 'login' ) . "\r\n\r\n";
-
-		$message .= wp_login_url() . "\r\n";
-
-		$wp_new_user_notification_email = array(
-			'to'      => $user->user_email,
-			/* translators: Login details notification email subject. %s: Site title. */
-			'subject' => __( '[%s] Login Details' ),
-			'message' => $message,
-			'headers' => '',
-		);
-
+		
 		/**
-		 * Filters the contents of the new user notification email sent to the new user.
+		 * Filter removed
 		 *
-		 * @since 4.9.0
+		 * $wp_new_user_notification_email = apply_filters( 'wp_new_user_notification_email', $wp_new_user_notification_email, $user, $blogname );
 		 *
-		 * @param array   $wp_new_user_notification_email {
-		 *     Used to build wp_mail().
+		 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
 		 *
-		 *     @type string $to      The intended recipient - New 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.
-		 * }
-		 * @param WP_User $user     User object for new user.
-		 * @param string  $blogname The site title.
+		 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+		 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+		 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+		 *
 		 */
-		$wp_new_user_notification_email = apply_filters( 'wp_new_user_notification_email', $wp_new_user_notification_email, $user, $blogname );
 
-		wp_mail(
-			$wp_new_user_notification_email['to'],
-			wp_specialchars_decode( sprintf( $wp_new_user_notification_email['subject'], $blogname ) ),
-			$wp_new_user_notification_email['message'],
-			$wp_new_user_notification_email['headers']
+		$wp_mail = array(
+			'id' => 'new_user',
+			'group' => 'blog',
+
+			'to' => $user->user_email,
+			/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+			'subject' => __( '[{{SITENAME}}] Login Details' ),
+			/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+			'message' => __(
+'{{HEADER}}
+
+Username: {{USERNAME}}
+
+To set your password, visit the following address:
+{{PASSWORDLINK}}
+
+{{LOGINLINK}}
+
+{{FOOTER}}'
+			),
+			'replacements' => array(
+				'{{USERNAME}}' => $user->user_login,
+				'{{PASSWORDLINK}}' => esc_url_raw( network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user->user_login ), 'login' ) ),
+				'{{LOGINLINK}}' => esc_url_raw( wp_login_url() ),
+			),
 		);
 
+		$wp_mailer = WP_Mailer::getInstance();
+		$wp_mailer->send( $wp_mail );
 		if ( $switched_locale ) {
 			restore_previous_locale();
 		}
Index: wp-includes/user.php
===================================================================
--- wp-includes/user.php	(revision 47320)
+++ wp-includes/user.php	(working copy)
@@ -1996,8 +1996,6 @@
 
 	if ( ! is_wp_error( $user_id ) ) {
 
-		$blog_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
-
 		$switched_locale = false;
 		if ( ! empty( $send_password_change_email ) || ! empty( $send_email_change_email ) ) {
 			$switched_locale = switch_to_locale( get_user_locale( $user_id ) );
@@ -2004,119 +2002,96 @@
 		}
 
 		if ( ! empty( $send_password_change_email ) ) {
-			/* translators: Do not translate USERNAME, ADMIN_EMAIL, EMAIL, SITENAME, SITEURL: those are placeholders. */
-			$pass_change_text = __(
-				'Hi ###USERNAME###,
 
-This notice confirms that your password was changed on ###SITENAME###.
+			/**
+			 * Filter removed
+			 *
+			 * $pass_change_email = apply_filters( 'password_change_email', $pass_change_email, $user, $userdata );
+			 *
+			 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
+			 *
+			 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+			 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+			 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+			 *
+			 */
 
+			$wp_mail = array(
+				'id' => 'password_change',
+				'group' => 'blog',
+
+				'to' => $user['user_email'],
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				'subject' => __( '[{{SITENAME}}] Password Changed' ),
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				'message' => __(
+'{{HEADER}}
+
+As {{USERNAME}}, this notice confirms that your password was changed on {{SITENAME}}.
+
 If you did not change your password, please contact the Site Administrator at
-###ADMIN_EMAIL###
+{{ADMIN_EMAIL}}
 
-This email has been sent to ###EMAIL###
+This email has been sent to {{EMAIL}}
 
-Regards,
-All at ###SITENAME###
-###SITEURL###'
+{{FOOTER}}'
+				),
+				'replacements' => array(
+					'{{USERNAME}}'	=> $user['user_login'],
+					'{{ADMIN_EMAIL}}' => get_option( 'admin_email' ),
+					'{{EMAIL}}'	=> $user['user_email'],
+				),
 			);
 
-			$pass_change_email = array(
-				'to'      => $user['user_email'],
-				/* translators: Password change notification email subject. %s: Site title. */
-				'subject' => __( '[%s] Password Changed' ),
-				'message' => $pass_change_text,
-				'headers' => '',
-			);
+			$wp_mailer = WP_Mailer::getInstance();
+			$wp_mailer->send( $wp_mail );
+		}
 
+		if ( ! empty( $send_email_change_email ) ) {
+
 			/**
-			 * Filters the contents of the email sent when the user's password is changed.
+			 * Filters removed
 			 *
-			 * @since 4.3.0
+			 * $email_change_email = apply_filters( 'email_change_email', $email_change_email, $user, $userdata );
 			 *
-			 * @param array $pass_change_email {
-			 *            Used to build wp_mail().
-			 *            @type string $to      The intended recipients. Add emails in a comma separated string.
-			 *            @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 current user's username.
-			 *                - ###ADMIN_EMAIL### The admin email in case this was unexpected.
-			 *                - ###EMAIL###       The user's email address.
-			 *                - ###SITENAME###    The name of the site.
-			 *                - ###SITEURL###     The URL to the site.
-			 *            @type string $headers Headers. Add headers in a newline (\r\n) separated string.
-			 *        }
-			 * @param array $user     The original user array.
-			 * @param array $userdata The updated user array.
+			 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
+			 *
+			 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+			 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+			 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+			 *
 			 */
-			$pass_change_email = apply_filters( 'password_change_email', $pass_change_email, $user, $userdata );
 
-			$pass_change_email['message'] = str_replace( '###USERNAME###', $user['user_login'], $pass_change_email['message'] );
-			$pass_change_email['message'] = str_replace( '###ADMIN_EMAIL###', get_option( 'admin_email' ), $pass_change_email['message'] );
-			$pass_change_email['message'] = str_replace( '###EMAIL###', $user['user_email'], $pass_change_email['message'] );
-			$pass_change_email['message'] = str_replace( '###SITENAME###', $blog_name, $pass_change_email['message'] );
-			$pass_change_email['message'] = str_replace( '###SITEURL###', home_url(), $pass_change_email['message'] );
+			$wp_mail = array(
+				'id' => 'email_change',
+				'group' => 'blog',
 
-			wp_mail( $pass_change_email['to'], sprintf( $pass_change_email['subject'], $blog_name ), $pass_change_email['message'], $pass_change_email['headers'] );
-		}
+				'to' => $user['user_email'],
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				'subject' => __( '[{{SITENAME}}] Email Changed' ),
+				/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+				'message' => __(
+'{{HEADER}}
 
-		if ( ! empty( $send_email_change_email ) ) {
-			/* translators: Do not translate USERNAME, ADMIN_EMAIL, NEW_EMAIL, EMAIL, SITENAME, SITEURL: those are placeholders. */
-			$email_change_text = __(
-				'Hi ###USERNAME###,
+As {{USERNAME}}, this notice confirms that your email address was changed on {{SITENAME}} to {{NEW_EMAIL}}.
 
-This notice confirms that your email address on ###SITENAME### was changed to ###NEW_EMAIL###.
+If you did not change your password, please contact the Site Administrator at
+{{ADMIN_EMAIL}}
 
-If you did not change your email, please contact the Site Administrator at
-###ADMIN_EMAIL###
+This email has been sent to {{EMAIL}}
 
-This email has been sent to ###EMAIL###
-
-Regards,
-All at ###SITENAME###
-###SITEURL###'
+{{FOOTER}}'
+				),
+				'replacements' => array(
+					'{{USERNAME}}'	=> $user['user_login'],
+					'{{ADMIN_EMAIL}}' => get_option( 'admin_email' ),
+					'{{EMAIL}}'	=> $user['user_email'],
+					'{{NEW_EMAIL}}'	=> $userdata['user_email'],
+				),
 			);
 
-			$email_change_email = array(
-				'to'      => $user['user_email'],
-				/* translators: Email change notification email subject. %s: Site title. */
-				'subject' => __( '[%s] Email Changed' ),
-				'message' => $email_change_text,
-				'headers' => '',
-			);
-
-			/**
-			 * Filters the contents of the email sent when the user's email is changed.
-			 *
-			 * @since 4.3.0
-			 *
-			 * @param array $email_change_email {
-			 *            Used to build wp_mail().
-			 *            @type string $to      The intended recipients.
-			 *            @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 current user's username.
-			 *                - ###ADMIN_EMAIL### The admin email in case this was unexpected.
-			 *                - ###NEW_EMAIL###   The new email address.
-			 *                - ###EMAIL###       The old email address.
-			 *                - ###SITENAME###    The name of the site.
-			 *                - ###SITEURL###     The URL to the site.
-			 *            @type string $headers Headers.
-			 *        }
-			 * @param array $user The original user array.
-			 * @param array $userdata The updated user array.
-			 */
-			$email_change_email = apply_filters( 'email_change_email', $email_change_email, $user, $userdata );
-
-			$email_change_email['message'] = str_replace( '###USERNAME###', $user['user_login'], $email_change_email['message'] );
-			$email_change_email['message'] = str_replace( '###ADMIN_EMAIL###', get_option( 'admin_email' ), $email_change_email['message'] );
-			$email_change_email['message'] = str_replace( '###NEW_EMAIL###', $userdata['user_email'], $email_change_email['message'] );
-			$email_change_email['message'] = str_replace( '###EMAIL###', $user['user_email'], $email_change_email['message'] );
-			$email_change_email['message'] = str_replace( '###SITENAME###', $blog_name, $email_change_email['message'] );
-			$email_change_email['message'] = str_replace( '###SITEURL###', home_url(), $email_change_email['message'] );
-
-			wp_mail( $email_change_email['to'], sprintf( $email_change_email['subject'], $blog_name ), $email_change_email['message'], $email_change_email['headers'] );
+			$wp_mailer = WP_Mailer::getInstance();
+			$wp_mailer->send( $wp_mail );
 		}
 
 		if ( $switched_locale ) {
@@ -2829,59 +2804,52 @@
 		);
 		update_user_meta( $current_user->ID, '_new_email', $new_user_email );
 
-		$sitename = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
+		/**
+		 * Filters removed
+		 *
+		 * $content = apply_filters( 'new_user_email_content', $email_text, $new_user_email );
+		 *
+		 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
+		 *
+		 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+		 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+		 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+		 *
+		 */
 
-		/* translators: Do not translate USERNAME, ADMIN_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */
-		$email_text = __(
-			'Howdy ###USERNAME###,
+		$wp_mail = array(
+			'id' => 'new_user_email',
+			'group' => 'blog',
 
-You recently requested to have the email address on your account changed.
+			'to' => $_POST['email'],
+			/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+			'subject' => __( '[{{SITENAME}}] Email Change Request' ),
+			/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+			'message' => __(
+'{{HEADER}}
 
+As {{USERNAME}}, you recently requested to have the email address on your account changed.
+
 If this is correct, please click on the following link to change it:
-###ADMIN_URL###
+{{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###
+This email has been sent to {{EMAIL}}
 
-Regards,
-All at ###SITENAME###
-###SITEURL###'
+{{FOOTER}}'
+			),
+			'replacements' => array(
+				'{{USERNAME}}'	=> $current_user->user_login,
+				'{{ADMIN_URL}}' => esc_url_raw( admin_url( 'profile.php?newuseremail=' . $hash ) ),
+				'{{EMAIL}}'	=> $_POST['email'],
+			),
 		);
 
-		/**
-		 * Filters the text of the email sent when a change of user 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 new email.
-		 * ###SITENAME###  The name of the site.
-		 * ###SITEURL###   The URL to the site.
-		 *
-		 * @since MU (3.0.0)
-		 * @since 4.9.0 This filter is no longer Multisite specific.
-		 *
-		 * @param string $email_text     Text in the email.
-		 * @param array  $new_user_email {
-		 *     Data relating to the new user email address.
-		 *
-		 *     @type string $hash     The secure hash used in the confirmation link URL.
-		 *     @type string $newemail The proposed new email address.
-		 * }
-		 */
-		$content = apply_filters( 'new_user_email_content', $email_text, $new_user_email );
+		$wp_mailer = WP_Mailer::getInstance();
+		$wp_mailer->send( $wp_mail );
 
-		$content = str_replace( '###USERNAME###', $current_user->user_login, $content );
-		$content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'profile.php?newuseremail=' . $hash ) ), $content );
-		$content = str_replace( '###EMAIL###', $_POST['email'], $content );
-		$content = str_replace( '###SITENAME###', $sitename, $content );
-		$content = str_replace( '###SITEURL###', home_url(), $content );
-
-		/* translators: New email address notification email subject. %s: Site title. */
-		wp_mail( $_POST['email'], sprintf( __( '[%s] Email Change Request' ), $sitename ), $content );
-
 		$_POST['email'] = $current_user->user_email;
 	}
 }
@@ -3188,6 +3156,7 @@
 		return;
 	}
 
+	$manage_url = '';
 	if ( 'export_personal_data' === $request->action_name ) {
 		$manage_url = admin_url( 'export-personal-data.php' );
 	} elseif ( 'remove_personal_data' === $request->action_name ) {
@@ -3196,139 +3165,52 @@
 	$action_description = wp_user_request_action_description( $request->action_name );
 
 	/**
-	 * Filters the recipient of the data request confirmation notification.
+	 * Filters removed
 	 *
-	 * In a Multisite environment, this will default to the email address of the
-	 * network admin because, by default, single site admins do not have the
-	 * capabilities required to process requests. Some networks may wish to
-	 * delegate those capabilities to a single-site admin, or a dedicated person
-	 * responsible for managing privacy requests.
+	 * $admin_email = apply_filters( 'user_request_confirmed_email_to', get_site_option( 'admin_email' ), $request );
+	 * $content = apply_filters( 'user_confirmed_action_email_content', $email_text, $email_data );
+	 * $subject = apply_filters( 'user_request_confirmed_email_subject', $subject, $email_data['sitename'], $email_data );
+	 * $headers = apply_filters( 'user_request_confirmed_email_headers', $headers, $subject, $content, $request_id, $email_data );
 	 *
-	 * @since 4.9.6
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
 	 *
-	 * @param string          $admin_email The email address of the notification recipient.
-	 * @param WP_User_Request $request     The request that is initiating the notification.
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
+	 *
 	 */
-	$admin_email = apply_filters( 'user_request_confirmed_email_to', get_site_option( 'admin_email' ), $request );
 
-	$email_data = array(
-		'request'     => $request,
-		'user_email'  => $request->email,
-		'description' => $action_description,
-		'manage_url'  => $manage_url,
-		'sitename'    => wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ),
-		'siteurl'     => home_url(),
-		'admin_email' => $admin_email,
-	);
+	$wp_mail = array(
+		'id' => 'user_request_confirmed_email',
+		'group' => 'privacy',
 
-	/* translators: Do not translate SITENAME, USER_EMAIL, DESCRIPTION, MANAGE_URL, SITEURL; those are placeholders. */
-	$email_text = __(
-		'Howdy,
+		'to' => get_site_option( 'admin_email' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( '[{{SITENAME}}] Action Confirmed: {{ACTION_NAME}}' ),
+		'message' => __(
+'{{HEADER}}
 
-A user data privacy request has been confirmed on ###SITENAME###:
+A user data privacy request has been confirmed on {{SITENAME}}:
 
-User: ###USER_EMAIL###
-Request: ###DESCRIPTION###
+User: {{EMAIL}}
+Request: {{ACTION_NAME}}
 
 You can view and manage these data privacy requests here:
 
-###MANAGE_URL###
+{{ADMIN_URL}}
 
-Regards,
-All at ###SITENAME###
-###SITEURL###'
+{{FOOTER}}'
+		),
+		'replacements' => array(
+			'{{EMAIL}}'	=> $request->email,
+			'{{ACTION_NAME}}' => wp_user_request_action_description( $request->action_name ),
+			'{{ADMIN_URL}}'   => esc_url_raw( $manage_url ),
+		),
 	);
 
-	/**
-	 * Filters the body of the user request confirmation email.
-	 *
-	 * The email is sent to an administrator when an user request is confirmed.
-	 * The following strings have a special meaning and will get replaced dynamically:
-	 *
-	 * ###SITENAME###    The name of the site.
-	 * ###USER_EMAIL###  The user email for the request.
-	 * ###DESCRIPTION### Description of the action being performed so the user knows what the email is for.
-	 * ###MANAGE_URL###  The URL to manage requests.
-	 * ###SITEURL###     The URL to the site.
-	 *
-	 * @since 4.9.6
-	 *
-	 * @param string $email_text Text in the email.
-	 * @param array  $email_data {
-	 *     Data relating to the account action email.
-	 *
-	 *     @type WP_User_Request $request     User request object.
-	 *     @type string          $user_email  The email address confirming a request
-	 *     @type string          $description Description of the action being performed so the user knows what the email is for.
-	 *     @type string          $manage_url  The link to click manage privacy requests of this type.
-	 *     @type string          $sitename    The site name sending the mail.
-	 *     @type string          $siteurl     The site URL sending the mail.
-	 *     @type string          $admin_email The administrator email receiving the mail.
-	 * }
-	 */
-	$content = apply_filters( 'user_confirmed_action_email_content', $email_text, $email_data );
+	$wp_mailer = WP_Mailer::getInstance();
+	$email_sent = $wp_mailer->send( $wp_mail );
 
-	$content = str_replace( '###SITENAME###', $email_data['sitename'], $content );
-	$content = str_replace( '###USER_EMAIL###', $email_data['user_email'], $content );
-	$content = str_replace( '###DESCRIPTION###', $email_data['description'], $content );
-	$content = str_replace( '###MANAGE_URL###', esc_url_raw( $email_data['manage_url'] ), $content );
-	$content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content );
-
-	$subject = sprintf(
-		/* translators: Privacy data request confirmed notification email subject. 1: Site title, 2: Name of the confirmed action. */
-		__( '[%1$s] Action Confirmed: %2$s' ),
-		$email_data['sitename'],
-		$action_description
-	);
-
-	/**
-	 * Filters the subject of the user request confirmation email.
-	 *
-	 * @since 4.9.8
-	 *
-	 * @param string $subject    The email subject.
-	 * @param string $sitename   The name of the site.
-	 * @param array  $email_data {
-	 *     Data relating to the account action email.
-	 *
-	 *     @type WP_User_Request $request     User request object.
-	 *     @type string          $user_email  The email address confirming a request
-	 *     @type string          $description Description of the action being performed so the user knows what the email is for.
-	 *     @type string          $manage_url  The link to click manage privacy requests of this type.
-	 *     @type string          $sitename    The site name sending the mail.
-	 *     @type string          $siteurl     The site URL sending the mail.
-	 *     @type string          $admin_email The administrator email receiving the mail.
-	 * }
-	 */
-	$subject = apply_filters( 'user_request_confirmed_email_subject', $subject, $email_data['sitename'], $email_data );
-
-	$headers = '';
-
-	/**
-	 * Filters the headers of the user request confirmation email.
-	 *
-	 * @since 5.4.0
-	 *
-	 * @param string|array $headers    The email headers.
-	 * @param string       $subject    The email subject.
-	 * @param string       $content    The email content.
-	 * @param int          $request_id The request ID.
-	 * @param array        $email_data {
-	 *     Data relating to the account action email.
-	 *
-	 *     @type WP_User_Request $request     User request object.
-	 *     @type string          $user_email  The email address confirming a request
-	 *     @type string          $description Description of the action being performed so the user knows what the email is for.
-	 *     @type string          $manage_url  The link to click manage privacy requests of this type.
-	 *     @type string          $sitename    The site name sending the mail.
-	 *     @type string          $siteurl     The site URL sending the mail.
-	 *     @type string          $admin_email The administrator email receiving the mail.
-	 * }
-	 */
-	$headers = apply_filters( 'user_request_confirmed_email_headers', $headers, $subject, $content, $request_id, $email_data );
-
-	$email_sent = wp_mail( $email_data['admin_email'], $subject, $content, $headers );
-
 	if ( $email_sent ) {
 		update_post_meta( $request_id, '_wp_admin_notified', true );
 	}
@@ -3356,6 +3238,8 @@
 		return;
 	}
 
+	$privacy_policy_url = get_privacy_policy_url();
+
 	// Localize message content for user; fallback to site default for visitors.
 	if ( ! empty( $request->user_id ) ) {
 		$locale = get_user_locale( $request->user_id );
@@ -3366,140 +3250,56 @@
 	$switched_locale = switch_to_locale( $locale );
 
 	/**
-	 * Filters the recipient of the data erasure fulfillment notification.
+	 * Filters removed
 	 *
-	 * @since 4.9.6
+	 * $user_email = apply_filters( 'user_erasure_fulfillment_email_to', $request->email, $request );
+	 * $subject = apply_filters( 'user_erasure_complete_email_subject', $subject, $email_data['sitename'], $email_data );
+	 * $content = apply_filters( 'user_confirmed_action_email_content', $email_text, $email_data );
+	 * $headers = apply_filters( 'user_erasure_complete_email_headers', $headers, $subject, $content, $request_id, $email_data );
 	 *
-	 * @param string          $user_email The email address of the notification recipient.
-	 * @param WP_User_Request $request    The request that is initiating the notification.
-	 */
-	$user_email = apply_filters( 'user_erasure_fulfillment_email_to', $request->email, $request );
-
-	$email_data = array(
-		'request'            => $request,
-		'message_recipient'  => $user_email,
-		'privacy_policy_url' => get_privacy_policy_url(),
-		'sitename'           => wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ),
-		'siteurl'            => home_url(),
-	);
-
-	$subject = sprintf(
-		/* translators: Erasure request fulfilled notification email subject. %s: Site title. */
-		__( '[%s] Erasure Request Fulfilled' ),
-		$email_data['sitename']
-	);
-
-	/**
-	 * Filters the subject of the email sent when an erasure request is completed.
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
 	 *
-	 * @since 4.9.8
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
 	 *
-	 * @param string $subject    The email subject.
-	 * @param string $sitename   The name of the site.
-	 * @param array  $email_data {
-	 *     Data relating to the account action email.
-	 *
-	 *     @type WP_User_Request $request            User request object.
-	 *     @type string          $message_recipient  The address that the email will be sent to. Defaults
-	 *                                               to the value of `$request->email`, but can be changed
-	 *                                               by the `user_erasure_fulfillment_email_to` filter.
-	 *     @type string          $privacy_policy_url Privacy policy URL.
-	 *     @type string          $sitename           The site name sending the mail.
-	 *     @type string          $siteurl            The site URL sending the mail.
-	 * }
 	 */
-	$subject = apply_filters( 'user_erasure_complete_email_subject', $subject, $email_data['sitename'], $email_data );
 
-	if ( empty( $email_data['privacy_policy_url'] ) ) {
-		/* translators: Do not translate SITENAME, SITEURL; those are placeholders. */
-		$email_text = __(
-			'Howdy,
+	$notify_message = array();
+	/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+	$notify_message[] = __(
+'{{HEADER}}
 
-Your request to erase your personal data on ###SITENAME### has been completed.
+Your request to erase your personal data on {{SITENAME}} has been completed.
 
-If you have any follow-up questions or concerns, please contact the site administrator.
+If you have any follow-up questions or concerns, please contact the site administrator.' 
+);
 
-Regards,
-All at ###SITENAME###
-###SITEURL###'
-		);
-	} else {
-		/* translators: Do not translate SITENAME, SITEURL, PRIVACY_POLICY_URL; those are placeholders. */
-		$email_text = __(
-			'Howdy,
-
-Your request to erase your personal data on ###SITENAME### has been completed.
-
-If you have any follow-up questions or concerns, please contact the site administrator.
-
-For more information, you can also read our privacy policy: ###PRIVACY_POLICY_URL###
-
-Regards,
-All at ###SITENAME###
-###SITEURL###'
-		);
+	if ( !empty( $privacy_policy_url ) ) {
+		$notify_message[] = '';
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		$notify_message[] = __( 'For more information, you can also read our privacy policy: {{PRIVACY_POLICY_URL}}' );
 	}
 
-	/**
-	 * Filters the body of the data erasure fulfillment notification.
-	 *
-	 * The email is sent to a user when a their data erasure request is fulfilled
-	 * by an administrator.
-	 *
-	 * The following strings have a special meaning and will get replaced dynamically:
-	 *
-	 * ###SITENAME###           The name of the site.
-	 * ###PRIVACY_POLICY_URL### Privacy policy page URL.
-	 * ###SITEURL###            The URL to the site.
-	 *
-	 * @since 4.9.6
-	 *
-	 * @param string $email_text Text in the email.
-	 * @param array  $email_data {
-	 *     Data relating to the account action email.
-	 *
-	 *     @type WP_User_Request $request            User request object.
-	 *     @type string          $message_recipient  The address that the email will be sent to. Defaults
-	 *                                               to the value of `$request->email`, but can be changed
-	 *                                               by the `user_erasure_fulfillment_email_to` filter.
-	 *     @type string          $privacy_policy_url Privacy policy URL.
-	 *     @type string          $sitename           The site name sending the mail.
-	 *     @type string          $siteurl            The site URL sending the mail.
-	 * }
-	 */
-	$content = apply_filters( 'user_confirmed_action_email_content', $email_text, $email_data );
+	$notify_message[] = '';
+	$notify_message[] = '{{FOOTER}}';
 
-	$content = str_replace( '###SITENAME###', $email_data['sitename'], $content );
-	$content = str_replace( '###PRIVACY_POLICY_URL###', $email_data['privacy_policy_url'], $content );
-	$content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content );
+	$wp_mail = array(
+		'id' => 'user_erasure_complete_email',
+		'group' => 'privacy',
 
-	$headers = '';
+		'to' => $request->email,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( '[{{SITENAME}}] Erasure Request Fulfilled' ),
+		'message' => implode( "\r\n", $notify_message ),
+		'replacements' => array(
+			'{{PRIVACY_POLICY_URL}}'   => esc_url_raw( $privacy_policy_url )
+		),
+	);
 
-	/**
-	 * Filters the headers of the data erasure fulfillment notification.
-	 *
-	 * @since 5.4.0
-	 *
-	 * @param string|array $headers    The email headers.
-	 * @param string       $subject    The email subject.
-	 * @param string       $content    The email content.
-	 * @param int          $request_id The request ID.
-	 * @param array        $email_data {
-	 *     Data relating to the account action email.
-	 *
-	 *     @type WP_User_Request $request            User request object.
-	 *     @type string          $message_recipient  The address that the email will be sent to. Defaults
-	 *                                               to the value of `$request->email`, but can be changed
-	 *                                               by the `user_erasure_fulfillment_email_to` filter.
-	 *     @type string          $privacy_policy_url Privacy policy URL.
-	 *     @type string          $sitename           The site name sending the mail.
-	 *     @type string          $siteurl            The site URL sending the mail.
-	 * }
-	 */
-	$headers = apply_filters( 'user_erasure_complete_email_headers', $headers, $subject, $content, $request_id, $email_data );
+	$wp_mailer = WP_Mailer::getInstance();
+	$email_sent = $wp_mailer->send( $wp_mail );
 
-	$email_sent = wp_mail( $user_email, $subject, $content, $headers );
-
 	if ( $switched_locale ) {
 		restore_previous_locale();
 	}
@@ -3661,20 +3461,7 @@
 		return new WP_Error( 'invalid_request', __( 'Invalid user request.' ) );
 	}
 
-	// Localize message content for user; fallback to site default for visitors.
-	if ( ! empty( $request->user_id ) ) {
-		$locale = get_user_locale( $request->user_id );
-	} else {
-		$locale = get_locale();
-	}
-
-	$switched_locale = switch_to_locale( $locale );
-
-	$email_data = array(
-		'request'     => $request,
-		'email'       => $request->email,
-		'description' => wp_user_request_action_description( $request->action_name ),
-		'confirm_url' => add_query_arg(
+	$confirm_url = add_query_arg(
 			array(
 				'action'      => 'confirmaction',
 				'request_id'  => $request_id,
@@ -3681,111 +3468,66 @@
 				'confirm_key' => wp_generate_user_request_key( $request_id ),
 			),
 			wp_login_url()
-		),
-		'sitename'    => wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ),
-		'siteurl'     => home_url(),
 	);
 
-	/* translators: Do not translate DESCRIPTION, CONFIRM_URL, SITENAME, SITEURL: those are placeholders. */
-	$email_text = __(
-		'Howdy,
+	$is_privacy = ( in_array( $request->action_name, _wp_privacy_action_request_types(), true ) );
 
-A request has been made to perform the following action on your account:
+	// Localize message content for user; fallback to site default for visitors.
+	if ( ! empty( $request->user_id ) ) {
+		$locale = get_user_locale( $request->user_id );
+	} else {
+		$locale = get_locale();
+	}
 
-     ###DESCRIPTION###
-
-To confirm this, please click on the following link:
-###CONFIRM_URL###
-
-You can safely ignore and delete this email if you do not want to
-take this action.
-
-Regards,
-All at ###SITENAME###
-###SITEURL###'
-	);
-
+	$switched_locale = switch_to_locale( $locale );
+	
 	/**
-	 * Filters the text of the email sent when an account action is attempted.
+	 * Filters removed
 	 *
-	 * The following strings have a special meaning and will get replaced dynamically:
+	 * $content = apply_filters( 'user_request_action_email_content', $email_text, $email_data );
+	 * $subject = apply_filters( 'user_request_action_email_subject', $subject, $email_data['sitename'], $email_data );
+	 * $headers = apply_filters( 'user_request_action_email_headers', $headers, $subject, $content, $request_id, $email_data );
 	 *
-	 * ###DESCRIPTION### Description of the action being performed so the user knows what the email is for.
-	 * ###CONFIRM_URL### The link to click on to confirm the account action.
-	 * ###SITENAME###    The name of the site.
-	 * ###SITEURL###     The URL to the site.
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
 	 *
-	 * @since 4.9.6
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
 	 *
-	 * @param string $email_text Text in the email.
-	 * @param array  $email_data {
-	 *     Data relating to the account action email.
-	 *
-	 *     @type WP_User_Request $request     User request object.
-	 *     @type string          $email       The email address this is being sent to.
-	 *     @type string          $description Description of the action being performed so the user knows what the email is for.
-	 *     @type string          $confirm_url The link to click on to confirm the account action.
-	 *     @type string          $sitename    The site name sending the mail.
-	 *     @type string          $siteurl     The site URL sending the mail.
-	 * }
 	 */
-	$content = apply_filters( 'user_request_action_email_content', $email_text, $email_data );
 
-	$content = str_replace( '###DESCRIPTION###', $email_data['description'], $content );
-	$content = str_replace( '###CONFIRM_URL###', esc_url_raw( $email_data['confirm_url'] ), $content );
-	$content = str_replace( '###EMAIL###', $email_data['email'], $content );
-	$content = str_replace( '###SITENAME###', $email_data['sitename'], $content );
-	$content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content );
+	$wp_mail = array(
+		'id' => 'user_request_action_email',
+		'group' => ( $is_privacy ) ? 'privacy' : 'blog',
 
-	/* translators: Confirm privacy data request notification email subject. 1: Site title, 2: Name of the action. */
-	$subject = sprintf( __( '[%1$s] Confirm Action: %2$s' ), $email_data['sitename'], $email_data['description'] );
+		'to' => $request->email,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( '[{{SITENAME}}] Confirm Action: {{ACTION_NAME}}' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => __(
+'{{HEADER}}
 
-	/**
-	 * Filters the subject of the email sent when an account action is attempted.
-	 *
-	 * @since 4.9.6
-	 *
-	 * @param string $subject    The email subject.
-	 * @param string $sitename   The name of the site.
-	 * @param array  $email_data {
-	 *     Data relating to the account action email.
-	 *
-	 *     @type WP_User_Request $request     User request object.
-	 *     @type string          $email       The email address this is being sent to.
-	 *     @type string          $description Description of the action being performed so the user knows what the email is for.
-	 *     @type string          $confirm_url The link to click on to confirm the account action.
-	 *     @type string          $sitename    The site name sending the mail.
-	 *     @type string          $siteurl     The site URL sending the mail.
-	 * }
-	 */
-	$subject = apply_filters( 'user_request_action_email_subject', $subject, $email_data['sitename'], $email_data );
+A request has been made to perform the following action on your account:
 
-	$headers = '';
+     {{ACTION_NAME}}
 
-	/**
-	 * Filters the headers of the email sent when an account action is attempted.
-	 *
-	 * @since 5.4.0
-	 *
-	 * @param string|array $headers    The email headers.
-	 * @param string       $subject    The email subject.
-	 * @param string       $content    The email content.
-	 * @param int          $request_id The request ID.
-	 * @param array        $email_data {
-	 *     Data relating to the account action email.
-	 *
-	 *     @type WP_User_Request $request     User request object.
-	 *     @type string          $email       The email address this is being sent to.
-	 *     @type string          $description Description of the action being performed so the user knows what the email is for.
-	 *     @type string          $confirm_url The link to click on to confirm the account action.
-	 *     @type string          $sitename    The site name sending the mail.
-	 *     @type string          $siteurl     The site URL sending the mail.
-	 * }
-	 */
-	$headers = apply_filters( 'user_request_action_email_headers', $headers, $subject, $content, $request_id, $email_data );
+To confirm this, please click on the following link:
+{{LOGINLINK}}
 
-	$email_sent = wp_mail( $email_data['email'], $subject, $content, $headers );
+You can safely ignore and delete this email if you do not want to
+take this action.
 
+{{FOOTER}}'
+		),
+		'replacements' => array(
+			'{{ACTION_NAME}}' => wp_user_request_action_description( $request->action_name ),
+			'{{LOGINLINK}}'   => esc_url_raw( $confirm_url ),
+		),
+	);
+
+	$wp_mailer = WP_Mailer::getInstance();
+	$email_sent = $wp_mailer->send( $wp_mail );
+
 	if ( $switched_locale ) {
 		restore_previous_locale();
 	}
Index: wp-login.php
===================================================================
--- wp-login.php	(revision 47320)
+++ wp-login.php	(working copy)
@@ -415,46 +415,54 @@
 		$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, just 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";
-
-	/* translators: Password reset notification email subject. %s: Site title. */
-	$title = sprintf( __( '[%s] Password Reset' ), $site_name );
-
 	/**
-	 * Filters the subject of the password reset email.
+	 * Filters removed
 	 *
-	 * @since 2.8.0
-	 * @since 4.4.0 Added the `$user_login` and `$user_data` parameters.
+	 * $title = apply_filters( 'retrieve_password_title', $title, $user_login, $user_data );
+	 * $message = apply_filters( 'retrieve_password_message', $message, $key, $user_login, $user_data );
 	 *
-	 * @param string  $title      Default email title.
-	 * @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.
+	 * all mails components are filterable using wp-includes/class-wp-mailer.php filters
 	 *
-	 * If the filtered message is empty, the password reset email will not be sent.
+	 *		apply_filters( 'wp_mailer', 			   $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_group_{$mail['group']}", $mail, $caller_info );
+	 *		apply_filters( "wp_mailer_{$mail['id']}", 	   $mail, $caller_info );
 	 *
-	 * @since 2.8.0
-	 * @since 4.1.0 Added `$user_login` and `$user_data` parameters.
-	 *
-	 * @param string  $message    Default mail 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 ) ) {
+	$wp_mail = array(
+		'id' => 'retrieve_password',
+		'group' => 'blog',
+
+		'to' => $user_email,
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'subject' => __( '[{{SITENAME}}] Password Reset' ),
+		/* translators: Do not translate any string between double curled brackets {{STRING}} : those are "mustache" placeholders. */
+		'message' => __(
+'{{HEADER}}
+
+Someone has requested a password reset for the following account:
+
+Site Name: {{SITENAME}}
+
+Username: {{USERNAME}}
+
+If this was a mistake, just ignore this email and nothing will happen.
+
+To reset your password, visit the following address:
+
+{{RESETLINK}}
+
+{{FOOTER}}'
+		),
+		'replacements' => array(
+			'{{SITENAME}}'	=> $site_name,
+			'{{USERNAME}}'	=> $user_login,
+			'{{RESETLINK}}' => esc_url_raw( network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) )
+		),
+	);
+
+	$wp_mailer = WP_Mailer::getInstance();
+	if ( ! $wp_mailer->send( $wp_mail ) ) {
 		$errors->add(
 			'retrieve_password_email_failure',
 			sprintf(
Index: wp-settings.php
===================================================================
--- wp-settings.php	(revision 47320)
+++ wp-settings.php	(working copy)
@@ -281,7 +281,9 @@
 require ABSPATH . WPINC . '/blocks/shortcode.php';
 require ABSPATH . WPINC . '/blocks/social-link.php';
 require ABSPATH . WPINC . '/blocks/tag-cloud.php';
+require ABSPATH . WPINC . '/class-wp-mailer.php';
 
+
 $GLOBALS['wp_embed'] = new WP_Embed();
 
 // Load multisite-specific files.
