rateLimiterCache = $cache; $this->timeFactory = $timeFactory; $this->hash = $hash; } #[\Override] public function login() { parent::login(); if ($this->capability->query('ID')) { try { $this->sendID(); /* ID is queued - force sending the queued command. */ $this->_sendCmd($this->_pipeline()); } catch (Horde_Imap_Client_Exception_NoSupportExtension) { // Ignore if server doesn't support ID extension. } } } #[\Override] protected function _login() { if ($this->rateLimiterCache === null) { return parent::_login(); } $now = $this->timeFactory->getTime(); $window = floor($now / (3 * 60 * 60)); $cacheKey = $this->hash . $window; $counter = $this->rateLimiterCache->get($cacheKey); if ($counter !== null && $counter >= 3) { // Enough errors. Let's fail without involving IMAP throw new Horde_Imap_Client_Exception( 'Too many auth attempts', Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED ); } try { return parent::_login(); } catch (Horde_Imap_Client_Exception $e) { if ($e->getCode() === Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED && $e->getMessage() === 'Authentication failed.') { $this->rateLimiterCache->inc($cacheKey); } throw $e; } } }