-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
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
Line ending problem? v6 and PHP7 #953
Comments
|
Cannot use SMTP, so I'm using only mail function. /**
* The default line ending.
*
* @note The default remains "\n". We force LE where we know
* it must be used via static::LE.
* @var string
*/
public $LE = "\n";
/**
* SMTP RFC standard line ending.
*
* @var string
*/
const LE = "\r\n"; Everywhere in your code you are using |
The public property needs deleting, thanks for spotting that. You're not meant to be able to change it any more, though the constant is static so you can override it easily. I'll need to double-check what is happening to the body. The mail function requires a local mail server, so what is stopping you connecting to localhost on port 25? |
No no.. Probably misunderstanding.. Email is sent, that is OK. I don't have a problem with Problem is, that if message is full of those characters |
I've been testing this. I can't get it to do anything wrong, sending via both mail and SMTP. Line break formats in bodies are preserved. If I use Unix line breaks, they get converted into Are you setting I got the wrong char earlier |
I think I stumpled exactly the same problem. While everything works fine in PHPMailer 5.2.22 Outlook 2016 is showing an empty Message body when using PHPMailer 6.0 (PHP 5.6 is used) |
Sorry for my late answer. I will send it to your email, but also type it here: I'm not changing
I'm using Windows, so my files contains
|
If it's switching to quoted-printable automatically, it means you're passing in content with very long lines. It's the only way to build messages that have very long lines without breaking them, and is the same behaviour used by other apps, for example Apple Mail does the same. There are some other issues in here relating to that. It seems that outlook is particularly prone to mishandling long lines and QP-encoding. |
Try wrapping your content to say 65 chars and see if that makes a difference. |
for me its still not working in PHPMailer 6.0 while it's working in 5.2.22 (sort of, line breaks are not shown in Outlook 2016) I dumped the PHPMailer objects, PHPMailer is not using SMTP, can it be server configuration problems? https://www.diffchecker.com/vcHMpOvG (i dumped before adding the receiver via addAddress so this is missing in both) |
The difference in config isn't apparently important; what matters is the exact binary of the sent message. It's a bit difficult to get hold of this because many MTAs (e.g. postfix) "correct" line breaks automatically on receipt. I think the closest we can get is to send the same message in 5.2 and 6.0 and grab the resulting message using |
ok, i'll try the best I can attached two screenshots created with exactly the same message content, line endings definitly are not the same PHPMailer 5.2PHPMailer 6.0the files were dumped as you told in your comment above, and then saved to disk via $mailHandler->preSend();
$message = $mailHandler->getSentMIMEMessage();
$fhandle = fopen("PHPMailer60.dump", "w");
fwrite($fhandle, $message);
fclose($fhandle); |
Think I got it in PHP's manual
So while the new behaviour is ok there must be an option to force LF only for older mail agents? |
@swiffer thanks for those. The next interesting thing to try would be to send a single message: grab it directly from PHPMailer, and compare that with what turns up in your outlook client - that will tell us if the messages changes between sending and receiving. This will also be visible in debug output. Ideally we'd get a control in there too, for example to BCC it to a gmail account, which will help eliminate/blame receiver-side processing. I can see that the reason that the message does not render is that it lacks a double line break between the header and body; this bit:
As for was we should be doing, the specs are absolutely clear. RFC5322 S 2.3 says:
RFC 2046 (MIME) S 4.1.1 says:
(incidentally, this same section also mandates automatic switching of transfer encoding for content with lines that are too long - I had thought this was just good practice, but it's actually an RFC recommendation too). In other words, 5.2.x is undeniably doing it wrong, which is why 6.0 is switching this way, however, something is clearly upsetting Outlook somehow. As has been mentioned earlier in this thread, it seems that only some configurations of Outlook have this issue, and it looks like it might be some kind of filter service because tests I've done in Outlook do not have any issues at all, and I have yet to manage to create an outbound message that looks anything like these corrupted received messages. |
is it different configuration of outlook (mine is using office365 in background) or is it some outgoing mail agents like qmail auto adding a second CR as mentioned in the PHP manual ? at least in some moodle blogs i can see the following code used: (opening the email in office 365 for web shows the same results outlook 2016 shows -> empty message in 6.0, normal message text without linebreaks in 5.2) What do you mean by sending a single message, didn't get what I should do now |
I mean send a message to an outlook account with PHPMailer; BCC it to a gmail (or other neutral provider); capture it using |
I posted about this previously - using someone else's troublesome content (posted in this thread) results in a perfectly good message in my outlook webmail. |
Ok, as i was Not using smtp i Switched to smtp (Office 365 smtp server) and everything works Fine Right now- at least in my case was a Problem of direct sender as far as i Can tell |
isMailNote that I'm still using I just tried send the same message as above into my 3 accounts. GMail, Outlook (outlook.com) and Centrum.cz (Czech mail service). Output in file is same as in my previous post. isSMTPNow I also tried If I tried to send email with SMTP, everything works in all those clients mentioned above. If I check source code, there is no |
Sadly I cannot. I'm using it on webhosting, not VPS or something similar and I cannot get more info about it. I will try to reproduce this error on different webhostings I have access to, but not sure that somewhere else I can find more info... |
If you
|
I cannot telnet my webhosting. It is blocked. That problem is happening on webhosting, where I don't have full access. It is regular webhosting as many others. |
I've managed to make my local postfix do something strange with line breaks that looks like it may be the underlying cause of this. PHP itself appears to add headers with a platform-specific line break type, which results in mixed line breaks in the message, which can lead to bad quoted-printable decoding. I need to look at PHP's source code to see exactly what it's up to. |
Your "legacy" challenge is the use of the PHP mail function, which (until PHP 5) has been reconciling two directly opposing requirements
Up to PHP 5, they had taken the logical/pragmatic step of simply adapting the win32 implementation to fix any lone LF (which kept everyone happy). PHP eliminated the automatic fix-up for v7 and clarified the documentation that RFC-compliant CR LF should be used in for additional headers (with a footnote to try lone LF if they legacy Linux mailer has issues). They have also stated intentions that change this "string" parameter to an "array", thus completely eliminating ANY line end issues. For maximum compatibility with PHP 5 vs PHP 7 on Linux vs. PHP 7 on Windows, you could make the $LE default depending on the mailer AND operating system platform:
This might provide for best backward compatibility while achieving standards compliance: if ( $this->Mailer == 'smtp' || ( $this->Mailer == 'mail' && stripos(PHP_OS, 'WIN') === 0 ) { // SMTP, mandates RFC compliant line ending |
Thanks @ASchmidt1 - great analysis. I think it's PHP itself causing the problem I'm seeing. If I submit a pure CRLF-break message, |
I've had a look in PHP's code and it does indeed use hard-coded I will make some changes to reflect this and we can see whether it fixes these issues. |
Fixed by PHP (https://bugs.php.net/bug.php?id=74005) in February snapshot so that it's backward compatible with PHP 5. |
FWIW - if you are using PHP mail, then it would be prudent to follow the manual, which explicitly states that all additional headers should be passed with CRLF (but that a lone LF could be attempted if one has to work around a qmail quirk). With the latest bug fix, the normalizing of headers in PHP 7 mail() has been reinstanted the way it had done it in PHP 5. |
Thanks. That is a real mess! From what I read in the code, if I pass in headers containing CRLF (as you suggest I do by following the docs), then it's guaranteed to break because it will inject headers containing LF, and postfix for example will produce the problem we're seeing in here already. sendmail will accept either LF or CRLF, but it must be consistent, and will make a mess of mixed-format breaks. Are you saying that the code you posted previously will work though the forest of PHP versions that were affected by this? |
Hi, It might help to see this in the historical context, because it explains why this clash of two philosophies was not recognized initially/early on - leaving all of us today with two incompatible, legacy branches. As you know, on Linux \n is the operating system line end. Any command line tool that expects input will look for \n. Since the PHP mail() function was conceived as a front-end to a Linux command line tool (sendmail), it made sense to work with "\n". When Windows hosting of PHP (and with that, the eventual hosting of PHP applications) became "a thing" PHP at some point recognized that there was no "standard" command line mailer and eventually started using the more convenient direct SMTP for the Win32 implementation. Eventually, Anti-Spam/Anti-Virus efforts in the SMTP world caught up and started enforcing strict RFC compliance and suddenly lone LF headers under Windows (or qmail doubled up CRLFCR under Linux) caused emails to not be delivered to certain recipients ("my gmail users don't get my emails...") At first, the answer for PHP seemed simple - stick to the RFCs and require CRLF. But then qmail failed because it translates each lone CR and each LF into CRLF. So the Linux site pointed out that mail() was never meant to be "SMTP" it was meant to be a sendmail frontend. (On top of that, people had abused the "additional_header" parameters to stuff entire nested MIME entities into it - so now they even contained data!) Conclusion:
As far as my code snippet:
|
I've just pushed some changes to attempt to address this - please give it a try. There are lots of things touched by this - quoted-printable encoding (the PHP built-in function does not allow you to specify a line break format), and the DKIM functions are affected too, so it would be good to test those if you can. |
Is this working for everyone? Anyone? |
Hi, |
Hi, I pulled the phpmailer.php 6.0 labeled "Attempt solution to line break issue, see #953" from a few days ago, then I used WordPress 4.7.2 on Windows, added the WordPress Exception class, and then replaced their 5.x version with the new "class_phpmailer.php". Using an unpatched PHP 7.1.2 on Windows 2012 R2 WordPress was able to use phpmailer to send messages to a the native Windows IIS SMTP server. However, the result were the following headers:
The good news - nothing broke due to your changes. Basically, all the custom headers had proper CRLF endings, EXCEPT... THAT one has a lone \n, which will cause these emails to be bounced by RFC enforcing SMTP relays or servers. PHP has developed a fix for THAT bug which is scheduled to be included in the next 7.x updates. |
I now retested with the today's PHP 7.1.3 snapshot which includes the fix for the X-PHP-Originating header. With that, all headers are sent with proper \r\n from Wordpress->phpmailer->mail()->SMTP under Windows:
Therefore, it seems that under Windows, your new code results in proper mail headers from WordPress now, regardless if the (otherwise necessary) 7.x fix is in place - or not. Also, since the 7.x fix simply restores the (unintentionally omitted) header normalization that had been in place in 5.x, I feel comfortable that your code will also work with PHP 5.x (although I have NOT test that explicitly). |
@ASchmidt1 Great, thanks for checking. So are there any versions of PHP that this will still be broken in? |
The only problem I'm aware of is sites with 7.x before 7.0.17 and before 7.1.3. They will have to specify mail.add_x_header = 0 to circumvent the PHP 7 bug, if they configured a (most likely Windows) SMTP server that blocks or doesn't fix-up lone LF headers. But at least if they do that, then the "to" and "additional_headers" parameters that PHPmailer 6 passes to the mail() function will be able to go through now. I'm not aware of any clashes with your updated PHPmailer 6 code and the mail() function of PHP 5. Without your updated code, users of PHP 7x before 7.0.17 and before 7.1.3 would have to explicitly set $LE = '\r\n', which of course is a customization of "core" code that would be beyond the ability of most CMS end users. |
Looking at the docs for |
Grrr. |
Yes, I had checked into the possibility to suppress this PHP setting for the affected 7.0/7.1 versions and came to the same conclusion. Frankly, now that a 7.x fix is out, at least it will be reasonable to advise folks to upgrade to the latest update for the current release. My gut feeling is that by the time PHPmailer 6 will be widely adopted (where any noisy error could be seen) by the various CMS, many PHP 7.x installations may have already installed current/fixed updates. Also, listing the PHP bug among the issues "circumvented" with PHPmailer will further help affected installations "discover" the need to upgrade to the current update of their PHP 7.x version, when googling for their symptoms. If it makes you feel any better: Keep in mind, that PHP bug had been able to linger for so long, because many MTAs will of course whitelist their own users (either by IP or with SMTP AUTH) - so the emails are always accepted. Many MTA might even fix up the headers as they are injecting their own Received headers before relaying it - thus also suppressing it. That's why it took me quite a bit to track this down, because of my two different Windows MTAs, only ONE brand kept the faulty headers intact so for the longest time, I never actually observed the lone line feed while trying to produce it until I tested with our secondary MTA. |
I'm on macOS running PHP 7.1.2 (i.e. without the fix), In this scenario, Anyway, I've now added a noisy warning if this magical combination is true:
Thoughts? |
Linux Mint (Ubuntu and Debian editions) (Laptop and Desktop) and PHP 7.1.2, using the |
One possible combination is someone who (maybe for historical reasons) is actually using a sendmail-like command line mailer on Windows rather than SMTP. Early adopters of PHP under Windows might have had to go that route. In that case their INI would have: Obviously the result would depend on each specific mailer program, however, since they all do expect a Windows file or pipe as input, it would be reasonable to assume that they all will expect \r\n, but may also have also been designed to fix-up lone \n. In which case, these would have never been effected by any of the back and forth and thus might not need to be "warned". |
In that case they could use PHPMailer's alternative |
Agreed, other than changing their code to isSendmail(), just disabling mail.add_x_header for those PHP versions is the most sensible temporary alternative if someone encounteres issues, until they can install their fixed PHP release. |
PHP 7.1.3/7.0.17 |
I have a problem with emails sent via PHPMailer v6 and PHP7. It looks like a problem with line endings, because there is
=0D
at the end of each line. However, if I send same email, with same message etc. those symbols are not there.This is quite big problem, cause some email clients then show empty message. So for now, v6 is totally useless for me.
Problem happen with latest PHPMailer v6, but with v5.2.21 email is OK
The text was updated successfully, but these errors were encountered: