From b2e14e9e00350d2cadfef1f08e0241a55f637610 Mon Sep 17 00:00:00 2001
From: Alex Kirk
Date: Thu, 19 Dec 2024 14:21:33 +0100
Subject: [PATCH] Add test for HTML in direct messages (#1093)
Co-authored-by: Matthias Pfefferle
---
CHANGELOG.md | 6 +++
includes/class-mailer.php | 9 +++-
readme.txt | 4 ++
tests/includes/class-test-mailer.php | 66 ++++++++++++++++++++++++++++
4 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ebc16e41..5b0be9d0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [Unreleased]
+
+### Improved
+
+* Direct Messages: Improve HTML to e-mail text conversion
+
## [4.5.1] - 2024-12-18
### Improved
diff --git a/includes/class-mailer.php b/includes/class-mailer.php
index de479b10..ceec4c66 100644
--- a/includes/class-mailer.php
+++ b/includes/class-mailer.php
@@ -171,10 +171,17 @@ public static function direct_message( $activity, $user_id ) {
$email = $user->user_email;
}
+ $content = \html_entity_decode(
+ \wp_strip_all_tags(
+ str_replace( '
', PHP_EOL . PHP_EOL, $activity['object']['content'] )
+ ),
+ ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401
+ );
+
/* translators: 1: Blog name, 2 Actor name */
$subject = \sprintf( \esc_html__( '[%1$s] Direct Message from: %2$s', 'activitypub' ), \esc_html( get_option( 'blogname' ) ), \esc_html( $actor['name'] ) );
/* translators: 1: Blog name, 2: Actor name */
- $message = \sprintf( \esc_html__( 'New Direct Message: %2$s', 'activitypub' ), \esc_html( get_option( 'blogname' ) ), \wp_strip_all_tags( $activity['object']['content'] ) ) . "\r\n\r\n";
+ $message = \sprintf( \esc_html__( 'New Direct Message: %2$s', 'activitypub' ), \esc_html( get_option( 'blogname' ) ), $content ) . "\r\n\r\n";
/* translators: Actor name */
$message .= \sprintf( \esc_html__( 'From: %s', 'activitypub' ), \esc_html( $actor['name'] ) ) . "\r\n";
/* translators: Actor URL */
diff --git a/readme.txt b/readme.txt
index bd14ea97..b7977494 100644
--- a/readme.txt
+++ b/readme.txt
@@ -132,6 +132,10 @@ For reasons of data protection, it is not possible to see the followers of other
== Changelog ==
+= Unreleased =
+
+* Improved: HTML to e-mail text conversion
+
= 4.5.1 =
* Improved: Reactions block: Remove the `wp-block-editor` dependency for frontend views
diff --git a/tests/includes/class-test-mailer.php b/tests/includes/class-test-mailer.php
index 78b596b0..a424be08 100644
--- a/tests/includes/class-test-mailer.php
+++ b/tests/includes/class-test-mailer.php
@@ -307,4 +307,70 @@ function ( $args ) {
remove_all_filters( 'wp_mail' );
wp_delete_user( $user_id );
}
+
+ /**
+ * Data provider for direct message notification text.
+ *
+ * @return array
+ */
+ public function direct_message_text_provider() {
+ return array(
+ 'HTML entities' => array(
+ json_decode( '"Interesting story from @test<\/span><\/a><\/span> about people who don't own their own domain.<\/p>"This is not a new issue, of course, but Service\u2019s implementation shows limitations."<\/p>"' ),
+ 'Interesting story from @test about people who don\'t own their own domain.' . PHP_EOL . PHP_EOL . '"This is not a new issue, of course, but Service’s implementation shows limitations."',
+ ),
+ 'invalid HTML' => array(
+ json_decode( '" 'https://example.com/author',
+ 'object' => array(
+ 'content' => $text,
+ ),
+ );
+
+ // Mock remote metadata.
+ add_filter(
+ 'pre_get_remote_metadata_by_actor',
+ function () {
+ return array(
+ 'name' => 'Test Sender',
+ 'url' => 'https://example.com/author',
+ );
+ }
+ );
+
+ // Capture email.
+ add_filter(
+ 'wp_mail',
+ function ( $args ) use ( $expected, $user_id ) {
+ $this->assertStringContainsString( $expected, $args['message'] );
+ $this->assertEquals( get_user_by( 'id', $user_id )->user_email, $args['to'] );
+ return $args;
+ }
+ );
+
+ Mailer::direct_message( $activity, $user_id );
+
+ // Clean up.
+ remove_all_filters( 'pre_get_remote_metadata_by_actor' );
+ remove_all_filters( 'wp_mail' );
+ wp_delete_user( $user_id );
+ }
}