#63127 closed defect (bug) (duplicate)
wp_mail resets custom headers when headers array is set to empty, causing loss of custom header data (e.g., boundary)
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | Priority: | normal | |
| Severity: | normal | Version: | 6.7.2 |
| Component: | Keywords: | ||
| Focuses: | Cc: |
Description
In WordPress wp_mail function, when custom headers are passed as an array, the headers array is being reset to an empty array in line 278. This results in the removal of any custom headers, including important headers like boundary for multipart emails, which causes issues when sending emails with custom content types or attachments.
Steps to Reproduce:
- Call wp_mail with custom headers that include a boundary in the Content-Type.
- WordPress internally resets the headers array to an empty array (line 278).
- Custom headers, including the boundary, are lost in the final email sent by wp_mail.
Expected Behavior:
The custom headers passed into the wp_mail function, including boundary in the Content-Type, should not be reset by WordPress and should be preserved in the final email headers.
Possible Fix:
Avoid resetting the headers array to an empty array in wp_mail. Instead, the function should either:
- Merge the custom headers correctly with the default ones, or
- Handle custom headers separately to ensure they are retained.
Change History (5)
#2
@
8 months ago
Yes, i wanted to add a boundary to the header. The only way it will be processed is to add it as a third array element.
<?php $boundary = uniqid (); $headers = array ('From: WordPress System <wordpress@domain.com>', 'Content-Type: multipart/related; charset=UTF-8;', 'boundary="' . $boundary . '"');
In x-debug I could see that the boundary is recognized. However, it is no longer included on the way to the phpmailer. And so it is not included in the final email.
#3
@
3 months ago
- Resolution set to duplicate
- Status changed from new to closed
Hello @regnalf
This is not a problem of wp_mail but PHPMailer
Long story short: If you pass a Content-Type to PHPMailer as a custom header, without using their functions, it will default into a simple Content-Type header, that removes the boundary.
This is more detailed in #15448 (explained in detail here)
There is a workaround, by using phpmailer_init hook, and inserting the multipart as PHPMailer likes (I'm assuming you are trying to send a multipart email, if you are trying to set the boundary in the Content-Type)
The workaround looks like this:
<?php add_action('phpmailer_init','wp_mail_set_text_body'); function wp_mail_set_text_body($phpmailer) { if (empty($phpmailer->AltBody)) {$phpmailer->AltBody = wp_strip_all_tags($phpmailer->Body);} }
And then you can pass a $message to wp_mail() with the HTML part, and you will see that the multipart with the automatic boundaries will be working flawlessly thanks to PHPMailer internals.
Thanks @regnalf. It looks like custom data gets processed in the following block after saving the $headers data to a $tempheaders variable.
See: https://github.com/WordPress/wordpress-develop/blob/360732e132c009bedd59cff77511514103077f50/src/wp-includes/pluggable.php#L282-L352
Is there a specific header that you expect to be processed that is not being accounted for in that block?