Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serialization Message object with attachments #475

Open
vmrfriz opened this issue Jun 5, 2023 · 1 comment
Open

Serialization Message object with attachments #475

vmrfriz opened this issue Jun 5, 2023 · 1 comment

Comments

@vmrfriz
Copy link

vmrfriz commented Jun 5, 2023

Is your feature request related to a problem? Please describe.
Using laravel-imap, I receive emails from mail and pass them to handlers in laravel queues. When passed to the queue, the object is serialized to JSON in the Illuminate\Queue\Queue::create Payload() method. As a result, I get an error:

Illuminate\Queue\InvalidPayloadException  Unable to JSON encode payload. Error code: 5.

--
 () at vendor/laravel/framework/src/Illuminate/Queue/Queue.php:108
 Illuminate\Queue\Queue->createPayload() at vendor/laravel/framework/src/Illuminate/Queue/DatabaseQueue.php:92
 Illuminate\Queue\DatabaseQueue->push() at vendor/laravel/framework/src/Illuminate/Queue/Queue.php:57
 Illuminate\Queue\Queue->pushOn() at vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:591
 Illuminate\Events\Dispatcher->queueHandler() at vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:515
 Illuminate\Events\Dispatcher->Illuminate\Events\{closure}() at vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:441
 Illuminate\Events\Dispatcher->Illuminate\Events\{closure}() at vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:249
 Illuminate\Events\Dispatcher->dispatch() at vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:433
 event() at vendor/laravel/framework/src/Illuminate/Foundation/Events/Dispatchable.php:14
 App\Events\EmailReceived::dispatch() at eval()'d code:2
 eval() at vendor/psy/psysh/src/ExecutionLoopClosure.php:53
 Psy\{closure}() at vendor/psy/psysh/src/ExecutionClosure.php:89
 Psy\ExecutionClosure->execute() at vendor/psy/psysh/src/Shell.php:395
 Psy\Shell->doInteractiveRun() at vendor/psy/psysh/src/Shell.php:366
 Psy\Shell->doRun() at vendor/symfony/console/Application.php:168
 Symfony\Component\Console\Application->run() at vendor/psy/psysh/src/Shell.php:341
 Psy\Shell->run() at vendor/laravel/tinker/src/Console/TinkerCommand.php:85
 Laravel\Tinker\Console\TinkerCommand->handle() at vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:36
 Illuminate\Container\BoundMethod::Illuminate\Container\{closure}() at vendor/laravel/framework/src/Illuminate/Container/Util.php:41
 Illuminate\Container\Util::unwrapIfClosure() at vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:93
 Illuminate\Container\BoundMethod::callBoundMethod() at vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:35
 Illuminate\Container\BoundMethod::call() at vendor/laravel/framework/src/Illuminate/Container/Container.php:662
 Illuminate\Container\Container->call() at vendor/laravel/framework/src/Illuminate/Console/Command.php:208
 Illuminate\Console\Command->execute() at vendor/symfony/console/Command/Command.php:312
 Symfony\Component\Console\Command\Command->run() at vendor/laravel/framework/src/Illuminate/Console/Command.php:177
 Illuminate\Console\Command->run() at vendor/symfony/console/Application.php:1040
 Symfony\Component\Console\Application->doRunCommand() at vendor/symfony/console/Application.php:314
 Symfony\Component\Console\Application->doRun() at vendor/symfony/console/Application.php:168
 Symfony\Component\Console\Application->run() at vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php:200
 Illuminate\Foundation\Console\Kernel->handle() at artisan:35

Describe the solution you'd like
For the solution, I added the methods __serialize() and __unserialize to the event object. After studying the source code of the \Webklex\PHPIMAP\Message class, I decided to do it by analogy with the save() and fromString() methods. It turned out the following:

<?php

namespace App\Events;

use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Webklex\PHPIMAP\ClientManager;
use Webklex\PHPIMAP\Message;

class EmailReceived
{
    use Dispatchable;
    use InteractsWithSockets;
    use SerializesModels;

    /**
     * Create a new event instance.
     */
    public function __construct(
        public Message $message
    ) {
        //
    }

    public function __serialize()
    {
        return [
            'message' => $this->message->getHeader()->raw . "\r\n\r\n" . $this->message->getRawBody(),
        ];
    }

    public function __unserialize(array $values)
    {
        // Load config for \Webklex\PHPIMAP\Message class
        new ClientManager();

        $this->message = Message::fromString($values['message']);
    }
}

I think the same solution can be applied for the \Webklex\PHPIMAP\Message class

Describe alternatives you've considered
Initially, I tried to solve the problem by serializing the \Webklex\PHPIMAP\Message object, but I wanted the event to accept an instance of the class, not a string.

In addition, serialize() and unserialize() incorrectly expand Attribute and adjacent objects. I found this fix in the issue to webklex\phpimap: #179.

Additional context
Without initializing new Client Manager();, the method \Webklex\PHPIMAP\Message::fromString() does not work. Therefore, I had to initialize it in the __unserialize() method. Perhaps there is a better solution?

This is what I get if I don't initialize new \Webklex\PHPIMAP\ClientManager():

Cannot assign null to property Webklex\PHPIMAP\Message::$config of type array {"exception":"[object] (TypeError(code: 0): Cannot assign null to property Webklex\\PHPIMAP\\Message::$config of type array at /run/media/mrfriz/Windows/xampp/htdocs/carzaem.local/vendor/webklex/php-imap/src/Message.php:368)\n[previous exception] [object] (TypeError(code: 0): Cannot assign null to property Webklex\\PHPIMAP\\Message::$config of type array at /run/media/mrfriz/Windows/xampp/htdocs/carzaem.local/vendor/webklex/php-imap/src/Message.php:368)"}
@Webklex
Copy link
Owner

Webklex commented Jun 23, 2023

Hi @vmrfriz ,
many thanks for your suggestion. I like the idea, but I'm afraid of another big "thing" - how to handle the active client connection? Or have you tested it and it already restores itself somehow?

If you would like to tackle this and perhaps create a pull request, please feel welcome to do so over here: https://github.com/Webklex/php-imap

webklex/php-imap is the core library this laravel package utilizes.

Best regards and happy coding,

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

No branches or pull requests

2 participants