regex.320

Update (July 2015)

This was related to the dot-deb, that kept using an old PCRE library. This has been fixed directly in the package by Guillaume Plessis, and is working fine now.

I’ll keep this post in case this helps anyone in similar situations, but this shouldn’t be useful anymore.

WordPress not sending mail while PHP 5.6.9 does

I lost quite some time yesterday with some apparent paradox : wordpress wouldn’t send mail while PHP was well configured for it.

If you want a quick fix

This is a regex problem. In the phpmailer class, there is a regex to validate emails before actually sending them. This regex doesn’t compile with PRCE 8.37, while it used to compile with the previous PRCE library that PHP used previously (8.34). The regex fails, and the mail is denied sending.

As a quick fix, I used this native function, instead the regex. According to the comment, it is not as good, but it is sufficient.

return filter_var($address, FILTER_VALIDATE_EMAIL);

Long story long

We upgraded the server to run PHP 5.6.9 when this version came available in May. All services ran fine on the new version. We felt some quirks about email not being delivered, but that’s quite usual with mail : nothing special to worry.

It became obvious with the beta version of exakat, that request a email before download. Now, the mail was not captured anymore, and a red error message was show on the site. Everything was working fine until then, and features were checked rigorously. It took us quite some time to link it to PHP version.

As usual, the first suspects were the wordpress plug-ins and their configuration. So, we updated anything that was lagging : it didn’t change a thing. It began apparent that email didn’t leave the server, and it was strange that mail wouldn’t be even recorded in the logs.

So, next suspect was the mail and the blacklists. Reinstallations lead to the conclusion that PHP would send the mail correctly. Using mail() in a simple script was working as expected, but still nothing from WordPress.

Following the error log

We tried a number of WP plug in, notably WP Mail Logging and Check Email. The latter wouldn’t work, just like any email feature of PHP : it failed silently. This was frustrating but it was a small piece of information. The former actually logged email activity, which lead us to think that the problem was between wp_mail and sendmail. Now, this is a good hint : the next step was to check PHP error log, and there it was :

PHP Warning: preg_match(): Compilation failed: internal error: previously-checked referenced subpattern not found at offset 728 in /var/www/wp-includes/class-phpmailer.php

The error was in a huge regex, used for validating email addresses :

<?php
//....
                return (bool)preg_match(
                    '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
                    '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
                    '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
                    '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
                    '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
                    '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
                    '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
                    '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
                    '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
                    $address
                );
                break;
//....
?>

That looked suspicious enough, but one detail was wrong : class-phpmailer.php is at least one year old in WordPress, and has not been touched for a long time. Why would this regex suddenly fail ?

Of course, when the same old code suddenly raise an error, it is the platform that must have changed. Here, it is not even PHP that really changed but the PRCE library it uses. It was upgraded to 8.37 for PHP 5.6.9 (http://php.net/ChangeLog-5.php) for security reasons. Now, we got all the pieces in place.

PHP 5.6.9 updated PRCE to 8.34, which lead the regex to fail with ‘previously-checked referenced subpattern not found’ error. The filter denied the address to be valid because it failed, and the mail was not send from WordPress.

Note that, once again, a strict comparison would have helped differentiating the errors and a failed filter. Indeed :

<?php
var_dump(preg_match("this is not a valid regex", "123")); // return false and an error
var_dump(preg_match("/this is a valid regex/", "123") ; // return 0 (nothing found)
?>

On the other hand, security wise, it is good that the validator returns ‘false’ if the regex failed, because of the address or the regex itself.

Funnily, once I understood the problem, I found right away other libraries having the same problem : (swiftmailer, PHPmailer (sic), owncloudcore)

As usual, the most difficult here was the distance between the symptoms (email not going out) and the actual fix (fixing a regex). I remember looking at this preg_match error early in the logs, but discarding it hastily : young and silly!

Don’t fix the framework

I hope this helps everyone meeting the same problem. Note for future : fixing the code in the source will break the next upgrade, so now I have to be careful with it. Hopefully, it will be fixed in the next WordPress upgrade.

One thought on “WordPress not sending mail while PHP 5.6.9 does

  1. Pingback: Homepage

Comments are closed.