zend-mail icon indicating copy to clipboard operation
zend-mail copied to clipboard

Zend\Mail\Storage\Maildir Instance Problems and EOL Parameter

Open nicohofmann opened this issue 9 years ago • 1 comments

Hi all,

i have a directory with a huge amount of Mails, so i decided to use the Zend\Mail\Storage\Maildir Class for getting all Mails within this directory. See my code:

<?php

use Zend\Mail\Storage\Maildir;

require __DIR__ . '/vendor/autoload.php';

$mails = new MailDir(
    array(
        'dirname' => __DIR__ . '/maildir/',
    )
);

$count  = $mails->countMessages();
$emails = array();

$message = $mails->getMessage(1);

var_dump($message->getHeaders()->get('To')->getFieldValue());

I guess there is an bug and an unhandled feature.

Bug: With the code above i got an exception

Fatal error: Uncaught exception 'Zend\Mail\Storage\Part\Exception\InvalidArgumentException' with message 'no file given in params' in /Users/nico/Workspaces/MailTest/vendor/zendframework/zend-mail/src/Storage/Part/File.php on line 37

The problem is that in Maildir.php::getMessage($id)

    public function getMessage($id)
    {
        // TODO that's ugly, would be better to let the message class decide
        if ($this->messageClass === Message\File::class
            || is_subclass_of($this->messageClass, Message\File::class)
        ) {
            return new $this->messageClass([
                'file'  => $this->getFileData($id, 'filename'),
                'flags' => $this->getFileData($id, 'flags'),
            ]);
        }

        return new $this->messageClass([
            'handler' => $this,
            'id'      => $id,
            'headers' => $this->getRawHeader($id),
            'flags'   => $this->getFileData($id, 'flags'),
        ]);
    }

At least in PHP 5.5.30, other i couldn't test at the moment, the if isn't true, and so the Message/File class is called with wrong parameters.

is_subclass_of($this->messageClass, Message\File::class) // = false $this->messageClass // = \Zend\Mail\Storage\Message\File Message\File::class // = Message\File

So i used my own Maildir class as a child class:

class MyMailDir extends \Zend\Mail\Storage\Maildir
{
    public function __construct($params)
    {
        parent::__construct($params);
    }

    public function getMessage($id)
    {
            // TODO that's ugly, would be better to let the message class decide
        if (strtolower($this->messageClass) == '\zend\mail\storage\message\file'
            || is_subclass_of($this->messageClass, '\Zend\Mail\Storage\Message\File')) {
            return new $this->messageClass(
                [
                    'file'  => $this->getFileData($id, 'filename'),
                    'flags' => $this->getFileData($id, 'flags'),
                    'EOL'   => "\n",
                ]
            );
        }

        return new $this->messageClass(['handler' => $this, 'id' => $id, 'headers' => $this->getRawHeader($id),
            'flags'   => $this->getFileData($id, 'flags')]);
    }
}

For now i could instance and run getMessage correctly.

Unhandled Feature: Furthermore in Part\File.php there is a possibility to call Headers::from String with EOL Parameter. To use this feature also with Maildir class it should be possible to hand over the parameter from params. Example above in MyMailDir::getMessage($id). Okay it should come from initial parameters for example:

$mails = new MailDir(
    array(
        'dirname' => __DIR__ . '/maildir/',
        'EOL' => "\n",
    )
);

nicohofmann avatar Aug 18 '16 15:08 nicohofmann

This repository has been closed and moved to laminas/laminas-mail; a new issue has been opened at https://github.com/laminas/laminas-mail/issues/50.

michalbundyra avatar Jan 15 '20 19:01 michalbundyra