php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #81158 Mails sent by mail function broken since PHP 8.0
Submitted: 2021-06-17 20:13 UTC Modified: 2021-06-17 21:26 UTC
Votes:4
Avg. Score:3.2 ± 0.8
Reproduced:3 of 3 (100.0%)
Same Version:3 (100.0%)
Same OS:1 (33.3%)
From: php at shyim dot de Assigned:
Status: Open Package: Mail related
PHP Version: 8.0.7 OS: Debian 10 (Docker)
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2021-06-17 20:13 UTC] php at shyim dot de
Description:
------------
Setup:

- Mailhog
- SSMTP
- Configured php.ini to ssmtp -t

Execute the test script with 7.4 and 8.0. The email looks correct in 7.4 and its totally broken on 8.0. The headers are in the body in PHP 8.0.

Test script:
---------------
$to      = 'nobody@example.com';
        $subject = 'the subject';
        $message = 'hello';
        $headers = 'From: webmaster@example.com' . "\r\n" .
            'Reply-To: webmaster@example.com' . "\r\n" .
            'X-Mailer: PHP/' . phpversion();

        mail($to, $subject, $message, $headers);

Taken from https://www.php.net/manual/en/function.mail

Expected result:
----------------
The mail is the same on both PHP versions

Actual result:
--------------
It's totally different. The PHP 8.0 doesn't have a subject. I guess it has something done with https://github.com/php/php-src/commit/6983ae751cd301886c966b84367fc7aaa1273b2d#diff-c6922cd89f6f75912eb377833ca1eddb7dd41de088be821024b8a0e340fed3df

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-06-17 20:15 UTC] php at shyim dot de
Here is a screenshot of the sent mail. The headers have always two new lines instead one:
https://i.imgur.com/iQEaUyi.png
 [2021-06-17 20:40 UTC] tiffany@php.net
Please keep in mind that CRLF for email headers is what's specified in the email RFC.

https://datatracker.ietf.org/doc/html/rfc2822#section-2.2
 [2021-06-17 21:13 UTC] php at shyim dot de
The headers are in CRLF in the example. Or was it a general comment?
 [2021-06-17 21:26 UTC] cmb@php.net
-Type: Bug +Type: Documentation Problem
 [2021-06-17 21:26 UTC] cmb@php.net
The fix for the bug, which has been reported more than ten years
ago, had deliberately been delayed to PHP 8 (a new major version).
It should probably get a changelog entry, but I am against
reverting this fix.  If your mail software replaces CRLF with
CRLFCRLF, or whatever, in mail headers, consider to report that
bug upstream.
 [2021-06-17 22:03 UTC] php at shyim dot de
You are correct. ssmtp and busybox sendmail doesn't care about CRLF. Where the postfix sendmail does the job correct.
 [2022-07-15 11:20 UTC] php-nospam at ecartz dot biz
While it is true that the email standard is CRLF, that's not really the issue here.  PHP invokes sendmail via the shell.  The Linux shell expects line endings to be LF.  Then the sendmail app converts the LF to CRLF.  As far as I know, that's how every shell-invoked sendmail works so as to allow people to pipe text directly to sendmail.  

sendmail me@example.com < body.txt

So what this change did, is it made PHP munge the line endings into ones that would be invalid to the shell.  This then breaks those sendmail apps that when invoked by shell expect line endings valid in the shell and replace the shell's line endings with those valid in an email without further checking to see if the line endings are already valid in an email.  

Prior to this change, those of us who maintain frameworks that run on many systems would tell people to us SMTP with CRLF line endings on Windows and sendmail with LF line endings on Linux.  Now, we have to tell people to use LF line endings on Linux when PHP < 8 and CRLF the rest of the time.  And if they happen to be using a sendmail that can't handle CRLF, tell them to switch sendmail.  And to make this worse, PHP didn't bother to report this in the changelog for PHP 8.  So I spent some time trying to figure out what changed from 7.4 to 8 (and only found it in a Drupal bug report).  

Now, it may be that the reasons for this change outweigh the reasons against it.  No one has linked any other bug reports that this change would fix, so I can't say.  But at minimum, it should be reported at https://www.php.net/manual/en/migration80.incompatible.php so that people can find it.  

It's also worth noting that another way of looking at the problem is that PHP is invoking sendmail via the shell.  If you want to send emails with CRLF, then the proper way is to invoke via SMTP.  SMTP expects CRLF line endings.  If PHP would make the SMTP connection directly without invoking sendmail through the shell, then this wouldn't be an issue.  Of course, then you would have to maintain code to email via SMTP.  

Alternately, you could allow systems to specify the line ending to use in php.ini so that they could configure it together with sendmail.  Then just do something like `if (ini_get('sendmail.fix-line-endings') ) $email = str_replace(["\r\n", "\r", "\n"], ini_get('sendmail.line-ending'), $email)` to fix the line endings.  Most frameworks use some kind of solution like this, controlling the behavior with configuration.

Long term, it looks like most hosts are switching to authenticated SMTP.  You might consider adding support for that in the mail function.  Or replacing mail entirely with a class where various properties can be set.  

My gut instinct is that the problem is that you are using the shell but trying to use the email RFC rules.  So I would think that the old behavior was correct and the new behavior is wrong.  But as I said, there may be reasons unknown to me why CRLF is necessary even when invoking through the shell.  If so, could you please link to places where this is discussed so that we can see what's going through your mind?  

All I see is https://bugs.php.net/bug.php?id=47983 which doesn't talk about the shell at all, even though this behavior should clearly be different based on the communication method.  Looking at the patch suggests that you do have separate behavior between Windows and Linux, so you could use the system line ending in the shell.
 [2022-12-12 05:24 UTC] farid dot jamili4118 at gmail dot com
That's great. I was impressed by your writing. I am happy to see such a topic. Please come to my blog and read it.

 (https://www.mygiftcardsite.vip/)php.net
 [2022-12-22 10:48 UTC] Rester256Walsh at gmail dot com
Add a mail header in the mail function:

$header = "From: noreply@example.com\r\n";
$header.= "MIME-Version: 1.0\r\n";
$header.= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$header.= "X-Priority: 1\r\n";

$status = mail($to, $subject, $message, $header);

if($status)
{
    echo '<p>Your mail has been sent!</p>';
} else {
    echo '<p>Something went wrong. Please try again!</p>';
}


(https://www.mycenturahealth.us/)github.com
 
PHP Copyright © 2001-2023 The PHP Group
All rights reserved.
Last updated: Thu Feb 02 14:03:58 2023 UTC