WordPress.org

Make WordPress Core

Opened 10 months ago

Last modified 6 weeks ago

#39753 accepted defect (bug)

wp_mail() under PHP 7 hosted on Windows creates malformed email messages

Reported by: Andy Schmidt Owned by: SergeyBiryukov
Milestone: Future Release Priority: normal
Severity: normal Version: 4.7.2
Component: Mail Keywords: has-patch needs-testing
Focuses: Cc:

Description

Synopsis: WordPress’ wp_mail function uses the third party component PHPmailer 5. PHPmailer 5 relies on the standard PHP mail() function for final delivery. With PHP 7.x hosted on Windows, WordPress mails are being rejected by providers, such as Gmail, due to RFC violations.

Reason: PHPmailer->LE (Version 5) defaults to a lone "LF" (\n) as the end-of-line character. That is in violation of SMTP, which expressly forbids lone LF characters. This known error in PHPmailer 5 and has been be resolved with (not yet released) PHPmailer 6.

Fortunately for WP (and other CMS'), Linux has an operating system default of "LF", so its mailer programs have always translated lone LF to CR/LF when creating SMTP data streams.

And, in PHP 5, the Windows implementation of mail() has always "fixed" lone "LF" by replacing them with CR/LF. Consequently, WordPress (et al) have worked in both environments.

As of PHP 7, the Windows implementation of mail() requires standards compliant input and no longer fixes malformed headers. The lone "LF" characters of the incorrect PHPmailer 5 defaults now "bleed" through and result in malformed SMTP data streams. (Linux is not effected, because PHP continues to launch the operating system's mailer programs.)

At a future time PHPmailer 6 will be the final solution.

In the meantime, WordPress wp_mail needs to explicitly set $phpmailer->LE = '\r\n' right after this line:

$phpmailer = new PHPMailer( true );

Attachments (1)

39753.patch (537 bytes) - added by bor0 6 months ago.

Download all attachments as: .zip

Change History (27)

#1 @SergeyBiryukov
10 months ago

  • Milestone changed from Awaiting Review to 4.7.3

#3 @Andy Schmidt
10 months ago

  • Keywords reporter-feedback added

Dear Kelderic, yes, I had noted that thread regarding PHPmailer 6. Since it seems that the underlying cause had not been discovered by them, I have now posted the information to their thread, about the breaking change in PHP 7 with the win32 implementation of mail(), and the intended future major change to mail().

I also suggested to them a pragmatic approach for PHPmailer 6 which would maintain backward compatibility with both operating system families and both PHP versions.

(The whole thing is quite a mess. If have been watching generations of PHP developers trying tackle this for more than 10 years, alternately trying to enforce RFC compliance, followed by retractions when they realize the legacy impact.)

#4 @Andy Schmidt
10 months ago

To avoid the possibility of side effects with legacy Linux mailers that might mangle RFC compliant line endings, you could either use the operating system line-end as the default value, e.g.:

$phpmailer = new PHPMailer( true );

<<insert here>>

$phpmailer->LE = PHP_EOL;

In essence, you would leave the default of \n in place for Linux, and would only change it to \r\n, which is proper for SMTP, which is the method used by Windows.

You could also make it operating system dependent, if you prefer:

$phpmailer = new PHPMailer( true );

<<insert here>>

if ( stripos(PHP_OS, 'WIN') === 0 ) { Windows uses SMTP, mandating RFC compliant line ending

$phpmailer->LE = '\r\n';
}

Explanation: Linux implementations are not affected by the change in PHP 7 because they launch command line mailers which have always been prepared to accept lines terminated by \n (their operating system default) as input. Those mailers will output proper \r\n when mailing anyway.

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


9 months ago

#6 @SergeyBiryukov
9 months ago

  • Owner set to SergeyBiryukov
  • Status changed from new to accepted

#7 @dd32
9 months ago

Reading https://github.com/PHPMailer/PHPMailer/issues/953 it sounds like this ended up being a bug in PHP 7.0/7.1 and will be fixed in the NEXT stable releases (7.0.17/7.1.3) for both branches.

I'd like to suggest that this is potentially something which we could skip working around, and assume that the minority of people using PHP 7.x on windows are more likely to update to recent releases - especially considering the level of breakage encountered in these scenario's.

If we do add a fix here however, we should specifically limit the fix to affected versions + environments (ie. Windows only, and PHP 7.x <= 7.0.16
7.1.2).

#8 @Andy Schmidt
9 months ago

Yes, I have worked my way upstream (securing fixes for PHP 7.0/7.1 and in PHPmailer 6), so that each step will use appropriate behavior. Being consistent throughout will avoid this problem flipping back and forth every so often.

So, let me just point to the PHP manual for mail():
http://php.net/manual/en/function.mail.php

PHP states clearly that both data as well as header ought to be terminated with \r\n.

It seems that at some point, WordPress should commit to follow the prescribed behavior as much as possible while being mindful about backward incompatibility with legacy Linux systems.

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


9 months ago

#10 @jnylen0
9 months ago

  • Milestone changed from 4.7.3 to 4.7.4

I'm going to punt this to 4.7.4 given that it doesn't have a patch yet, and may not be something we want to work around per comment:7.

#11 @dd32
9 months ago

PHP states clearly that both data as well as header ought to be terminated with \r\n.

It seems that at some point, WordPress should commit to follow the prescribed behavior as much as possible while being mindful about backward incompatibility with legacy Linux systems.

My feeling here is that we should stick to PHPMailer's defaults - If PHPMailer releases an updated version in the 5.x series which uses \r\n we'll update to that.

#12 @swissspidy
8 months ago

  • Keywords reporter-feedback removed

The good news is that the original bug got fixed in PHP 7.1.3/7.0.17 yesterday. However, there's still no update for PHPMailer. I guess we just have to wait for that upstream fix and hope a PR emerges in time.

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


8 months ago

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


7 months ago

#15 @swissspidy
7 months ago

  • Keywords needs-patch added

#16 @swissspidy
7 months ago

  • Milestone changed from 4.7.4 to 4.7.5

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


6 months ago

#18 @desrosj
6 months ago

  • Milestone changed from 4.7.5 to 4.8.1

Punting since there has been no activity on this by PHPMailer.

@bor0
6 months ago

#19 @bor0
6 months ago

  • Keywords has-patch added; needs-patch removed

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


4 months ago

#21 @jbpaul17
4 months ago

  • Keywords needs-testing added

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


4 months ago

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


4 months ago

#24 @jbpaul17
4 months ago

  • Milestone changed from 4.8.1 to 4.9

Punting to 4.9 to give us time to confirm whether the upstream PHPMailer patch resolves this issue (in which case we can close this ticket) and if it does not resolve the issue then to give time to confirm if the existing patch needs a refresh or is otherwise good to go.

#25 @westonruter
6 weeks ago

  • Milestone changed from 4.9 to Future Release

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


6 weeks ago

Note: See TracTickets for help on using tickets.