Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong line endings with PHP 8.1 and nullmailer #2870

Closed
AdrienPoupa opened this issue Feb 6, 2023 · 4 comments
Closed

Wrong line endings with PHP 8.1 and nullmailer #2870

AdrienPoupa opened this issue Feb 6, 2023 · 4 comments

Comments

@AdrienPoupa
Copy link

AdrienPoupa commented Feb 6, 2023

We recently updated PHPMailer from an ancient 5.2 version to the latest, 6.7.1.

We have a bit of an exotic setup, with PHPMailer using the mail driver, then nullmailer handles sending the email to a remote SMTP server. This is done for performance purposes, so we don't have to wait synchronously for PHPMailer to connect to the SMTP server and block the user while it is doing it.

When sending multi multipart/mixed emails, the raw email looks as follows:

...
X-Mailer: PHPMailer 6.7.1 (https://github.com/PHPMailer/PHPMailer)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="b1=_123"
Content-Transfer-Encoding: 8bit

--b1=_123

Content-Type: text/html; charset=UTF-8

Content-Transfer-Encoding: 8bit

Notice the extra new lines after the boundary between the two Content entries. It should be:

X-Mailer: PHPMailer 6.7.1 (https://github.com/PHPMailer/PHPMailer)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="b1=_123"
Content-Transfer-Encoding: 8bit

--b1=_123
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit

We narrowed it down to this block in preSend:

    public function preSend()
    {
        if (
            'smtp' === $this->Mailer
            || ('mail' === $this->Mailer && (\PHP_VERSION_ID >= 80000 || stripos(PHP_OS, 'WIN') === 0))
        ) {
            //SMTP mandates RFC-compliant line endings
            //and it's also used with mail() on Windows
            static::setLE(self::CRLF);
        } else {
            //Maintain backward compatibility with legacy Linux command line mailers
            static::setLE(PHP_EOL);
        }

Because we are running the mailer driver and PHP 8.1, static::setLE(self::CRLF); is triggered. But since we are using a legacy Linux CLI mailer, what we need is static::setLE(PHP_EOL);.

Now, I understand our setup is not ideal, convoluted and probably not common.

However, I would have appreciated more flexibility for setting the line endings. I had to overwrite setLE in a child class to prevent the CRLF call from modifying the line endings.

Maybe this block could be extracted to a smaller, overwritable function? Or this could be an editable parameter somewhere? I had something like this in mind:

    public function setLineEndings()
    {
        if (
            'smtp' === $this->Mailer
            || ('mail' === $this->Mailer && (\PHP_VERSION_ID >= 80000 || stripos(PHP_OS, 'WIN') === 0))
        ) {
            //SMTP mandates RFC-compliant line endings
            //and it's also used with mail() on Windows
            static::setLE(self::CRLF);
        } else {
            //Maintain backward compatibility with legacy Linux command line mailers
            static::setLE(PHP_EOL);
        }
    }

    public function preSend()
    {
        $this->setLineEndings();
...
@Synchro
Copy link
Member

Synchro commented Feb 6, 2023

Since all the mail() function does is open a synchronous SMTP connection to localhost, I would recommend switching to SMTP to submit your message directly to nullmailer, skipping the mail function entirely. It should be faster (also not holding up your users), will avoid issues with line endings and line length, and also be safer since it doesn't have to run the shell escaping gauntlet (the subject of several CVEs!). Can that work for you?

@AdrienPoupa
Copy link
Author

Wow, thanks for the fast reply. Using the SMTP driver with localhost would most likely work yes, but also still apply CRLF endings, so I will check if the issue is still there or not. Thank you!

@Synchro
Copy link
Member

Synchro commented Feb 6, 2023

That should not be a problem - the issue with line endings only occurs in the mail() function, and is a PHP peculiarity. Things that talk proper SMTP will expect CRLF endings regardless of platform.

@AdrienPoupa
Copy link
Author

After more tests, I was not able to connect to nullmailer using SMTP - I am not even sure that is supported.

However, I was able to use nullmailer with the Sendmail driver (isSendmail) and it uses the appropriate line endings.

Thanks your support!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants