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
617 stars 177 forks source link

Webklex\PHPIMAP\Exceptions\RuntimeException: idle failed #453

Closed dokicro closed 1 year ago

dokicro commented 1 year ago

Describe the bug After 10-30minutes of running custom idle command per instructions (https://www.php-imap.com/frameworks/laravel/commands) I get the following error:

[2022-10-11 13:30:58] production.ERROR: Webklex\PHPIMAP\Exceptions\RuntimeException: idle failed in /var/www/laravel/vendor/webklex/php-imap/src/Connection/Protocols/ImapProtocol.php:1055
Stack trace:
#0 /var/www/laravel/vendor/webklex/php-imap/src/Folder.php(402): Webklex\PHPIMAP\Connection\Protocols\ImapProtocol->idle()
#1 /var/www/laravel/app/Console/Commands/PayTicketIdleCommand.php(81): Webklex\PHPIMAP\Folder->idle()
#2 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): App\Console\Commands\PayTicketIdleCommand->handle()
#3 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Container/Util.php(40): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#4 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\Container\Util::unwrapIfClosure()
#5 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(37): Illuminate\Container\BoundMethod::callBoundMethod()
#6 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php(653): Illuminate\Container\BoundMethod::call()
#7 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Console/Command.php(136): Illuminate\Container\Container->call()
#8 /var/www/laravel/vendor/symfony/console/Command/Command.php(298): Illuminate\Console\Command->execute()
#9 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Console/Command.php(121): Symfony\Component\Console\Command\Command->run()
#10 /var/www/laravel/vendor/symfony/console/Application.php(1015): Illuminate\Console\Command->run()
#11 /var/www/laravel/vendor/symfony/console/Application.php(299): Symfony\Component\Console\Application->doRunCommand()
#12 /var/www/laravel/vendor/symfony/console/Application.php(171): Symfony\Component\Console\Application->doRun()
#13 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Console/Application.php(94): Symfony\Component\Console\Application->run()
#14 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(129): Illuminate\Console\Application->run()
#15 /var/www/laravel/artisan(37): Illuminate\Foundation\Console\Kernel->handle()
#16 {main}

I am connected to Gmail business account

Desktop / Server (please complete the following information):

dokicro commented 1 year ago

I played with debug mode and here is the output:

<< TAG3 OK [READ-WRITE] INBOX selected. (Success)
>> TAG4 IDLE
<< + idling
<< * 1 EXPUNGE
>> DONE
<< * 1 EXISTS
>> TAG5 IDLE
<< TAG4 OK IDLE terminated (Success)
>> DONE
<< + idling
>> TAG6 IDLE
<< TAG5 OK IDLE terminated (Success)

   Webklex\PHPIMAP\Exceptions\RuntimeException

  idle failed

  at vendor/webklex/php-imap/src/Connection/Protocols/ImapProtocol.php:1055
    1051▕      */
    1052▕     public function idle() {
    1053▕         $this->sendRequest("IDLE");
    1054▕         if (!$this->assumedNextLine('+ ')) {
  ➜ 1055▕             throw new RuntimeException('idle failed');
    1056▕         }
    1057▕     }
    1058▕
    1059▕     /**

      +1 vendor frames
  2   app/Console/Commands/InfoTicketIdleCommand.php:81
      Webklex\PHPIMAP\Folder::idle()

      +13 vendor frames
  16  artisan:37
      Illuminate\Foundation\Console\Kernel::handle()
>> TAG7 LOGOUT
<< + idling
<< TAG6 BAD Could not parse command

The problem could be that TAG5 came after TAG6 ?

HandsomeStrife commented 1 year ago

I've had the same issue happen to me; it seems I can replicate it by sending an email to the account I'm listening to (a gmail account), and then deleting the email that comes in (via the gMail interface). The exception is then thrown. This wouldn't be too much of an issue, except for the fact that the artisan command keeps running, and then it doesn't monitor any new incoming emails :\

dokicro commented 1 year ago

I solve that by changing Folder.php idle method to just throw the exception so from this:

catch (Exceptions\RuntimeException $e) {
                if(strpos($e->getMessage(), "empty response") >= 0 && $connection->connected()) {
                    $connection->done();
                    $connection->idle();
                    continue;
                }
                if(strpos($e->getMessage(), "connection closed") === false) {
                    throw $e;
                }

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

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

To this:

catch (Exceptions\RuntimeException $e) {
               throw $e;
}

And in my idle command I have this:

try {
            $folder->idle(function ($message) {
                $this->onNewMessage($message);
            });
        } catch (\Exception $e) {
            return;
        }

This way artisan command is not stuck but it restarts itself (I set my restart interval to 1s)

As an additional check, I have a command that runs every 10 minutes and checks if there are some unread emails and imports them...

Its quite hacky way but it works...

edh72 commented 1 year ago

Having this issues as well on Gmail Workspace accounts. Also tested on generic IMAP server setup via Mail-in-a-Box with same issue. Hopefully this simple repro will help.

Easy Repro:

  1. Start default IDLE Command ( src/Commands/ImapIdleCommand.php) using a default config from file
  2. Delete any mail from the Inbox - does not need to be a new mail IDLE saw (using any mail client)
  3. IDLE Is now broken - see relevant debug with Inline Notes below
<< TAG3 OK [READ-WRITE] INBOX selected. (Success)
>> TAG4 IDLE
<< + idling
*** Message from INBOX Deleted Here from a email client***
<< * 3 EXPUNGE
>> DONE
<< * 2 EXISTS
>> DONE
<< TAG4 OK IDLE terminated (Success)
>> TAG5 IDLE
<< * BAD [CLIENTBUG] Invalid tag
>> TAG6 LOGOUT
<< + idling
<< TAG5 BAD Could not parse command
*** IDLE is no longer working at this point, even a client->reconnect() will not help ***
Webklex commented 1 year ago

Hi @dokicro @danives @edh72 , many thanks for the report and all the examples / outputs.

Are you using the latest webklex/php-imap release v4.1.0 ? If not, please update and try again. This repository (webklex/laravel-imap) depends on webklex/php-imap, Please report any future issues over there :)

https://github.com/webklex/php-imap/issues

However, I can see how deleting / moving an email while it's being processed might cause issues. But what you are describing sounds like you receive a new mail, it gets parsed, you delete this email through some other client and idle stops working as expected?

If you look at your config file, are you using IMAP::ST_UID or IMAP::ST_MSGN as sequence? If you are using ST_MSGN, please switch to IMAP::ST_UID and try again.

Best regards & happy coding,

HandsomeStrife commented 1 year ago

Hey; yes I'm using the 4.1.0 of php-imap, and can see in my imap.php file that the sequence is set to use \Webklex\PHPIMAP\IMAP::ST_UID.

Still no luck in being able to resolve the issue myself, namely as I'm also encountering the an issue thats been reported on the main repo as well: https://github.com/Webklex/php-imap/issues/334

I too am using it on a Gmail workspace account (or was using it on it), so maybe it's something with gmail?

muhammadsaeedparacha commented 1 year ago

Bump. Experiencing the same "Idle Failed"

Even though it was working fine till a couple of days ago.

eliezermbr commented 1 year ago

having same issue . . .

ojsoft commented 1 year ago

Same issue with me and I do not delete anything. Just sent the first email: Works send the second email: idle failed.

omega-uo commented 1 year ago

Hi @dokicro @danives @edh72 , many thanks for the report and all the examples / outputs.

Are you using the latest webklex/php-imap release v4.1.0 ? If not, please update and try again. This repository (webklex/laravel-imap) depends on webklex/php-imap, Please report any future issues over there :)

https://github.com/webklex/php-imap/issues

under php-imap it says, that we should try to reproduce the problem with version 5.1. But I am currently using laravel-imap and then 5.1 is not available. I also tried to switch to php-imap, but then idle did not register the new mail.

Webklex commented 1 year ago

For anyone experiencing the same issue, please update to the latest release >= v5.3. If the issue persists, please head over to https://github.com/Webklex/php-imap/issues/new?assignees=&labels=&projects=&template=bug_report.md and create a new report.

Best regards & happy coding,