1

I'm working on a project with Zend Framework 2.4.13, and I have to retrieve mails from an imap mailbox. For this purpose I use \Zend\Mail\Storage\Imap:

foreach ($this->imap as $index => $message) {
    // ...
}

It's working well, except for a particular mail which fails to parse. The From header is invalid because it contains raw UTF-8 characters (french accents):

From: "Stéph" <abc@def.fr>

Then I get the following Zend error:

An error occurred during execution; please try again later.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Informations complémentaires:

Zend\Mail\Header\Exception\InvalidArgumentException

Fichier:

    /var/www/project/vendor/zendframework/zendframework/library/Zend/Mail/Header/GenericHeader.php:61

Message:

    Invalid header value detected

Pile d'exécution:

    #0 /var/www/project/vendor/zendframework/zendframework/library/Zend/Mail/Header/GenericHeader.php(35): Zend\Mail\Header\GenericHeader::splitHeaderLine('From: "St\xC3\xA9ph" ...')
    #1 /var/www/project/vendor/zendframework/zendframework/library/Zend/Mail/Headers.php(230): Zend\Mail\Header\GenericHeader::fromString('From: "St\xC3\xA9ph" ...')
    #2 /var/www/project/vendor/zendframework/zendframework/library/Zend/Mail/Headers.php(95): Zend\Mail\Headers->addHeaderLine('From: "St\xC3\xA9ph" ...')
    #3 /var/www/project/vendor/zendframework/zendframework/library/Zend/Mime/Decode.php(141): Zend\Mail\Headers::fromString('MIME-Version: 1...', '\n')
    #4 /var/www/project/vendor/zendframework/zendframework/library/Zend/Mail/Storage/Part.php(106): Zend\Mime\Decode::splitMessage('MIME-Version: 1...', 'MIME-Version: 1...', '')
    #5 /var/www/project/vendor/zendframework/zendframework/library/Zend/Mail/Storage/Message.php(54): Zend\Mail\Storage\Part->__construct(Array)
    #6 /var/www/project/vendor/zendframework/zendframework/library/Zend/Mail/Storage/Imap.php(118): Zend\Mail\Storage\Message->__construct(Array)
    #7 /var/www/project/vendor/zendframework/zendframework/library/Zend/Mail/Storage/AbstractStorage.php(267): Zend\Mail\Storage\Imap->getMessage(1)
    #8 /var/www/project/module/Application/src/Application/Helpers/LeadParser/Mail/Inbox.php(52): Zend\Mail\Storage\AbstractStorage->current()
    #9 /var/www/project/module/Application/src/Application/Helpers/LeadParser/InboxProcessor.php(81): Application\Helpers\LeadParser\Mail\Inbox->getMails()
    #10 /var/www/project/module/Application/src/WebService/Controller/LeadParserController.php(52): Application\Helpers\LeadParser\InboxProcessor->process()
    #11 /var/www/project/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractActionController.php(82): WebService\Controller\LeadParserController->indexAction()
    #12 [internal function]: Zend\Mvc\Controller\AbstractActionController->onDispatch(Object(Zend\Mvc\MvcEvent))
    #13 /var/www/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(444): call_user_func(Array, Object(Zend\Mvc\MvcEvent))
    #14 /var/www/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(205): Zend\EventManager\EventManager->triggerListeners('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
    #15 /var/www/project/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractController.php(118): Zend\EventManager\EventManager->trigger('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
    #16 /var/www/project/vendor/zendframework/zendframework/library/Zend/Mvc/DispatchListener.php(93): Zend\Mvc\Controller\AbstractController->dispatch(Object(Zend\Http\PhpEnvironment\Request), Object(Zend\Http\PhpEnvironment\Response))
    #17 [internal function]: Zend\Mvc\DispatchListener->onDispatch(Object(Zend\Mvc\MvcEvent))
    #18 /var/www/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(444): call_user_func(Array, Object(Zend\Mvc\MvcEvent))
    #19 /var/www/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(205): Zend\EventManager\EventManager->triggerListeners('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
    #20 /var/www/project/vendor/zendframework/zendframework/library/Zend/Mvc/Application.php(314): Zend\EventManager\EventManager->trigger('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
    #21 /var/www/project/public/index.php(69): Zend\Mvc\Application->run()
    #22 {main}

