php-imap icon indicating copy to clipboard operation
php-imap copied to clipboard

V6: Idle connection breaks due to NOOP command being sent during active IDLE session

Open booklet-mikolajczak opened this issue 9 months ago • 5 comments

Hi!

After updating from 5.5.0 to 6.1.0 Idle connection stopped working. When using the idle() method, the library tries to read stream line by using getConnection():

public function idle(callable $callback, int $timeout = 300): void {
    ...
    $idle_client->getConnection()->idle();
    ...
    while (true) {
        try {
            // This polymorphic call is fine - Protocol::idle() will throw an exception beforehand
            $line = $idle_client->getConnection()->nextLine(Response::empty());
        }

getConnection() call connected() in ImapProtocol

public function connected(): bool {
    if ((bool)$this->stream) {
        try {
            $this->requestAndResponse('NOOP'); // <--
            return true;
        } catch (ImapServerErrorException|RuntimeException) {
            return false;
        }
    }
    return false;
}

which leads to sending a NOOP command during an active IDLE session.

TAG5 IDLE
+ idling
TAG6 NOOP       <-- This shouldn't happen during IDLE
TAG5 BAD Could not parse command

This breaks the IDLE functionality and prevents receiving real-time updates.

According to the IMAP protocol specification (RFC 2177), when a client is in IDLE mode, the only valid command that can be sent is DONE to terminate the IDLE state. Any other commands (including NOOP) will cause protocol errors.

This would probably require adding an additional is_idle_mode attribute to the Protocol class to prevent send NOOP to check connection status.

I tested on Gmail servers

booklet-mikolajczak avatar Mar 01 '25 21:03 booklet-mikolajczak

Incidentally, I experienced the same issue today (first time trying IDLE in php-imap).

Both on Dovecot and Cyrus IMAP servers.

madbob avatar Mar 03 '25 02:03 madbob

can this be the cause of my issue ? Is there like a workaround ?

Egensolve avatar Mar 23 '25 08:03 Egensolve

I tested after commenting the line provided by @booklet-mikolajczak and it did fix my issue:

/**
     * Check if the current session is connected
     *
     * @return bool
     * @throws ImapBadRequestException
     */
    public function connected(): bool {
        if ((bool)$this->stream) {
            try {
                // $this->requestAndResponse('NOOP');
                return true;
            } catch (ImapServerErrorException|RuntimeException) {
                return false;
            }
        }
        return false;
    }

Egensolve avatar Mar 23 '25 08:03 Egensolve

I also encountered a problem with the IDLE function in Gmail, but after making the modification described by Egensolve, it is now working correctly.

rambco avatar Apr 10 '25 18:04 rambco

Confirmed: commenting out this line resolves the issue with receiving live events on the Dovecot IMAP server.

mayestik1 avatar Jul 28 '25 08:07 mayestik1