Page MenuHomePhabricator

PHP Fatal error: Call to undefined method PEAR::encodeHeader() when Echo is enabled
Closed, ResolvedPublic

Description

Mail notifications work fine on MediaWiki 1.30.0 (PHP 7.0.19-1 (fpm-fcgi)) if Echo extension is not installed. When I enable Echo, adding a new message to another user's talk page doesn't send any email, despite user preferences having it enabled.

Enabling the debug log prints this:

UserMailer::send: sending mail to Test54364646 <**********.com>
Assembling multipart mime email
[fatal] [bf6afdf4] PHP Fatal Error: Call to undefined method PEAR::encodeHeader()

The PHP error log displays this:

PHP Fatal error:  Call to undefined method PEAR::encodeHeader() in mediawiki-1.30.0/vendor/pear/pear-core-minimal/src/PEAR.php on line 231
Stack trace:
#0 mediawiki-1.30.0/vendor/pear/mail_mime/Mail/mime.php(1348): PEAR::__callStatic('encodeHeader', Array)
#1 mediawiki-1.30.0/vendor/pear/mail_mime/Mail/mime.php(1324): Mail_mime->encodeHeader('MIME-Version', '1.0', 'ISO-8859-1', 'quoted-printabl...')
#2 mediawiki-1.30.0/vendor/pear/mail_mime/Mail/mime.php(1111): Mail_mime->encodeHeaders(Array)
#3 mediawiki-1.30.0/includes/mail/UserMailer.php(320): Mail_mime->headers(Array)
#4 mediawiki-1.30.0/includes/mail/UserMailer.php(189): UserMailer::sendInternal(Array, Object(MailAddress), '\xE2\x80\xAACiencia Al P...', '--=_3f3c61fb81c...', Array)
#5 mediawiki-1.30.0/extensions/Echo/includes/Notifier.php(97): UserMailer::send(Array, Object(MailAddress), '\xE2\x80\xAACiencia Al P...', Array, Array)
#6 mediawiki-1.30.0/extensions/Echo/includes/controller/NotificationController.php(337): EchoNotifier::notifyWithEmail(Object(User), Object(EchoEvent))
#7 mediawiki-1.30.0/extensions/Echo/includes/controller/NotificationController.php(116): EchoNotificationController::doNotification(Object(EchoEvent), Object(User), 'email')
#8 mediawiki-1.30.0/extensions/Echo/includes/model/Event.php(171): EchoNotificationController::notify(Object(EchoEvent), true)
#9 mediawiki-1.30.0/extensions/Echo/includes/DiscussionParser.php(93): EchoEvent::create(Array)
#10 mediawiki-1.30.0/extensions/Echo/Hooks.php(552): EchoDiscussionParser::generateEventsForRevision(Object(Revision))
#11 mediawiki-1.30.0/includes/deferred/MWCallableUpdate.php(30): EchoHooks::{closure}()
#12 mediawiki-1.30.0/includes/deferred/DeferredUpdates.php(257): MWCallableUpdate->doUpdate()
#13 mediawiki-1.30.0/includes/deferred/DeferredUpdates.php(210): DeferredUpdates::runUpdate(Object(MWCallableUpdate), Object(Wikimedia\Rdbms\LBFactorySimple), 'run', 2)
#14 mediawiki-1.30.0/includes/deferred/DeferredUpdates.php(131): DeferredUpdates::execute(Array, 'run', 2)
#15 mediawiki-1.30.0/includes/MediaWiki.php(895): DeferredUpdates::doUpdates('run')
#16 mediawiki-1.30.0/includes/MediaWiki.php(719): MediaWiki->restInPeace('normal', false)
#17 mediawiki-1.30.0/includes/MediaWiki.php(740): MediaWiki->{closure}()
#18 mediawiki-1.30.0/includes/MediaWiki.php(553): MediaWiki->doPostOutputShutdown('normal')
#19 mediawiki-1.30.0/index.php(43): MediaWiki->run()
#20 {main}

This error message starts appearing on the logs after enabling Echo extension.

Despite the fatal error, there's no visible error message on the page.

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript

After trying to figure out where's the problem (it wasn't obvious to me), I came across this SO reply: https://stackoverflow.com/a/31181192/7268905

vendor/pear/mail_mime/Mail/mime.php on MediaWiki 1.30 contains:

require_once 'Mail/mimePart.php';

I changed it to:

require_once 'mimePart.php';

Now it works correctly, the email is sent and the user also gets the notification (which was also missing)

I'm a bit confused, isn't require_once supposed to fatal if it doesn't find the file being loaded? Or maybe it does nothing because it has been autoloaded before? But still why it fails at this point?

I'm confused... I downloaded Vagrant and expected to be some tests about this, or at least I'd try to write a test to make it fail because of this bug and then fix it. But, to my surprise, PEAR libraries are not inside the /vendor folder. Yet it's listed on the git repo https://phabricator.wikimedia.org/diffusion/MWVD/history/master/pear/mail_mime/

cc'ing Reedy since he added PEAR to the vendor repo, maybe you can shed some light on this...

https://github.com/wikimedia/mediawiki/blob/master/composer.json#L76-L78

They're in suggests, so composer won't install them by deault

They're in the MW Vendor folder (which vagrant doesn't use), for WMF prod purposes (though not 100% sure if they're actually being used; we haven't got round to removing the debian packages that also provide this stuff)

https://github.com/pear/Mail_Mime/blob/1.10.2/Mail/mime.php#L63 - Might be worth a bug upstream about this... Considering https://github.com/pear/Mail_Mime/blob/1.10.2/Mail/mimePart.php is in the same folder

That require_once hasn't been touched in 11 years, I don't think this is a bug in that library.

However, MediaWiki vendor defines some autoload classes, that the system PEAR package doesn't:

./vendor/composer/autoload_static.php:618:        'Mail_mimePart' => __DIR__ . '/..' . '/pear/mail_mime/Mail/mimePart.php',                                                                                                                                   
./vendor/composer/autoload_classmap.php:422:    'Mail_mimePart' => $vendorDir . '/pear/mail_mime/Mail/mimePart.php',

If I comment-out the line in autoload_static.php, the mail is sent just fine and no errors appear in the debug log.

I'm not sure what to do here, the class/path resolution algorithm for the require/include instructions in PHP is weird, specially when combined with autoload classes. I guess I'll have to maintain a local modification on my installation and remember to modify it again/retest on every upgrade... Sigh...

If these classes are autoloaded and distributed with vendor, we shouldn't need to require anything...

Change 429131 had a related patch set uploaded (by Legoktm; owner: Legoktm):
[mediawiki/core@master] mail: Refactor checks looking for PEAR libraries to be clearer

https://gerrit.wikimedia.org/r/429131

Do require statements like https://github.com/pear/Mail_Mime/blob/master/Mail/mime.php#L63 even work if the class is only distributed with composer?

Why don't we just drop the PEAR version and go for composer only? 1.31.x seems like a good release to do so.

Why don't we just drop the PEAR version and go for composer only? 1.31.x seems like a good release to do so.

Seems reasonable to me.

We require composer (and have for quite a while), so it's not like "I can't install $package by composer" is a valid response, whereas not being able to install it via apt/pecl etc would be.

Change 429131 merged by jenkins-bot:
[mediawiki/core@master] mail: Refactor checks looking for PEAR libraries to be clearer

https://gerrit.wikimedia.org/r/429131

Change 435051 had a related patch set uploaded (by Chad; owner: Legoktm):
[mediawiki/core@REL1_30] mail: Refactor checks looking for PEAR libraries to be clearer

https://gerrit.wikimedia.org/r/435051

Change 435051 merged by jenkins-bot:
[mediawiki/core@REL1_30] mail: Refactor checks looking for PEAR libraries to be clearer

https://gerrit.wikimedia.org/r/435051

Change 435059 had a related patch set uploaded (by Chad; owner: Legoktm):
[mediawiki/core@REL1_31] mail: Refactor checks looking for PEAR libraries to be clearer

https://gerrit.wikimedia.org/r/435059

Change 435059 merged by jenkins-bot:
[mediawiki/core@REL1_31] mail: Refactor checks looking for PEAR libraries to be clearer

https://gerrit.wikimedia.org/r/435059

demon claimed this task.

Kunal's fix is in master/REL1_31/REL1_30. My addition (removing non-composer support for SMTP) is in master and REL1_31.

My addition (removing non-composer support for SMTP) is in master and REL1_31.

For the record, your change is rMWee5a9b788a2fa3d98aaadbe0284e38ec5f9fdbfa