I guess the problems deals about RFC. Accordingly to the RFC-2822 this header is not valid because of the UTF-8 characters, and Zend complains about it when the header is validated.

I saw many issues around this on the web, but most of them talk about email creation, not reception.

I also saw the RFC-6532 which deals about Internationalized Email Headers, but the mail doesn't seem to respect this standard (there is no message/global part).

Actual workaround

The only solution I found for the moment is to use barbushin/php-imap, a wrapper around native php imap functions. This package seems to be more tolerant/updated, and retrieves the mail correctly.

Question

I need to find a solution to make the mail reception process more tolerant, in order to accept such mail headers. But I'm not convinced with my workaround, which adds vendor dependencies for something already implemented in the framework.

Is it possible to solve this issue directly via the ZF2 framework?

Community
  • 1
  • 1
yolenoyer
  • 8,797
  • 2
  • 27
  • 61
  • Two comments, neither of which present a solution. First, you don't need message/global-anything to conform to 6532. [This test message](https://github.com/arnt/eai-test-messages/blob/master/addresses) is legal. Second, 6532 is mostly about the addresses, abc@def.fr in your case. It allows Stéph but that's really just a driveby simplification. It's legalised as a result of allowing é almost everywhere, the motivation is to allow é in addresses. As for your problem... you might say that Zend is bad at handling syntax errors in cases where the errors have no ill effects. Good luck. – arnt Aug 02 '19 at 13:32
  • @arnt Nice to know that, thanks; I talk about 6532 in my question, but unfortunately I think [ZF2 conforms only to 2822](https://github.com/zendframework/zend-mail/blob/master/src/Header/HeaderValue.php#L65) – yolenoyer Aug 02 '19 at 13:39
  • I know, and that's why I said 6532 isn't the solution to your problem. But come to think if it, actually patching ZF2 to implement 6532 would solve your problem, and might be the simplest way to solve it. Implementing *reading* support for 6532 is extremely simple. – arnt Aug 02 '19 at 14:03
  • Must admit I didn't fully read the rfc... To implement this in ZF2, would it mean just allowing more character codes, simply by "removing/updating" validation conditions like `if ($ord === 10 || $ord > 127) { return false; }` ? Or would it be more work in your opinion? – yolenoyer Aug 02 '19 at 14:16
  • That would be enough to read (well, plus unit tests of course). Being able to generate and send such mail would be more work, and 6533 support is another chunk, but read-only support for 6532 is both useful and very simple. – arnt Aug 02 '19 at 14:41
  • @arnt your comments could be an answer, thank you – yolenoyer Aug 02 '19 at 15:02

1 Answers1

1

Although RFC 6532 isn't strictly relevant to the problem, implementing reading support for it in ZF2 is probably the simplest way to solve your problem.

This is because 6532 extends the message format to support addresses such as stéph@example.com, and it does so in a way that resembles common behaviour up through the years. People do a lot of inappropriate just-send-8, and the authors of 6532 chose to match the most common type of observed user behaviour. The message you want to read uses just the kind of inappropriate just-send-8 that 6532 codifies and allows.

Adding support for reading 6532-compliant messages should be as simple as editing various syntax checks and letting through more code points. I have some test messages on github; if ZF2 can parse those you'll be able to read and act on the EAI messages real users send.

Acting on messages sent by mailer-daemon requires 6533 support as well, and replying may require more 6532-relevant work. That bit is complex. But reading mail is a useful ability in itself.

Community
  • 1
  • 1
arnt
  • 8,949
  • 5
  • 24
  • 32