Problem/Motivation

Using Drupal 7 with php 8.0.24.

When sending a Test E-Mail with the htmlmail modul the received e-mail has not the correct format.
The Test Mail Sending Class is HTMLMailSystem.
If the DefaultMailSystem Class is used, then the content of the receiving email is correct.

With the HTMLMailSystem Class following content is received.

<h1><a href="http://drupal.org/project/htmlmail">HTML Mail</a> test message</h1>
<div class="htmlmail-body">
<p>Test<br />
- asdfsda<br />
- asdfasdf</p>
</div>

Following E-Mail Header:

Arc-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of xx@xx.de designates 91.250.69.35 as permitted sender) smtp.mailfrom=xx@xx.de
Mime-Version: 1.0 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 8Bit X-Mailer: Drupal Return-Path: xx@xx.de Sender: xx@xx.de From: "xxx" <xx@xx.de>
Authentication-Results: mx.google.com; spf=pass (google.com: domain of xx@xx.de designates 91.250.69.35 as permitted sender) smtp.mailfrom=xx@xx.de
X-Bounce-Key: webpack.hosteurope.de;xx@xx.de;1667550549;5c2f9c70;
X-He-Smsgid: 1oqs4a-0002uV-Fu
Return-Path: <xx@xx.de>
Arc-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=date:from:message-id:mime-version:subject:to; bh=h/z7be5KasC87Q2mKTeaa8zkUTRc84oFD+/UT9xIC1s=; b=GAOMjy1BdAzalLc+rg1o5W0NZq3dj0orhXQWygYlXbZC6FXR3EMZCK6EK3Y9DUmfc+ pkzNeJjdDDaUKXZ0WX1mVUgnrgWYBZFnP7Ip1Xo3VhiCqdMMDEUA6F7LnGHhsDy8f7/M x4IyYURxTyLHKfdYpGFdHeJxalwcYMuVaKFSm4Xca94bGvZB0qkoToGnyzrhnQEVamZk 6Pva8iK0hxKymB3s+BTa300DrtMF2qWFJ3b7+P9TNTGHP5CdaFBo+62ECt0tZCJcNI4g Z3awXPn2I9mQHpqR1DC1nvfT9nTg3gw9TsBxiYrG8CG7O1uL7OUBAeApkrwGfDsmBmr+ P1kg==
Arc-Seal: i=1; a=rsa-sha256; t=1667550549; cv=none; d=google.com; s=arc-20160816; b=UCaRZwsqnURzNP7goWqfUzny5k7JZt1x9xSVZ+6oyTwwKKlIygfSgSeEB3AnuitZXN w0e2+gJUQ4xjreyCaTX7Tc/V7WohY/noI7Ixtj5lXZ9/kDVsnNdXBYgAMv92NsLDX7IK G+Kua3MfRrFsPD3Y9ELHvpBj8fDYj+WadttWMHTfdBEvjZboGW2hFCkh9eUR1dd1m2YZ j6jwDW6cT1umrffluxNB0zZKKwzsN4VlvEiiKCc0FZXamdte5lF/q1E7Tv79E0JrjO0f lC4YSTCgR70lAMa14JrEGj1UzygMan3dgiTSVED9cDeUv1vyDaAKhrzD6p+L981tgh7S qEWg==
X-Received: by 2002:a05:600c:a0b:b0:3b4:f9a7:f79b with SMTP id z11-20020a05600c0a0b00b003b4f9a7f79bmr31755843wmp.99.1667550549148; Fri, 04 Nov 2022 01:29:09 -0700 (PDT)
Received: by 2002:a05:7022:219a:b0:46:d7aa:21b9 with SMTP id bh26csp98495dlb; Fri, 4 Nov 2022 01:29:09 -0700 (PDT)
Received: from xxx.webpack.hosteurope.de (xx.webpack.hosteurope.de. [91.250.69.35]) by mx.google.com with ESMTPS id g9-20020adfd1e9000000b0023a43b7cd83si1680925wrd.599.2022.11.04.01.29.08 for <xx.xx@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Nov 2022 01:29:09 -0700 (PDT)
Received: from localhost ([127.0.0.1]) by xxx.webpack.hosteurope.de running ExIM with local id 1oqs4a-0002uV-Fu; Fri, 04 Nov 2022 09:29:08 +0100
Received-Spf: pass (google.com: domain of xx@xx.de designates 91.250.69.35 as permitted sender) client-ip=91.250.69.35;
Delivered-To: xx.xx@gmail.com
<E1oqs4a-0002uV-Fu@xx.webpack.hosteurope.de>
X-He-Php-Submitted: yes
X-Google-Smtp-Source: AMsMyM4vmHbu3b4jDkbFIIgJLCcYx1V6kPaRZmFyNqbMl6hk5CVtq8hP3G6uGQki4kXa0Idq5mrD

Issue fork drupal-3319062

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

down2under created an issue. See original summary.

longwave’s picture

HTML Mail is not part of Drupal core. Is this a duplicate of #3318128: PHP 8 HTML Test Message fails?

down2under’s picture

Yes, they suggest to post a issue here.

longwave’s picture

But then this is just a duplicate of #3270647: PhpMail : broken mail headers in PHP 8.0+ because of LF characters? You can help by testing the patch over there, posting a duplicate issue won't help get it fixed more quickly.

down2under’s picture

But that patch is for version 9. I am using drupal version 7

poker10’s picture

Title: PHP 8 HTML Mail is incorrect » [D7] PhpMail : broken mail headers in PHP 8.0+ because of LF characters
Priority: Normal » Major

Yes, it is possible that this is the same problem as in the D9/10 issue. I think we need to be cautious with the D7 fix, because we can easily broke this for some other sites using PHP 7.4 and lower, see:

the "mail" function is replacing CRLF characters by LF characters, because some MTA may misinterpret CRLF and convert CRLF into CRCRLF.

and also this: https://bugs.php.net/bug.php?id=81158

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.

So I think this fix (line-endings change from LF to CRLF) needs to be done only for PHP 8 (or only as opt-in approach).

Retitled the issue and changed the priority to correspond the D9/10 issue. Correctly this issue should be postponed (as per backport policy), but lets wait a bit for the approach in the D9/10 issue. Because I think that at least for D10 the approach will be a bit different, as the minimum PHP version in D10 is 8.1, so it does not need to care about what was working on lower PHP.

rclemings’s picture

What would the fix look like for Drupal 7?

I tried changing line 68 of /modules/system/system_mail_inc and it had no effect:

from:
$mail_headers = join("\n", $mimeheaders);
to

$mail_headers = join("\r\n", $mimeheaders);

Insofar as PHP7 is now officially EOL it would be nice to get a patch that works for Drupal 7, even if it came with a warning not to use it with PHP<8.

Here's what I see in the emails:

PHP7.4:

X-PHP-Script: xxx.xxxx.xxx/index.php for xx.xx.x.xx(CRLF)
X-PHP-Originating-Script: 1022:mimemail.module(CRLF)
MIME-Version: 1.0(CRLF)
Content-Type: multipart/mixed; boundary="2b2f18089ded86e7e78fb7efac1da77458809f9e3"(CRLF)
Content-Transfer-Encoding: 8Bit(CRLF)
X-Mailer: Drupal(CRLF)
From: "XxxxxxxXxxxxxx (xxx.xxxx.xxx)" <xxxxxxxxx@xxxx.xxx>(CRLF)
x-bounce-identifier: 03662?d8-ac63-!b07-aaf!-71!a131d8e0e(CRLF)
Message-Id: <E1oz5x5-0005up-DT@xxxx2.xxxxxxxxxxxx.xx>(CRLF)
Date: Sun, 27 Nov 2022 00:55:23 +0000(CRLF)

PHP8.1:

X-PHP-Script: xxx.xxxx.xxx/index.php for xx.xx.x.xx X-PHP-Originating-Script: 1022:mimemail.module(CRLF)
MIME-Version: 1.0 Content-Type: multipart/mixed;(CRLF)
  boundary="442a7dab9ef2b2160683d0bfc284bf7a1f4ef8dc3" Content-Transfer-Encoding: 8Bit X-Mailer: Drupal Sender: "XxxxxxxXxxxxxx (xxx.xxxx.xxx)" <xxxxxxxxx@xxxx.xxx> From: "XxxxxxxXxxxxxx (xxx.xxxx.xxx)" <xxxxxxxxx@xxxx.xxx> x-bounce-identifier: 2d011!21-c1b7-!ddf-bef7-!?d3bfb8!b8f(CRLF)
Message-Id: <E1oz5vV-0005q4-1Y@xxxx2.XxxxxxxXxxxxxx.xx>(CRLF)
From: xxxxxx@xxxx.xxx(CRLF)
Date: Sun, 27 Nov 2022 00:53:45 +0000(CRLF)

I inserted "(CRLF)" manually. Among other things, some are missing.

arx-e’s picture

For me changing line 68 of /modules/system/system_mail_inc
to $mail_headers = join("\r\n", $mimeheaders); as described in #7 solved the problem with webform mails.

But while trying to solve similar issue in other sites i had some success changing line 13 of includes/mail.inc

I also added the following lines in settings.php (one of them is for use by the mimemail module)

$conf['mail_line_endings'] = "\r\n";
$conf['mimemail_crlf'] = "\r\n";

rclemings’s picture

@arx-e: How did you change line 13 of includes/mail.inc?

I did this (which of course could be abbreviated) and it works, but I'm worried it could have some unpredictable side effects.

define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') !== FALSE) ? "\r\n" : "\r\n");

This is on a CentOS server v7.9.2009, so not Windows.

I also made the other changes you listed but they didn't work until I changed line 13.

arx-e’s picture

@rclemings I did the same thing as you as a quick solution with minimal editing.
And it worked for some system messages but not for webform messages for example.

I read in an old issue that LF ("\n) is what should be used in Linux systems and CRLF ("\r\n") was reserved only for windows servers.
I am not sure but maybe this has changed?
The old issue is this one drupal_mail(), CRLF, and Windows

arx-e’s picture

I suppose if it is safe to have it universally as CRLF, this could be shortened to something like this:
define('MAIL_LINE_ENDINGS', "\r\n");

rclemings’s picture

Right above line 13 in includes/mail.inc it says:

 * $conf['mail_line_endings'] will override this setting.

So I added this to settings.php:

$conf['mail_line_endings'] = "\r\n";

and it had no effect. I had to change line 13 in includes/mail.inc from:

define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') !== FALSE) ? "\r\n" : "\n");

to:

define('MAIL_LINE_ENDINGS', "\r\n");

and then outgoing emails were properly formatted (using CentOS 7.9.2009, PHP 8.1, Drupal 7.94, Commerce Email 7.x-2.x-dev, HTML Mail 7.x-2.71, and Mime Mail 7.x-1.2). I checked the password reset email, a Simplenews newsletter, and order notifications from Commerce 1.x and all looked correct.

I'm not smart enough to troubleshoot this further but it looks as if there's something squirrelly about how $conf['mail_line_endings'] works with this combination.

rclemings’s picture

Status: Active » Needs review
StatusFileSize
new439 bytes

Here's a patch with the fix from #12. Works for me (using CentOS 7.9.2009, PHP 8.1, Drupal 7.94, Commerce Email 7.x-2.x-dev, HTML Mail 7.x-2.71, and Mime Mail 7.x-1.2), but not tested otherwise.

Status: Needs review » Needs work

The last submitted patch, 13: d7email_header_fix-3319062-13.patch, failed testing. View results

aitala’s picture

Hi,

I'm not sure this is working... I'm still getting the leading spaces..

X-PHP-Script: ipmsusa.org/index.php for 71.58.100.178
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8; format=flowed; delsp=yes
 Content-Transfer-Encoding: 8Bit
 X-Mailer: Drupal
 Sender: webmaster@ipmsusa.org
 From: "ema13@psu.edu via IPMS/USA Home Page" <webmaster@ipmsusa.org>
 Reply-To: ema13@psu.edu

This is with D7.94, PHP 8.1.16, no special Mailers... and with (and without) the patch from https://www.drupal.org/node/111702

Thx,
Eric

arx-e’s picture

The modification as in patch #13 had resolved the problem for me but the issue resurfaced the last couple of weeks or so.

I just now discovered another place where the same modification resolves the issue again:
line 67 in modules/system/system.mail.inc is now
$mail_headers = join("\n", $mimeheaders);

and it obviously ruins the messages.
This modification solved the problem again:
$mail_headers = join("\r\n", $mimeheaders);

arx-e’s picture

Status: Needs work » Needs review
StatusFileSize
new1.28 KB

And here is a patch containing both modifications (#13 + #16).

aitala’s picture

Patch #17 seems to have worked for me.

Thanks,
Eric

Status: Needs review » Needs work

The last submitted patch, 17: d7email_header_fix-3319062-17.patch, failed testing. View results

edvanleeuwen’s picture

Manually applied the changes. This works.

jbiechele’s picture

I also can confirm that the patch in #17 works, on two D7 sites with PHP 8.2. Thanks for the patches.

chase.’s picture

Running installations on Debian-based distributions with exim4 or Postfix, the patch from #17 fixes the issue without noticeable side-effects.

poker10’s picture

Thanks for confimation that the patch is working! However, the patch has a number of failures, so either is it not working correctly in all cases, or the tests needs to be updated. Unfortunatelly it cannot be committed in the current shape until we deal with the failing tests.

arx-e’s picture

StatusFileSize
new6.97 KB

As far as I managed to understand the tests fail because of the drupal_html_to_text function that is found in the includes\mail.inc file.
But I also found lots of other places where LF line endings are being used.
And from what is stated here https://www.drupal.org/project/drupal/issues/3270647 the line endings should be CRLF for PHP 8+ and LF for prior PHP versions except on Windows servers.
So in this patch I have tried to define line endings according to the php version and server software and I replaced all occurrences of LF with a variable $line_endings
My experience with code is relatively limited so I don't really know whether all those changes are needed and/or correct but I have tested these modifications at one Drupal 7.98 site and it seems to be working without any issues.

arx-e’s picture

StatusFileSize
new3.46 KB

One more patch keeping the logic that distinguishes between PHP versions and uses CRLF only when PHP is 8 or 8+ or when on a Windows server.
The rest of the changes have been kept to a minimum but the result works for me on a couple PHP8 sites.

arx-e’s picture

StatusFileSize
new3.54 KB

Reuploading the patch as the last one had a syntax error.

edvanleeuwen’s picture

Tested and verified patch #26.

poker10’s picture

Thanks for working on this @arx-e!

Only a quick review / questions:

1. Are we sure we need all these changes to the $message['body'] formatting and drupal_html_to_text()?

 function drupal_wrap_mail($text, $indent = '') {
-  // Convert CRLF into LF.
-  $text = str_replace("\r", '', $text);
   if (count($urls)) {
-    $footnotes .= "\n";
+    $footnotes .= MAIL_LINE_ENDINGS;
     for ($i = 0, $max = count($urls); $i < $max; $i++) {
-      $footnotes .= '[' . ($i + 1) . '] ' . $urls[$i] . "\n";
+      $footnotes .= '[' . ($i + 1) . '] ' . $urls[$i] . MAIL_LINE_ENDINGS;
-          $output .= drupal_wrap_mail('', implode('', $indent)) . "\n";
+          $output .= drupal_wrap_mail('', implode('', $indent)) . MAIL_LINE_ENDINGS;
-    $message['body'] = implode("\n\n", $message['body']);
+    $message['body'] = implode($line_endings, $message['body']);

The issue summary does not mention any problems with the mail body and the parent D10 issue have not made any changes to the mail body as well. I am curious if it wouldn't be sufficient to make only this change:

-    // For headers, PHP's API suggests that we use CRLF normally,
-    // but some MTAs incorrectly replace LF with CRLF. See #234403.
-    $mail_headers = join("\n", $mimeheaders);
+    // Use here also the vcariable MAIL_LINE_ENDINGS
+    $mail_headers = join($line_endings, $mimeheaders);

Plus the change to the MAIL_LINE_ENDINGS constant definition, which looks reasonable. If a change to the mail body is needed, then we should explain the reasons for this change.

2. Core is not using PHP_MAJOR_VERSION constant anywhere, let's use the standard comparision used on other places:

PHP_VERSION_ID < 80000;

3. If the updated patch will pass on all PHP versions, we should also backport the new test from D10.

arx-e’s picture

StatusFileSize
new1.85 KB

@poker10
No, I was not at all sure about those changes. I was just trying to make the tests work.

So i am uploading a new patch with only:
1. the change in the definition of MAIL_LINE_ENDINGS in includes/mail.inc
2. and the change in modules/system/system.mail.inc

stevewilson’s picture

I've manually applied the changes at #29 which seem to fix the issue for me.

I'm keen to see the fix for this issue committed, so I'd be really appreciative if somebody could sort out the issues with the failed tests that seem to be the stumbling block. I'd be happy to help, but as I'm not a programmer I'm not sure how I could actually contribute.

danrod’s picture

I had the exact same issue and the patch #29 worked fine, solved the issues that I had the the outgoing email format.

Thank you !

davidwhthomas’s picture

Status: Needs work » Needs review

The patch in #29 fixed the issue I was having with line endings being stripped in mail headers, preventing html email being sent, in Drupal 7.102
The email headers would show all on one line and the email body shows the plain text html tags.
After the patch, the headers are formatted correctly and the email comes through HTML formatted, with thanks.

Before:

MIME-Version: 1.0 Content-Type: text/html; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8Bit X-Mailer: Drupal Sender: email@example.com From: Example <email@example.com>

After:

MIME-Version: 1.0
Content-Type: text/html; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8Bit
X-Mailer: Drupal
Sender: email@example.com
From: Example <email@example.com>
mcdruid’s picture

#29 looks reasonable but I'd be happier committing this if we could verify that the comment above the changes to the constant is true:

	  * $conf['mail_line_endings'] will override this setting.
	  */

In other words, I'd like to ensure that sites can override these changes if they need to (e.g. because they use a quirky MTA or similar).

An earlier comment in this issue suggested that the $conf / variable does not in fact override the constant.

It'd also be good to see tests passing in an MR with the new d.o testing pipeline.

poker10’s picture

Status: Needs review » Needs work

I converted the patch #29 to the MR and it is failing on PHP8+: https://git.drupalcode.org/project/drupal/-/pipelines/358167

I think the reason is in drupal_html_to_text , which in D7 uses:

$output .= drupal_wrap_mail($chunk, implode('', $indent)) . MAIL_LINE_ENDINGS;

but in D10:

$line_endings = Settings::get('mail_line_endings', PHP_EOL);
// Format it and apply the current indentation.
$output .= static::wrapMail($chunk, implode('', $indent)) . $line_endings;

I compared the tests and they looks the same, so this seems like the only difference. On Linux, PHP 8, in D7, after the patch is applied there will be "\r\n", but on Linux, PHP8, in D10 it is just "\n".

I can update the test with a similar code from D10:

$line_endings = variable_get('mail_line_endings', PHP_EOL);
$output .= drupal_wrap_mail($chunk, implode('', $indent)) . $line_endings;

But the question is, if this is a sign of the broken test, or we are unintentionally changing something else.

//edit: if we update it to

$line_endings = variable_get('mail_line_endings', MAIL_LINE_ENDINGS);
$output .= drupal_wrap_mail($chunk, implode('', $indent)) . $line_endings;

Then I think it will still fail, because we are not testing the variable, therefore the outcome will be the same as the current state with only MAIL_LINE_ENDINGS used.

poker10’s picture

It is still failing on PHP8:

I think the patch is not correct.

D10 code:

    $line_endings = Settings::get('mail_line_endings', PHP_EOL);
    // Prepare mail commands.
    $mail_subject = (new UnstructuredHeader('subject', $message['subject']))->getBodyAsString();
    // Note: email uses CRLF for line-endings. PHP's API requires LF
    // on Unix and CRLF on Windows. Drupal automatically guesses the
    // line-ending format appropriate for your system. If you need to
    // override this, adjust $settings['mail_line_endings'] in settings.php.
    $mail_body = preg_replace('@\r?\n@', $line_endings, $message['body']);
    $mail_headers = $headers->toString();

D7 code:

    $line_endings = variable_get('mail_line_endings', MAIL_LINE_ENDINGS);
    // Prepare mail commands.
    $mail_subject = mime_header_encode($message['subject']);
    // Note: e-mail uses CRLF for line-endings. PHP's API requires LF
    // on Unix and CRLF on Windows. Drupal automatically guesses the
    // line-ending format appropriate for your system. If you need to
    // override this, adjust $conf['mail_line_endings'] in settings.php.
    $mail_body = preg_replace('@\r?\n@', $line_endings, $message['body']);
    // Use here also the variable MAIL_LINE_ENDINGS
    $mail_headers = join($line_endings, $mimeheaders);

You can see, that if we change the MAIL_LINE_ENDINGS in D7, it does change also the body line endings, which I suppose is something we do not want to change. These line endings should be only linux/windows dependent. But after the proposed change, on PHP8, also the body has "\r\n" even on linux. That is a cause of the failure.

The correct approach seems to be to only touch headers, as proposed in the issue summary and issue title. So to change this line:

    $mail_headers = join("\n", $mimeheaders);

to be "\n" on PHP<8 and "\r\n" on PHP>=8.

poker10’s picture

Status: Needs work » Needs review

I have updated the MR according to my findings from #36 (the comment I have used in the code is borrowed from Drupal 9.5, see: https://git.drupalcode.org/project/drupal/-/commit/40ad8b5e57e3dc534de77...).

Tests are now green: https://git.drupalcode.org/project/drupal/-/pipelines/358280

poker10’s picture

But now the change cannot be opted-out by using $conf['mail_line_endings']. Should we introduce another variable? I did not want to use an existing one, because as we found out, mixing line endings and header line endings is not a good option.

mcdruid’s picture

Sounds like it might make sense to add another variable; perhaps one we wouldn't add to default.settings.php if it's intended to accommodate sites with edge case mail setups.

poker10’s picture

Issue tags: +Needs change record

Added a new variable mail_headers_line_endings.

Tests are green: https://git.drupalcode.org/project/drupal/-/pipelines/358322

I think it is still worth a manual testing - at least to compare the email headers on linux - PHP 7.4 vs 8.0. Plus this will need a change record, in case we will decide to commit it. Thanks!

mcdruid’s picture

Status: Needs review » Reviewed & tested by the community

I think the new patch looks good.

Having yet another conf / variable is not ideal but it obviously avoids the situation where a change like this breaks sites with a certain mail setup and they're left with no choice but to hack core.

@poker10 and I looked at this to do some manual testing; it's a little tricky because MTAs / SMTP servers etc.. tend to be so accommodating of all sorts of weird stuff in email. For example mailpit (very useful tool included in ddev) has a relevant option - which defaults to false:

--smtp-strict-rfc-headers / MP_SMTP_STRICT_RFC_HEADERS

Force Mailpit to return an SMTP error if message headers contain \n instead to \r\n line breaks. By default Mailpit will silently fix incorrect line breaks generated by some broken sendmail clients (see related Github issue).

https://mailpit.axllent.org/docs/configuration/runtime-options/#smtp-server

However turning that on didn't seem to help us verify that anything was broken without the patch. Almost every way of actually testing mail that we tried (including with e.g. mimemail enabled or not) did not seem to show any problem without the patch on PHP8 (although I think we did reproduce html mail appearing a bit broken).

We eventually managed to observe the specific difference that the patch makes using strace to observe what PHP emits when Drupal's mail system sends a message. (FWIW we used https://www.drupal.org/project/drush_debug_tools which includes a command to send test email from drush - it's old and dusty but still works).

So we verified that without the patch, on PHP 8.2, just a couple of the mail headers were separated by only \n. For example:

Errors-To: hello@example.com\nSender: hello@example.com\nFrom: hello@example.com

Whereas with the patch applied, this was:

Errors-To: hello@example.com\r\nSender: hello@example.com\r\nFrom: hello@example.com

It looks like - at least in the testing we were doing - those were the only headers being inserted by the code in question. All other headers were not influenced by these changes (and always had the correct line endings).

So I believe that verifies that this patch is having the desired effect.

If it has any unintended consequences with a particular mail set up, the new variable should allow for the change to be overridden without killing kittens hacking core.

  • mcdruid committed 0e0a0915 on 7.x
    Issue #3319062 by arx-e, poker10, rclemings, down2under, mcdruid, aitala...
mcdruid’s picture

Status: Reviewed & tested by the community » Fixed

Thanks everyone!

poker10’s picture

Issue tags: -Needs change record
pentium’s picture

StatusFileSize
new956 bytes

After the Drupal 7.103 core update, i'm still experiencing a problem with outgoing e-mails using drupal_mail() function.
This is how a 3 rows html test mail body is shown in all the e-mail clients that the receiver uses (including gmail webmail).

This is a multi-part message in MIME format.

--0239714e6c488a2e4f394263b8f561e40c281d241
Content-Type: multipart/alternative;
 boundary="d736db4fc82e3e0f3789544c5fca10674e03b1370"
Content-Transfer-Encoding: 8bit


--d736db4fc82e3e0f3789544c5fca10674e03b1370
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: 8bit

Questa è la prima riga.

Questa è la seconda riga.

Questa è la terza riga.


--d736db4fc82e3e0f3789544c5fca10674e03b1370
Content-Type: text/html; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: 8Bit

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      </head>
  <body id="mimemail-body" class="dmail-smtp-dmail-invio-diretto-html">
    <div id="center">
      <div id="main">
         <p style="color: #ff5733; font-size: 20px; margin-bottom: 10px;">Questa è la prima riga.</p>
    <p style="color: #33c3ff; font-size: 18px; margin-bottom: 10px;">Questa è la seconda riga.</p>
    <p style="color: #28a745; font-size: 16px; font-style: italic;">Questa è la terza riga.</p></div>
    </div>
  </body>
</html>

--d736db4fc82e3e0f3789544c5fca10674e03b1370--

--0239714e6c488a2e4f394263b8f561e40c281d241--

I'm using PHP 8.3 on Almalinux 8.x.
In my Drupal conf, Mail System is set to use Site-wide default MailSystemInterface class => "MimeMailSystem".
I fixed this problem with the attached patch
Hope it may help others with the same problem

mcdruid’s picture

Sorry, I haven't had time to look at the details properly, but do you need to apply a patch?

Can't you fix your problem with the two variables that control the line-endings?

modules/system/system.mail.inc:55:    $line_endings = variable_get('mail_line_endings', MAIL_LINE_ENDINGS);
modules/system/system.mail.inc:65:    $headers_line_endings = variable_get('mail_headers_line_endings', "\n");
pentium’s picture

As you correctly said, we can also adjust the conf "mail_line_endings", because the $message['body'] uses it, while the patch i'm using changes default value in case that "mail_line_endings" is not set.

$line_endings = variable_get('mail_line_endings', MAIL_LINE_ENDINGS);
$mail_body = preg_replace('@\r?\n@', $line_endings, $message['body']);

So, all linux users, must either:
1- Set the "'mail_line_endings'" variable to "\r\n" manually, adding this row to settings.php:
$conf['mail_line_endings'] = "\r\n");

2- Apply the patch, because in the file "/includes/mail.inc" there is this line (line 10):

define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') !== FALSE) ? "\r\n" : "\n");

that re-defines the MAIL_LINE_ENDINGS constant, setting it to "\n" (i'm on linux - AlmaLinux 8.x)

poker10’s picture

So, all linux users, must either:

I do not think this is the only one condition which makes this bug present. We have debugged it pretty long and were unable to reproduce the broken emails with the Drupal core itself. So I suppose this is also dependent on mailserver somehow.

The reason why the patch from #45 is not a good idea are explained in #36. This issue was about changing the header line endings. If we have changed also the MAIL_LINE_ENDINGS constant, the mail body line endings would have changed as well, which is something very different (and Drupal 10/11 also does not have this). If there is an issue with mail body line endings, that is probably a separate issue and hopefully can be solved by fine-tuning values of both variables without the need of any custom core changes.

Re:

2- Apply the patch, because in the file "/includes/mail.inc" there is this line (line 10):

I do not think this is correct/needed anymore. The MAIL_LINE_ENDINGS constant is defined on the top of the mail.inc file. Then, when it is used in the mail() function, there is a possibility to override it via mail_line_endings variable:

DefaultMailSystem::mail():

    $line_endings = variable_get('mail_line_endings', MAIL_LINE_ENDINGS);
    // Prepare mail commands.
    $mail_subject = mime_header_encode($message['subject']);
    // Note: e-mail uses CRLF for line-endings. PHP's API requires LF
    // on Unix and CRLF on Windows. Drupal automatically guesses the
    // line-ending format appropriate for your system. If you need to
    // override this, adjust $conf['mail_line_endings'] in settings.php.
    $mail_body = preg_replace('@\r?\n@', $line_endings, $message['body']);
    // For headers, PHP's API suggests that we use CRLF normally,
    // but some MTAs incorrectly replace LF with CRLF. See #234403.
    $headers_line_endings = variable_get('mail_headers_line_endings', "\n");

So everything from in the mail body should be changed to specified newlines by this line:

$mail_body = preg_replace('@\r?\n@', $line_endings, $message['body']);

The precedence is by the variable, not by the constant. If this code is not working as expected, that is a separate issue.

Can you please doublecheck again, why do you need to change the constant at all? If you are using another mailer and the seding is not done by core DefaultMailSystem::mail(), then it is indeed a problem of the contrib module.

Thanks!

poker10’s picture

Drupal 10/11 is using PHP_EOL for the mail body line endings, so it is not using \r\n in linux, see: https://git.drupalcode.org/project/drupal/-/blob/11.x/core/lib/Drupal/Co...

That is another reason against using the \r\n for the mail body line endings in linux in Drupal 7.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.