userManager = $userManager; $this->accountService = $accountService; $this->syncService = $syncService; $this->mailboxSync = $mailboxSync; $this->logger = $logger; $this->jobList = $jobList; $configuredSyncInterval = $config->getSystemValueInt('app.mail.background-sync-interval'); if ($configuredSyncInterval > 0) { $this->forcedSyncInterval = true; } else { $this->forcedSyncInterval = false; $configuredSyncInterval = self::DEFAULT_SYNC_INTERVAL; } $this->setInterval(max(5 * 60, $configuredSyncInterval)); $this->setTimeSensitivity(self::TIME_SENSITIVE); } /** * @return void */ #[\Override] protected function run($argument) { $accountId = (int)$argument['accountId']; try { $account = $this->accountService->findById($accountId); } catch (DoesNotExistException $e) { $this->logger->debug('Could not find account <' . $accountId . '> removing from jobs'); $this->jobList->remove(self::class, $argument); return; } if (!$account->getMailAccount()->canAuthenticateImap()) { $this->logger->debug('No authentication on IMAP possible, skipping background sync job'); return; } // If an admin configured a custom sync interval, always abide by it if (!$this->forcedSyncInterval) { $now = $this->time->getTime(); $heartbeat = (int)$this->config->getUserValue( $account->getUserId(), Application::APP_ID, 'ui-heartbeat', $now + 1, // Force negative value for $lastUsed in case of no heartbeat ); $lastUsed = $now - $heartbeat; if ($lastUsed > 3 * 24 * 3600) { // User did not open the app in more than three days -> defer sync $this->setInterval(6 * 3600); } elseif ($lastUsed > 24 * 3600) { // User opened the app at least once within the last three days -> default sync $this->setInterval(self::DEFAULT_SYNC_INTERVAL); } elseif ($lastUsed > 0) { // User opened the app at least once within the last 24 hours -> sync more often $this->setInterval(15 * 60); } else { // Default to the hourly interval in case there is no heartbeat $this->setInterval(self::DEFAULT_SYNC_INTERVAL); } } $user = $this->userManager->get($account->getUserId()); if ($user === null || !$user->isEnabled()) { $this->logger->debug(sprintf( 'Account %d of user %s could not be found or was disabled, skipping background sync', $account->getId(), $account->getUserId() )); return; } try { $this->mailboxSync->sync($account, $this->logger, true); $this->syncService->syncAccount($account, $this->logger); } catch (IncompleteSyncException $e) { $this->logger->warning($e->getMessage(), [ 'exception' => $e, ]); } catch (Throwable $e) { if ($e instanceof ServiceException && $e->getPrevious() instanceof Horde_Imap_Client_Exception && $e->getPrevious()->getCode() === Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED) { $this->logger->info('Cron mail sync authentication failed for account {accountId}', [ 'accountId' => $accountId, 'exception' => $e, ]); } else { $this->logger->error('Cron mail sync failed for account {accountId}', [ 'accountId' => $accountId, 'exception' => $e, ]); } } } }