Make WordPress Core

Opened 11 years ago

Last modified 13 days ago

#30128 new enhancement

Allow to use associative arrays beside indexed arrays in wp_mail $headers

Reported by: marsjaninzmarsa's profile marsjaninzmarsa Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version:
Component: Mail Keywords: has-patch has-unit-tests has-test-info changes-requested
Focuses: Cc:

Description

eg:

$headers = [
	'From' => 'Me Myself <me@example.net>',
	'Cc'   => 'John Q Codex <jqc@wordpress.org>',
];

beside:

$headers = [
	'From: Me Myself <me@example.net>',
	'Cc: John Q Codex <jqc@wordpress.org>',
];

and also (because why not):

$headers = [
	'From' => 'Me Myself <me@example.net>',
	'Cc'   => [
		'John Q Codex <jqc@wordpress.org>',
		'iluvwp@wordpress.org',
	],
];

Attachments (4)

30128.path (1.9 KB) - added by marsjaninzmarsa 11 years ago.
30128.patch (1.9 KB) - added by marsjaninzmarsa 11 years ago.
fixes (typo in previous filename)
30128.2.patch (1.6 KB) - added by jorbin 11 years ago.
30128.unit-tests-only.patch (2.9 KB) - added by SirLouen 3 months ago.
Unit Tests

Download all attachments as: .zip

Change History (23)

#1 @marsjaninzmarsa
11 years ago

  • Keywords has-patch needs-testing needs-codex added

This ticket was mentioned in IRC in #wordpress-dev by marsjaninzmarsa. View the logs.


11 years ago

#3 @marsjaninzmarsa
11 years ago

It is also possible to use single line notation for multiple CC/BCC, eg:

$headers = [
	'From: Me Myself <me@example.net>',
	'Cc: Fo McFoo <foo@example.com>, bar@example.com',
];

@marsjaninzmarsa
11 years ago

fixes (typo in previous filename)

#4 @boonebgorges
11 years ago

  • Version changed from trunk to 2.3

@jorbin
11 years ago

#5 @jorbin
11 years ago

  • Keywords needs-unit-tests added

This looks like a good idea. It could use some unit tests though to be on the safe side. The current mail unit tests pass.

I've refreshed the patch above so that it applies cleanly.

#6 @desrosj
5 years ago

  • Keywords needs-refresh added; needs-testing removed
  • Milestone set to Future Release

Looks like 30128.2.patch needs an additional refresh on trunk, and still needs unit tests.

#7 @SirLouen
3 months ago

  • Keywords changes-requested has-unit-tests added; needs-codex needs-unit-tests needs-refresh removed

The current patch is not only not applying, but it's completely failing to achieve its purpose (parsing the associative array with another array within, like the multiple CC example).

It can actually parse simple associative arrays though. So basically we can say it needs a little more work.

I think that if we are going to enable associative arrays for CC and BCC, why not also add this for any other custom header according to the standard?

This was commented on here #56779, so I think we can kill two birds with one stone with a minimal extra work

I've been trying to work on this patch, but I've noticed there is another function that is on the way and I don't understand what it's doing in formatting.php: wp_staticize_emoji_for_email (this function was created one year after this report was made). This is almost a copy-paste of the original header manipulation function in wp_mail, definitely a WET function that we should consider refactoring for the health of a patch for this report.

Finally, I'm attaching some unit tests so anyone that would like to work on refining the current patch could have a testing reference (for both CC/BCC thing and the Custom Headers)

Version 4, edited 3 months ago by SirLouen (previous) (next) (diff)

@SirLouen
3 months ago

Unit Tests

This ticket was mentioned in PR #9971 on WordPress/wordpress-develop by @SirLouen.


5 weeks ago
#8

Reviewed Patch 30128.2.patch with many improvements

Explaining the patch

formatting.php

In both pluggable and formatting for the wp_staticize_emoji_for_email function, we have to apply the same headers parsing logic. This is a duplication that has existed for more than 10 years, so we have to bear with it. Maybe in the future a refactor can be done, but there are risks of BC, and since this function is only targeting the Content-Type, we will leave it for now.
Basically it takes the same logic as in 30128.2.patch and applies it here. Very straightforward: after exploding, some short-circuiting, if the array is not associative, and the content is not a simple string, then it's not going to be the Content-Type, so keep iterating.

