Skip to content

$streamPartEndPos in ZBateson\MailMimeParser\Parser\PartBuilder can be null when there is no body part in the mime message #269

Description

@hazington

Today I've received an email without body part causing following Error (exception):

Error: Typed property ZBateson\MailMimeParser\Parser\PartBuilder::$streamPartEndPos must not be accessed before initialization

The error is reproducible with this test message:

Return-Path: <test@host.tld>
Message-ID: id

And this unit Test (if added to \ZBateson\MailMimeParser\IntegrationTests\EmailFunctionalTest) and stored as invalid-no-body.txt:

    public function testParseEmailInvalidNoBody() : void
    {
        $messagePath = $this->messageDir . '/invalid-no-body.txt';
        $handle = \fopen($messagePath, 'r');
        $message = $this->parser->parse($handle, true);
        self::assertEquals(file_get_contents($messagePath), (string) $message);
    }

It throws the error at (string) $message. I tried to find the root cause, but I couldn't. The parsing flow is kinda complex and nested. But that's what I figured out so far:

  • The message is identified as non-mime-message and in the \ZBateson\MailMimeParser\Parser\NonMimeParserService::parseContent() method the resource handle becomes empty and thus has neither $streamPartEndPos nor $streamPartStartPos initiated.
  • The resource handle is not always empty, but it somehow seems to become empty in the \ZBateson\MailMimeParser\Parser\Part\ParserPartStreamContainer::requestParsedStream() method, when $this->parserProxy->parseAll() is called.

My first fix attempt was to make sure that $streamPartEndPos and $streamPartStartPos have 0 as default value and thus cannot be null. To be honest, these properties should be part of the constructor, because they should never be null. This also would help finding the root cause of this issue easier. However, making sure that $streamPartEndPos and $streamPartStartPos are never null fixed that the Error was thrown, but the empty stream resulted in an empty message, which doesn't fix the bug. The main issue is that the resource handle becomes empty in the parsing process.

My mail server had no problem handling those "broken" mime messages without body part via IMAP. But I store them as .eml files on my disk and index them in my application and that's when I encounter the described error. Emails without body are also sometimes attached in mailer daemons. In other words, these "broken" emails exist in the real world and should be parsable as mime messages with an empty body and valid headers. At least the latter is the case.

Maybe some maintainer with better understanding of the codebase and parsing workflow can help me to find the root cause to fix the issue? I didn't want to add workarounds like checking if the resource handle is empty, and if so to generate a new handle from the initial stream. This feels like a dirty hack and shouldn't be the solution.

Thank you in advance!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions