Webklex / laravel-imap

Laravel IMAP is an easy way to integrate both the native php-imap module and an extended custom imap protocol into your Laravel app.
https://www.php-imap.com
MIT License
641 stars 182 forks source link

Ide failed during Laravel command #455

Closed psaulus closed 2 years ago

psaulus commented 2 years ago

Describe the bug I was using idle Laravel command and then got the error on one of the accounts:

Link to the error: https://pastebin.com/64imu0Bs

To Reproduce Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior It should work like on other accounts.

Desktop / Server (please complete the following information):

Additional context I tried it on different accounts, like on gmail and everything was okey but on this specific account I got an error. I wrote to the email provider with question do they support IDLE IMAP and they answered that yes, so I don't know where is the problem.

Webklex commented 2 years ago

Hi @psaulus , many thanks for your report. This looks like the DONE command isn't supported by your provider.

Here is an alternative, which doesn't use DONE:

/** @var \Webklex\PHPIMAP\Client $client */
$client->connect();
/** @var \Webklex\PHPIMAP\Folder $folder */
$folder = $client->getFolder("INBOX");
$timeout = 300;
$callback = function($message){
    dump("New message received: ".$message->subject);
};

/**
 * @param \Webklex\PHPIMAP\Connection\Protocols\ProtocolInterface $connection
 * @return void
 */
function idle($connection) {
    $connection->sendRequest("IDLE");
}

$client->setTimeout($timeout);
if (!in_array("IDLE", $client->getConnection()->getCapabilities())) {
    throw new NotSupportedCapabilityException("IMAP server does not support IDLE");
}
$client->openFolder($folder->path, true);
$connection = $client->getConnection();
idle($connection);

$sequence = ClientManager::get('options.sequence', IMAP::ST_MSGN);

while (true) {
    try {
        $line = $connection->nextLine();

        if (($pos = strpos($line, "EXISTS")) !== false) {
            $connection->done();
            $msgn = (int) substr($line, 2, $pos -2);

            $client->openFolder($folder->path, true);
            $message = $folder->query()->getMessageByMsgn($msgn);
            $message->setSequence($sequence);
            $callback($message);

            $event = $folder->getEvent("message", "new");
            $event::dispatch($message);
            idle($connection);
        }
    }catch (\Webklex\PHPIMAP\Exceptions\RuntimeException $e) {
        if(strpos($e->getMessage(), "empty response") >= 0 && $connection->connected()) {
            $connection->done();
            idle($connection);
            continue;
        }
        if(strpos($e->getMessage(), "connection closed") === false) {
            throw $e;
        }

        $client->reconnect();
        $client->openFolder($folder->path, true);

        $connection = $client->getConnection();
        idle($connection);
    }
}

Best regards & happy coding,

psaulus commented 2 years ago

Thank you very much for the quick answer and help. I will write to my provider about that, but will use your method too. Awesome!