pluggable.php
Similar logic. First, start iterating, but take into account the possibility that the header content can be an associative array; in that case, convert it into the basic comma-separated string before passing it to the switch
I'm relying a lot on the original algorithm provided by 30128.2.patch
From there, it will keep this as an array. This way it will also serve for the issue presented in #56779 that will become a duplicate after this patch.

wpMail.php
For the tests, I will be testing two things:

  1. The associative array and multiple associative array nature of the headers
  2. The possibility of multiple values with identical keys as part of the same header (more relevant to #56779, but because this patch is actually targeting this problem in parallel, we can hit two birds with one stone).

Testing Information

  • To test this, you can do multiple scenarios, so you need to setup an email with multiple different headers:
  1. First: Add two custom headers with identical key.
  • Currently: It will only keep one of the two
  • After the patch: It should keep the two
  1. Second: Add associative arrays including the. From, the CC, the BCC and the Reply-To. It can be a combination of one, two, all, and even each of them could have another array within (for example the BCC can have an array of addresses). Be wary, that From cannot have more than one address, only CC, BCC and Reply-To can have multiple addresses
  • Currently: Arrays are not admitted
  • After the patch: You should see all the addresses introduced in the associative array after you send the email and check the result

Trac ticket: https://core.trac.wordpress.org/ticket/30128

#9 @SirLouen
5 weeks ago

  • Keywords has-test-info needs-testing added; changes-requested removed
  • Version 2.3 deleted

#10 @SirLouen
5 weeks ago

#56779 was marked as a duplicate.

This ticket was mentioned in Slack in #core-test by sirlouen. View the logs.


5 weeks ago

#12 @sajjad67
5 weeks ago

Test Report

Description

This report validates whether the indicated patch works as expected.

Patch tested: https://github.com/WordPress/wordpress-develop/pull/9971

Environment

  • WordPress: 6.9-alpha-60093-src
  • PHP: 8.2.29
  • Server: nginx/1.29.1
  • Database: mysqli (Server: 8.4.6 / Client: mysqlnd 8.2.29)
  • Browser: Chrome 140.0.0.0
  • OS: Windows 10/11
  • Theme: Twenty Twenty-Five 1.3
  • MU Plugins: None activated
  • Plugins:
    • Email Testing 1.0.0
    • Test Reports 1.2.0

Actual Results

  1. ✅ Issue resolved with patch.

Before Patch

  Return-Path: <from@example.com>
  Received: from localhost (wordpress-develop-php-1.wordpress-develop_wpdevnet. [172.18.0.3])
          by 27db0e562ef1 (Mailpit) with SMTP
          for <test@example.com>; Mon, 22 Sep 2025 16:50:05 +0000 (UTC)
  Date: Mon, 22 Sep 2025 16:50:05 +0000
  To: test@example.com
  From: WordPress <from@example.com>
  Subject: Test Subject
  Message-ID: <Lws9sTYCYPmMZJdB58Uxv380VoEZOfQtCCeGfYO4@localhost>
  X-Mailer: PHPMailer 6.10.0 (https://github.com/PHPMailer/PHPMailer)
  X-Test: two
  MIME-Version: 1.0
  Content-Type: text/plain; charset=UTF-8

  Testing headers

After Patch

  Bcc: hidden1@example.com, hidden2@example.com
  Return-Path: <sender@example.com>
  Received: from localhost (wordpress-develop-php-1.wordpress-develop_wpdevnet. [172.18.0.3])
          by 27db0e562ef1 (Mailpit) with SMTP
          for <test@example.com>; Mon, 22 Sep 2025 16:58:58 +0000 (UTC)
  Date: Mon, 22 Sep 2025 16:58:58 +0000
  To: test@example.com
  From: WordPress <sender@example.com>
  Cc: cc1@example.com, cc2@example.com
  Reply-To: reply1@example.com, reply2@example.com
  Subject: Test Subject
  Message-ID: <mvWwx9qTw902pxelEy4TxkQ702mjwWt9QC46V5DFhw@localhost>
  X-Mailer: PHPMailer 6.10.0 (https://github.com/PHPMailer/PHPMailer)
  X-Test: one
  X-Test: two
  MIME-Version: 1.0
  Content-Type: text/plain; charset=UTF-8

  Testing headers

This ticket was mentioned in Slack in #core-test by sajjad67. View the logs.


5 weeks ago

This ticket was mentioned in Slack in #core-test by sirlouen. View the logs.


5 weeks ago

#15 @nikunj8866
5 weeks ago

  • Keywords needs-testing removed

Test Report

Description

✅ This report validates that the indicated patch works as expected.

Patch tested: https://github.com/WordPress/wordpress-develop/pull/9971

Environment

  • WordPress: 6.8.2
  • PHP: 8.4.10
  • Server: nginx/1.26.1
  • Database: mysqli (Server: 8.0.35 / Client: mysqlnd 8.4.10)
  • Browser: Chrome 140.0.0.0
  • OS: Windows 10/11
  • Theme: ModernPress 1.0.0
  • MU Plugins:
    • Email Testing 30128 1.0.0
  • Plugins:
    • Test Reports 1.2.0

Steps to Test

  1. Create a site in LocalWP.
  2. Add the Email Testing 30128 plugin into the wp-content/mu-plugins folder, which contains wp_mail() with associative array headers.
  3. Open the browser and run YOURSITE.local/?send_test_email=1. Replace YOURSITE with the actual LocalWP site name.
  4. 🐞 Before patch: You may see a fatal error because wp_mail() did not support associative array headers (https://prnt.sc/021DKTty7V6a).
  5. For viewing email logs within LocalWP, click, Tools > Mailpit > Open Mailpit button (https://prnt.sc/-pgSGe_z-0ub).

Actual Results

  1. ✅ Issue resolved with patch.
  2. Email sent successfully without errors, with all headers and data correctly applied.

Example email headers from Mailpit:

Return-Path: <me@example.net>
Received: from DESKTOP-23CTATP (kubernetes.docker.internal. [127.0.0.1])
        by DESKTOP-23CTATP (Mailpit) with SMTP
        for <test@example.com>; Fri, 26 Sep 2025 13:15:02 +0530 (IST)
Subject: Test Subject
To: test@example.com
X-PHP-Originating-Script: 0:PHPMailer.php
Date: Fri, 26 Sep 2025 07:45:02 +0000
From: Me Myself <me@example.net>
Cc: John Q Codex <jqc@wordpress.org>, iluvwp@wordpress.org
Message-ID: <3FKnT6ayHPNRsacz6GgfJiYsKSSD3SiEu4NXED7d4@wpgetapi.local>
X-Mailer: PHPMailer 6.9.3 (https://github.com/PHPMailer/PHPMailer)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8

Testing multiple headers

Additional Notes

  • Tested single-line notation for multiple CC/BCC addresses:
    $headers = [
    	'From: Me Myself <me@example.net>',
    	'Cc: Fo McFoo <foo@example.com>, bar@example.com',
    ];
    
  • ✅ Email sent successfully with this format as well.
  • ✅ Verified default WordPress email functionality (e.g., password reset link) sent successfully without issues.

Supplemental Artifacts

Associative array headers: https://prnt.sc/SS32Bczx-Qhr
Single-line notation headers: https://prnt.sc/SL4h2-1N95xD

This ticket was mentioned in Slack in #core-test by nikunj8866. View the logs.


5 weeks ago

#17 @SirLouen
5 weeks ago

  • Milestone changed from Future Release to 6.9

This patch has been well tested and reviewed by now.
Ready to be shipped.

This ticket was mentioned in Slack in #core by welcher. View the logs.


2 weeks ago

#19 @SirLouen
13 days ago

  • Keywords changes-requested added
  • Milestone changed from 6.9 to Future Release

As @westonruter suggested, Content-Type is not being considered into the tests, neither the possibilities among a full header as array.

I'm going to put back this into Future Milestone and see if I can give it a second thought to improve the code.

Edits are not superdifficult as the logic is 95% there, but I need to review both unit tests and the emoji part (also I don't like the fact that the emoji is replicating part of the logic within wp_mail, same logic could pretty much cover both scenarios without replication of code)

Last edited 13 days ago by SirLouen (previous) (diff)
Note: See TracTickets for help on using tickets.