Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 31 additions & 101 deletions src/wp-admin/includes/privacy-tools.php
Original file line number Diff line number Diff line change
Expand Up @@ -623,121 +623,51 @@ function wp_privacy_send_personal_data_export_email( $request_id ) {
$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,
'request' => $request,
'expiration' => $expiration,
'expiration_date' => $expiration_date,
'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.
*
* @since 5.3.0
*
* @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_Mailer::register_email(
'privacy_export',
'privacy',
array(
/* translators: Personal data export notification email subject. %s: Site title. */
'subject' => __( '[{{sitename}}] Personal Data Export' ),
/* translators: Do not translate {{expiration_date}}, {{export_file_url}}, {{sitename}}, {{siteurl}}: those are placeholders. */
'body' => __(
'Howdy,

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_date}},
so please download it before then.

###LINK###
{{export_file_url}}

Regards,
All at ###SITENAME###
###SITEURL###'
All at {{sitename}}
{{siteurl}}'
),
)
);

/**
* 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 );

$content = str_replace( '###EXPIRATION###', $expiration_date, $content );
$content = str_replace( '###LINK###', sanitize_url( $export_file_url ), $content );
$content = str_replace( '###EMAIL###', $request_email, $content );
$content = str_replace( '###SITENAME###', $site_name, $content );
$content = str_replace( '###SITEURL###', sanitize_url( $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 );
/** This filter is documented in wp-admin/includes/privacy-tools.php */
$headers = apply_filters( 'wp_privacy_personal_data_email_headers', $headers, '', '', $request_id, $email_data );

$mail_success = wp_mail( $request_email, $subject, $content, $headers );
$mail_success = WP_Mailer::send(
'privacy_export',
array(
'to' => $request_email,
'headers' => $headers,
),
$email_data
);

if ( $switched_locale ) {
restore_previous_locale();
Expand Down
179 changes: 179 additions & 0 deletions src/wp-includes/class-wp-mailer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
<?php
/**
* WP_Mailer class.
*
* A standard way to manage emails sent by WordPress core.
*
* @package WordPress
* @subpackage Mail
* @since 7.1.0
*/

/**
* Core class used to send standardized emails.
*
* @since 7.1.0
*/
class WP_Mailer {

/**
* Registered emails.
*
* @since 7.1.0
* @var array
*/
private static $emails = array();

/**
* Sends a standardized email.
*
* @since 7.1.0
*
* @param string $email_id Email identifier.
* @param array $args {
* Optional. Email arguments.
*
* @type string|string[] $to Array or comma-separated list of email addresses.
* @type string|string[] $headers Optional. Additional headers.
* @type string|string[] $attachments Optional. Paths to files to attach.
* }
* @param array $data Optional. Data to be used in the template placeholders.
* @return bool Whether the email was sent successfully.
*/
public static function send( $email_id, $args = array(), $data = array() ) {
$email = self::get_email( $email_id );

if ( ! $email ) {
return false;
}

$group = $email[ 'group' ];

Check failure on line 50 in src/wp-includes/class-wp-mailer.php

View workflow job for this annotation

GitHub Actions / Coding standards / PHP checks

Array keys must NOT be surrounded by spaces if they only contain a string or an integer.

/**
* Filters the data used for email template rendering.
*
* @since 7.1.0
*
* @param array $data The template data.
* @param string $email_id The email identifier.
* @param string $group The email group.
*/
$data = apply_filters( "wp_mailer_{$group}_data", $data, $email_id, $group );
$data = apply_filters( "wp_mailer_{$email_id}_data", $data, $email_id, $group );

$subject = self::render( $email[ 'subject' ], $data );

Check failure on line 64 in src/wp-includes/class-wp-mailer.php

View workflow job for this annotation

GitHub Actions / Coding standards / PHP checks

Array keys must NOT be surrounded by spaces if they only contain a string or an integer.
$message = self::render( $email[ 'body' ], $data );

Check failure on line 65 in src/wp-includes/class-wp-mailer.php

View workflow job for this annotation

GitHub Actions / Coding standards / PHP checks

Array keys must NOT be surrounded by spaces if they only contain a string or an integer.

/**
* Filters the email subject before sending.
*
* @since 7.1.0
*
* @param string $subject The rendered subject.
* @param string $email_id The email identifier.
* @param array $data The template data.
*/
$subject = apply_filters( "wp_mailer_{$group}_subject", $subject, $email_id, $data );
$subject = apply_filters( "wp_mailer_{$email_id}_subject", $subject, $email_id, $data );

/**
* Filters the email message before sending.
*
* @since 7.1.0
*
* @param string $message The rendered message.
* @param string $email_id The email identifier.
* @param array $data The template data.
*/
$message = apply_filters( "wp_mailer_{$group}_message", $message, $email_id, $data );
$message = apply_filters( "wp_mailer_{$email_id}_message", $message, $email_id, $data );

$to = isset( $args[ 'to' ] ) ? $args[ 'to' ] : '';

Check failure on line 91 in src/wp-includes/class-wp-mailer.php

View workflow job for this annotation

GitHub Actions / Coding standards / PHP checks

Array keys must NOT be surrounded by spaces if they only contain a string or an integer.

Check failure on line 91 in src/wp-includes/class-wp-mailer.php

View workflow job for this annotation

GitHub Actions / Coding standards / PHP checks

Array keys must NOT be surrounded by spaces if they only contain a string or an integer.
$headers = isset( $args[ 'headers' ] ) ? $args[ 'headers' ] : '';

Check failure on line 92 in src/wp-includes/class-wp-mailer.php

View workflow job for this annotation

GitHub Actions / Coding standards / PHP checks

Array keys must NOT be surrounded by spaces if they only contain a string or an integer.

Check failure on line 92 in src/wp-includes/class-wp-mailer.php

View workflow job for this annotation

GitHub Actions / Coding standards / PHP checks

Array keys must NOT be surrounded by spaces if they only contain a string or an integer.
$attachments = isset( $args[ 'attachments' ] ) ? $args[ 'attachments' ] : array();

Check failure on line 93 in src/wp-includes/class-wp-mailer.php

View workflow job for this annotation

GitHub Actions / Coding standards / PHP checks

Array keys must NOT be surrounded by spaces if they only contain a string or an integer.

/**
* Filters the email headers before sending.
*
* @since 7.1.0
*
* @param string|array $headers The email headers.
* @param string $email_id The email identifier.
* @param array $data The template data.
*/
$headers = apply_filters( "wp_mailer_{$group}_headers", $headers, $email_id, $data );
$headers = apply_filters( "wp_mailer_{$email_id}_headers", $headers, $email_id, $data );

return wp_mail( $to, $subject, $message, $headers, $attachments );
}

/**
* Registers an email template.
*
* @since 7.1.0
*
* @param string $email_id Email identifier.
* @param string $group Email group (e.g., 'privacy', 'admin').
* @param array $args {
* Email template arguments.
*
* @type string $subject Email subject template.
* @type string $body Email body template.
* }
*/
public static function register_email( $email_id, $group, $args ) {
self::$emails[ $email_id ] = array(
'group' => $group,
'subject' => $args[ 'subject' ],
'body' => $args[ 'body' ],
);
}

/**
* Retrieves an email template.
*
* @since 7.1.0
*
* @param string $email_id Email identifier.
* @return array|false Email template data on success, false on failure.
*/
public static function get_email( $email_id ) {
if ( isset( self::$emails[ $email_id ] ) ) {
return self::$emails[ $email_id ];
}

/**
* Filters the email template before it is retrieved.
*
* This allows for lazy registration of emails.
*
* @since 7.1.0
*
* @param array|null $email The email template data.
* @param string $email_id The email identifier.
*/
return apply_filters( "wp_mailer_get_email_{$email_id}", null, $email_id );
}

/**
* Renders a template with data.
*
* Supports {{mustache}} style placeholders.
*
* @since 7.1.0
*
* @param string $template The template string.
* @param array $data The data for replacement.
* @return string The rendered string.
*/
public static function render( $template, $data ) {
return preg_replace_callback(
'/{{(.*?)}}/',
function( $matches ) use ( $data ) {
$key = trim( $matches[ 1 ] );
return isset( $data[ $key ] ) ? $data[ $key ] : $matches[ 0 ];
},
$template
);
}
}
Loading
Loading