diff --git a/lib/Account.php b/lib/Account.php index ad1697a20e..d81fecd4b8 100644 --- a/lib/Account.php +++ b/lib/Account.php @@ -9,12 +9,9 @@ */ namespace OCA\Mail; -use JsonSerializable; use OCA\Mail\Db\MailAccount; -use OCA\Mail\Service\Quota; -use ReturnTypeWillChange; -class Account implements JsonSerializable { +class Account { public function __construct(private MailAccount $account) { } @@ -22,58 +19,4 @@ public function getMailAccount(): MailAccount { return $this->account; } - /** - * @return int - */ - public function getId() { - return $this->account->getId(); - } - - /** - * @return string - */ - public function getName() { - return $this->account->getName(); - } - - /** - * @return string - */ - public function getEMailAddress() { - return $this->account->getEmail(); - } - - #[ReturnTypeWillChange] - public function jsonSerialize() { - return $this->account->toJson(); - } - - public function getEmail(): string { - return $this->account->getEmail(); - } - - /** - * @return string - */ - public function getUserId() { - return $this->account->getUserId(); - } - - /** - * Set the quota percentage - * @param Quota $quota - * @return void - */ - public function calculateAndSetQuotaPercentage(Quota $quota): void { - if ($quota->getLimit() === 0) { - $this->account->setQuotaPercentage(0); - return; - } - $percentage = (int)round($quota->getUsage() / $quota->getLimit() * 100); - $this->account->setQuotaPercentage($percentage); - } - - public function getQuotaPercentage(): ?int { - return $this->account->getQuotaPercentage(); - } } diff --git a/lib/BackgroundJob/MigrateImportantJob.php b/lib/BackgroundJob/MigrateImportantJob.php index c72d5b42ae..b21530366e 100644 --- a/lib/BackgroundJob/MigrateImportantJob.php +++ b/lib/BackgroundJob/MigrateImportantJob.php @@ -9,7 +9,6 @@ namespace OCA\Mail\BackgroundJob; -use OCA\Mail\Account; use OCA\Mail\Db\MailAccountMapper; use OCA\Mail\Db\MailboxMapper; @@ -65,27 +64,25 @@ public function run($argument) { try { $mailAccount = $this->mailAccountMapper->findById($accountId); } catch (DoesNotExistException $e) { - $this->logger->debug('Could not find account <' . $accountId . '>'); + $this->logger->debug('Could not find mailAccount <' . $accountId . '>'); return; } - $account = new Account($mailAccount); - $client = $this->imapClientFactory->getClient($account); - + $client = $this->imapClientFactory->getClient($mailAccount); try { - if ($this->mailManager->isPermflagsEnabled($client, $account, $mailbox->getName()) === false) { + if ($this->mailManager->isPermflagsEnabled($client, $mailAccount, $mailbox->getName()) === false) { $this->logger->debug('Permflags not enabled for <' . $accountId . '>'); return; } try { - $this->migration->migrateImportantOnImap($client, $account, $mailbox); + $this->migration->migrateImportantOnImap($client, $mailbox); } catch (ServiceException $e) { $this->logger->debug('Could not flag messages on IMAP for mailbox <' . $mailboxId . '>.'); } try { - $this->migration->migrateImportantFromDb($client, $account, $mailbox); + $this->migration->migrateImportantFromDb($client, $mailbox); } catch (ServiceException $e) { $this->logger->debug('Could not flag messages from DB on IMAP for mailbox <' . $mailboxId . '>.'); } diff --git a/lib/BackgroundJob/PreviewEnhancementProcessingJob.php b/lib/BackgroundJob/PreviewEnhancementProcessingJob.php index 604035ed80..0e215e5209 100644 --- a/lib/BackgroundJob/PreviewEnhancementProcessingJob.php +++ b/lib/BackgroundJob/PreviewEnhancementProcessingJob.php @@ -57,7 +57,7 @@ public function run($argument) { return; } - if (!$account->getMailAccount()->canAuthenticateImap()) { + if (!$account->canAuthenticateImap()) { $this->logger->info('Ignoring preprocessing job for provisioned account as athentication on IMAP not possible'); return; } diff --git a/lib/BackgroundJob/QuotaJob.php b/lib/BackgroundJob/QuotaJob.php index 61b2527f8f..b13b913256 100644 --- a/lib/BackgroundJob/QuotaJob.php +++ b/lib/BackgroundJob/QuotaJob.php @@ -8,7 +8,6 @@ namespace OCA\Mail\BackgroundJob; -use OCA\Mail\Account; use OCA\Mail\Contracts\IMailManager; use OCA\Mail\Service\AccountService; use OCP\AppFramework\Db\DoesNotExistException; @@ -18,6 +17,7 @@ use OCP\IUserManager; use OCP\Notification\IManager; use Psr\Log\LoggerInterface; +use function round; use function sprintf; class QuotaJob extends TimedJob { @@ -54,7 +54,6 @@ public function __construct(ITimeFactory $time, protected function run($argument): void { $accountId = (int)$argument['accountId']; try { - /** @var Account $account */ $account = $this->accountService->findById($accountId); } catch (DoesNotExistException $e) { $this->logger->debug('Could not find account <' . $accountId . '> removing from jobs'); @@ -62,7 +61,7 @@ protected function run($argument): void { return; } - if(!$account->getMailAccount()->canAuthenticateImap()) { + if(!$account->canAuthenticateImap()) { $this->logger->debug('No authentication on IMAP possible, skipping quota job'); return; } @@ -82,9 +81,14 @@ protected function run($argument): void { $this->logger->debug('Could not get quota information for account <' . $account->getEmail() . '>', ['app' => 'mail']); return; } - $previous = $account->getMailAccount()->getQuotaPercentage(); - $account->calculateAndSetQuotaPercentage($quota); - $this->accountService->update($account->getMailAccount()); + $previous = $account->getQuotaPercentage(); + if ($quota->getLimit() === 0) { + $account->setQuotaPercentage(0); + return; + } + $percentage = (int)round($quota->getUsage() / $quota->getLimit() * 100); + $account->setQuotaPercentage($percentage); + $this->accountService->update($account); $current = $account->getQuotaPercentage(); // Only notify if we've reached the rising edge diff --git a/lib/BackgroundJob/SyncJob.php b/lib/BackgroundJob/SyncJob.php index b5508a3d9c..5eb55be639 100644 --- a/lib/BackgroundJob/SyncJob.php +++ b/lib/BackgroundJob/SyncJob.php @@ -73,7 +73,7 @@ protected function run($argument) { return; } - if(!$account->getMailAccount()->canAuthenticateImap()) { + if(!$account->canAuthenticateImap()) { $this->logger->debug('No authentication on IMAP possible, skipping background sync job'); return; } diff --git a/lib/BackgroundJob/TrainImportanceClassifierJob.php b/lib/BackgroundJob/TrainImportanceClassifierJob.php index c43d453d58..84d2c62ceb 100644 --- a/lib/BackgroundJob/TrainImportanceClassifierJob.php +++ b/lib/BackgroundJob/TrainImportanceClassifierJob.php @@ -58,7 +58,7 @@ protected function run($argument) { return; } - if(!$account->getMailAccount()->canAuthenticateImap()) { + if(!$account->canAuthenticateImap()) { $this->logger->debug('Cron importance classifier training not possible: no authentication on IMAP possible'); return; } diff --git a/lib/BackgroundJob/TrashRetentionJob.php b/lib/BackgroundJob/TrashRetentionJob.php index d832e089b2..1373eeebf3 100644 --- a/lib/BackgroundJob/TrashRetentionJob.php +++ b/lib/BackgroundJob/TrashRetentionJob.php @@ -9,8 +9,8 @@ namespace OCA\Mail\BackgroundJob; -use OCA\Mail\Account; use OCA\Mail\Contracts\IMailManager; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\MailAccountMapper; use OCA\Mail\Db\MailboxMapper; use OCA\Mail\Db\MessageMapper; @@ -46,9 +46,7 @@ public function __construct( public function run($argument) { $accounts = $this->accountMapper->getAllAccounts(); foreach ($accounts as $account) { - $account = new Account($account); - - $retentionDays = $account->getMailAccount()->getTrashRetentionDays(); + $retentionDays = $account->getTrashRetentionDays(); if ($retentionDays === null || $retentionDays <= 0) { continue; } @@ -62,7 +60,7 @@ public function run($argument) { 'exception' => $e, 'userId' => $account->getUserId(), 'accountId' => $account->getId(), - 'trashMailboxId' => $account->getMailAccount()->getTrashMailboxId(), + 'trashMailboxId' => $account->getTrashMailboxId(), ]); } } @@ -73,8 +71,8 @@ public function run($argument) { * @throws ClientException * @throws ServiceException */ - private function cleanTrash(Account $account, int $retentionSeconds): void { - $trashMailboxId = $account->getMailAccount()->getTrashMailboxId(); + private function cleanTrash(MailAccount $account, int $retentionSeconds): void { + $trashMailboxId = $account->getTrashMailboxId(); if ($trashMailboxId === null) { return; } diff --git a/lib/Command/DeleteAccount.php b/lib/Command/DeleteAccount.php index 05a3dde4a4..2fc3291270 100644 --- a/lib/Command/DeleteAccount.php +++ b/lib/Command/DeleteAccount.php @@ -9,7 +9,7 @@ namespace OCA\Mail\Command; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Exception\ClientException; use OCA\Mail\Service\AccountService; use OCP\AppFramework\Db\DoesNotExistException; @@ -53,7 +53,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $output->writeLn('Found account with email: ' . $account->getEmail() . ''); - if (!is_null($account->getMailAccount()->getProvisioningId())) { + if (!is_null($account->getProvisioningId())) { $output->writeLn('This is a provisioned account which can not be deleted from CLI. Use the Provisioning UI instead.'); return 2; } @@ -63,7 +63,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 0; } - private function delete(Account $account, OutputInterface $output): void { + private function delete(MailAccount $account, OutputInterface $output): void { $id = $account->getId(); try { $this->accountService->deleteByAccountId($account->getId()); diff --git a/lib/Command/DiagnoseAccount.php b/lib/Command/DiagnoseAccount.php index c711279bb7..00f5ec9176 100644 --- a/lib/Command/DiagnoseAccount.php +++ b/lib/Command/DiagnoseAccount.php @@ -61,7 +61,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 1; } - if ($account->getMailAccount()->getInboundPassword() === null) { + if ($account->getInboundPassword() === null) { $output->writeln('No IMAP passwort set. The user might have to log into their account to set it.'); } $imapClient = $this->clientFactory->getClient($account); diff --git a/lib/Command/ExportAccount.php b/lib/Command/ExportAccount.php index 0b9e74949d..8e9176a15f 100644 --- a/lib/Command/ExportAccount.php +++ b/lib/Command/ExportAccount.php @@ -1,96 +1,96 @@ -accountService = $service; - $this->crypto = $crypto; - } - - /** - * @return void - */ - protected function configure() { - $this->setName('mail:account:export'); - $this->setDescription('Exports a user\'s IMAP account(s)'); - $this->addArgument(self::ARGUMENT_USER_ID, InputArgument::REQUIRED); - $this->addOption(self::ARGUMENT_OUTPUT_FORMAT, '', InputOption::VALUE_OPTIONAL); - } - - private function getAccountsData($accounts) { - $accountsData = []; - - foreach ($accounts as $account) { - $accountsData[] = [ - 'id' => $account->getId(), - 'email' => $account->getEmail(), - 'name' => $account->getName(), - 'provision' => [ - 'status' => $account->getMailAccount()->getProvisioningId() ? 'set' : 'none', - 'id' => $account->getMailAccount()->getProvisioningId() ?: 'N/A' - ], - 'imap' => [ - 'user' => $account->getMailAccount()->getInboundUser(), - 'host' => $account->getMailAccount()->getInboundHost(), - 'port' => $account->getMailAccount()->getInboundPort(), - 'security' => $account->getMailAccount()->getInboundSslMode() - ], - 'smtp' => [ - 'user' => $account->getMailAccount()->getOutboundUser(), - 'host' => $account->getMailAccount()->getOutboundHost(), - 'port' => $account->getMailAccount()->getOutboundPort(), - 'security' => $account->getMailAccount()->getOutboundSslMode() - ] - ]; - } - - return $accountsData; - } - - protected function execute(InputInterface $input, OutputInterface $output): int { - $userId = $input->getArgument(self::ARGUMENT_USER_ID); - - $accounts = $this->accountService->findByUserId($userId); - - if ($input->getOption(self::ARGUMENT_OUTPUT_FORMAT) === 'json') { - $output->writeln(json_encode($this->getAccountsData($accounts))); - } elseif ($input->getOption(self::ARGUMENT_OUTPUT_FORMAT) === 'json_pretty') { - $output->writeln(json_encode($this->getAccountsData($accounts), JSON_PRETTY_PRINT)); - } else { - foreach ($accounts as $account) { - $output->writeln('Account ' . $account->getId() . ':'); - $output->writeln('- E-Mail: ' . $account->getEmail()); - $output->writeln('- Name: ' . $account->getName()); - $output->writeln('- Provision: ' . ($account->getMailAccount()->getProvisioningId() ? 'set' : 'none'). ' ID: ' . ($account->getMailAccount()->getProvisioningId() ? $account->getMailAccount()->getProvisioningId():'N/A')); - $output->writeln('- IMAP user: ' . $account->getMailAccount()->getInboundUser()); - $output->writeln('- IMAP host: ' . $account->getMailAccount()->getInboundHost() . ':' . $account->getMailAccount()->getInboundPort() . ', security: ' . $account->getMailAccount()->getInboundSslMode()); - $output->writeln('- SMTP user: ' . $account->getMailAccount()->getOutboundUser()); - $output->writeln('- SMTP host: ' . $account->getMailAccount()->getOutboundHost() . ':' . $account->getMailAccount()->getOutboundPort() . ', security: ' . $account->getMailAccount()->getOutboundSslMode()); - } - } - - return 0; - } -} +accountService = $service; + $this->crypto = $crypto; + } + + /** + * @return void + */ + protected function configure() { + $this->setName('mail:account:export'); + $this->setDescription('Exports a user\'s IMAP account(s)'); + $this->addArgument(self::ARGUMENT_USER_ID, InputArgument::REQUIRED); + $this->addOption(self::ARGUMENT_OUTPUT_FORMAT, '', InputOption::VALUE_OPTIONAL); + } + + private function getAccountsData($accounts) { + $accountsData = []; + + foreach ($accounts as $account) { + $accountsData[] = [ + 'id' => $account->getId(), + 'email' => $account->getEmail(), + 'name' => $account->getName(), + 'provision' => [ + 'status' => $account->getProvisioningId() ? 'set' : 'none', + 'id' => $account->getProvisioningId() ?: 'N/A' + ], + 'imap' => [ + 'user' => $account->getInboundUser(), + 'host' => $account->getInboundHost(), + 'port' => $account->getInboundPort(), + 'security' => $account->getInboundSslMode() + ], + 'smtp' => [ + 'user' => $account->getOutboundUser(), + 'host' => $account->getOutboundHost(), + 'port' => $account->getOutboundPort(), + 'security' => $account->getOutboundSslMode() + ] + ]; + } + + return $accountsData; + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $userId = $input->getArgument(self::ARGUMENT_USER_ID); + + $accounts = $this->accountService->findByUserId($userId); + + if ($input->getOption(self::ARGUMENT_OUTPUT_FORMAT) === 'json') { + $output->writeln(json_encode($this->getAccountsData($accounts))); + } elseif ($input->getOption(self::ARGUMENT_OUTPUT_FORMAT) === 'json_pretty') { + $output->writeln(json_encode($this->getAccountsData($accounts), JSON_PRETTY_PRINT)); + } else { + foreach ($accounts as $account) { + $output->writeln('Account ' . $account->getId() . ':'); + $output->writeln('- E-Mail: ' . $account->getEmail()); + $output->writeln('- Name: ' . $account->getName()); + $output->writeln('- Provision: ' . ($account->getProvisioningId() ? 'set' : 'none'). ' ID: ' . ($account->getProvisioningId() ? $account->getProvisioningId():'N/A')); + $output->writeln('- IMAP user: ' . $account->getInboundUser()); + $output->writeln('- IMAP host: ' . $account->getInboundHost() . ':' . $account->getInboundPort() . ', security: ' . $account->getInboundSslMode()); + $output->writeln('- SMTP user: ' . $account->getOutboundUser()); + $output->writeln('- SMTP host: ' . $account->getOutboundHost() . ':' . $account->getOutboundPort() . ', security: ' . $account->getOutboundSslMode()); + } + } + + return 0; + } +} diff --git a/lib/Command/ExportAccount.php.orig b/lib/Command/ExportAccount.php.orig new file mode 100644 index 0000000000..50b5e369ef --- /dev/null +++ b/lib/Command/ExportAccount.php.orig @@ -0,0 +1,103 @@ +accountService = $service; + $this->crypto = $crypto; + } + + /** + * @return void + */ + protected function configure() { + $this->setName('mail:account:export'); + $this->setDescription('Exports a user\'s IMAP account(s)'); + $this->addArgument(self::ARGUMENT_USER_ID, InputArgument::REQUIRED); + $this->addOption(self::ARGUMENT_OUTPUT_FORMAT, '', InputOption::VALUE_OPTIONAL); + } + + private function getAccountsData($accounts) { + $accountsData = []; + + foreach ($accounts as $account) { + $accountsData[] = [ + 'id' => $account->getId(), + 'email' => $account->getEmail(), + 'name' => $account->getName(), + 'provision' => [ + 'status' => $account->getProvisioningId() ? 'set' : 'none', + 'id' => $account->getProvisioningId() ?: 'N/A' + ], + 'imap' => [ + 'user' => $account->getInboundUser(), + 'host' => $account->getInboundHost(), + 'port' => $account->getInboundPort(), + 'security' => $account->getInboundSslMode() + ], + 'smtp' => [ + 'user' => $account->getOutboundUser(), + 'host' => $account->getOutboundHost(), + 'port' => $account->getOutboundPort(), + 'security' => $account->getOutboundSslMode() + ] + ]; + } + + return $accountsData; + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $userId = $input->getArgument(self::ARGUMENT_USER_ID); + + $accounts = $this->accountService->findByUserId($userId); + + if ($input->getOption(self::ARGUMENT_OUTPUT_FORMAT) === 'json') { + $output->writeln(json_encode($this->getAccountsData($accounts))); + } elseif ($input->getOption(self::ARGUMENT_OUTPUT_FORMAT) === 'json_pretty') { + $output->writeln(json_encode($this->getAccountsData($accounts), JSON_PRETTY_PRINT)); + } else { + foreach ($accounts as $account) { +<<<<<<< Updated upstream + $output->writeln('Account ' . $account->getId() . ':'); + $output->writeln('- E-Mail: ' . $account->getEmail()); + $output->writeln('- Name: ' . $account->getName()); + $output->writeln('- Provision: ' . ($account->getProvisioningId() ? 'set' : 'none'). ' ID: ' . ($account->getProvisioningId() ? $account->getProvisioningId():'N/A')); +======= + $output->writeln('Account ' . $account->getId() . ':'); + $output->writeln('- E-Mail: ' . $account->getEmail()); + $output->writeln('- Name: ' . $account->getName()); + $output->writeln('- Provision: ' . ($account->getProvisioningId() ? 'set' : 'none'). ' ID: ' . ($account->getProvisioningId() ?: 'N/A')); +>>>>>>> Stashed changes + $output->writeln('- IMAP user: ' . $account->getInboundUser()); + $output->writeln('- IMAP host: ' . $account->getInboundHost() . ':' . $account->getInboundPort() . ', security: ' . $account->getInboundSslMode()); + $output->writeln('- SMTP user: ' . $account->getOutboundUser()); + $output->writeln('- SMTP host: ' . $account->getOutboundHost() . ':' . $account->getOutboundPort() . ', security: ' . $account->getOutboundSslMode()); + } + } + + return 0; + } +} diff --git a/lib/Command/SyncAccount.php b/lib/Command/SyncAccount.php index 96a99a3da6..2e2e48ef0a 100644 --- a/lib/Command/SyncAccount.php +++ b/lib/Command/SyncAccount.php @@ -9,7 +9,7 @@ namespace OCA\Mail\Command; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Exception\IncompleteSyncException; use OCA\Mail\Exception\ServiceException; use OCA\Mail\IMAP\MailboxSync; @@ -77,7 +77,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 0; } - private function sync(Account $account, bool $force, OutputInterface $output): void { + private function sync(MailAccount $account, bool $force, OutputInterface $output): void { $consoleLogger = new ConsoleLoggerDecorator( $this->logger, $output diff --git a/lib/Contracts/IDkimService.php b/lib/Contracts/IDkimService.php index 024ad1a954..627f68dabb 100644 --- a/lib/Contracts/IDkimService.php +++ b/lib/Contracts/IDkimService.php @@ -9,10 +9,10 @@ namespace OCA\Mail\Contracts; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; interface IDkimService { - public function validate(Account $account, Mailbox $mailbox, int $id): bool; - public function getCached(Account $account, Mailbox $mailbox, int $id): ?bool; + public function validate(MailAccount $account, Mailbox $mailbox, int $id): bool; + public function getCached(MailAccount $account, Mailbox $mailbox, int $id): ?bool; } diff --git a/lib/Contracts/IMailManager.php b/lib/Contracts/IMailManager.php index e498f2721f..a5dea53c0a 100644 --- a/lib/Contracts/IMailManager.php +++ b/lib/Contracts/IMailManager.php @@ -10,8 +10,8 @@ namespace OCA\Mail\Contracts; use Horde_Imap_Client_Socket; -use OCA\Mail\Account; use OCA\Mail\Attachment; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\Message; use OCA\Mail\Db\Tag; @@ -34,23 +34,19 @@ interface IMailManager { public function getMailbox(string $uid, int $id): Mailbox; /** - * @param Account $account - * * @return Mailbox[] - * * @throws ServiceException */ - public function getMailboxes(Account $account): array; + public function getMailboxes(MailAccount $account): array; /** - * @param Account $account * @param string $name * * @return Mailbox * * @throws ServiceException */ - public function createMailbox(Account $account, string $name): Mailbox; + public function createMailbox(MailAccount $account, string $name): Mailbox; /** * @param Mailbox $mailbox @@ -72,7 +68,6 @@ public function getMessage(string $uid, int $id): Message; /** * @param Horde_Imap_Client_Socket $client - * @param Account $account * @param string $mailbox * @param int $uid * @@ -81,13 +76,12 @@ public function getMessage(string $uid, int $id): Message; * @throws ServiceException */ public function getSource(Horde_Imap_Client_Socket $client, - Account $account, + MailAccount $account, string $mailbox, int $uid): ?string; /** * @param Horde_Imap_Client_Socket $client - * @param Account $account * @param Mailbox $mailbox * @param int $uid * @param bool $loadBody @@ -97,47 +91,42 @@ public function getSource(Horde_Imap_Client_Socket $client, * @throws ServiceException */ public function getImapMessage(Horde_Imap_Client_Socket $client, - Account $account, + MailAccount $account, Mailbox $mailbox, int $uid, bool $loadBody = false): IMAPMessage; /** - * @param Account $account * @param string $threadRootId thread root id * * @return Message[] */ - public function getThread(Account $account, string $threadRootId): array; + public function getThread(MailAccount $account, string $threadRootId): array; /** - * @param Account $sourceAccount * @param string $sourceFolderId * @param int $uid - * @param Account $destinationAccount * @param string $destFolderId * @return int the new UID * * @throws ServiceException */ - public function moveMessage(Account $sourceAccount, + public function moveMessage(MailAccount $sourceAccount, string $sourceFolderId, int $uid, - Account $destinationAccount, + MailAccount $destinationAccount, string $destFolderId): int; /** - * @param Account $account * @param string $mailboxId * @param int $messageUid * * @throws ClientException * @throws ServiceException */ - public function deleteMessage(Account $account, string $mailboxId, int $messageUid): void; + public function deleteMessage(MailAccount $account, string $mailboxId, int $messageUid): void; /** - * @param Account $account * @param Mailbox $mailbox * @param int $messageUid * @param Horde_Imap_Client_Socket $client The caller is responsible to close the client. @@ -147,7 +136,7 @@ public function deleteMessage(Account $account, string $mailboxId, int $messageU * @throws TrashMailboxNotSetException If no trash folder is configured for the given account. */ public function deleteMessageWithClient( - Account $account, + MailAccount $account, Mailbox $mailbox, int $messageUid, Horde_Imap_Client_Socket $client, @@ -156,13 +145,11 @@ public function deleteMessageWithClient( /** * Mark all messages of a folder as read * - * @param Account $account * @param Mailbox $mailbox */ - public function markFolderAsRead(Account $account, Mailbox $mailbox): void; + public function markFolderAsRead(MailAccount $account, Mailbox $mailbox): void; /** - * @param Account $account * @param string $mailbox * @param int $uid * @param string $flag @@ -171,10 +158,9 @@ public function markFolderAsRead(Account $account, Mailbox $mailbox): void; * @throws ClientException * @throws ServiceException */ - public function flagMessage(Account $account, string $mailbox, int $uid, string $flag, bool $value): void; + public function flagMessage(MailAccount $account, string $mailbox, int $uid, string $flag, bool $value): void; /** - * @param Account $account * @param string $mailbox * @param Message $message * @param Tag $tag @@ -183,19 +169,16 @@ public function flagMessage(Account $account, string $mailbox, int $uid, string * @throws ClientException * @throws ServiceException */ - public function tagMessage(Account $account, string $mailbox, Message $message, Tag $tag, bool $value): void; + public function tagMessage(MailAccount $account, string $mailbox, Message $message, Tag $tag, bool $value): void; /** - * @param Account $account - * * @return Quota|null */ - public function getQuota(Account $account): ?Quota; + public function getQuota(MailAccount $account): ?Quota; /** * Rename a mailbox and get the new (cached) version * - * @param Account $account * @param Mailbox $mailbox * @param string $name * @@ -203,26 +186,23 @@ public function getQuota(Account $account): ?Quota; * * @throw ServiceException */ - public function renameMailbox(Account $account, Mailbox $mailbox, string $name): Mailbox; + public function renameMailbox(MailAccount $account, Mailbox $mailbox, string $name): Mailbox; /** - * @param Account $account * @param Mailbox $mailbox * * @throws ServiceException */ - public function deleteMailbox(Account $account, Mailbox $mailbox): void; + public function deleteMailbox(MailAccount $account, Mailbox $mailbox): void; /** - * @param Account $account * @param Mailbox $mailbox * * @throws ServiceException */ - public function clearMailbox(Account $account, Mailbox $mailbox): void; + public function clearMailbox(MailAccount $account, Mailbox $mailbox): void; /** - * @param Account $account * @param Mailbox $mailbox * @param bool $subscribed * @@ -230,7 +210,7 @@ public function clearMailbox(Account $account, Mailbox $mailbox): void; * @throws ClientException * @throws ServiceException */ - public function updateSubscription(Account $account, + public function updateSubscription(MailAccount $account, Mailbox $mailbox, bool $subscribed): Mailbox; @@ -246,21 +226,19 @@ public function enableMailboxBackgroundSync(Mailbox $mailbox, bool $syncInBackground): Mailbox; /** - * @param Account $account * @param Mailbox $mailbox * @param Message $message * @return Attachment[] */ - public function getMailAttachments(Account $account, Mailbox $mailbox, Message $message) : array; + public function getMailAttachments(MailAccount $account, Mailbox $mailbox, Message $message) : array; /** - * @param Account $account * @param Mailbox $mailbox * @param Message $message * @param string $attachmentId * @return Attachment */ - public function getMailAttachment(Account $account, Mailbox $mailbox, Message $message, string $attachmentId): Attachment; + public function getMailAttachment(MailAccount $account, Mailbox $mailbox, Message $message, string $attachmentId): Attachment; /** * @param string $imapLabel @@ -272,12 +250,8 @@ public function getTagByImapLabel(string $imapLabel, string $userId): Tag; /** * Check IMAP server for support for PERMANENTFLAGS - * - * @param Account $account - * @param string $mailbox - * @return boolean */ - public function isPermflagsEnabled(Horde_Imap_Client_Socket $client, Account $account, string $mailbox): bool; + public function isPermflagsEnabled(Horde_Imap_Client_Socket $client, MailAccount $account, string $mailbox): bool; /** * Create a mail tag @@ -314,32 +288,29 @@ public function deleteTag(int $id, string $userId, array $accounts): Tag; * * @throws ClientException */ - public function deleteTagForAccount(int $id, string $userId, Tag $tag, Account $account): void; + public function deleteTagForAccount(int $id, string $userId, Tag $tag, MailAccount $account): void; + /** - * @param Account $srcAccount * @param Mailbox $srcMailbox - * @param Account $dstAccount * @param Mailbox $dstMailbox * @param string $threadRootId * @return int[] the new UIDs * @throws ServiceException */ - public function moveThread(Account $srcAccount, Mailbox $srcMailbox, Account $dstAccount, Mailbox $dstMailbox, string $threadRootId): array; + public function moveThread(MailAccount $srcAccount, Mailbox $srcMailbox, MailAccount $dstAccount, Mailbox $dstMailbox, string $threadRootId): array; /** - * @param Account $account * @param Mailbox $mailbox * @param string $threadRootId * @return void * @throws ClientException * @throws ServiceException */ - public function deleteThread(Account $account, Mailbox $mailbox, string $threadRootId): void; + public function deleteThread(MailAccount $account, Mailbox $mailbox, string $threadRootId): void; /** - * @param Account $account * @param string $messageId * @return Message[] */ - public function getByMessageId(Account $account, string $messageId): array; + public function getByMessageId(MailAccount $account, string $messageId): array; } diff --git a/lib/Contracts/IMailSearch.php b/lib/Contracts/IMailSearch.php index a579808950..53ac97c48e 100644 --- a/lib/Contracts/IMailSearch.php +++ b/lib/Contracts/IMailSearch.php @@ -9,7 +9,7 @@ namespace OCA\Mail\Contracts; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\Message; use OCA\Mail\Exception\ClientException; @@ -25,12 +25,11 @@ interface IMailSearch { * @throws ClientException * @throws ServiceException */ - public function findMessage(Account $account, + public function findMessage(MailAccount $account, Mailbox $mailbox, Message $message): Message; /** - * @param Account $account * @param Mailbox $mailbox * @param string $sortOrder * @param string|null $filter @@ -42,7 +41,7 @@ public function findMessage(Account $account, * @throws ClientException * @throws ServiceException */ - public function findMessages(Account $account, + public function findMessages(MailAccount $account, Mailbox $mailbox, string $sortOrder, ?string $filter, diff --git a/lib/Contracts/IMailTransmission.php b/lib/Contracts/IMailTransmission.php index 98a0a932ea..a3b3a02a98 100644 --- a/lib/Contracts/IMailTransmission.php +++ b/lib/Contracts/IMailTransmission.php @@ -9,8 +9,8 @@ namespace OCA\Mail\Contracts; -use OCA\Mail\Account; use OCA\Mail\Db\LocalMessage; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\Message; use OCA\Mail\Exception\ClientException; @@ -22,21 +22,20 @@ interface IMailTransmission { /** * Send a new message or reply to an existing one * - * @param Account $account + * @param MailAccount $account * @param LocalMessage $localMessage * @throws SentMailboxNotSetException * @throws ServiceException */ - public function sendMessage(Account $account, LocalMessage $localMessage): void; + public function sendMessage(MailAccount $account, LocalMessage $localMessage): void; /** - * @param Account $account * @param LocalMessage $message * @throws ClientException * @throws ServiceException * @return void */ - public function saveLocalDraft(Account $account, LocalMessage $message): void; + public function saveLocalDraft(MailAccount $account, LocalMessage $message): void; /** * Save a message draft @@ -54,10 +53,9 @@ public function saveDraft(NewMessageData $message, ?Message $previousDraft = nul /** * Send a mdn message * - * @param Account $account * @param Mailbox $mailbox * @param Message $message the message to send an mdn for * @throws ServiceException */ - public function sendMdn(Account $account, Mailbox $mailbox, Message $message): void; + public function sendMdn(MailAccount $account, Mailbox $mailbox, Message $message): void; } diff --git a/lib/Controller/AccountsController.php b/lib/Controller/AccountsController.php index 6b8bd41f24..7cf0050db6 100644 --- a/lib/Controller/AccountsController.php +++ b/lib/Controller/AccountsController.php @@ -35,6 +35,7 @@ use OCP\IRequest; use OCP\Security\IRemoteHostValidator; use Psr\Log\LoggerInterface; +use ReturnTypeWillChange; #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] class AccountsController extends Controller { @@ -92,7 +93,7 @@ public function index(): JSONResponse { $json = []; foreach ($mailAccounts as $mailAccount) { - $conf = $mailAccount->jsonSerialize(); + $conf = $mailAccount->toJson(); $conf['aliases'] = $this->aliasesService->findAll($conf['accountId'], $this->currentUserId); $json[] = $conf; } @@ -231,7 +232,7 @@ public function patchAccount(int $id, ?bool $searchBody = null): JSONResponse { $account = $this->accountService->find($this->currentUserId, $id); - $dbAccount = $account->getMailAccount(); + $dbAccount = $account; if ($draftsMailboxId !== null) { $this->mailManager->getMailbox($this->currentUserId, $draftsMailboxId); @@ -483,7 +484,7 @@ public function getQuota(int $id): JSONResponse { * @throws ClientException */ public function updateSmimeCertificate(int $id, ?int $smimeCertificateId = null) { - $account = $this->accountService->find($this->currentUserId, $id)->getMailAccount(); + $account = $this->accountService->find($this->currentUserId, $id); $account->setSmimeCertificateId($smimeCertificateId); $this->accountService->update($account); return MailJsonResponse::success(); diff --git a/lib/Controller/GoogleIntegrationController.php b/lib/Controller/GoogleIntegrationController.php index b61536e6f5..d020504340 100644 --- a/lib/Controller/GoogleIntegrationController.php +++ b/lib/Controller/GoogleIntegrationController.php @@ -142,7 +142,7 @@ public function oauthRedirect(?string $code, ?string $state, ?string $scope, ?st $account, $code, ); - $this->accountService->update($updated->getMailAccount()); + $this->accountService->update($updated); try { $this->mailboxSync->sync($account, $this->logger); } catch (ServiceException $e) { diff --git a/lib/Controller/MicrosoftIntegrationController.php b/lib/Controller/MicrosoftIntegrationController.php index c62bfaf7df..3c25ed24ad 100644 --- a/lib/Controller/MicrosoftIntegrationController.php +++ b/lib/Controller/MicrosoftIntegrationController.php @@ -140,7 +140,7 @@ public function oauthRedirect(?string $code, ?string $state, ?string $session_st $account, $code, ); - $this->accountService->update($updated->getMailAccount()); + $this->accountService->update($updated); return new StandaloneTemplateResponse( Application::APP_ID, diff --git a/lib/Controller/OutOfOfficeController.php b/lib/Controller/OutOfOfficeController.php index 72e54642b2..3ae43117ce 100644 --- a/lib/Controller/OutOfOfficeController.php +++ b/lib/Controller/OutOfOfficeController.php @@ -53,7 +53,7 @@ public function getState(int $accountId): JsonResponse { return JsonResponse::fail([], Http::STATUS_NOT_FOUND); } - $state = $this->outOfOfficeService->parseState($account->getMailAccount()); + $state = $this->outOfOfficeService->parseState($account); return JsonResponse::success($state); } @@ -76,7 +76,7 @@ public function followSystem(int $accountId) { return JsonResponse::fail([], Http::STATUS_NOT_FOUND); } - $mailAccount = $account->getMailAccount(); + $mailAccount = $account; if (!$mailAccount->getOutOfOfficeFollowsSystem()) { $mailAccount->setOutOfOfficeFollowsSystem(true); $this->accountService->update($mailAccount); @@ -112,7 +112,7 @@ public function update( throw new ServiceException('Missing start date'); } - $mailAccount = $account->getMailAccount(); + $mailAccount = $account; if ($mailAccount->getOutOfOfficeFollowsSystem()) { $mailAccount->setOutOfOfficeFollowsSystem(false); $this->accountService->update($mailAccount); diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index 2dd0e1dd34..ea8e914108 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -45,6 +45,7 @@ use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; +use ReturnTypeWillChange; use Throwable; use function class_exists; use function http_build_query; @@ -149,7 +150,7 @@ public function index(): TemplateResponse { $mailAccounts = $this->accountService->findByUserId($this->currentUserId); $accountsJson = []; foreach ($mailAccounts as $mailAccount) { - $json = $mailAccount->jsonSerialize(); + $json = $mailAccount->toJson(); $json['aliases'] = $this->aliasesService->findAll($mailAccount->getId(), $this->currentUserId); try { diff --git a/lib/Db/MailboxMapper.php b/lib/Db/MailboxMapper.php index 434c63fd10..24eed2012b 100644 --- a/lib/Db/MailboxMapper.php +++ b/lib/Db/MailboxMapper.php @@ -9,7 +9,6 @@ namespace OCA\Mail\Db; -use OCA\Mail\Account; use OCA\Mail\Exception\MailboxLockedException; use OCA\Mail\Exception\ServiceException; use OCP\AppFramework\Db\DoesNotExistException; @@ -36,11 +35,9 @@ public function __construct(IDBConnection $db, } /** - * @param Account $account - * * @return Mailbox[] */ - public function findAll(Account $account): array { + public function findAll(MailAccount $account): array { $qb = $this->db->getQueryBuilder(); $select = $qb->select('*') @@ -69,7 +66,7 @@ public function findAllIds(): \Generator { * @throws DoesNotExistException * @throws ServiceException */ - public function find(Account $account, string $name): Mailbox { + public function find(MailAccount $account, string $name): Mailbox { $qb = $this->db->getQueryBuilder(); $select = $qb->select('*') diff --git a/lib/Db/MessageMapper.php b/lib/Db/MessageMapper.php index 47cf21292a..d348d918f5 100644 --- a/lib/Db/MessageMapper.php +++ b/lib/Db/MessageMapper.php @@ -9,7 +9,6 @@ namespace OCA\Mail\Db; -use OCA\Mail\Account; use OCA\Mail\Address; use OCA\Mail\AddressList; use OCA\Mail\Contracts\IMailSearch; @@ -179,11 +178,9 @@ public function findUidsForIds(Mailbox $mailbox, array $ids) { } /** - * @param Account $account - * * @return DatabaseMessage[] */ - public function findThreadingData(Account $account): array { + public function findThreadingData(MailAccount $account): array { $mailboxesQuery = $this->db->getQueryBuilder(); $messagesQuery = $this->db->getQueryBuilder(); @@ -256,7 +253,7 @@ public function writeThreadIds(array $messages): void { * @param Message ...$messages * @return void */ - public function insertBulk(Account $account, Message ...$messages): void { + public function insertBulk(MailAccount $account, Message ...$messages): void { $this->db->beginTransaction(); try { $qb1 = $this->db->getQueryBuilder(); @@ -348,12 +345,11 @@ public function insertBulk(Account $account, Message ...$messages): void { } /** - * @param Account $account * @param bool $permflagsEnabled * @param Message[] $messages * @return Message[] */ - public function updateBulk(Account $account, bool $permflagsEnabled, Message ...$messages): array { + public function updateBulk(MailAccount $account, bool $permflagsEnabled, Message ...$messages): array { $this->db->beginTransaction(); $perf = $this->performanceLogger->start( @@ -510,12 +506,11 @@ public function updateBulk(Account $account, bool $permflagsEnabled, Message ... } /** - * @param Account $account * @param Message $message * @param Tag[][] $tags * @param PerformanceLoggerTask $perf */ - private function updateTags(Account $account, Message $message, array $tags, PerformanceLoggerTask $perf): void { + private function updateTags(MailAccount $account, Message $message, array $tags, PerformanceLoggerTask $perf): void { $imapTags = $message->getTags(); $dbTags = $tags[$message->getMessageId()] ?? []; @@ -734,12 +729,11 @@ public function deleteByUid(Mailbox $mailbox, int ...$uids): void { } /** - * @param Account $account * @param string $threadRootId * * @return Message[] */ - public function findThread(Account $account, string $threadRootId): array { + public function findThread(MailAccount $account, string $threadRootId): array { $qb = $this->db->getQueryBuilder(); $qb->select('messages.*') ->from($this->getTableName(), 'messages') @@ -754,12 +748,11 @@ public function findThread(Account $account, string $threadRootId): array { } /** - * @param Account $account * @param string $messageId * * @return Message[] */ - public function findByMessageId(Account $account, string $messageId): array { + public function findByMessageId(MailAccount $account, string $messageId): array { $qb = $this->db->getQueryBuilder(); $qb->select('messages.*') ->from($this->getTableName(), 'messages') @@ -1411,7 +1404,7 @@ public function findNewIds(Mailbox $mailbox, array $ids, ?int $lastMessageTimest /** * Currently unused */ - public function findChanged(Account $account, Mailbox $mailbox, int $since): array { + public function findChanged(MailAccount $account, Mailbox $mailbox, int $since): array { $qb = $this->db->getQueryBuilder(); $select = $qb diff --git a/lib/Events/BeforeImapClientCreated.php b/lib/Events/BeforeImapClientCreated.php index 436468e696..72facf4872 100644 --- a/lib/Events/BeforeImapClientCreated.php +++ b/lib/Events/BeforeImapClientCreated.php @@ -9,22 +9,17 @@ namespace OCA\Mail\Events; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCP\EventDispatcher\Event; - class BeforeImapClientCreated extends Event { - /** @var Account */ - private $account; + private MailAccount $account; - public function __construct(Account $account) { + public function __construct(MailAccount $account) { parent::__construct(); $this->account = $account; } - /** - * @return Account - */ - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } } diff --git a/lib/Events/BeforeMessageDeletedEvent.php b/lib/Events/BeforeMessageDeletedEvent.php index 41d33c303b..3744b5690f 100644 --- a/lib/Events/BeforeMessageDeletedEvent.php +++ b/lib/Events/BeforeMessageDeletedEvent.php @@ -9,12 +9,11 @@ namespace OCA\Mail\Events; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCP\EventDispatcher\Event; class BeforeMessageDeletedEvent extends Event { - /** @var Account */ - private $account; + private MailAccount $account; /** @var string */ private $folderId; @@ -22,14 +21,14 @@ class BeforeMessageDeletedEvent extends Event { /** @var int */ private $messageId; - public function __construct(Account $account, string $mailbox, int $messageId) { + public function __construct(MailAccount $account, string $mailbox, int $messageId) { parent::__construct(); $this->account = $account; $this->folderId = $mailbox; $this->messageId = $messageId; } - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } diff --git a/lib/Events/DraftMessageCreatedEvent.php b/lib/Events/DraftMessageCreatedEvent.php index c96deedf93..9b7287bfe9 100644 --- a/lib/Events/DraftMessageCreatedEvent.php +++ b/lib/Events/DraftMessageCreatedEvent.php @@ -9,7 +9,7 @@ namespace OCA\Mail\Events; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Message; use OCP\EventDispatcher\Event; @@ -17,20 +17,17 @@ * @psalm-immutable */ class DraftMessageCreatedEvent extends Event { - /** @var Account */ - private $account; /** @var Message */ private $draft; - public function __construct(Account $account, + public function __construct(private MailAccount $account, Message $draft) { parent::__construct(); - $this->account = $account; $this->draft = $draft; } - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } diff --git a/lib/Events/DraftSavedEvent.php b/lib/Events/DraftSavedEvent.php index 747ae00f6b..04ab1130cf 100644 --- a/lib/Events/DraftSavedEvent.php +++ b/lib/Events/DraftSavedEvent.php @@ -9,31 +9,27 @@ namespace OCA\Mail\Events; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Message; use OCA\Mail\Model\NewMessageData; use OCP\EventDispatcher\Event; class DraftSavedEvent extends Event { - /** @var Account */ - private $account; - /** @var NewMessageData|null */ private $newMessageData; /** @var Message|null */ private $draft; - public function __construct(Account $account, + public function __construct(private MailAccount $account, ?NewMessageData $newMessageData = null, ?Message $draft = null) { parent::__construct(); - $this->account = $account; $this->newMessageData = $newMessageData; $this->draft = $draft; } - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } diff --git a/lib/Events/MailboxesSynchronizedEvent.php b/lib/Events/MailboxesSynchronizedEvent.php index 5ffa94c3b4..69aa7ff16c 100644 --- a/lib/Events/MailboxesSynchronizedEvent.php +++ b/lib/Events/MailboxesSynchronizedEvent.php @@ -9,22 +9,18 @@ namespace OCA\Mail\Events; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCP\EventDispatcher\Event; /** * @psalm-immutable */ class MailboxesSynchronizedEvent extends Event { - /** @var Account */ - private $account; - - public function __construct(Account $account) { + public function __construct(private MailAccount $account) { parent::__construct(); - $this->account = $account; } - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } } diff --git a/lib/Events/MessageDeletedEvent.php b/lib/Events/MessageDeletedEvent.php index 311966d9b8..740223cbc3 100644 --- a/lib/Events/MessageDeletedEvent.php +++ b/lib/Events/MessageDeletedEvent.php @@ -9,30 +9,26 @@ namespace OCA\Mail\Events; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCP\EventDispatcher\Event; class MessageDeletedEvent extends Event { - /** @var Account */ - private $account; - /** @var Mailbox */ private $mailbox; /** @var int */ private $messageId; - public function __construct(Account $account, + public function __construct(private MailAccount $account, Mailbox $mailbox, int $messageId) { parent::__construct(); - $this->account = $account; $this->mailbox = $mailbox; $this->messageId = $messageId; } - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } diff --git a/lib/Events/MessageFlaggedEvent.php b/lib/Events/MessageFlaggedEvent.php index 3fbafddd1f..0531460e40 100644 --- a/lib/Events/MessageFlaggedEvent.php +++ b/lib/Events/MessageFlaggedEvent.php @@ -9,14 +9,11 @@ namespace OCA\Mail\Events; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCP\EventDispatcher\Event; class MessageFlaggedEvent extends Event { - /** @var Account */ - private $account; - /** @var Mailbox */ private $mailbox; @@ -29,20 +26,19 @@ class MessageFlaggedEvent extends Event { /** @var bool */ private $set; - public function __construct(Account $account, + public function __construct(private MailAccount $account, Mailbox $mailbox, int $uid, string $flag, bool $set) { parent::__construct(); - $this->account = $account; $this->mailbox = $mailbox; $this->uid = $uid; $this->flag = $flag; $this->set = $set; } - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } diff --git a/lib/Events/MessageSentEvent.php b/lib/Events/MessageSentEvent.php index c2d47f16b4..e8b95928bd 100644 --- a/lib/Events/MessageSentEvent.php +++ b/lib/Events/MessageSentEvent.php @@ -9,24 +9,21 @@ namespace OCA\Mail\Events; -use OCA\Mail\Account; use OCA\Mail\Db\LocalMessage; +use OCA\Mail\Db\MailAccount; use OCP\EventDispatcher\Event; /** * @psalm-immutable */ class MessageSentEvent extends Event { - /** @var Account */ - private $account; - - public function __construct(Account $account, + public function __construct(private MailAccount $account, private LocalMessage $localMessage) { parent::__construct(); $this->account = $account; } - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } diff --git a/lib/Events/NewMessagesSynchronized.php b/lib/Events/NewMessagesSynchronized.php index aa77cac3b1..12e1312ebd 100644 --- a/lib/Events/NewMessagesSynchronized.php +++ b/lib/Events/NewMessagesSynchronized.php @@ -9,14 +9,12 @@ namespace OCA\Mail\Events; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\Message; use OCP\EventDispatcher\Event; class NewMessagesSynchronized extends Event { - /** @var Account */ - private $account; /** @var Mailbox */ private $mailbox; @@ -25,20 +23,18 @@ class NewMessagesSynchronized extends Event { private $messages; /** - * @param Account $account * @param Mailbox $mailbox * @param Message[] $messages */ - public function __construct(Account $account, + public function __construct(private MailAccount $account, Mailbox $mailbox, array $messages) { parent::__construct(); - $this->account = $account; $this->mailbox = $mailbox; $this->messages = $messages; } - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } diff --git a/lib/Events/OutboxMessageCreatedEvent.php b/lib/Events/OutboxMessageCreatedEvent.php index 098b76843d..137e5a42e8 100644 --- a/lib/Events/OutboxMessageCreatedEvent.php +++ b/lib/Events/OutboxMessageCreatedEvent.php @@ -9,7 +9,7 @@ namespace OCA\Mail\Events; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Message; use OCP\EventDispatcher\Event; @@ -17,20 +17,16 @@ * @psalm-immutable */ class OutboxMessageCreatedEvent extends Event { - /** @var Account */ - private $account; - /** @var Message */ private $draft; - public function __construct(Account $account, + public function __construct(private MailAccount $account, Message $draft) { parent::__construct(); - $this->account = $account; $this->draft = $draft; } - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } diff --git a/lib/Events/SaveDraftEvent.php b/lib/Events/SaveDraftEvent.php index 634332d84c..50c36ce106 100644 --- a/lib/Events/SaveDraftEvent.php +++ b/lib/Events/SaveDraftEvent.php @@ -9,31 +9,27 @@ namespace OCA\Mail\Events; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Message; use OCA\Mail\Model\NewMessageData; use OCP\EventDispatcher\Event; class SaveDraftEvent extends Event { - /** @var Account */ - private $account; - /** @var NewMessageData */ private $newMessageData; /** @var Message|null */ private $draft; - public function __construct(Account $account, + public function __construct(private MailAccount $account, NewMessageData $newMessageData, ?Message $draft) { parent::__construct(); - $this->account = $account; $this->newMessageData = $newMessageData; $this->draft = $draft; } - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } diff --git a/lib/Events/SynchronizationEvent.php b/lib/Events/SynchronizationEvent.php index 26392dd7a6..e250ad073e 100644 --- a/lib/Events/SynchronizationEvent.php +++ b/lib/Events/SynchronizationEvent.php @@ -9,13 +9,11 @@ namespace OCA\Mail\Events; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCP\EventDispatcher\Event; use Psr\Log\LoggerInterface; class SynchronizationEvent extends Event { - /** @var Account */ - private $account; /** @var LoggerInterface */ private $logger; @@ -23,17 +21,15 @@ class SynchronizationEvent extends Event { /** @var bool */ private $rebuildThreads; - public function __construct(Account $account, + public function __construct(private MailAccount $account, LoggerInterface $logger, bool $rebuildThreads) { parent::__construct(); - - $this->account = $account; $this->logger = $logger; $this->rebuildThreads = $rebuildThreads; } - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } diff --git a/lib/IMAP/FolderMapper.php b/lib/IMAP/FolderMapper.php index a4815de2f3..93191b74a4 100644 --- a/lib/IMAP/FolderMapper.php +++ b/lib/IMAP/FolderMapper.php @@ -12,7 +12,7 @@ use Horde_Imap_Client; use Horde_Imap_Client_Exception; use Horde_Imap_Client_Socket; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Exception\ServiceException; use OCA\Mail\Folder; use Psr\Log\LoggerInterface; @@ -40,14 +40,13 @@ public function __construct(LoggerInterface $logger) { ]; /** - * @param Account $account * @param Horde_Imap_Client_Socket $client * @param string $pattern * * @return Folder[] * @throws Horde_Imap_Client_Exception */ - public function getFolders(Account $account, Horde_Imap_Client_Socket $client, + public function getFolders(MailAccount $account, Horde_Imap_Client_Socket $client, string $pattern = '*'): array { $mailboxes = $client->listMailboxes($pattern, Horde_Imap_Client::MBOX_ALL_SUBSCRIBED, [ 'delimiter' => true, @@ -75,7 +74,7 @@ public function getFolders(Account $account, Horde_Imap_Client_Socket $client, } public function createFolder(Horde_Imap_Client_Socket $client, - Account $account, + MailAccount $account, string $name): Folder { $client->createMailbox($name); diff --git a/lib/IMAP/IMAPClientFactory.php b/lib/IMAP/IMAPClientFactory.php index 14e96a942f..3150b1ef87 100644 --- a/lib/IMAP/IMAPClientFactory.php +++ b/lib/IMAP/IMAPClientFactory.php @@ -12,8 +12,8 @@ use Horde_Imap_Client_Cache_Backend_Null; use Horde_Imap_Client_Password_Xoauth2; use Horde_Imap_Client_Socket; -use OCA\Mail\Account; use OCA\Mail\Cache\Cache; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Events\BeforeImapClientCreated; use OCP\AppFramework\Utility\ITimeFactory; use OCP\EventDispatcher\IEventDispatcher; @@ -60,22 +60,22 @@ public function __construct(ICrypto $crypto, * responsible to log out as soon as possible to keep the number of open * (and stale) connections at a minimum. * - * @param Account $account + * @param MailAccount $account * @param bool $useCache * @return Horde_Imap_Client_Socket */ - public function getClient(Account $account, bool $useCache = true): Horde_Imap_Client_Socket { + public function getClient(MailAccount $account, bool $useCache = true): Horde_Imap_Client_Socket { $this->eventDispatcher->dispatchTyped( new BeforeImapClientCreated($account) ); - $host = $account->getMailAccount()->getInboundHost(); - $user = $account->getMailAccount()->getInboundUser(); + $host = $account->getInboundHost(); + $user = $account->getInboundUser(); $decryptedPassword = null; - if ($account->getMailAccount()->getInboundPassword() !== null) { - $decryptedPassword = $this->crypto->decrypt($account->getMailAccount()->getInboundPassword()); + if ($account->getInboundPassword() !== null) { + $decryptedPassword = $this->crypto->decrypt($account->getInboundPassword()); } - $port = $account->getMailAccount()->getInboundPort(); - $sslMode = $account->getMailAccount()->getInboundSslMode(); + $port = $account->getInboundPort(); + $sslMode = $account->getInboundSslMode(); if ($sslMode === 'none') { $sslMode = false; } @@ -94,8 +94,8 @@ public function getClient(Account $account, bool $useCache = true): Horde_Imap_C ], ], ]; - if ($account->getMailAccount()->getAuthMethod() === 'xoauth2') { - $decryptedAccessToken = $this->crypto->decrypt($account->getMailAccount()->getOauthAccessToken()); + if ($account->getAuthMethod() === 'xoauth2') { + $decryptedAccessToken = $this->crypto->decrypt($account->getOauthAccessToken()); $params['password'] = $decryptedAccessToken; // Not used, but Horde wants this $params['xoauth2_token'] = new Horde_Imap_Client_Password_Xoauth2( diff --git a/lib/IMAP/MailboxSync.php b/lib/IMAP/MailboxSync.php index 1d73bbc8e1..1b21420580 100644 --- a/lib/IMAP/MailboxSync.php +++ b/lib/IMAP/MailboxSync.php @@ -13,7 +13,7 @@ use Horde_Imap_Client_Data_Namespace; use Horde_Imap_Client_Exception; use Horde_Imap_Client_Namespace_List; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\MailAccountMapper; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\MailboxMapper; @@ -76,10 +76,10 @@ public function __construct(MailboxMapper $mailboxMapper, /** * @throws ServiceException */ - public function sync(Account $account, + public function sync(MailAccount $account, LoggerInterface $logger, bool $force = false): void { - if (!$force && $account->getMailAccount()->getLastMailboxSync() >= ($this->timeFactory->getTime() - 7200)) { + if (!$force && $account->getLastMailboxSync() >= ($this->timeFactory->getTime() - 7200)) { $logger->debug('account is up to date, skipping mailbox sync'); return; } @@ -91,7 +91,7 @@ public function sync(Account $account, 'ob_return' => true, ]); $personalNamespace = $this->getPersonalNamespace($namespaces); - $account->getMailAccount()->setPersonalNamespace( + $account->setPersonalNamespace( $personalNamespace ); } catch (Horde_Imap_Client_Exception $e) { @@ -139,12 +139,11 @@ public function sync(Account $account, /** * Sync unread and total message statistics. * - * @param Account $account * @param Mailbox $mailbox * * @throws ServiceException */ - public function syncStats(Account $account, Mailbox $mailbox): void { + public function syncStats(MailAccount $account, Mailbox $mailbox): void { $client = $this->imapClientFactory->getClient($account); try { $allStats = $this->folderMapper->getFoldersStatusAsObject($client, [$mailbox->getName()]); @@ -172,7 +171,7 @@ public function syncStats(Account $account, Mailbox $mailbox): void { /** * @return Mailbox[] */ - private function persist(Account $account, + private function persist(MailAccount $account, array $folders, array $existing, ?Horde_Imap_Client_Namespace_List $namespaces): array { @@ -199,8 +198,8 @@ private function persist(Account $account, $this->mailboxMapper->delete($leftover); } - $account->getMailAccount()->setLastMailboxSync($this->timeFactory->getTime()); - $this->mailAccountMapper->update($account->getMailAccount()); + $account->setLastMailboxSync($this->timeFactory->getTime()); + $this->mailAccountMapper->update($account); return $mailboxes; } @@ -230,7 +229,7 @@ private function updateMailboxFromFolder(Folder $folder, Mailbox $mailbox, ?Hord return $this->mailboxMapper->update($mailbox); } - private function createMailboxFromFolder(Account $account, Folder $folder, ?Horde_Imap_Client_Namespace_List $namespaces): Mailbox { + private function createMailboxFromFolder(MailAccount $account, Folder $folder, ?Horde_Imap_Client_Namespace_List $namespaces): Mailbox { $mailbox = new Mailbox(); $mailbox->setName($folder->getMailbox()); $mailbox->setAccountId($account->getId()); diff --git a/lib/IMAP/PreviewEnhancer.php b/lib/IMAP/PreviewEnhancer.php index 99ce4b54e2..91bca65e5e 100644 --- a/lib/IMAP/PreviewEnhancer.php +++ b/lib/IMAP/PreviewEnhancer.php @@ -10,7 +10,7 @@ namespace OCA\Mail\IMAP; use Horde_Imap_Client_Exception; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\Message; use OCA\Mail\Db\MessageMapper as DbMapper; @@ -49,7 +49,7 @@ public function __construct(IMAPClientFactory $clientFactory, * * @return Message[] */ - public function process(Account $account, Mailbox $mailbox, array $messages): array { + public function process(MailAccount $account, Mailbox $mailbox, array $messages): array { $needAnalyze = array_reduce($messages, static function (array $carry, Message $message) { if ($message->getStructureAnalyzed()) { // Nothing to do diff --git a/lib/IMAP/Search/Provider.php b/lib/IMAP/Search/Provider.php index 35133f14d2..b0313c374c 100644 --- a/lib/IMAP/Search/Provider.php +++ b/lib/IMAP/Search/Provider.php @@ -11,7 +11,7 @@ use Horde_Imap_Client_Exception; use Horde_Imap_Client_Search_Query; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Exception\ServiceException; use OCA\Mail\IMAP\IMAPClientFactory; @@ -30,7 +30,7 @@ public function __construct(IMAPClientFactory $clientFactory) { * @return int[] * @throws ServiceException */ - public function findMatches(Account $account, + public function findMatches(MailAccount $account, Mailbox $mailbox, SearchQuery $searchQuery): array { $client = $this->clientFactory->getClient($account); diff --git a/lib/Integration/GoogleIntegration.php b/lib/Integration/GoogleIntegration.php index 5707335f05..defe103463 100644 --- a/lib/Integration/GoogleIntegration.php +++ b/lib/Integration/GoogleIntegration.php @@ -10,8 +10,8 @@ namespace OCA\Mail\Integration; use Exception; -use OCA\Mail\Account; use OCA\Mail\AppInfo\Application; +use OCA\Mail\Db\MailAccount; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Http\Client\IClientService; use OCP\IConfig; @@ -75,13 +75,13 @@ public function getClientId(): ?string { return $value; } - public function isGoogleOauthAccount(Account $account): bool { - return $account->getMailAccount()->getInboundHost() === 'imap.gmail.com' - && $account->getMailAccount()->getAuthMethod() === 'xoauth2'; + public function isGoogleOauthAccount(MailAccount $account): bool { + return $account->getInboundHost() === 'imap.gmail.com' + && $account->getAuthMethod() === 'xoauth2'; } - public function finishConnect(Account $account, - string $code): Account { + public function finishConnect(MailAccount $account, + string $code): MailAccount { $clientId = $this->config->getAppValue(Application::APP_ID, 'google_oauth_client_id'); $encryptedClientSecret = $this->config->getAppValue(Application::APP_ID, 'google_oauth_client_secret'); if (empty($clientId) || empty($encryptedClientSecret)) { @@ -111,21 +111,21 @@ public function finishConnect(Account $account, $data = json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR); $encryptedRefreshToken = $this->crypto->encrypt($data['refresh_token']); - $account->getMailAccount()->setOauthRefreshToken($encryptedRefreshToken); + $account->setOauthRefreshToken($encryptedRefreshToken); $encryptedAccessToken = $this->crypto->encrypt($data['access_token']); - $account->getMailAccount()->setOauthAccessToken($encryptedAccessToken); - $account->getMailAccount()->setOauthTokenTtl($this->timeFactory->getTime() + $data['expires_in']); + $account->setOauthAccessToken($encryptedAccessToken); + $account->setOauthTokenTtl($this->timeFactory->getTime() + $data['expires_in']); return $account; } - public function refresh(Account $account): Account { - if ($account->getMailAccount()->getOauthTokenTtl() === null || $account->getMailAccount()->getOauthRefreshToken() === null) { + public function refresh(MailAccount $account): MailAccount { + if ($account->getOauthTokenTtl() === null || $account->getOauthRefreshToken() === null) { // Account is not authorized yet return $account; } // Only refresh if the token expires in the next minute - if ($this->timeFactory->getTime() <= ($account->getMailAccount()->getOauthTokenTtl() - 60)) { + if ($this->timeFactory->getTime() <= ($account->getOauthTokenTtl() - 60)) { // No need to refresh yet return $account; } @@ -137,7 +137,7 @@ public function refresh(Account $account): Account { return $account; } - $refreshToken = $this->crypto->decrypt($account->getMailAccount()->getOauthRefreshToken()); + $refreshToken = $this->crypto->decrypt($account->getOauthRefreshToken()); $clientSecret = $this->crypto->decrypt($encryptedClientSecret); $httpClient = $this->clientService->newClient(); try { @@ -159,8 +159,8 @@ public function refresh(Account $account): Account { $data = json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR); $encryptedAccessToken = $this->crypto->encrypt($data['access_token']); - $account->getMailAccount()->setOauthAccessToken($encryptedAccessToken); - $account->getMailAccount()->setOauthTokenTtl($this->timeFactory->getTime() + $data['expires_in']); + $account->setOauthAccessToken($encryptedAccessToken); + $account->setOauthTokenTtl($this->timeFactory->getTime() + $data['expires_in']); return $account; } diff --git a/lib/Integration/MicrosoftIntegration.php b/lib/Integration/MicrosoftIntegration.php index 2cf92f8043..2f0c125d14 100644 --- a/lib/Integration/MicrosoftIntegration.php +++ b/lib/Integration/MicrosoftIntegration.php @@ -10,8 +10,8 @@ namespace OCA\Mail\Integration; use Exception; -use OCA\Mail\Account; use OCA\Mail\AppInfo\Application; +use OCA\Mail\Db\MailAccount; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Http\Client\IClientService; use OCP\IConfig; @@ -89,13 +89,13 @@ public function getClientId(): ?string { return $value; } - public function isMicrosoftOauthAccount(Account $account): bool { - return $account->getMailAccount()->getInboundHost() === 'outlook.office365.com' - && $account->getMailAccount()->getAuthMethod() === 'xoauth2'; + public function isMicrosoftOauthAccount(MailAccount $account): bool { + return $account->getInboundHost() === 'outlook.office365.com' + && $account->getAuthMethod() === 'xoauth2'; } - public function finishConnect(Account $account, - string $code): Account { + public function finishConnect(MailAccount $account, + string $code): MailAccount { $tenantId = $this->getTenantId(); $clientId = $this->config->getAppValue(Application::APP_ID, 'microsoft_oauth_client_id'); $encryptedClientSecret = $this->config->getAppValue(Application::APP_ID, 'microsoft_oauth_client_secret'); @@ -125,21 +125,21 @@ public function finishConnect(Account $account, $data = json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR); $encryptedRefreshToken = $this->crypto->encrypt($data['refresh_token']); - $account->getMailAccount()->setOauthRefreshToken($encryptedRefreshToken); + $account->setOauthRefreshToken($encryptedRefreshToken); $encryptedAccessToken = $this->crypto->encrypt($data['access_token']); - $account->getMailAccount()->setOauthAccessToken($encryptedAccessToken); - $account->getMailAccount()->setOauthTokenTtl($this->timeFactory->getTime() + $data['expires_in']); + $account->setOauthAccessToken($encryptedAccessToken); + $account->setOauthTokenTtl($this->timeFactory->getTime() + $data['expires_in']); return $account; } - public function refresh(Account $account): Account { - if ($account->getMailAccount()->getOauthTokenTtl() === null || $account->getMailAccount()->getOauthRefreshToken() === null) { + public function refresh(MailAccount $account): MailAccount { + if ($account->getOauthTokenTtl() === null || $account->getOauthRefreshToken() === null) { // Account is not authorized yet return $account; } // Only refresh if the token expires in the next minute - if ($this->timeFactory->getTime() <= ($account->getMailAccount()->getOauthTokenTtl() - 60)) { + if ($this->timeFactory->getTime() <= ($account->getOauthTokenTtl() - 60)) { // No need to refresh yet return $account; } @@ -152,7 +152,7 @@ public function refresh(Account $account): Account { return $account; } - $refreshToken = $this->crypto->decrypt($account->getMailAccount()->getOauthRefreshToken()); + $refreshToken = $this->crypto->decrypt($account->getOauthRefreshToken()); $clientSecret = $this->crypto->decrypt($encryptedClientSecret); $httpClient = $this->clientService->newClient(); try { @@ -174,8 +174,8 @@ public function refresh(Account $account): Account { $data = json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR); $encryptedAccessToken = $this->crypto->encrypt($data['access_token']); - $account->getMailAccount()->setOauthAccessToken($encryptedAccessToken); - $account->getMailAccount()->setOauthTokenTtl($this->timeFactory->getTime() + $data['expires_in']); + $account->setOauthAccessToken($encryptedAccessToken); + $account->setOauthTokenTtl($this->timeFactory->getTime() + $data['expires_in']); return $account; } diff --git a/lib/Listener/AccountSynchronizedThreadUpdaterListener.php b/lib/Listener/AccountSynchronizedThreadUpdaterListener.php index 6051bea337..31006a6b22 100644 --- a/lib/Listener/AccountSynchronizedThreadUpdaterListener.php +++ b/lib/Listener/AccountSynchronizedThreadUpdaterListener.php @@ -50,7 +50,8 @@ public function handle(Event $event): void { return; } - $accountId = $event->getAccount()->getId(); + $account = $event->getAccount(); + $accountId = $account->getId(); $logger->debug("Building threads for account $accountId"); $messages = $this->mapper->findThreadingData($event->getAccount()); $logger->debug("Account $accountId has " . count($messages) . ' messages with threading information'); diff --git a/lib/Listener/AddressCollectionListener.php b/lib/Listener/AddressCollectionListener.php index eaa53245e0..aa5c1feee7 100644 --- a/lib/Listener/AddressCollectionListener.php +++ b/lib/Listener/AddressCollectionListener.php @@ -45,7 +45,8 @@ public function handle(Event $event): void { if (!($event instanceof MessageSentEvent)) { return; } - if ($this->preferences->getPreference($event->getAccount()->getUserId(), 'collect-data', 'true') !== 'true') { + $account1 = $event->getAccount(); + if ($this->preferences->getPreference($account1->getUserId(), 'collect-data', 'true') !== 'true') { $this->logger->debug('Not collecting email addresses because the user opted out'); return; } @@ -59,7 +60,8 @@ public function handle(Event $event): void { $addresses = $to->merge($cc)->merge($bcc); - $this->collector->addAddresses($event->getAccount()->getUserId(), $addresses); + $account = $event->getAccount(); + $this->collector->addAddresses($account->getUserId(), $addresses); } catch (Throwable $e) { $this->logger->warning('Error while collecting mail addresses: ' . $e, [ 'exception' => $e, diff --git a/lib/Listener/DeleteDraftListener.php b/lib/Listener/DeleteDraftListener.php index 5e8b1b6d6f..86adda6e35 100644 --- a/lib/Listener/DeleteDraftListener.php +++ b/lib/Listener/DeleteDraftListener.php @@ -11,7 +11,7 @@ use Horde_Imap_Client; use Horde_Imap_Client_Exception; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\MailboxMapper; use OCA\Mail\Db\Message; @@ -65,10 +65,9 @@ public function handle(Event $event): void { } /** - * @param Account $account * @param Message $draft */ - private function deleteDraft(Account $account, Message $draft): void { + private function deleteDraft(MailAccount $account, Message $draft): void { $client = $this->imapClientFactory->getClient($account); try { $draftsMailbox = $this->getDraftsMailbox($account); @@ -108,8 +107,8 @@ private function deleteDraft(Account $account, Message $draft): void { /** * @throws DoesNotExistException */ - private function getDraftsMailbox(Account $account): Mailbox { - $draftsMailboxId = $account->getMailAccount()->getDraftsMailboxId(); + private function getDraftsMailbox(MailAccount $account): Mailbox { + $draftsMailboxId = $account->getDraftsMailboxId(); if ($draftsMailboxId === null) { throw new DoesNotExistException('No drafts mailbox ID set'); } diff --git a/lib/Listener/FollowUpClassifierListener.php b/lib/Listener/FollowUpClassifierListener.php index 9b9a39e996..6b7891048c 100644 --- a/lib/Listener/FollowUpClassifierListener.php +++ b/lib/Listener/FollowUpClassifierListener.php @@ -36,7 +36,7 @@ public function handle(Event $event): void { } if (!$event->getMailbox()->isSpecialUse('sent') - && $event->getAccount()->getMailAccount()->getSentMailboxId() !== $event->getMailbox()->getId() + && $event->getAccount()->getSentMailboxId() !== $event->getMailbox()->getId() ) { return; } @@ -52,7 +52,8 @@ public function handle(Event $event): void { // Do not process emails older than 14D to save some processing power $notBefore = (new DateTimeImmutable('now')) ->sub(new DateInterval('P14D')); - $userId = $event->getAccount()->getUserId(); + $account = $event->getAccount(); + $userId = $account->getUserId(); foreach ($event->getMessages() as $message) { if ($message->getSentAt() < $notBefore->getTimestamp()) { continue; diff --git a/lib/Listener/MailboxesSynchronizedSpecialMailboxesUpdater.php b/lib/Listener/MailboxesSynchronizedSpecialMailboxesUpdater.php index c4de8ded3a..526aaeb49e 100644 --- a/lib/Listener/MailboxesSynchronizedSpecialMailboxesUpdater.php +++ b/lib/Listener/MailboxesSynchronizedSpecialMailboxesUpdater.php @@ -51,7 +51,7 @@ public function __construct(MailAccountMapper $mailAccountMapper, public function handle(Event $event): void { /** @var MailboxesSynchronizedEvent $event */ $account = $event->getAccount(); - $mailAccount = $account->getMailAccount(); + $mailAccount = $account; $mailboxes = $this->indexMailboxes( $this->mailboxMapper->findAll($account) ); diff --git a/lib/Listener/MessageKnownSinceListener.php b/lib/Listener/MessageKnownSinceListener.php index f9a8db58f0..d04ec1ba2d 100644 --- a/lib/Listener/MessageKnownSinceListener.php +++ b/lib/Listener/MessageKnownSinceListener.php @@ -32,12 +32,12 @@ public function handle(Event $event): void { return; } - $trashRetention = $event->getAccount()->getMailAccount()->getTrashRetentionDays(); + $trashRetention = $event->getAccount()->getTrashRetentionDays(); if ($trashRetention === null) { return; } - $trashMailboxId = $event->getAccount()->getMailAccount()->getTrashMailboxId(); + $trashMailboxId = $event->getAccount()->getTrashMailboxId(); if ($trashMailboxId === null) { return; } diff --git a/lib/Listener/MoveJunkListener.php b/lib/Listener/MoveJunkListener.php index ec481fa88f..2fff4c7ffc 100644 --- a/lib/Listener/MoveJunkListener.php +++ b/lib/Listener/MoveJunkListener.php @@ -33,7 +33,7 @@ public function handle(Event $event): void { } $account = $event->getAccount(); - $mailAccount = $account->getMailAccount(); + $mailAccount = $account; $junkMailboxId = $mailAccount->getJunkMailboxId(); if ($junkMailboxId === null) { diff --git a/lib/Listener/NewMessageClassificationListener.php b/lib/Listener/NewMessageClassificationListener.php index 780fbd3723..2bb0c30749 100644 --- a/lib/Listener/NewMessageClassificationListener.php +++ b/lib/Listener/NewMessageClassificationListener.php @@ -65,7 +65,8 @@ public function handle(Event $event): void { return; } - if (!$this->classificationSettingsService->isClassificationEnabled($event->getAccount()->getUserId())) { + $account3 = $event->getAccount(); + if (!$this->classificationSettingsService->isClassificationEnabled($account3->getUserId())) { return; } @@ -79,9 +80,10 @@ public function handle(Event $event): void { $messages = $event->getMessages(); // if this is a message that's been flagged / tagged as important before, we don't want to reclassify it again. + $account2 = $event->getAccount(); $doNotReclassify = $this->tagMapper->getTaggedMessageIdsForMessages( $event->getMessages(), - $event->getAccount()->getUserId(), + $account2->getUserId(), Tag::LABEL_IMPORTANT ); $messages = array_filter($messages, static function ($message) use ($doNotReclassify) { @@ -89,10 +91,12 @@ public function handle(Event $event): void { }); try { - $important = $this->tagMapper->getTagByImapLabel(Tag::LABEL_IMPORTANT, $event->getAccount()->getUserId()); + $account1 = $event->getAccount(); + $important = $this->tagMapper->getTagByImapLabel(Tag::LABEL_IMPORTANT, $account1->getUserId()); } catch (DoesNotExistException $e) { // just in case - if we get here, the tag is missing - $this->logger->error('Could not find important tag for ' . $event->getAccount()->getUserId(). ' ' . $e->getMessage(), [ + $account = $event->getAccount(); + $this->logger->error('Could not find important tag for ' . $account->getUserId() . ' ' . $e->getMessage(), [ 'exception' => $e, ]); return; diff --git a/lib/Listener/OauthTokenRefreshListener.php b/lib/Listener/OauthTokenRefreshListener.php index 80cffe3985..f3aa5635aa 100644 --- a/lib/Listener/OauthTokenRefreshListener.php +++ b/lib/Listener/OauthTokenRefreshListener.php @@ -43,6 +43,6 @@ public function handle(Event $event): void { return; } - $this->accountService->update($updated->getMailAccount()); + $this->accountService->update($updated); } } diff --git a/lib/Listener/OutOfOfficeListener.php b/lib/Listener/OutOfOfficeListener.php index 582d41d7c8..ea86a008d5 100644 --- a/lib/Listener/OutOfOfficeListener.php +++ b/lib/Listener/OutOfOfficeListener.php @@ -61,7 +61,7 @@ public function handle(Event $event): void { $accounts = $this->accountService->findByUserId($event->getData()->getUser()->getUID()); foreach ($accounts as $account) { - if (!$account->getMailAccount()->getOutOfOfficeFollowsSystem()) { + if (!$account->getOutOfOfficeFollowsSystem()) { continue; } @@ -73,7 +73,7 @@ public function handle(Event $event): void { $eventData->getMessage(), ); try { - $this->outOfOfficeService->update($account->getMailAccount(), $state); + $this->outOfOfficeService->update($account, $state); } catch (Exception $e) { $this->logger->error('Failed to apply out-of-office sieve script: ' . $e->getMessage(), [ 'exception' => $e, diff --git a/lib/Migration/MigrateImportantFromImapAndDb.php b/lib/Migration/MigrateImportantFromImapAndDb.php index 3216f1f692..c02ec417a7 100644 --- a/lib/Migration/MigrateImportantFromImapAndDb.php +++ b/lib/Migration/MigrateImportantFromImapAndDb.php @@ -11,7 +11,6 @@ use Horde_Imap_Client_Exception; use Horde_Imap_Client_Socket; -use OCA\Mail\Account; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\MailboxMapper; use OCA\Mail\Db\Tag; @@ -42,7 +41,7 @@ public function __construct(MessageMapper $messageMapper, $this->logger = $logger; } - public function migrateImportantOnImap(Horde_Imap_Client_Socket $client, Account $account, Mailbox $mailbox): void { + public function migrateImportantOnImap(Horde_Imap_Client_Socket $client, Mailbox $mailbox): void { try { $uids = $this->messageMapper->getFlagged($client, $mailbox, '$important'); } catch (Horde_Imap_Client_Exception $e) { @@ -59,7 +58,7 @@ public function migrateImportantOnImap(Horde_Imap_Client_Socket $client, Account } } - public function migrateImportantFromDb(Horde_Imap_Client_Socket $client, Account $account, Mailbox $mailbox): void { + public function migrateImportantFromDb(Horde_Imap_Client_Socket $client, Mailbox $mailbox): void { $uids = $this->mailboxMapper->findFlaggedImportantUids($mailbox->getId()); // store our data on imap if ($uids !== []) { diff --git a/lib/Model/NewMessageData.php b/lib/Model/NewMessageData.php index f4ea8a044a..9a668a3336 100644 --- a/lib/Model/NewMessageData.php +++ b/lib/Model/NewMessageData.php @@ -9,8 +9,8 @@ namespace OCA\Mail\Model; -use OCA\Mail\Account; use OCA\Mail\AddressList; +use OCA\Mail\Db\MailAccount; /** * Simple data class that wraps the request data of a new message or reply @@ -22,8 +22,7 @@ class NewMessageData { private bool $smimeSign; private bool $smimeEncrypt; - /** @var Account */ - private $account; + private MailAccount $account; /** @var AddressList */ private $to; @@ -50,7 +49,6 @@ class NewMessageData { private $isMdnRequested; /** - * @param Account $account * @param AddressList $to * @param AddressList $cc * @param AddressList $bcc @@ -62,7 +60,7 @@ class NewMessageData { * @param bool $smimeSign * @param bool $isMdnRequested */ - public function __construct(Account $account, + public function __construct(MailAccount $account, AddressList $to, AddressList $cc, AddressList $bcc, @@ -89,7 +87,6 @@ public function __construct(Account $account, } /** - * @param Account $account * @param string $subject * @param string $body * @param string|null $to @@ -102,7 +99,7 @@ public function __construct(Account $account, * @param bool $smimeSign * @return NewMessageData */ - public static function fromRequest(Account $account, + public static function fromRequest(MailAccount $account, string $subject, string $body, ?string $to = null, @@ -134,10 +131,7 @@ public static function fromRequest(Account $account, ); } - /** - * @return Account - */ - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } diff --git a/lib/Model/RepliedMessageData.php b/lib/Model/RepliedMessageData.php index 3d5bf049d1..0377af1e59 100644 --- a/lib/Model/RepliedMessageData.php +++ b/lib/Model/RepliedMessageData.php @@ -9,7 +9,7 @@ namespace OCA\Mail\Model; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Message; /** @@ -18,18 +18,17 @@ * @psalm-immutable */ class RepliedMessageData { - /** @var Account */ - private $account; + private MailAccount $account; /** @var Message */ private $message; - public function __construct(Account $account, Message $message) { + public function __construct(MailAccount $account, Message $message) { $this->account = $account; $this->message = $message; } - public function getAccount(): Account { + public function getAccount(): MailAccount { return $this->account; } diff --git a/lib/Provider/MailProvider.php b/lib/Provider/MailProvider.php index 29877ef17c..820de158da 100644 --- a/lib/Provider/MailProvider.php +++ b/lib/Provider/MailProvider.php @@ -8,7 +8,7 @@ */ namespace OCA\Mail\Provider; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Exception\ClientException; use OCA\Mail\Service\AccountService; use OCP\IL10N; @@ -151,11 +151,10 @@ public function initiateService(): IService { * @since 4.0.0 * * @param string $userId system user id - * @param Account $account mail account * * @return IService service object */ - protected function serviceFromAccount(string $userId, Account $account): IService { + protected function serviceFromAccount(string $userId, MailAccount $account): IService { // extract values $serviceId = (string)$account->getId(); $serviceLabel = $account->getName(); diff --git a/lib/SMTP/SmtpClientFactory.php b/lib/SMTP/SmtpClientFactory.php index 2a2d954254..74344b43c9 100644 --- a/lib/SMTP/SmtpClientFactory.php +++ b/lib/SMTP/SmtpClientFactory.php @@ -13,7 +13,7 @@ use Horde_Mail_Transport_Mail; use Horde_Mail_Transport_Smtphorde; use Horde_Smtp_Password_Xoauth2; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Support\HostNameFactory; use OCP\IConfig; use OCP\Security\ICrypto; @@ -37,12 +37,10 @@ public function __construct(IConfig $config, } /** - * @param Account $account - * * @return Horde_Mail_Transport */ - public function create(Account $account): Horde_Mail_Transport { - $mailAccount = $account->getMailAccount(); + public function create(MailAccount $account): Horde_Mail_Transport { + $mailAccount = $account; $transport = $this->config->getSystemValue('app.mail.transport', 'smtp'); if ($transport === 'php-mail') { return new Horde_Mail_Transport_Mail(); @@ -68,8 +66,8 @@ public function create(Account $account): Horde_Mail_Transport { ], ], ]; - if ($account->getMailAccount()->getAuthMethod() === 'xoauth2') { - $decryptedAccessToken = $this->crypto->decrypt($account->getMailAccount()->getOauthAccessToken()); + if ($account->getAuthMethod() === 'xoauth2') { + $decryptedAccessToken = $this->crypto->decrypt($account->getOauthAccessToken()); $params['password'] = $decryptedAccessToken; // Not used, but Horde wants this $params['xoauth2_token'] = new Horde_Smtp_Password_Xoauth2( diff --git a/lib/Send/AHandler.php b/lib/Send/AHandler.php index e687ce993f..51fd9a6f0e 100644 --- a/lib/Send/AHandler.php +++ b/lib/Send/AHandler.php @@ -7,8 +7,8 @@ */ namespace OCA\Mail\Send; -use OCA\Mail\Account; use OCA\Mail\Db\LocalMessage; +use OCA\Mail\Db\MailAccount; abstract class AHandler { @@ -18,9 +18,9 @@ public function setNext(AHandler $next): AHandler { return $next; } - abstract public function process(Account $account, LocalMessage $localMessage): LocalMessage; + abstract public function process(MailAccount $account, LocalMessage $localMessage): LocalMessage; - protected function processNext(Account $account, LocalMessage $localMessage): LocalMessage { + protected function processNext(MailAccount $account, LocalMessage $localMessage): LocalMessage { if ($this->next !== null) { return $this->next->process($account, $localMessage); } diff --git a/lib/Send/AntiAbuseHandler.php b/lib/Send/AntiAbuseHandler.php index 5d176f109c..180e18ac80 100644 --- a/lib/Send/AntiAbuseHandler.php +++ b/lib/Send/AntiAbuseHandler.php @@ -7,8 +7,8 @@ */ namespace OCA\Mail\Send; -use OCA\Mail\Account; use OCA\Mail\Db\LocalMessage; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Service\AntiAbuseService; use OCP\IUserManager; use Psr\Log\LoggerInterface; @@ -19,7 +19,7 @@ public function __construct(private IUserManager $userManager, private AntiAbuseService $service, private LoggerInterface $logger) { } - public function process(Account $account, LocalMessage $localMessage): LocalMessage { + public function process(MailAccount $account, LocalMessage $localMessage): LocalMessage { if ($localMessage->getStatus() === LocalMessage::STATUS_IMAP_SENT_MAILBOX_FAIL || $localMessage->getStatus() === LocalMessage::STATUS_PROCESSED) { return $this->processNext($account, $localMessage); diff --git a/lib/Send/Chain.php b/lib/Send/Chain.php index b8d2c97094..b39a78baf2 100644 --- a/lib/Send/Chain.php +++ b/lib/Send/Chain.php @@ -7,9 +7,9 @@ */ namespace OCA\Mail\Send; -use OCA\Mail\Account; use OCA\Mail\Db\LocalMessage; use OCA\Mail\Db\LocalMessageMapper; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Exception\ServiceException; use OCA\Mail\Service\Attachment\AttachmentService; use OCP\DB\Exception; @@ -30,7 +30,7 @@ public function __construct(private SentMailboxHandler $sentMailboxHandler, * @throws Exception * @throws ServiceException */ - public function process(Account $account, LocalMessage $localMessage): LocalMessage { + public function process(MailAccount $account, LocalMessage $localMessage): LocalMessage { $handlers = $this->sentMailboxHandler; $handlers->setNext($this->antiAbuseHandler) ->setNext($this->sendHandler) diff --git a/lib/Send/CopySentMessageHandler.php b/lib/Send/CopySentMessageHandler.php index 38b62d67ed..cd452b237e 100644 --- a/lib/Send/CopySentMessageHandler.php +++ b/lib/Send/CopySentMessageHandler.php @@ -8,8 +8,8 @@ namespace OCA\Mail\Send; use Horde_Imap_Client_Exception; -use OCA\Mail\Account; use OCA\Mail\Db\LocalMessage; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\MailboxMapper; use OCA\Mail\IMAP\IMAPClientFactory; use OCA\Mail\IMAP\MessageMapper; @@ -23,7 +23,7 @@ public function __construct(private IMAPClientFactory $imapClientFactory, private MessageMapper $messageMapper, ) { } - public function process(Account $account, LocalMessage $localMessage): LocalMessage { + public function process(MailAccount $account, LocalMessage $localMessage): LocalMessage { if ($localMessage->getStatus() === LocalMessage::STATUS_PROCESSED) { return $this->processNext($account, $localMessage); } @@ -34,7 +34,7 @@ public function process(Account $account, LocalMessage $localMessage): LocalMess return $localMessage; } - $sentMailboxId = $account->getMailAccount()->getSentMailboxId(); + $sentMailboxId = $account->getSentMailboxId(); if ($sentMailboxId === null) { // We can't write the "sent mailbox" status here bc that would trigger an additional send. // Thus, we leave the "imap copy to sent mailbox" status. diff --git a/lib/Send/FlagRepliedMessageHandler.php b/lib/Send/FlagRepliedMessageHandler.php index a56b1c1176..b91a2dca7d 100644 --- a/lib/Send/FlagRepliedMessageHandler.php +++ b/lib/Send/FlagRepliedMessageHandler.php @@ -9,8 +9,8 @@ use Horde_Imap_Client; use Horde_Imap_Client_Exception; -use OCA\Mail\Account; use OCA\Mail\Db\LocalMessage; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\MailboxMapper; use OCA\Mail\Db\MessageMapper as DbMessageMapper; use OCA\Mail\IMAP\IMAPClientFactory; @@ -27,7 +27,7 @@ public function __construct(private IMAPClientFactory $imapClientFactory, ) { } - public function process(Account $account, LocalMessage $localMessage): LocalMessage { + public function process(MailAccount $account, LocalMessage $localMessage): LocalMessage { if ($localMessage->getStatus() !== LocalMessage::STATUS_PROCESSED) { return $localMessage; } diff --git a/lib/Send/SendHandler.php b/lib/Send/SendHandler.php index c3e2edaea0..827dd39b49 100644 --- a/lib/Send/SendHandler.php +++ b/lib/Send/SendHandler.php @@ -7,16 +7,16 @@ */ namespace OCA\Mail\Send; -use OCA\Mail\Account; use OCA\Mail\Contracts\IMailTransmission; use OCA\Mail\Db\LocalMessage; +use OCA\Mail\Db\MailAccount; class SendHandler extends AHandler { public function __construct(private IMailTransmission $transmission, ) { } - public function process(Account $account, LocalMessage $localMessage): LocalMessage { + public function process(MailAccount $account, LocalMessage $localMessage): LocalMessage { if ($localMessage->getStatus() === LocalMessage::STATUS_IMAP_SENT_MAILBOX_FAIL || $localMessage->getStatus() === LocalMessage::STATUS_PROCESSED) { return $this->processNext($account, $localMessage); diff --git a/lib/Send/SentMailboxHandler.php b/lib/Send/SentMailboxHandler.php index b613aa7b16..dbbd31f64c 100644 --- a/lib/Send/SentMailboxHandler.php +++ b/lib/Send/SentMailboxHandler.php @@ -7,12 +7,12 @@ */ namespace OCA\Mail\Send; -use OCA\Mail\Account; use OCA\Mail\Db\LocalMessage; +use OCA\Mail\Db\MailAccount; class SentMailboxHandler extends AHandler { - public function process(Account $account, LocalMessage $localMessage): LocalMessage { - if ($account->getMailAccount()->getSentMailboxId() === null) { + public function process(MailAccount $account, LocalMessage $localMessage): LocalMessage { + if ($account->getSentMailboxId() === null) { $localMessage->setStatus(LocalMessage::STATUS_NO_SENT_MAILBOX); return $localMessage; } diff --git a/lib/Service/AccountService.php b/lib/Service/AccountService.php index dea1e33985..87f7bc6d2a 100644 --- a/lib/Service/AccountService.php +++ b/lib/Service/AccountService.php @@ -10,7 +10,6 @@ namespace OCA\Mail\Service; -use OCA\Mail\Account; use OCA\Mail\BackgroundJob\PreviewEnhancementProcessingJob; use OCA\Mail\BackgroundJob\QuotaJob; use OCA\Mail\BackgroundJob\SyncJob; @@ -31,7 +30,7 @@ class AccountService { /** * Cache accounts for multiple calls to 'findByUserId' * - * @var array + * @var array */ private array $accounts = []; @@ -56,13 +55,11 @@ public function __construct(MailAccountMapper $mapper, /** * @param string $currentUserId - * @return Account[] + * @return MailAccount[] */ public function findByUserId(string $currentUserId): array { if (!isset($this->accounts[$currentUserId])) { - $this->accounts[$currentUserId] = array_map(static function ($a) { - return new Account($a); - }, $this->mapper->findByUserId($currentUserId)); + $this->accounts[$currentUserId] = $this->mapper->findByUserId($currentUserId); } return $this->accounts[$currentUserId]; @@ -71,11 +68,10 @@ public function findByUserId(string $currentUserId): array { /** * @param int $id * - * @return Account * @throws DoesNotExistException */ - public function findById(int $id): Account { - return new Account($this->mapper->findById($id)); + public function findById(int $id): MailAccount { + return $this->mapper->findById($id); } /** @@ -111,10 +107,9 @@ public function findByUserIdAndAddress(string $userId, string $address): array { * @param string $userId * @param int $id * - * @return Account * @throws ClientException */ - public function find(string $userId, int $id): Account { + public function find(string $userId, int $id): MailAccount { if (isset($this->accounts[$userId])) { foreach ($this->accounts[$userId] as $account) { if ($account->getId() === $id) { @@ -125,7 +120,7 @@ public function find(string $userId, int $id): Account { } try { - return new Account($this->mapper->find($userId, $id)); + return $this->mapper->find($userId, $id); } catch (DoesNotExistException $e) { throw new ClientException("Account $id does not exist or you don\'t have permission to access it"); } @@ -191,7 +186,7 @@ public function update(MailAccount $account): MailAccount { */ public function updateSignature(int $id, string $uid, ?string $signature = null): void { $account = $this->find($uid, $id); - $mailAccount = $account->getMailAccount(); + $mailAccount = $account; $mailAccount->setSignature($signature); $this->mapper->save($mailAccount); } diff --git a/lib/Service/AiIntegrations/AiIntegrationsService.php b/lib/Service/AiIntegrations/AiIntegrationsService.php index dcadf0b7d3..33d1e3d02f 100644 --- a/lib/Service/AiIntegrations/AiIntegrationsService.php +++ b/lib/Service/AiIntegrations/AiIntegrationsService.php @@ -10,9 +10,9 @@ namespace OCA\Mail\Service\AiIntegrations; use JsonException; -use OCA\Mail\Account; use OCA\Mail\AppInfo\Application; use OCA\Mail\Contracts\IMailManager; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\Message; use OCA\Mail\Exception\ServiceException; @@ -62,7 +62,6 @@ public function __construct(ContainerInterface $container, Cache $cache, IMAPCli $this->config = $config; } /** - * @param Account $account * @param string $threadId * @param array $messages * @param string $currentUserId @@ -71,7 +70,7 @@ public function __construct(ContainerInterface $container, Cache $cache, IMAPCli * * @throws ServiceException */ - public function summarizeThread(Account $account, string $threadId, array $messages, string $currentUserId): null|string { + public function summarizeThread(MailAccount $account, string $threadId, array $messages, string $currentUserId): null|string { try { $manager = $this->container->get(IManager::class); } catch (\Throwable $e) { @@ -118,7 +117,7 @@ public function summarizeThread(Account $account, string $threadId, array $messa /** * @param Message[] $messages */ - public function generateEventData(Account $account, string $threadId, array $messages, string $currentUserId): ?EventData { + public function generateEventData(MailAccount $account, string $threadId, array $messages, string $currentUserId): ?EventData { try { /** @var IManager $manager */ $manager = $this->container->get(IManager::class); @@ -164,7 +163,7 @@ public function generateEventData(Account $account, string $threadId, array $mes * @return ?string[] * @throws ServiceException */ - public function getSmartReply(Account $account, Mailbox $mailbox, Message $message, string $currentUserId): ?array { + public function getSmartReply(MailAccount $account, Mailbox $mailbox, Message $message, string $currentUserId): ?array { try { $manager = $this->container->get(IManager::class); } catch (\Throwable $e) { @@ -226,7 +225,7 @@ public function getSmartReply(Account $account, Mailbox $mailbox, Message $messa * @throws ServiceException */ public function requiresFollowUp( - Account $account, + MailAccount $account, Mailbox $mailbox, Message $message, string $currentUserId, diff --git a/lib/Service/AntiSpamService.php b/lib/Service/AntiSpamService.php index 8a063fcc2b..6550673721 100644 --- a/lib/Service/AntiSpamService.php +++ b/lib/Service/AntiSpamService.php @@ -12,9 +12,9 @@ use Horde_Imap_Client_Exception; use Horde_Mime_Exception; use Horde_Mime_Mail; -use OCA\Mail\Account; use OCA\Mail\Address; use OCA\Mail\AddressList; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\MessageMapper; use OCA\Mail\Exception\ClientException; @@ -72,13 +72,13 @@ public function deleteConfig(): void { } /** - * @param Account $account + * @param MailAccount $account * @param Mailbox $mailbox * @param int $uid * @param string $flag * @throws ServiceException */ - public function sendReportEmail(Account $account, Mailbox $mailbox, int $uid, string $flag): void { + public function sendReportEmail(MailAccount $account, Mailbox $mailbox, int $uid, string $flag): void { $reportEmail = ($flag === '$junk') ? $this->getSpamEmail() : $this->getHamEmail(); if ($reportEmail === '') { return; @@ -91,13 +91,13 @@ public function sendReportEmail(Account $account, Mailbox $mailbox, int $uid, st throw new ServiceException('Could not find reported message'); } - if ($account->getMailAccount()->getSentMailboxId() === null) { + if ($account->getSentMailboxId() === null) { throw new ServiceException('Could not find sent mailbox'); } $message = new Message(); $from = new AddressList([ - Address::fromRaw($account->getName(), $account->getEMailAddress()), + Address::fromRaw($account->getName(), $account->getEmail()), ]); $to = new AddressList([ Address::fromRaw($reportEmail, $reportEmail), @@ -108,7 +108,7 @@ public function sendReportEmail(Account $account, Mailbox $mailbox, int $uid, st $message->setContent($subject); // Gets original of other message - $userId = $account->getMailAccount()->getUserId(); + $userId = $account->getUserId(); try { $attachmentMessage = $this->mailManager->getMessage($userId, $messageId); } catch (DoesNotExistException $e) { @@ -175,7 +175,7 @@ public function sendReportEmail(Account $account, Mailbox $mailbox, int $uid, st ); } - $sentMailboxId = $account->getMailAccount()->getSentMailboxId(); + $sentMailboxId = $account->getSentMailboxId(); if ($sentMailboxId === null) { $this->logger->warning("No sent mailbox exists, can't save sent message"); return; diff --git a/lib/Service/Attachment/AttachmentService.php b/lib/Service/Attachment/AttachmentService.php index a6f5666a4d..bfe031bb76 100644 --- a/lib/Service/Attachment/AttachmentService.php +++ b/lib/Service/Attachment/AttachmentService.php @@ -12,12 +12,12 @@ use finfo; use InvalidArgumentException; use OCA\Files_Sharing\SharedStorage; -use OCA\Mail\Account; use OCA\Mail\Contracts\IAttachmentService; use OCA\Mail\Contracts\IMailManager; use OCA\Mail\Db\LocalAttachment; use OCA\Mail\Db\LocalAttachmentMapper; use OCA\Mail\Db\LocalMessage; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Exception\AttachmentNotFoundException; use OCA\Mail\Exception\UploadException; use OCA\Mail\IMAP\MessageMapper; @@ -213,7 +213,7 @@ public function updateLocalMessageAttachments(string $userId, LocalMessage $mess * @param array $attachments * @return int[] */ - public function handleAttachments(Account $account, array $attachments, \Horde_Imap_Client_Socket $client): array { + public function handleAttachments(MailAccount $account, array $attachments, \Horde_Imap_Client_Socket $client): array { $attachmentIds = []; if ($attachments === []) { @@ -249,12 +249,11 @@ public function handleAttachments(Account $account, array $attachments, \Horde_I /** * Add a message as attachment * - * @param Account $account * @param mixed[] $attachment * @param \Horde_Imap_Client_Socket $client * @return int|null */ - private function handleForwardedMessageAttachment(Account $account, array $attachment, \Horde_Imap_Client_Socket $client): ?int { + private function handleForwardedMessageAttachment(MailAccount $account, array $attachment, \Horde_Imap_Client_Socket $client): ?int { $attachmentMessage = $this->mailManager->getMessage($account->getUserId(), (int)$attachment['id']); $mailbox = $this->mailManager->getMailbox($account->getUserId(), $attachmentMessage->getMailboxId()); $fullText = $this->messageMapper->getFullText( @@ -286,13 +285,12 @@ private function handleForwardedMessageAttachment(Account $account, array $attac /** * Adds an emails attachments * - * @param Account $account * @param mixed[] $attachment * @param \Horde_Imap_Client_Socket $client * @return int * @throws DoesNotExistException */ - private function handleForwardedAttachment(Account $account, array $attachment, \Horde_Imap_Client_Socket $client): ?int { + private function handleForwardedAttachment(MailAccount $account, array $attachment, \Horde_Imap_Client_Socket $client): ?int { $mailbox = $this->mailManager->getMailbox($account->getUserId(), $attachment['mailboxId']); $attachments = $this->messageMapper->getRawAttachments( @@ -346,11 +344,10 @@ private function hasDownloadPermissions(File $file, string $fileName): bool { } /** - * @param Account $account * @param array $attachment * @return int|null */ - private function handleCloudAttachment(Account $account, array $attachment): ?int { + private function handleCloudAttachment(MailAccount $account, array $attachment): ?int { if (!isset($attachment['fileName'])) { return null; } diff --git a/lib/Service/Classification/FeatureExtraction/CompositeExtractor.php b/lib/Service/Classification/FeatureExtraction/CompositeExtractor.php index eefadd92ba..7604892925 100644 --- a/lib/Service/Classification/FeatureExtraction/CompositeExtractor.php +++ b/lib/Service/Classification/FeatureExtraction/CompositeExtractor.php @@ -9,7 +9,7 @@ namespace OCA\Mail\Service\Classification\FeatureExtraction; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Message; use function OCA\Mail\array_flat_map; @@ -32,7 +32,7 @@ public function __construct(ImportantMessagesExtractor $ex1, ]; } - public function prepare(Account $account, + public function prepare(MailAccount $account, array $incomingMailboxes, array $outgoingMailboxes, array $messages): void { diff --git a/lib/Service/Classification/FeatureExtraction/IExtractor.php b/lib/Service/Classification/FeatureExtraction/IExtractor.php index 9ee868f82d..edab53c8ba 100644 --- a/lib/Service/Classification/FeatureExtraction/IExtractor.php +++ b/lib/Service/Classification/FeatureExtraction/IExtractor.php @@ -9,7 +9,7 @@ namespace OCA\Mail\Service\Classification\FeatureExtraction; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\Message; @@ -18,12 +18,11 @@ interface IExtractor { * Initialize any data that is used for all messages and return whether the * extractor is applicable for this account * - * @param Account $account * @param Mailbox[] $incomingMailboxes * @param Mailbox[] $outgoingMailboxes * @param Message[] $messages */ - public function prepare(Account $account, + public function prepare(MailAccount $account, array $incomingMailboxes, array $outgoingMailboxes, array $messages): void; diff --git a/lib/Service/Classification/FeatureExtraction/ImportantMessagesExtractor.php b/lib/Service/Classification/FeatureExtraction/ImportantMessagesExtractor.php index 50a3f0a61f..8fa8269ed8 100644 --- a/lib/Service/Classification/FeatureExtraction/ImportantMessagesExtractor.php +++ b/lib/Service/Classification/FeatureExtraction/ImportantMessagesExtractor.php @@ -9,7 +9,7 @@ namespace OCA\Mail\Service\Classification\FeatureExtraction; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Message; use OCA\Mail\Db\StatisticsDao; use RuntimeException; @@ -30,7 +30,7 @@ public function __construct(StatisticsDao $statisticsDao) { $this->statisticsDao = $statisticsDao; } - public function prepare(Account $account, + public function prepare(MailAccount $account, array $incomingMailboxes, array $outgoingMailboxes, array $messages): void { diff --git a/lib/Service/Classification/FeatureExtraction/ReadMessagesExtractor.php b/lib/Service/Classification/FeatureExtraction/ReadMessagesExtractor.php index b12a66ec85..9715b9dc0c 100644 --- a/lib/Service/Classification/FeatureExtraction/ReadMessagesExtractor.php +++ b/lib/Service/Classification/FeatureExtraction/ReadMessagesExtractor.php @@ -9,7 +9,7 @@ namespace OCA\Mail\Service\Classification\FeatureExtraction; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Message; use OCA\Mail\Db\StatisticsDao; use RuntimeException; @@ -30,7 +30,7 @@ public function __construct(StatisticsDao $statisticsDao) { $this->statisticsDao = $statisticsDao; } - public function prepare(Account $account, + public function prepare(MailAccount $account, array $incomingMailboxes, array $outgoingMailboxes, array $messages): void { diff --git a/lib/Service/Classification/FeatureExtraction/RepliedMessagesExtractor.php b/lib/Service/Classification/FeatureExtraction/RepliedMessagesExtractor.php index 2262b6a971..b8cec62cb9 100644 --- a/lib/Service/Classification/FeatureExtraction/RepliedMessagesExtractor.php +++ b/lib/Service/Classification/FeatureExtraction/RepliedMessagesExtractor.php @@ -9,7 +9,7 @@ namespace OCA\Mail\Service\Classification\FeatureExtraction; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Message; use OCA\Mail\Db\StatisticsDao; use RuntimeException; @@ -30,7 +30,7 @@ public function __construct(StatisticsDao $statisticsDao) { $this->statisticsDao = $statisticsDao; } - public function prepare(Account $account, + public function prepare(MailAccount $account, array $incomingMailboxes, array $outgoingMailboxes, array $messages): void { diff --git a/lib/Service/Classification/FeatureExtraction/SentMessagesExtractor.php b/lib/Service/Classification/FeatureExtraction/SentMessagesExtractor.php index 7ea7eb5217..a2d10831d4 100644 --- a/lib/Service/Classification/FeatureExtraction/SentMessagesExtractor.php +++ b/lib/Service/Classification/FeatureExtraction/SentMessagesExtractor.php @@ -9,7 +9,7 @@ namespace OCA\Mail\Service\Classification\FeatureExtraction; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Message; use OCA\Mail\Db\StatisticsDao; use RuntimeException; @@ -30,7 +30,7 @@ public function __construct(StatisticsDao $statisticsDao) { $this->statisticsDao = $statisticsDao; } - public function prepare(Account $account, + public function prepare(MailAccount $account, array $incomingMailboxes, array $outgoingMailboxes, array $messages): void { diff --git a/lib/Service/Classification/ImportanceClassifier.php b/lib/Service/Classification/ImportanceClassifier.php index 434d0c5bcc..5e1640b628 100644 --- a/lib/Service/Classification/ImportanceClassifier.php +++ b/lib/Service/Classification/ImportanceClassifier.php @@ -10,8 +10,8 @@ namespace OCA\Mail\Service\Classification; use Horde_Imap_Client; -use OCA\Mail\Account; use OCA\Mail\Db\Classifier; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\MailboxMapper; use OCA\Mail\Db\Message; @@ -135,10 +135,8 @@ private function filterMessageHasSenderEmail(Message $message): bool { * * To prevent memory exhaustion, the process will only load a fixed maximum * number of messages per account. - * - * @param Account $account */ - public function train(Account $account, LoggerInterface $logger): void { + public function train(MailAccount $account, LoggerInterface $logger): void { $perf = $this->performanceLogger->start('importance classifier training'); $incomingMailboxes = $this->getIncomingMailboxes($account); $logger->debug('found ' . count($incomingMailboxes) . ' incoming mailbox(es)'); @@ -210,11 +208,9 @@ public function train(Account $account, LoggerInterface $logger): void { } /** - * @param Account $account - * * @return Mailbox[] */ - private function getIncomingMailboxes(Account $account): array { + private function getIncomingMailboxes(MailAccount $account): array { return array_filter($this->mailboxMapper->findAll($account), static function (Mailbox $mailbox) { foreach (self::EXEMPT_FROM_TRAINING as $excluded) { if ($mailbox->isSpecialUse($excluded)) { @@ -226,14 +222,12 @@ private function getIncomingMailboxes(Account $account): array { } /** - * @param Account $account - * * @return Mailbox[] * @todo allow more than one outgoing mailbox */ - private function getOutgoingMailboxes(Account $account): array { + private function getOutgoingMailboxes(MailAccount $account): array { try { - $sentMailboxId = $account->getMailAccount()->getSentMailboxId(); + $sentMailboxId = $account->getSentMailboxId(); if ($sentMailboxId === null) { return []; } @@ -249,14 +243,13 @@ private function getOutgoingMailboxes(Account $account): array { /** * Get the feature vector of every message * - * @param Account $account * @param Mailbox[] $incomingMailboxes * @param Mailbox[] $outgoingMailboxes * @param Message[] $messages * * @return array */ - private function getFeaturesAndImportance(Account $account, + private function getFeaturesAndImportance(MailAccount $account, array $incomingMailboxes, array $outgoingMailboxes, array $messages): array { @@ -277,13 +270,12 @@ private function getFeaturesAndImportance(Account $account, } /** - * @param Account $account * @param Message[] $messages * * @return bool[] * @throws ServiceException */ - public function classifyImportance(Account $account, array $messages): array { + public function classifyImportance(MailAccount $account, array $messages): array { $estimator = null; try { $estimator = $this->persistenceService->loadLatest($account); diff --git a/lib/Service/Classification/ImportanceRulesClassifier.php b/lib/Service/Classification/ImportanceRulesClassifier.php index 6ee9450f9a..203a057bb1 100644 --- a/lib/Service/Classification/ImportanceRulesClassifier.php +++ b/lib/Service/Classification/ImportanceRulesClassifier.php @@ -9,7 +9,7 @@ namespace OCA\Mail\Service\Classification; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\Message; use OCA\Mail\Service\Classification\FeatureExtraction\ImportantMessagesExtractor; @@ -43,14 +43,13 @@ public function __construct(ImportantMessagesExtractor $importantMessagesExtract } /** - * @param Account $account * @param Mailbox[] $incomingMailboxes * @param Mailbox[] $outgoingMailboxes * @param Message[] $messages * * @return bool[] */ - public function classifyImportance(Account $account, + public function classifyImportance(MailAccount $account, array $incomingMailboxes, array $outgoingMailboxes, array $messages): array { diff --git a/lib/Service/Classification/PersistenceService.php b/lib/Service/Classification/PersistenceService.php index 5cd73c09c6..945bc61bb3 100644 --- a/lib/Service/Classification/PersistenceService.php +++ b/lib/Service/Classification/PersistenceService.php @@ -9,10 +9,10 @@ namespace OCA\Mail\Service\Classification; -use OCA\Mail\Account; use OCA\Mail\AppInfo\Application; use OCA\Mail\Db\Classifier; use OCA\Mail\Db\ClassifierMapper; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\MailAccountMapper; use OCA\Mail\Exception\ServiceException; use OCP\App\IAppManager; @@ -140,12 +140,10 @@ public function persist(Classifier $classifier, Learner $estimator): void { } /** - * @param Account $account - * * @return Estimator|null * @throws ServiceException */ - public function loadLatest(Account $account): ?Estimator { + public function loadLatest(MailAccount $account): ?Estimator { try { $latestModel = $this->mapper->findLatest($account->getId()); } catch (DoesNotExistException $e) { diff --git a/lib/Service/DkimService.php b/lib/Service/DkimService.php index d55af887d3..7dc24ef7f2 100644 --- a/lib/Service/DkimService.php +++ b/lib/Service/DkimService.php @@ -9,9 +9,9 @@ namespace OCA\Mail\Service; -use OCA\Mail\Account; use OCA\Mail\Contracts\IDkimService; use OCA\Mail\Contracts\IDkimValidator; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Exception\ServiceException; use OCA\Mail\IMAP\IMAPClientFactory; @@ -46,7 +46,7 @@ public function __construct( $this->dkimValidator = $dkimValidator; } - public function validate(Account $account, Mailbox $mailbox, int $id): bool { + public function validate(MailAccount $account, Mailbox $mailbox, int $id): bool { $cached = $this->getCached($account, $mailbox, $id); if (is_bool($cached)) { return $cached; @@ -77,11 +77,11 @@ public function validate(Account $account, Mailbox $mailbox, int $id): bool { return $result; } - public function getCached(Account $account, Mailbox $mailbox, int $id): ?bool { + public function getCached(MailAccount $account, Mailbox $mailbox, int $id): ?bool { return $this->cache->get($this->buildCacheKey($account, $mailbox, $id)); } - private function buildCacheKey(Account $account, Mailbox $mailbox, int $id): string { + private function buildCacheKey(MailAccount $account, Mailbox $mailbox, int $id): string { return $account->getId() . '_' . $mailbox->getName() . '_' . $id; } } diff --git a/lib/Service/DraftsService.php b/lib/Service/DraftsService.php index 43aabe5f71..d601c6bb39 100644 --- a/lib/Service/DraftsService.php +++ b/lib/Service/DraftsService.php @@ -9,11 +9,11 @@ namespace OCA\Mail\Service; -use OCA\Mail\Account; use OCA\Mail\Contracts\IMailManager; use OCA\Mail\Contracts\IMailTransmission; use OCA\Mail\Db\LocalMessage; use OCA\Mail\Db\LocalMessageMapper; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Recipient; use OCA\Mail\Events\DraftMessageCreatedEvent; use OCA\Mail\Exception\ClientException; @@ -83,7 +83,6 @@ public function deleteMessage(string $userId, LocalMessage $message): void { } /** - * @param Account $account * @param LocalMessage $message * @param array $to * @param array $cc @@ -91,7 +90,7 @@ public function deleteMessage(string $userId, LocalMessage $message): void { * @param array $attachments * @return LocalMessage */ - public function saveMessage(Account $account, LocalMessage $message, array $to, array $cc, array $bcc, array $attachments = []): LocalMessage { + public function saveMessage(MailAccount $account, LocalMessage $message, array $to, array $cc, array $bcc, array $attachments = []): LocalMessage { $toRecipients = self::convertToRecipient($to, Recipient::TYPE_TO); $ccRecipients = self::convertToRecipient($cc, Recipient::TYPE_CC); $bccRecipients = self::convertToRecipient($bcc, Recipient::TYPE_BCC); @@ -125,7 +124,6 @@ public function saveMessage(Account $account, LocalMessage $message, array $to, } /** - * @param Account $account * @param LocalMessage $message * @param array $to * @param array $cc @@ -133,7 +131,7 @@ public function saveMessage(Account $account, LocalMessage $message, array $to, * @param array $attachments * @return LocalMessage */ - public function updateMessage(Account $account, LocalMessage $message, array $to, array $cc, array $bcc, array $attachments = []): LocalMessage { + public function updateMessage(MailAccount $account, LocalMessage $message, array $to, array $cc, array $bcc, array $attachments = []): LocalMessage { $toRecipients = self::convertToRecipient($to, Recipient::TYPE_TO); $ccRecipients = self::convertToRecipient($cc, Recipient::TYPE_CC); $bccRecipients = self::convertToRecipient($bcc, Recipient::TYPE_BCC); @@ -156,7 +154,7 @@ public function updateMessage(Account $account, LocalMessage $message, array $to return $message; } - public function handleDraft(Account $account, int $draftId): void { + public function handleDraft(MailAccount $account, int $draftId): void { $message = $this->mailManager->getMessage($account->getUserId(), $draftId); $this->eventDispatcher->dispatchTyped(new DraftMessageCreatedEvent($account, $message)); } @@ -165,10 +163,9 @@ public function handleDraft(Account $account, int $draftId): void { * "Send" the message * * @param LocalMessage $message - * @param Account $account * @return void */ - public function sendMessage(LocalMessage $message, Account $account): void { + public function sendMessage(LocalMessage $message, MailAccount $account): void { try { $this->transmission->saveLocalDraft($account, $message); } catch (ClientException|ServiceException $e) { diff --git a/lib/Service/IMipService.php b/lib/Service/IMipService.php index b23f2de22d..953f36e49d 100644 --- a/lib/Service/IMipService.php +++ b/lib/Service/IMipService.php @@ -9,7 +9,6 @@ namespace OCA\Mail\Service; -use OCA\Mail\Account; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\MailboxMapper; use OCA\Mail\Db\Message; @@ -83,7 +82,6 @@ public function process(): void { /** @var Mailbox $mailbox */ foreach ($mailboxes as $mailbox) { - /** @var Account $account */ $account = $accounts[$mailbox->getAccountId()]; $filteredMessages = array_filter($messages, static function ($message) use ($mailbox) { return $message->getMailboxId() === $mailbox->getId(); @@ -96,11 +94,11 @@ public function process(): void { // Check for accounts or mailboxes that no longer exist, // no processing for drafts, sent items, junk or archive if ($account === null - || $account->getMailAccount()->getArchiveMailboxId() === $mailbox->getId() - || $account->getMailAccount()->getSnoozeMailboxId() === $mailbox->getId() - || $account->getMailAccount()->getTrashMailboxId() === $mailbox->getId() - || $account->getMailAccount()->getSentMailboxId() === $mailbox->getId() - || $account->getMailAccount()->getDraftsMailboxId() === $mailbox->getId() + || $account->getArchiveMailboxId() === $mailbox->getId() + || $account->getSnoozeMailboxId() === $mailbox->getId() + || $account->getTrashMailboxId() === $mailbox->getId() + || $account->getSentMailboxId() === $mailbox->getId() + || $account->getDraftsMailboxId() === $mailbox->getId() || $mailbox->isSpecialUse(\Horde_Imap_Client::SPECIALUSE_ARCHIVE) ) { $processedMessages = array_map(static function (Message $message) { diff --git a/lib/Service/ItineraryService.php b/lib/Service/ItineraryService.php index 37c296bab8..f094424056 100644 --- a/lib/Service/ItineraryService.php +++ b/lib/Service/ItineraryService.php @@ -10,7 +10,7 @@ namespace OCA\Mail\Service; use Nextcloud\KItinerary\Itinerary; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\IMAP\IMAPClientFactory; use OCA\Mail\IMAP\MessageMapper; @@ -53,11 +53,11 @@ public function __construct(IMAPClientFactory $clientFactory, $this->logger = $logger; } - private function buildCacheKey(Account $account, Mailbox $mailbox, int $id): string { + private function buildCacheKey(MailAccount $account, Mailbox $mailbox, int $id): string { return $account->getId() . '_' . $mailbox->getName() . '_' . $id; } - public function getCached(Account $account, Mailbox $mailbox, int $id): ?Itinerary { + public function getCached(MailAccount $account, Mailbox $mailbox, int $id): ?Itinerary { if ($cached = ($this->cache->get($this->buildCacheKey($account, $mailbox, $id)))) { return Itinerary::fromJson($cached); } @@ -65,7 +65,7 @@ public function getCached(Account $account, Mailbox $mailbox, int $id): ?Itinera return null; } - public function extract(Account $account, Mailbox $mailbox, int $id): Itinerary { + public function extract(MailAccount $account, Mailbox $mailbox, int $id): Itinerary { if ($cached = ($this->getCached($account, $mailbox, $id))) { return $cached; } diff --git a/lib/Service/MailManager.php b/lib/Service/MailManager.php index 75728d82aa..c44788e193 100644 --- a/lib/Service/MailManager.php +++ b/lib/Service/MailManager.php @@ -14,9 +14,9 @@ use Horde_Imap_Client_Exception_NoSupportExtension; use Horde_Imap_Client_Socket; use Horde_Mime_Exception; -use OCA\Mail\Account; use OCA\Mail\Attachment; use OCA\Mail\Contracts\IMailManager; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\MailboxMapper; use OCA\Mail\Db\Message; @@ -125,25 +125,22 @@ public function getMailbox(string $uid, int $id): Mailbox { } /** - * @param Account $account - * * @return Mailbox[] * @throws ServiceException */ - public function getMailboxes(Account $account): array { + public function getMailboxes(MailAccount $account): array { $this->mailboxSync->sync($account, $this->logger); return $this->mailboxMapper->findAll($account); } /** - * @param Account $account * @param string $name * * @return Mailbox * @throws ServiceException */ - public function createMailbox(Account $account, string $name): Mailbox { + public function createMailbox(MailAccount $account, string $name): Mailbox { $client = $this->imapClientFactory->getClient($account); try { $folder = $this->folderMapper->createFolder($client, $account, $name); @@ -166,7 +163,6 @@ public function createMailbox(Account $account, string $name): Mailbox { /** * @param Horde_Imap_Client_Socket $client - * @param Account $account * @param Mailbox $mailbox * @param int $uid * @param bool $loadBody @@ -177,7 +173,7 @@ public function createMailbox(Account $account, string $name): Mailbox { * @throws SmimeDecryptException */ public function getImapMessage(Horde_Imap_Client_Socket $client, - Account $account, + MailAccount $account, Mailbox $mailbox, int $uid, bool $loadBody = false): IMAPMessage { @@ -199,13 +195,12 @@ public function getImapMessage(Horde_Imap_Client_Socket $client, } /** - * @param Account $account * @param Mailbox $mailbox * @param int[] $uids * @return IMAPMessage[] * @throws ServiceException */ - public function getImapMessagesForScheduleProcessing(Account $account, + public function getImapMessagesForScheduleProcessing(MailAccount $account, Mailbox $mailbox, array $uids): array { $client = $this->imapClientFactory->getClient($account); @@ -228,7 +223,7 @@ public function getImapMessagesForScheduleProcessing(Account $account, } } - public function getThread(Account $account, string $threadRootId): array { + public function getThread(MailAccount $account, string $threadRootId): array { return $this->dbMessageMapper->findThread($account, $threadRootId); } @@ -242,7 +237,6 @@ public function getMessage(string $uid, int $id): Message { /** * @param Horde_Imap_Client_Socket $client - * @param Account $account * @param string $mailbox * @param int $uid * @@ -251,7 +245,7 @@ public function getMessage(string $uid, int $id): Message { * @throws ServiceException */ public function getSource(Horde_Imap_Client_Socket $client, - Account $account, + MailAccount $account, string $mailbox, int $uid): ?string { try { @@ -268,19 +262,17 @@ public function getSource(Horde_Imap_Client_Socket $client, } /** - * @param Account $sourceAccount * @param string $sourceFolderId * @param int $uid - * @param Account $destinationAccount * @param string $destFolderId * * @return int * @throws ServiceException */ - public function moveMessage(Account $sourceAccount, + public function moveMessage(MailAccount $sourceAccount, string $sourceFolderId, int $uid, - Account $destinationAccount, + MailAccount $destinationAccount, string $destFolderId): int { if ($sourceAccount->getId() === $destinationAccount->getId()) { try { @@ -313,7 +305,7 @@ public function moveMessage(Account $sourceAccount, * @throws ServiceException * @todo evaluate if we should sync mailboxes first */ - public function deleteMessage(Account $account, + public function deleteMessage(MailAccount $account, string $mailboxId, int $messageUid): void { try { @@ -338,7 +330,7 @@ public function deleteMessage(Account $account, * @todo evaluate if we should sync mailboxes first */ public function deleteMessageWithClient( - Account $account, + MailAccount $account, Mailbox $mailbox, int $messageUid, Horde_Imap_Client_Socket $client, @@ -348,7 +340,7 @@ public function deleteMessageWithClient( ); try { - $trashMailboxId = $account->getMailAccount()->getTrashMailboxId(); + $trashMailboxId = $account->getTrashMailboxId(); if ($trashMailboxId === null) { throw new TrashMailboxNotSetException(); } @@ -379,7 +371,6 @@ public function deleteMessageWithClient( } /** - * @param Account $account * @param string $sourceFolderId * @param string $destFolderId * @param int $messageId @@ -388,7 +379,7 @@ public function deleteMessageWithClient( * @throws ServiceException * */ - private function moveMessageOnSameAccount(Account $account, + private function moveMessageOnSameAccount(MailAccount $account, string $sourceFolderId, string $destFolderId, int $messageId): int { @@ -400,7 +391,7 @@ private function moveMessageOnSameAccount(Account $account, } } - public function markFolderAsRead(Account $account, Mailbox $mailbox): void { + public function markFolderAsRead(MailAccount $account, Mailbox $mailbox): void { $client = $this->imapClientFactory->getClient($account); try { $this->imapMessageMapper->markAllRead($client, $mailbox->getName()); @@ -409,7 +400,7 @@ public function markFolderAsRead(Account $account, Mailbox $mailbox): void { } } - public function updateSubscription(Account $account, Mailbox $mailbox, bool $subscribed): Mailbox { + public function updateSubscription(MailAccount $account, Mailbox $mailbox, bool $subscribed): Mailbox { /** * 1. Change subscription on IMAP */ @@ -444,7 +435,7 @@ public function enableMailboxBackgroundSync(Mailbox $mailbox, return $this->mailboxMapper->update($mailbox); } - public function flagMessage(Account $account, string $mailbox, int $uid, string $flag, bool $value): void { + public function flagMessage(MailAccount $account, string $mailbox, int $uid, string $flag, bool $value): void { try { $mb = $this->mailboxMapper->find($account, $mailbox); } catch (DoesNotExistException $e) { @@ -495,7 +486,7 @@ public function flagMessage(Account $account, string $mailbox, int $uid, string * @throws ClientException * @throws ServiceException */ - public function tagMessagesWithClient(Horde_Imap_Client_Socket $client, Account $account, Mailbox $mailbox, array $messages, Tag $tag, bool $value):void { + public function tagMessagesWithClient(Horde_Imap_Client_Socket $client, MailAccount $account, Mailbox $mailbox, array $messages, Tag $tag, bool $value):void { if ($this->isPermflagsEnabled($client, $account, $mailbox->getName()) === true) { $messageIds = array_map(static function (Message $message) { return $message->getUid(); @@ -530,7 +521,6 @@ public function tagMessagesWithClient(Horde_Imap_Client_Socket $client, Account /** * Tag (flag) a message on IMAP * - * @param Account $account * @param string $mailbox * @param Message $message * @param Tag $tag @@ -543,7 +533,7 @@ public function tagMessagesWithClient(Horde_Imap_Client_Socket $client, Account * * @link https://github.com/nextcloud/mail/issues/25 */ - public function tagMessage(Account $account, string $mailbox, Message $message, Tag $tag, bool $value): void { + public function tagMessage(MailAccount $account, string $mailbox, Message $message, Tag $tag, bool $value): void { try { $mb = $this->mailboxMapper->find($account, $mailbox); } catch (DoesNotExistException $e) { @@ -558,12 +548,10 @@ public function tagMessage(Account $account, string $mailbox, Message $message, } /** - * @param Account $account - * * @return Quota|null * @see https://tools.ietf.org/html/rfc2087 */ - public function getQuota(Account $account): ?Quota { + public function getQuota(MailAccount $account): ?Quota { /** * Get all the quotas roots of the user's mailboxes */ @@ -608,7 +596,7 @@ public function getQuota(Account $account): ?Quota { ); } - public function renameMailbox(Account $account, Mailbox $mailbox, string $name): Mailbox { + public function renameMailbox(MailAccount $account, Mailbox $mailbox, string $name): Mailbox { /* * 1. Rename on IMAP */ @@ -639,12 +627,11 @@ public function renameMailbox(Account $account, Mailbox $mailbox, string $name): } /** - * @param Account $account * @param Mailbox $mailbox * * @throws ServiceException */ - public function deleteMailbox(Account $account, + public function deleteMailbox(MailAccount $account, Mailbox $mailbox): void { $client = $this->imapClientFactory->getClient($account); try { @@ -658,7 +645,6 @@ public function deleteMailbox(Account $account, /** * Clear messages in folder * - * @param Account $account * @param Mailbox $mailbox * * @throws DoesNotExistException @@ -666,10 +652,10 @@ public function deleteMailbox(Account $account, * @throws Horde_Imap_Client_Exception_NoSupportExtension * @throws ServiceException */ - public function clearMailbox(Account $account, + public function clearMailbox(MailAccount $account, Mailbox $mailbox): void { $client = $this->imapClientFactory->getClient($account); - $trashMailboxId = $account->getMailAccount()->getTrashMailboxId(); + $trashMailboxId = $account->getTrashMailboxId(); $currentMailboxId = $mailbox->getId(); try { if (($currentMailboxId !== $trashMailboxId) && !is_null($trashMailboxId)) { @@ -689,12 +675,11 @@ public function clearMailbox(Account $account, } /** - * @param Account $account * @param Mailbox $mailbox * @param Message $message * @return Attachment[] */ - public function getMailAttachments(Account $account, Mailbox $mailbox, Message $message): array { + public function getMailAttachments(MailAccount $account, Mailbox $mailbox, Message $message): array { $client = $this->imapClientFactory->getClient($account); try { return $this->imapMessageMapper->getAttachments( @@ -709,7 +694,6 @@ public function getMailAttachments(Account $account, Mailbox $mailbox, Message $ } /** - * @param Account $account * @param Mailbox $mailbox * @param Message $message * @param string $attachmentId @@ -721,7 +705,7 @@ public function getMailAttachments(Account $account, Mailbox $mailbox, Message $ * @throws ServiceException * @throws Horde_Mime_Exception */ - public function getMailAttachment(Account $account, + public function getMailAttachment(MailAccount $account, Mailbox $mailbox, Message $message, string $attachmentId): Attachment { @@ -760,7 +744,7 @@ public function getTagByImapLabel(string $imapLabel, string $userId): Tag { * @param string $mailbox * @return array */ - public function filterFlags(Horde_Imap_Client_Socket $client, Account $account, string $flag, string $mailbox): array { + public function filterFlags(Horde_Imap_Client_Socket $client, MailAccount $account, string $flag, string $mailbox): array { // check for RFC server flags if (array_key_exists($flag, self::ALLOWED_FLAGS) === true) { return self::ALLOWED_FLAGS[$flag]; @@ -776,12 +760,8 @@ public function filterFlags(Horde_Imap_Client_Socket $client, Account $account, /** * Check IMAP server for support for PERMANENTFLAGS - * - * @param Account $account - * @param string $mailbox - * @return boolean */ - public function isPermflagsEnabled(Horde_Imap_Client_Socket $client, Account $account, string $mailbox): bool { + public function isPermflagsEnabled(Horde_Imap_Client_Socket $client, MailAccount $account, string $mailbox): bool { try { $capabilities = $client->status($mailbox, Horde_Imap_Client::STATUS_PERMFLAGS); } catch (Horde_Imap_Client_Exception $e) { @@ -844,7 +824,7 @@ public function deleteTag(int $id, string $userId, array $accounts) :Tag { return $this->tagMapper->delete($tag); } - public function deleteTagForAccount(int $id, string $userId, Tag $tag, Account $account) :void { + public function deleteTagForAccount(int $id, string $userId, Tag $tag, MailAccount $account) :void { try { $messageTags = $this->messageTagsMapper->getMessagesByTag($id); $messages = array_merge(... array_map(function ($messageTag) use ($account) { @@ -878,8 +858,8 @@ public function deleteTagForAccount(int $id, string $userId, Tag $tag, Account $ } } - public function moveThread(Account $srcAccount, Mailbox $srcMailbox, Account $dstAccount, Mailbox $dstMailbox, string $threadRootId): array { - $mailAccount = $srcAccount->getMailAccount(); + public function moveThread(MailAccount $srcAccount, Mailbox $srcMailbox, MailAccount $dstAccount, Mailbox $dstMailbox, string $threadRootId): array { + $mailAccount = $srcAccount; $messageInTrash = $srcMailbox->getId() === $mailAccount->getTrashMailboxId(); $messages = $this->threadMapper->findMessageUidsAndMailboxNamesByAccountAndThreadRoot( @@ -911,8 +891,8 @@ public function moveThread(Account $srcAccount, Mailbox $srcMailbox, Account $ds * @throws ClientException * @throws ServiceException */ - public function deleteThread(Account $account, Mailbox $mailbox, string $threadRootId): void { - $mailAccount = $account->getMailAccount(); + public function deleteThread(MailAccount $account, Mailbox $mailbox, string $threadRootId): void { + $mailAccount = $account; $messageInTrash = $mailbox->getId() === $mailAccount->getTrashMailboxId(); $messages = $this->threadMapper->findMessageUidsAndMailboxNamesByAccountAndThreadRoot( @@ -938,7 +918,7 @@ public function deleteThread(Account $account, Mailbox $mailbox, string $threadR /** * @return Message[] */ - public function getByMessageId(Account $account, string $messageId): array { + public function getByMessageId(MailAccount $account, string $messageId): array { return $this->dbMessageMapper->findByMessageId($account, $messageId); } } diff --git a/lib/Service/MailTransmission.php b/lib/Service/MailTransmission.php index 0cdbded2e8..9fdf907b24 100644 --- a/lib/Service/MailTransmission.php +++ b/lib/Service/MailTransmission.php @@ -25,11 +25,11 @@ use Horde_Mime_Mail; use Horde_Mime_Mdn; use Horde_Smtp_Exception; -use OCA\Mail\Account; use OCA\Mail\Address; use OCA\Mail\AddressList; use OCA\Mail\Contracts\IMailTransmission; use OCA\Mail\Db\LocalMessage; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\MailboxMapper; use OCA\Mail\Db\Message; @@ -70,7 +70,7 @@ public function __construct( ) { } - public function sendMessage(Account $account, LocalMessage $localMessage): void { + public function sendMessage(MailAccount $account, LocalMessage $localMessage): void { $to = $this->transmissionService->getAddressList($localMessage, Recipient::TYPE_TO); $cc = $this->transmissionService->getAddressList($localMessage, Recipient::TYPE_CC); $bcc = $this->transmissionService->getAddressList($localMessage, Recipient::TYPE_BCC); @@ -80,7 +80,7 @@ public function sendMessage(Account $account, LocalMessage $localMessage): void if ($localMessage->getAliasId() !== null) { $alias = $this->aliasesService->find($localMessage->getAliasId(), $account->getUserId()); } - $fromEmail = $alias ? $alias->getAlias() : $account->getEMailAddress(); + $fromEmail = $alias ? $alias->getAlias() : $account->getEmail(); $from = new AddressList([ Address::fromRaw($account->getName(), $fromEmail), ]); @@ -165,7 +165,7 @@ public function sendMessage(Account $account, LocalMessage $localMessage): void ); } - public function saveLocalDraft(Account $account, LocalMessage $message): void { + public function saveLocalDraft(MailAccount $account, LocalMessage $message): void { $to = $this->transmissionService->getAddressList($message, Recipient::TYPE_TO); $cc = $this->transmissionService->getAddressList($message, Recipient::TYPE_CC); $bcc = $this->transmissionService->getAddressList($message, Recipient::TYPE_BCC); @@ -177,7 +177,7 @@ public function saveLocalDraft(Account $account, LocalMessage $message): void { $imapMessage->setTo($to); $imapMessage->setSubject($message->getSubject()); $from = new AddressList([ - Address::fromRaw($account->getName(), $account->getEMailAddress()), + Address::fromRaw($account->getName(), $account->getEmail()), ]); $imapMessage->setFrom($from); $imapMessage->setCC($cc); @@ -215,7 +215,7 @@ public function saveLocalDraft(Account $account, LocalMessage $message): void { $mail->send($transport, false, false); $perfLogger->step('create IMAP draft message'); // save the message in the drafts folder - $draftsMailboxId = $account->getMailAccount()->getDraftsMailboxId(); + $draftsMailboxId = $account->getDraftsMailboxId(); if ($draftsMailboxId === null) { throw new ClientException('No drafts mailbox configured'); } @@ -263,7 +263,7 @@ public function saveDraft(NewMessageData $message, ?Message $previousDraft = nul $imapMessage->setTo($message->getTo()); $imapMessage->setSubject($message->getSubject()); $from = new AddressList([ - Address::fromRaw($account->getName(), $account->getEMailAddress()), + Address::fromRaw($account->getName(), $account->getEmail()), ]); $imapMessage->setFrom($from); $imapMessage->setCC($message->getCc()); @@ -297,7 +297,7 @@ public function saveDraft(NewMessageData $message, ?Message $previousDraft = nul $mail->send($transport, false, false); $perfLogger->step('create IMAP message'); // save the message in the drafts folder - $draftsMailboxId = $account->getMailAccount()->getDraftsMailboxId(); + $draftsMailboxId = $account->getDraftsMailboxId(); if ($draftsMailboxId === null) { throw new ClientException('No drafts mailbox configured'); } @@ -327,7 +327,7 @@ public function saveDraft(NewMessageData $message, ?Message $previousDraft = nul return [$account, $draftsMailbox, $newUid]; } - public function sendMdn(Account $account, Mailbox $mailbox, Message $message): void { + public function sendMdn(MailAccount $account, Mailbox $mailbox, Message $message): void { $query = new Horde_Imap_Client_Fetch_Query(); $query->flags(); $query->uid(); @@ -384,10 +384,10 @@ public function sendMdn(Account $account, Mailbox $mailbox, Message $message): v true, true, 'displayed', - $account->getMailAccount()->getOutboundHost(), + $account->getOutboundHost(), $smtpClient, [ - 'from_addr' => $account->getEMailAddress(), + 'from_addr' => $account->getEmail(), 'charset' => 'UTF-8', ] ); diff --git a/lib/Service/OutboxService.php b/lib/Service/OutboxService.php index ff214a4dce..c3fa90921e 100644 --- a/lib/Service/OutboxService.php +++ b/lib/Service/OutboxService.php @@ -9,11 +9,11 @@ namespace OCA\Mail\Service; -use OCA\Mail\Account; use OCA\Mail\Contracts\IMailManager; use OCA\Mail\Contracts\IMailTransmission; use OCA\Mail\Db\LocalMessage; use OCA\Mail\Db\LocalMessageMapper; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Recipient; use OCA\Mail\Events\OutboxMessageCreatedEvent; use OCA\Mail\Exception\ClientException; @@ -122,12 +122,11 @@ public function deleteMessage(string $userId, LocalMessage $message): void { * @throws Exception * @throws ServiceException */ - public function sendMessage(LocalMessage $message, Account $account): LocalMessage { + public function sendMessage(LocalMessage $message, MailAccount $account): LocalMessage { return $this->sendChain->process($account, $message); } /** - * @param Account $account * @param LocalMessage $message * @param array $to * @param array $cc @@ -135,7 +134,7 @@ public function sendMessage(LocalMessage $message, Account $account): LocalMessa * @param array $attachments * @return LocalMessage */ - public function saveMessage(Account $account, LocalMessage $message, array $to, array $cc, array $bcc, array $attachments = []): LocalMessage { + public function saveMessage(MailAccount $account, LocalMessage $message, array $to, array $cc, array $bcc, array $attachments = []): LocalMessage { $toRecipients = self::convertToRecipient($to, Recipient::TYPE_TO); $ccRecipients = self::convertToRecipient($cc, Recipient::TYPE_CC); $bccRecipients = self::convertToRecipient($bcc, Recipient::TYPE_BCC); @@ -158,7 +157,6 @@ public function saveMessage(Account $account, LocalMessage $message, array $to, } /** - * @param Account $account * @param LocalMessage $message * @param array $to * @param array $cc @@ -166,7 +164,7 @@ public function saveMessage(Account $account, LocalMessage $message, array $to, * @param array $attachments * @return LocalMessage */ - public function updateMessage(Account $account, LocalMessage $message, array $to, array $cc, array $bcc, array $attachments = []): LocalMessage { + public function updateMessage(MailAccount $account, LocalMessage $message, array $to, array $cc, array $bcc, array $attachments = []): LocalMessage { $toRecipients = self::convertToRecipient($to, Recipient::TYPE_TO); $ccRecipients = self::convertToRecipient($cc, Recipient::TYPE_CC); $bccRecipients = self::convertToRecipient($bcc, Recipient::TYPE_BCC); @@ -189,11 +187,10 @@ public function updateMessage(Account $account, LocalMessage $message, array $to } /** - * @param Account $account * @param int $draftId * @return void */ - public function handleDraft(Account $account, int $draftId): void { + public function handleDraft(MailAccount $account, int $draftId): void { $message = $this->mailManager->getMessage($account->getUserId(), $draftId); $this->eventDispatcher->dispatch( OutboxMessageCreatedEvent::class, diff --git a/lib/Service/PreprocessingService.php b/lib/Service/PreprocessingService.php index b1d07e09ab..3c68715927 100644 --- a/lib/Service/PreprocessingService.php +++ b/lib/Service/PreprocessingService.php @@ -7,7 +7,7 @@ */ namespace OCA\Mail\Service; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\MailboxMapper; use OCA\Mail\Db\MessageMapper; @@ -32,7 +32,7 @@ public function __construct( $this->previewEnhancer = $previewEnhancer; } - public function process(int $limitTimestamp, Account $account): void { + public function process(int $limitTimestamp, MailAccount $account): void { $mailboxes = $this->mailboxMapper->findAll($account); if ($mailboxes === []) { $this->logger->debug('No mailboxes found.'); diff --git a/lib/Service/Search/MailSearch.php b/lib/Service/Search/MailSearch.php index 917c7eccc0..58bc056605 100644 --- a/lib/Service/Search/MailSearch.php +++ b/lib/Service/Search/MailSearch.php @@ -10,8 +10,8 @@ namespace OCA\Mail\Service\Search; use Horde_Imap_Client; -use OCA\Mail\Account; use OCA\Mail\Contracts\IMailSearch; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\MailboxMapper; use OCA\Mail\Db\Message; @@ -59,7 +59,7 @@ public function __construct(FilterStringParser $filterStringParser, $this->timeFactory = $timeFactory; } - public function findMessage(Account $account, + public function findMessage(MailAccount $account, Mailbox $mailbox, Message $message): Message { $processed = $this->previewEnhancer->process( @@ -74,7 +74,6 @@ public function findMessage(Account $account, } /** - * @param Account $account * @param Mailbox $mailbox * @param string $sortOrder * @param string|null $filter @@ -86,7 +85,7 @@ public function findMessage(Account $account, * @throws ClientException * @throws ServiceException */ - public function findMessages(Account $account, + public function findMessages(MailAccount $account, Mailbox $mailbox, string $sortOrder, ?string $filter, @@ -152,7 +151,7 @@ public function findMessagesGlobally(IUser $user, * * @throws ServiceException */ - private function getIdsLocally(Account $account, Mailbox $mailbox, SearchQuery $query, string $sortOrder, ?int $limit): array { + private function getIdsLocally(MailAccount $account, Mailbox $mailbox, SearchQuery $query, string $sortOrder, ?int $limit): array { if (empty($query->getBodies())) { return $this->messageMapper->findIdsByQuery($mailbox, $query, $sortOrder, $limit); } diff --git a/lib/Service/SetupService.php b/lib/Service/SetupService.php index 40df87afd9..c5e6a56c98 100644 --- a/lib/Service/SetupService.php +++ b/lib/Service/SetupService.php @@ -13,7 +13,6 @@ use Horde_Mail_Exception; use Horde_Mail_Transport_Smtphorde; use InvalidArgumentException; -use OCA\Mail\Account; use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\TagMapper; use OCA\Mail\Exception\CouldNotConnectException; @@ -60,8 +59,6 @@ public function __construct(AccountService $accountService, /** * @throws CouldNotConnectException * @throws ServiceException - * - * @return Account */ public function createNewAccount(string $accountName, string $emailAddress, @@ -77,7 +74,7 @@ public function createNewAccount(string $accountName, ?string $smtpPassword, string $uid, string $authMethod, - ?int $accountId = null): Account { + ?int $accountId = null): MailAccount { $this->logger->info('Setting up manually configured account'); $newAccount = new MailAccount([ 'accountId' => $accountId, @@ -104,10 +101,9 @@ public function createNewAccount(string $accountName, } $newAccount->setAuthMethod($authMethod); - $account = new Account($newAccount); if ($authMethod === 'password' && $imapPassword !== null) { $this->logger->debug('Connecting to account {account}', ['account' => $newAccount->getEmail()]); - $this->testConnectivity($account); + $this->testConnectivity($newAccount); } $this->accountService->save($newAccount); @@ -115,15 +111,14 @@ public function createNewAccount(string $accountName, $this->tagMapper->createDefaultTags($newAccount); - return $account; + return $newAccount; } /** - * @param Account $account * @throws CouldNotConnectException */ - protected function testConnectivity(Account $account): void { - $mailAccount = $account->getMailAccount(); + protected function testConnectivity(MailAccount $account): void { + $mailAccount = $account; $imapClient = $this->imapClientFactory->getClient($account); try { diff --git a/lib/Service/SieveService.php b/lib/Service/SieveService.php index 8442cee556..d4907f26d4 100644 --- a/lib/Service/SieveService.php +++ b/lib/Service/SieveService.php @@ -63,14 +63,14 @@ public function updateActiveScript(string $userId, int $accountId, string $scrip private function getClient(string $userId, int $accountId): \Horde\ManageSieve { $account = $this->accountService->find($userId, $accountId); - if (!$account->getMailAccount()->isSieveEnabled()) { + if (!$account->isSieveEnabled()) { throw new ClientException('ManageSieve is disabled'); } try { $sieve = $this->sieveClientFactory->getClient($account); } catch (ManagesieveException $e) { - throw new CouldNotConnectException($e, 'ManageSieve', $account->getMailAccount()->getSieveHost(), $account->getMailAccount()->getSievePort()); + throw new CouldNotConnectException($e, 'ManageSieve', $account->getSieveHost(), $account->getSievePort()); } return $sieve; diff --git a/lib/Service/SnoozeService.php b/lib/Service/SnoozeService.php index d8863c2b69..754d175e32 100644 --- a/lib/Service/SnoozeService.php +++ b/lib/Service/SnoozeService.php @@ -9,8 +9,8 @@ namespace OCA\Mail\Service; -use OCA\Mail\Account; use OCA\Mail\Contracts\IMailManager; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\MailAccountMapper; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\MailboxMapper; @@ -50,8 +50,6 @@ public function __construct( public function wakeMessages(): void { $accounts = $this->accountMapper->getAllAccounts(); foreach ($accounts as $account) { - $account = new Account($account); - try { $this->wakeMessagesByAccount($account); } catch (ServiceException|ClientException $e) { @@ -59,7 +57,7 @@ public function wakeMessages(): void { 'exception' => $e, 'userId' => $account->getUserId(), 'accountId' => $account->getId(), - 'snoozeMailboxId' => $account->getMailAccount()->getSnoozeMailboxId(), + 'snoozeMailboxId' => $account->getSnoozeMailboxId(), ]); } } @@ -68,9 +66,7 @@ public function wakeMessages(): void { /** * @param Message $message * @param int $unixTimestamp - * @param Account $srcAccount * @param Mailbox $srcMailbox - * @param Account $dstAccount * @param Mailbox $dstMailbox * * @return void @@ -80,9 +76,9 @@ public function wakeMessages(): void { public function snoozeMessage( Message $message, int $unixTimestamp, - Account $srcAccount, + MailAccount $srcAccount, Mailbox $srcMailbox, - Account $dstAccount, + MailAccount $dstAccount, Mailbox $dstMailbox ): void { $newUid = $this->mailManager->moveMessage( @@ -146,9 +142,7 @@ public function unSnoozeMessage( /** * @param Message $selectedMessage * @param int $unixTimestamp - * @param Account $srcAccount * @param Mailbox $srcMailbox - * @param Account $dstAccount * @param Mailbox $dstMailbox * * @return void @@ -158,9 +152,9 @@ public function unSnoozeMessage( public function snoozeThread( Message $selectedMessage, int $unixTimestamp, - Account $srcAccount, + MailAccount $srcAccount, Mailbox $srcMailbox, - Account $dstAccount, + MailAccount $dstAccount, Mailbox $dstMailbox ): void { $newUids = $this->mailManager->moveThread( @@ -271,8 +265,8 @@ public function snoozeThreadDB(array $uids, Mailbox $dstMailbox, int $unixTimest /** * @throws ServiceException */ - private function wakeMessagesByAccount(Account $account): void { - $snoozeMailboxId = $account->getMailAccount()->getSnoozeMailboxId(); + private function wakeMessagesByAccount(MailAccount $account): void { + $snoozeMailboxId = $account->getSnoozeMailboxId(); if ($snoozeMailboxId === null) { return; } diff --git a/lib/Service/Sync/ImapToDbSynchronizer.php b/lib/Service/Sync/ImapToDbSynchronizer.php index 0217bb6b3d..7b3b1a11a8 100644 --- a/lib/Service/Sync/ImapToDbSynchronizer.php +++ b/lib/Service/Sync/ImapToDbSynchronizer.php @@ -1,488 +1,486 @@ -dbMapper = $dbMapper; - $this->clientFactory = $clientFactory; - $this->imapMapper = $imapMapper; - $this->mailboxMapper = $mailboxMapper; - $this->synchronizer = $synchronizer; - $this->dispatcher = $dispatcher; - $this->performanceLogger = $performanceLogger; - $this->logger = $logger; - $this->mailManager = $mailManager; - } - - /** - * @throws ClientException - * @throws ServiceException - */ - public function syncAccount(Account $account, - LoggerInterface $logger, - bool $force = false, - int $criteria = Horde_Imap_Client::SYNC_NEWMSGSUIDS | Horde_Imap_Client::SYNC_FLAGSUIDS | Horde_Imap_Client::SYNC_VANISHEDUIDS): void { - $rebuildThreads = false; - $trashMailboxId = $account->getMailAccount()->getTrashMailboxId(); - $snoozeMailboxId = $account->getMailAccount()->getSnoozeMailboxId(); - $sentMailboxId = $account->getMailAccount()->getSentMailboxId(); - $trashRetentionDays = $account->getMailAccount()->getTrashRetentionDays(); - - $client = $this->clientFactory->getClient($account); - - foreach ($this->mailboxMapper->findAll($account) as $mailbox) { - $syncTrash = $trashMailboxId === $mailbox->getId() && $trashRetentionDays !== null; - $syncSnooze = $snoozeMailboxId === $mailbox->getId(); - $syncSent = $sentMailboxId === $mailbox->getId() || $mailbox->isSpecialUse('sent'); - - if (!$syncTrash && !$mailbox->isInbox() && !$syncSnooze && !$mailbox->getSyncInBackground() && !$syncSent) { - $logger->debug('Skipping mailbox sync for ' . $mailbox->getId()); - continue; - } - $logger->debug('Syncing ' . $mailbox->getId()); - if ($this->sync( - $account, - $client, - $mailbox, - $logger, - $criteria, - null, - $force, - true - )) { - $rebuildThreads = true; - } - } - - $client->logout(); - - $this->dispatcher->dispatchTyped( - new SynchronizationEvent( - $account, - $logger, - $rebuildThreads, - ) - ); - } - - /** - * Clear all cached data of a mailbox - * - * @param Account $account - * @param Mailbox $mailbox - * - * @throws MailboxLockedException - * @throws ServiceException - */ - public function clearCache(Account $account, - Mailbox $mailbox): void { - $id = $account->getId() . ':' . $mailbox->getName(); - try { - $this->mailboxMapper->lockForNewSync($mailbox); - $this->mailboxMapper->lockForChangeSync($mailbox); - $this->mailboxMapper->lockForVanishedSync($mailbox); - - $this->resetCache($account, $mailbox); - } catch (Throwable $e) { - throw new ServiceException("Could not clear mailbox cache for $id: " . $e->getMessage(), 0, $e); - } finally { - $this->mailboxMapper->unlockFromNewSync($mailbox); - $this->mailboxMapper->unlockFromChangedSync($mailbox); - $this->mailboxMapper->unlockFromVanishedSync($mailbox); - } - } - - /** - * Wipe all cached messages of a mailbox from the database - * - * Warning: the caller has to ensure the mailbox is locked - * - * @param Account $account - * @param Mailbox $mailbox - */ - private function resetCache(Account $account, Mailbox $mailbox): void { - $id = $account->getId() . ':' . $mailbox->getName(); - $this->dbMapper->deleteAll($mailbox); - $this->logger->debug("All messages of $id cleared"); - $mailbox->setSyncNewToken(null); - $mailbox->setSyncChangedToken(null); - $mailbox->setSyncVanishedToken(null); - $this->mailboxMapper->update($mailbox); - } - - /** - * @throws ClientException - * @throws MailboxNotCachedException - * @throws ServiceException - * @return bool whether to rebuild threads or not - */ - public function sync(Account $account, - Horde_Imap_Client_Base $client, - Mailbox $mailbox, - LoggerInterface $logger, - int $criteria = Horde_Imap_Client::SYNC_NEWMSGSUIDS | Horde_Imap_Client::SYNC_FLAGSUIDS | Horde_Imap_Client::SYNC_VANISHEDUIDS, - ?array $knownUids = null, - bool $force = false, - bool $batchSync = false): bool { - $rebuildThreads = true; - if ($mailbox->getSelectable() === false) { - return $rebuildThreads; - } - - $client->login(); // Need to login before fetching capabilities. - - // There is no partial sync when using QRESYNC. As per RFC the client will always pull - // all changes. This is a cheap operation when using QRESYNC as the server keeps track - // of a client's state through the sync token. We could just update the sync tokens and - // call it a day because Horde caches unrelated/unrequested changes until the next - // operation. However, our cache is not reliable as some instance might use APCu which - // isn't shared between cron and web requests. - if ($client->capability->isEnabled('QRESYNC')) { - $this->logger->debug('Forcing full sync due to QRESYNC'); - $criteria |= Horde_Imap_Client::SYNC_NEWMSGSUIDS - | Horde_Imap_Client::SYNC_FLAGSUIDS - | Horde_Imap_Client::SYNC_VANISHEDUIDS; - } - - if ($force || ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS)) { - $logger->debug('Locking mailbox ' . $mailbox->getId() . ' for new messages sync'); - $this->mailboxMapper->lockForNewSync($mailbox); - } - if ($force || ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS)) { - $logger->debug('Locking mailbox ' . $mailbox->getId() . ' for changed messages sync'); - $this->mailboxMapper->lockForChangeSync($mailbox); - } - if ($force || ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS)) { - $logger->debug('Locking mailbox ' . $mailbox->getId() . ' for vanished messages sync'); - $this->mailboxMapper->lockForVanishedSync($mailbox); - } - - try { - if ($force - || $mailbox->getSyncNewToken() === null - || $mailbox->getSyncChangedToken() === null - || $mailbox->getSyncVanishedToken() === null) { - $logger->debug('Running initial sync for ' . $mailbox->getId()); - $this->runInitialSync($client, $account, $mailbox, $logger); - } else { - try { - $logger->debug('Running partial sync for ' . $mailbox->getId()); - // Only rebuild threads if there were new or vanished messages - $rebuildThreads = $this->runPartialSync($client, $account, $mailbox, $logger, $criteria, $knownUids); - } catch (UidValidityChangedException $e) { - $logger->warning('Mailbox UID validity changed. Wiping cache and performing full sync for ' . $mailbox->getId()); - $this->resetCache($account, $mailbox); - $logger->debug('Running initial sync for ' . $mailbox->getId() . ' after cache reset'); - $this->runInitialSync($client, $account, $mailbox, $logger); - } catch (MailboxDoesNotSupportModSequencesException $e) { - $logger->warning('Mailbox does not support mod-sequences error occured. Wiping cache and performing full sync for ' . $mailbox->getId(), [ - 'exception' => $e, - ]); - $this->resetCache($account, $mailbox); - $logger->debug('Running initial sync for ' . $mailbox->getId() . ' after cache reset - no mod-sequences error'); - $this->runInitialSync($client, $account, $mailbox, $logger); - } - } - } catch (ServiceException $e) { - // Just rethrow, don't wrap into another exception - throw $e; - } catch (Throwable $e) { - throw new ServiceException('Sync failed for ' . $account->getId() . ':' . $mailbox->getName() . ': ' . $e->getMessage(), 0, $e); - } finally { - if ($force || ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS)) { - $logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from vanished messages sync'); - $this->mailboxMapper->unlockFromVanishedSync($mailbox); - } - if ($force || ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS)) { - $logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from changed messages sync'); - $this->mailboxMapper->unlockFromChangedSync($mailbox); - } - if ($force || ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS)) { - $logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from new messages sync'); - $this->mailboxMapper->unlockFromNewSync($mailbox); - } - } - - if (!$batchSync) { - $this->dispatcher->dispatchTyped( - new SynchronizationEvent( - $account, - $this->logger, - $rebuildThreads, - ) - ); - } - - return $rebuildThreads; - } - - /** - * @throws ServiceException - * @throws IncompleteSyncException - */ - private function runInitialSync( - Horde_Imap_Client_Base $client, - Account $account, - Mailbox $mailbox, - LoggerInterface $logger): void { - $perf = $this->performanceLogger->startWithLogger( - 'Initial sync ' . $account->getId() . ':' . $mailbox->getName(), - $logger - ); - - // Need a client without a cache - $client->logout(); - $client = $this->clientFactory->getClient($account, false); - - $highestKnownUid = $this->dbMapper->findHighestUid($mailbox); - try { - $imapMessages = $this->imapMapper->findAll( - $client, - $mailbox->getName(), - self::MAX_NEW_MESSAGES, - $highestKnownUid ?? 0, - $logger, - $perf, - $account->getUserId(), - ); - $perf->step(sprintf('fetch %d messages from IMAP', count($imapMessages))); - } catch (Horde_Imap_Client_Exception $e) { - throw new ServiceException('Can not get messages from mailbox ' . $mailbox->getName() . ': ' . $e->getMessage(), 0, $e); - } - - foreach (array_chunk($imapMessages['messages'], 500) as $chunk) { - $messages = array_map(static function (IMAPMessage $imapMessage) use ($mailbox, $account) { - return $imapMessage->toDbMessage($mailbox->getId(), $account->getMailAccount()); - }, $chunk); - $this->dbMapper->insertBulk($account, ...$messages); - $perf->step(sprintf('persist %d messages in database', count($chunk))); - // Free the memory - unset($messages); - } - - if (!$imapMessages['all']) { - // We might need more attempts to fill the cache - $loggingMailboxId = $account->getId() . ':' . $mailbox->getName(); - $total = $imapMessages['total']; - $cached = count($this->dbMapper->findAllUids($mailbox)); - $perf->step('find number of cached UIDs'); - - $perf->end(); - throw new IncompleteSyncException("Initial sync is not complete for $loggingMailboxId ($cached of $total messages cached)."); - } - - $mailbox->setSyncNewToken($client->getSyncToken($mailbox->getName())); - $mailbox->setSyncChangedToken($client->getSyncToken($mailbox->getName())); - $mailbox->setSyncVanishedToken($client->getSyncToken($mailbox->getName())); - $this->mailboxMapper->update($mailbox); - - $perf->end(); - } - - /** - * @param int[] $knownUids - * - * @throws ServiceException - * @throws UidValidityChangedException - * @return bool whether there are new or vanished messages - */ - private function runPartialSync( - Horde_Imap_Client_Base $client, - Account $account, - Mailbox $mailbox, - LoggerInterface $logger, - int $criteria, - ?array $knownUids = null): bool { - $newOrVanished = false; - $perf = $this->performanceLogger->startWithLogger( - 'partial sync ' . $account->getId() . ':' . $mailbox->getName(), - $logger - ); - - $uids = $knownUids ?? $this->dbMapper->findAllUids($mailbox); - $perf->step('get all known UIDs'); - - if ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS) { - $response = $this->synchronizer->sync( - $client, - new Request( - $mailbox->getName(), - $mailbox->getSyncNewToken(), - $uids - ), - $account->getUserId(), - Horde_Imap_Client::SYNC_NEWMSGSUIDS - ); - $perf->step('get new messages via Horde'); - - $highestKnownUid = $this->dbMapper->findHighestUid($mailbox); - if ($highestKnownUid === null) { - // Everything is relevant - $newMessages = $response->getNewMessages(); - } else { - // Filter out anything that is already in the DB. Ideally this never happens, but if there is an error - // during a consecutive chunk INSERT, the sync token won't be updated. In that case the same message(s) - // will be seen as *new* and therefore cause conflicts. - $newMessages = array_filter($response->getNewMessages(), static function (IMAPMessage $imapMessage) use ($highestKnownUid) { - return $imapMessage->getUid() > $highestKnownUid; - }); - } - - foreach (array_chunk($newMessages, 500) as $chunk) { - $dbMessages = array_map(static function (IMAPMessage $imapMessage) use ($mailbox, $account) { - return $imapMessage->toDbMessage($mailbox->getId(), $account->getMailAccount()); - }, $chunk); - - $this->dbMapper->insertBulk($account, ...$dbMessages); - - $this->dispatcher->dispatch( - NewMessagesSynchronized::class, - new NewMessagesSynchronized($account, $mailbox, $dbMessages) - ); - $perf->step('classified a chunk of new messages'); - } - $perf->step('persist new messages'); - - $mailbox->setSyncNewToken($client->getSyncToken($mailbox->getName())); - $newOrVanished = $newMessages !== []; - } - if ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS) { - $response = $this->synchronizer->sync( - $client, - new Request( - $mailbox->getName(), - $mailbox->getSyncChangedToken(), - $uids - ), - $account->getUserId(), - Horde_Imap_Client::SYNC_FLAGSUIDS - ); - $perf->step('get changed messages via Horde'); - - $permflagsEnabled = $this->mailManager->isPermflagsEnabled($client, $account, $mailbox->getName()); - - foreach (array_chunk($response->getChangedMessages(), 500) as $chunk) { - $this->dbMapper->updateBulk($account, $permflagsEnabled, ...array_map(static function (IMAPMessage $imapMessage) use ($mailbox, $account) { - return $imapMessage->toDbMessage($mailbox->getId(), $account->getMailAccount()); - }, $chunk)); - } - $perf->step('persist changed messages'); - - // If a list of UIDs was *provided* (as opposed to loaded from the DB, - // we can not assume that all changes were detected, hence this is kinda - // a silent sync and we don't update the change token until the next full - // mailbox sync - if ($knownUids === null) { - $mailbox->setSyncChangedToken($client->getSyncToken($mailbox->getName())); - } - } - if ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS) { - $response = $this->synchronizer->sync( - $client, - new Request( - $mailbox->getName(), - $mailbox->getSyncVanishedToken(), - $uids - ), - $account->getUserId(), - Horde_Imap_Client::SYNC_VANISHEDUIDS - ); - $perf->step('get vanished messages via Horde'); - - foreach (array_chunk($response->getVanishedMessageUids(), 500) as $chunk) { - $this->dbMapper->deleteByUid($mailbox, ...$chunk); - } - $perf->step('delete vanished messages'); - - // If a list of UIDs was *provided* (as opposed to loaded from the DB, - // we can not assume that all changes were detected, hence this is kinda - // a silent sync and we don't update the vanish token until the next full - // mailbox sync - if ($knownUids === null) { - $mailbox->setSyncVanishedToken($client->getSyncToken($mailbox->getName())); - } - $newOrVanished = $newOrVanished || !empty($response->getVanishedMessageUids()); - } - $this->mailboxMapper->update($mailbox); - $perf->end(); - - return $newOrVanished; - } -} +dbMapper = $dbMapper; + $this->clientFactory = $clientFactory; + $this->imapMapper = $imapMapper; + $this->mailboxMapper = $mailboxMapper; + $this->synchronizer = $synchronizer; + $this->dispatcher = $dispatcher; + $this->performanceLogger = $performanceLogger; + $this->logger = $logger; + $this->mailManager = $mailManager; + } + + /** + * @throws ClientException + * @throws ServiceException + */ + public function syncAccount(MailAccount $account, + LoggerInterface $logger, + bool $force = false, + int $criteria = Horde_Imap_Client::SYNC_NEWMSGSUIDS | Horde_Imap_Client::SYNC_FLAGSUIDS | Horde_Imap_Client::SYNC_VANISHEDUIDS): void { + $rebuildThreads = false; + $trashMailboxId = $account->getTrashMailboxId(); + $snoozeMailboxId = $account->getSnoozeMailboxId(); + $sentMailboxId = $account->getSentMailboxId(); + $trashRetentionDays = $account->getTrashRetentionDays(); +  + $client = $this->clientFactory->getClient($account); +  + foreach ($this->mailboxMapper->findAll($account) as $mailbox) { + $syncTrash = $trashMailboxId === $mailbox->getId() && $trashRetentionDays !== null; + $syncSnooze = $snoozeMailboxId === $mailbox->getId(); + $syncSent = $sentMailboxId === $mailbox->getId() || $mailbox->isSpecialUse('sent'); + + if (!$syncTrash && !$mailbox->isInbox() && !$syncSnooze && !$mailbox->getSyncInBackground() && !$syncSent) { + $logger->debug('Skipping mailbox sync for ' . $mailbox->getId()); + continue; + } + $logger->debug('Syncing ' . $mailbox->getId()); + if ($this->sync( + $account, + $client, + $mailbox, + $logger, + $criteria, + null, + $force, + true + )) { + $rebuildThreads = true; + } + } +  + $client->logout(); + + $this->dispatcher->dispatchTyped( + new SynchronizationEvent( + $account, + $logger, + $rebuildThreads, + ) + ); + } + + /** + * Clear all cached data of a mailbox + * + * @param Mailbox $mailbox + * + * @throws MailboxLockedException + * @throws ServiceException + */ + public function clearCache(MailAccount $account, + Mailbox $mailbox): void { + $id = $account->getId() . ':' . $mailbox->getName(); + try { + $this->mailboxMapper->lockForNewSync($mailbox); + $this->mailboxMapper->lockForChangeSync($mailbox); + $this->mailboxMapper->lockForVanishedSync($mailbox); + + $this->resetCache($account, $mailbox); + } catch (Throwable $e) { + throw new ServiceException("Could not clear mailbox cache for $id: " . $e->getMessage(), 0, $e); + } finally { + $this->mailboxMapper->unlockFromNewSync($mailbox); + $this->mailboxMapper->unlockFromChangedSync($mailbox); + $this->mailboxMapper->unlockFromVanishedSync($mailbox); + } + } + + /** + * Wipe all cached messages of a mailbox from the database + * + * Warning: the caller has to ensure the mailbox is locked + * + * @param Mailbox $mailbox + */ + private function resetCache(MailAccount $account, Mailbox $mailbox): void { + $id = $account->getId() . ':' . $mailbox->getName(); + $this->dbMapper->deleteAll($mailbox); + $this->logger->debug("All messages of $id cleared"); + $mailbox->setSyncNewToken(null); + $mailbox->setSyncChangedToken(null); + $mailbox->setSyncVanishedToken(null); + $this->mailboxMapper->update($mailbox); + } + + /** + * @throws ClientException + * @throws MailboxNotCachedException + * @throws ServiceException + * @return bool whether to rebuild threads or not + */ + public function sync(MailAccount $account, + Horde_Imap_Client_Base $client, + Mailbox $mailbox, + LoggerInterface $logger, + int $criteria = Horde_Imap_Client::SYNC_NEWMSGSUIDS | Horde_Imap_Client::SYNC_FLAGSUIDS | Horde_Imap_Client::SYNC_VANISHEDUIDS, + ?array $knownUids = null, + bool $force = false, + bool $batchSync = false): bool { + $rebuildThreads = true; + if ($mailbox->getSelectable() === false) { + return $rebuildThreads; + } + + $client->login(); // Need to login before fetching capabilities. + + // There is no partial sync when using QRESYNC. As per RFC the client will always pull + // all changes. This is a cheap operation when using QRESYNC as the server keeps track + // of a client's state through the sync token. We could just update the sync tokens and + // call it a day because Horde caches unrelated/unrequested changes until the next + // operation. However, our cache is not reliable as some instance might use APCu which + // isn't shared between cron and web requests. + if ($client->capability->isEnabled('QRESYNC')) { + $this->logger->debug('Forcing full sync due to QRESYNC'); + $criteria |= Horde_Imap_Client::SYNC_NEWMSGSUIDS + | Horde_Imap_Client::SYNC_FLAGSUIDS + | Horde_Imap_Client::SYNC_VANISHEDUIDS; + } + + if ($force || ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS)) { + $logger->debug('Locking mailbox ' . $mailbox->getId() . ' for new messages sync'); + $this->mailboxMapper->lockForNewSync($mailbox); + } + if ($force || ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS)) { + $logger->debug('Locking mailbox ' . $mailbox->getId() . ' for changed messages sync'); + $this->mailboxMapper->lockForChangeSync($mailbox); + } + if ($force || ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS)) { + $logger->debug('Locking mailbox ' . $mailbox->getId() . ' for vanished messages sync'); + $this->mailboxMapper->lockForVanishedSync($mailbox); + } + + try { + if ($force + || $mailbox->getSyncNewToken() === null + || $mailbox->getSyncChangedToken() === null + || $mailbox->getSyncVanishedToken() === null) { + $logger->debug('Running initial sync for ' . $mailbox->getId()); + $this->runInitialSync($client, $account, $mailbox, $logger); + } else { + try { + $logger->debug('Running partial sync for ' . $mailbox->getId()); + // Only rebuild threads if there were new or vanished messages + $rebuildThreads = $this->runPartialSync($client, $account, $mailbox, $logger, $criteria, $knownUids); + } catch (UidValidityChangedException $e) { + $logger->warning('Mailbox UID validity changed. Wiping cache and performing full sync for ' . $mailbox->getId()); + $this->resetCache($account, $mailbox); + $logger->debug('Running initial sync for ' . $mailbox->getId() . ' after cache reset'); + $this->runInitialSync($client, $account, $mailbox, $logger); + } catch (MailboxDoesNotSupportModSequencesException $e) { + $logger->warning('Mailbox does not support mod-sequences error occured. Wiping cache and performing full sync for ' . $mailbox->getId(), [ + 'exception' => $e, + ]); + $this->resetCache($account, $mailbox); + $logger->debug('Running initial sync for ' . $mailbox->getId() . ' after cache reset - no mod-sequences error'); + $this->runInitialSync($client, $account, $mailbox, $logger); + } + } + } catch (ServiceException $e) { + // Just rethrow, don't wrap into another exception + throw $e; + } catch (Throwable $e) { + throw new ServiceException('Sync failed for ' . $account->getId() . ':' . $mailbox->getName() . ': ' . $e->getMessage(), 0, $e); + } finally { + if ($force || ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS)) { + $logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from vanished messages sync'); + $this->mailboxMapper->unlockFromVanishedSync($mailbox); + } + if ($force || ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS)) { + $logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from changed messages sync'); + $this->mailboxMapper->unlockFromChangedSync($mailbox); + } + if ($force || ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS)) { + $logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from new messages sync'); + $this->mailboxMapper->unlockFromNewSync($mailbox); + } + } + + if (!$batchSync) { + $this->dispatcher->dispatchTyped( + new SynchronizationEvent( + $account, + $this->logger, + $rebuildThreads, + ) + ); + } + + return $rebuildThreads; + } + + /** + * @throws ServiceException + * @throws IncompleteSyncException + */ + private function runInitialSync( + Horde_Imap_Client_Base $client, + MailAccount $account, + Mailbox $mailbox, + LoggerInterface $logger): void { + $perf = $this->performanceLogger->startWithLogger( + 'Initial sync ' . $account->getId() . ':' . $mailbox->getName(), + $logger + ); + + // Need a client without a cache + $client->logout(); + $client = $this->clientFactory->getClient($account, false); + + $highestKnownUid = $this->dbMapper->findHighestUid($mailbox); + try { + $imapMessages = $this->imapMapper->findAll( + $client, + $mailbox->getName(), + self::MAX_NEW_MESSAGES, + $highestKnownUid ?? 0, + $logger, + $perf, + $account->getUserId(), + ); + $perf->step(sprintf('fetch %d messages from IMAP', count($imapMessages))); + } catch (Horde_Imap_Client_Exception $e) { + throw new ServiceException('Can not get messages from mailbox ' . $mailbox->getName() . ': ' . $e->getMessage(), 0, $e); + } + + foreach (array_chunk($imapMessages['messages'], 500) as $chunk) { + $messages = array_map(static function (IMAPMessage $imapMessage) use ($mailbox, $account) { + return $imapMessage->toDbMessage($mailbox->getId(), $account); + }, $chunk); + $this->dbMapper->insertBulk($account, ...$messages); + $perf->step(sprintf('persist %d messages in database', count($chunk))); + // Free the memory + unset($messages); + } + + if (!$imapMessages['all']) { + // We might need more attempts to fill the cache + $loggingMailboxId = $account->getId() . ':' . $mailbox->getName(); + $total = $imapMessages['total']; + $cached = count($this->dbMapper->findAllUids($mailbox)); + $perf->step('find number of cached UIDs'); + + $perf->end(); + throw new IncompleteSyncException("Initial sync is not complete for $loggingMailboxId ($cached of $total messages cached)."); + } + + $mailbox->setSyncNewToken($client->getSyncToken($mailbox->getName())); + $mailbox->setSyncChangedToken($client->getSyncToken($mailbox->getName())); + $mailbox->setSyncVanishedToken($client->getSyncToken($mailbox->getName())); + $this->mailboxMapper->update($mailbox); + + $perf->end(); + } + + /** + * @param int[] $knownUids + * + * @throws ServiceException + * @throws UidValidityChangedException + * @return bool whether there are new or vanished messages + */ + private function runPartialSync( + Horde_Imap_Client_Base $client, + MailAccount $account, + Mailbox $mailbox, + LoggerInterface $logger, + int $criteria, + ?array $knownUids = null): bool { + $newOrVanished = false; + $perf = $this->performanceLogger->startWithLogger( + 'partial sync ' . $account->getId() . ':' . $mailbox->getName(), + $logger + ); + + $uids = $knownUids ?? $this->dbMapper->findAllUids($mailbox); + $perf->step('get all known UIDs'); + + if ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS) { + $response = $this->synchronizer->sync( + $client, + new Request( + $mailbox->getName(), + $mailbox->getSyncNewToken(), + $uids + ), + $account->getUserId(), + Horde_Imap_Client::SYNC_NEWMSGSUIDS + ); + $perf->step('get new messages via Horde'); + + $highestKnownUid = $this->dbMapper->findHighestUid($mailbox); + if ($highestKnownUid === null) { + // Everything is relevant + $newMessages = $response->getNewMessages(); + } else { + // Filter out anything that is already in the DB. Ideally this never happens, but if there is an error + // during a consecutive chunk INSERT, the sync token won't be updated. In that case the same message(s) + // will be seen as *new* and therefore cause conflicts. + $newMessages = array_filter($response->getNewMessages(), static function (IMAPMessage $imapMessage) use ($highestKnownUid) { + return $imapMessage->getUid() > $highestKnownUid; + }); + } + + foreach (array_chunk($newMessages, 500) as $chunk) { + $dbMessages = array_map(static function (IMAPMessage $imapMessage) use ($mailbox, $account) { + return $imapMessage->toDbMessage($mailbox->getId(), $account); + }, $chunk); + + $this->dbMapper->insertBulk($account, ...$dbMessages); + + $this->dispatcher->dispatch( + NewMessagesSynchronized::class, + new NewMessagesSynchronized($account, $mailbox, $dbMessages) + ); + $perf->step('classified a chunk of new messages'); + } + $perf->step('persist new messages'); + + $mailbox->setSyncNewToken($client->getSyncToken($mailbox->getName())); + $newOrVanished = $newMessages !== []; + } + if ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS) { + $response = $this->synchronizer->sync( + $client, + new Request( + $mailbox->getName(), + $mailbox->getSyncChangedToken(), + $uids + ), + $account->getUserId(), + Horde_Imap_Client::SYNC_FLAGSUIDS + ); + $perf->step('get changed messages via Horde'); + + $permflagsEnabled = $this->mailManager->isPermflagsEnabled($client, $account, $mailbox->getName()); + + foreach (array_chunk($response->getChangedMessages(), 500) as $chunk) { + $this->dbMapper->updateBulk($account, $permflagsEnabled, ...array_map(static function (IMAPMessage $imapMessage) use ($mailbox, $account) { + return $imapMessage->toDbMessage($mailbox->getId(), $account); + }, $chunk)); + } + $perf->step('persist changed messages'); + + // If a list of UIDs was *provided* (as opposed to loaded from the DB, + // we can not assume that all changes were detected, hence this is kinda + // a silent sync and we don't update the change token until the next full + // mailbox sync + if ($knownUids === null) { + $mailbox->setSyncChangedToken($client->getSyncToken($mailbox->getName())); + } + } + if ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS) { + $response = $this->synchronizer->sync( + $client, + new Request( + $mailbox->getName(), + $mailbox->getSyncVanishedToken(), + $uids + ), + $account->getUserId(), + Horde_Imap_Client::SYNC_VANISHEDUIDS + ); + $perf->step('get vanished messages via Horde'); + + foreach (array_chunk($response->getVanishedMessageUids(), 500) as $chunk) { + $this->dbMapper->deleteByUid($mailbox, ...$chunk); + } + $perf->step('delete vanished messages'); + + // If a list of UIDs was *provided* (as opposed to loaded from the DB, + // we can not assume that all changes were detected, hence this is kinda + // a silent sync and we don't update the vanish token until the next full + // mailbox sync + if ($knownUids === null) { + $mailbox->setSyncVanishedToken($client->getSyncToken($mailbox->getName())); + } + $newOrVanished = $newOrVanished || !empty($response->getVanishedMessageUids()); + } + $this->mailboxMapper->update($mailbox); + $perf->end(); + + return $newOrVanished; + } +} diff --git a/lib/Service/Sync/ImapToDbSynchronizer.php.orig b/lib/Service/Sync/ImapToDbSynchronizer.php.orig new file mode 100644 index 0000000000..57c562ebce --- /dev/null +++ b/lib/Service/Sync/ImapToDbSynchronizer.php.orig @@ -0,0 +1,497 @@ +dbMapper = $dbMapper; + $this->clientFactory = $clientFactory; + $this->imapMapper = $imapMapper; + $this->mailboxMapper = $mailboxMapper; + $this->synchronizer = $synchronizer; + $this->dispatcher = $dispatcher; + $this->performanceLogger = $performanceLogger; + $this->logger = $logger; + $this->mailManager = $mailManager; + } + + /** + * @throws ClientException + * @throws ServiceException + */ + public function syncAccount(MailAccount $account, + LoggerInterface $logger, + bool $force = false, + int $criteria = Horde_Imap_Client::SYNC_NEWMSGSUIDS | Horde_Imap_Client::SYNC_FLAGSUIDS | Horde_Imap_Client::SYNC_VANISHEDUIDS): void { + $rebuildThreads = false; +<<<<<<< Updated upstream + $trashMailboxId = $account->getTrashMailboxId(); + $snoozeMailboxId = $account->getSnoozeMailboxId(); + $sentMailboxId = $account->getSentMailboxId(); + $trashRetentionDays = $account->getTrashRetentionDays(); + + $client = $this->clientFactory->getClient($account); + +======= + $trashMailboxId = $account->getTrashMailboxId(); + $snoozeMailboxId = $account->getSnoozeMailboxId(); + $sentMailboxId = $account->getSentMailboxId(); + $trashRetentionDays = $account->getTrashRetentionDays(); +>>>>>>> Stashed changes + foreach ($this->mailboxMapper->findAll($account) as $mailbox) { + $syncTrash = $trashMailboxId === $mailbox->getId() && $trashRetentionDays !== null; + $syncSnooze = $snoozeMailboxId === $mailbox->getId(); + $syncSent = $sentMailboxId === $mailbox->getId() || $mailbox->isSpecialUse('sent'); + + if (!$syncTrash && !$mailbox->isInbox() && !$syncSnooze && !$mailbox->getSyncInBackground() && !$syncSent) { + $logger->debug('Skipping mailbox sync for ' . $mailbox->getId()); + continue; + } + $logger->debug('Syncing ' . $mailbox->getId()); + if ($this->sync( + $account, + $client, + $mailbox, + $logger, + $criteria, + null, + $force, + true + )) { + $rebuildThreads = true; + } + } + + $client->logout(); + + $this->dispatcher->dispatchTyped( + new SynchronizationEvent( + $account, + $logger, + $rebuildThreads, + ) + ); + } + + /** + * Clear all cached data of a mailbox + * + * @param Mailbox $mailbox + * + * @throws MailboxLockedException + * @throws ServiceException + */ + public function clearCache(MailAccount $account, + Mailbox $mailbox): void { + $id = $account->getId() . ':' . $mailbox->getName(); + try { + $this->mailboxMapper->lockForNewSync($mailbox); + $this->mailboxMapper->lockForChangeSync($mailbox); + $this->mailboxMapper->lockForVanishedSync($mailbox); + + $this->resetCache($account, $mailbox); + } catch (Throwable $e) { + throw new ServiceException("Could not clear mailbox cache for $id: " . $e->getMessage(), 0, $e); + } finally { + $this->mailboxMapper->unlockFromNewSync($mailbox); + $this->mailboxMapper->unlockFromChangedSync($mailbox); + $this->mailboxMapper->unlockFromVanishedSync($mailbox); + } + } + + /** + * Wipe all cached messages of a mailbox from the database + * + * Warning: the caller has to ensure the mailbox is locked + * + * @param Mailbox $mailbox + */ + private function resetCache(MailAccount $account, Mailbox $mailbox): void { + $id = $account->getId() . ':' . $mailbox->getName(); + $this->dbMapper->deleteAll($mailbox); + $this->logger->debug("All messages of $id cleared"); + $mailbox->setSyncNewToken(null); + $mailbox->setSyncChangedToken(null); + $mailbox->setSyncVanishedToken(null); + $this->mailboxMapper->update($mailbox); + } + + /** + * @throws ClientException + * @throws MailboxNotCachedException + * @throws ServiceException + * @return bool whether to rebuild threads or not + */ +<<<<<<< Updated upstream + public function sync(Account $account, + Horde_Imap_Client_Base $client, +======= + public function sync(MailAccount $account, +>>>>>>> Stashed changes + Mailbox $mailbox, + LoggerInterface $logger, + int $criteria = Horde_Imap_Client::SYNC_NEWMSGSUIDS | Horde_Imap_Client::SYNC_FLAGSUIDS | Horde_Imap_Client::SYNC_VANISHEDUIDS, + ?array $knownUids = null, + bool $force = false, + bool $batchSync = false): bool { + $rebuildThreads = true; + if ($mailbox->getSelectable() === false) { + return $rebuildThreads; + } + + $client->login(); // Need to login before fetching capabilities. + + // There is no partial sync when using QRESYNC. As per RFC the client will always pull + // all changes. This is a cheap operation when using QRESYNC as the server keeps track + // of a client's state through the sync token. We could just update the sync tokens and + // call it a day because Horde caches unrelated/unrequested changes until the next + // operation. However, our cache is not reliable as some instance might use APCu which + // isn't shared between cron and web requests. + if ($client->capability->isEnabled('QRESYNC')) { + $this->logger->debug('Forcing full sync due to QRESYNC'); + $criteria |= Horde_Imap_Client::SYNC_NEWMSGSUIDS + | Horde_Imap_Client::SYNC_FLAGSUIDS + | Horde_Imap_Client::SYNC_VANISHEDUIDS; + } + + if ($force || ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS)) { + $logger->debug('Locking mailbox ' . $mailbox->getId() . ' for new messages sync'); + $this->mailboxMapper->lockForNewSync($mailbox); + } + if ($force || ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS)) { + $logger->debug('Locking mailbox ' . $mailbox->getId() . ' for changed messages sync'); + $this->mailboxMapper->lockForChangeSync($mailbox); + } + if ($force || ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS)) { + $logger->debug('Locking mailbox ' . $mailbox->getId() . ' for vanished messages sync'); + $this->mailboxMapper->lockForVanishedSync($mailbox); + } + + try { + if ($force + || $mailbox->getSyncNewToken() === null + || $mailbox->getSyncChangedToken() === null + || $mailbox->getSyncVanishedToken() === null) { + $logger->debug('Running initial sync for ' . $mailbox->getId()); + $this->runInitialSync($client, $account, $mailbox, $logger); + } else { + try { + $logger->debug('Running partial sync for ' . $mailbox->getId()); + // Only rebuild threads if there were new or vanished messages + $rebuildThreads = $this->runPartialSync($client, $account, $mailbox, $logger, $criteria, $knownUids); + } catch (UidValidityChangedException $e) { + $logger->warning('Mailbox UID validity changed. Wiping cache and performing full sync for ' . $mailbox->getId()); + $this->resetCache($account, $mailbox); + $logger->debug('Running initial sync for ' . $mailbox->getId() . ' after cache reset'); + $this->runInitialSync($client, $account, $mailbox, $logger); + } catch (MailboxDoesNotSupportModSequencesException $e) { + $logger->warning('Mailbox does not support mod-sequences error occured. Wiping cache and performing full sync for ' . $mailbox->getId(), [ + 'exception' => $e, + ]); + $this->resetCache($account, $mailbox); + $logger->debug('Running initial sync for ' . $mailbox->getId() . ' after cache reset - no mod-sequences error'); + $this->runInitialSync($client, $account, $mailbox, $logger); + } + } + } catch (ServiceException $e) { + // Just rethrow, don't wrap into another exception + throw $e; + } catch (Throwable $e) { + throw new ServiceException('Sync failed for ' . $account->getId() . ':' . $mailbox->getName() . ': ' . $e->getMessage(), 0, $e); + } finally { + if ($force || ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS)) { + $logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from vanished messages sync'); + $this->mailboxMapper->unlockFromVanishedSync($mailbox); + } + if ($force || ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS)) { + $logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from changed messages sync'); + $this->mailboxMapper->unlockFromChangedSync($mailbox); + } + if ($force || ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS)) { + $logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from new messages sync'); + $this->mailboxMapper->unlockFromNewSync($mailbox); + } + } + + if (!$batchSync) { + $this->dispatcher->dispatchTyped( + new SynchronizationEvent( + $account, + $this->logger, + $rebuildThreads, + ) + ); + } + + return $rebuildThreads; + } + + /** + * @throws ServiceException + * @throws IncompleteSyncException + */ + private function runInitialSync( + Horde_Imap_Client_Base $client, + MailAccount $account, + Mailbox $mailbox, + LoggerInterface $logger): void { + $perf = $this->performanceLogger->startWithLogger( + 'Initial sync ' . $account->getId() . ':' . $mailbox->getName(), + $logger + ); + + // Need a client without a cache + $client->logout(); + $client = $this->clientFactory->getClient($account, false); + + $highestKnownUid = $this->dbMapper->findHighestUid($mailbox); + try { + $imapMessages = $this->imapMapper->findAll( + $client, + $mailbox->getName(), + self::MAX_NEW_MESSAGES, + $highestKnownUid ?? 0, + $logger, + $perf, + $account->getUserId(), + ); + $perf->step(sprintf('fetch %d messages from IMAP', count($imapMessages))); + } catch (Horde_Imap_Client_Exception $e) { + throw new ServiceException('Can not get messages from mailbox ' . $mailbox->getName() . ': ' . $e->getMessage(), 0, $e); + } + + foreach (array_chunk($imapMessages['messages'], 500) as $chunk) { + $messages = array_map(static function (IMAPMessage $imapMessage) use ($mailbox, $account) { + return $imapMessage->toDbMessage($mailbox->getId(), $account); + }, $chunk); + $this->dbMapper->insertBulk($account, ...$messages); + $perf->step(sprintf('persist %d messages in database', count($chunk))); + // Free the memory + unset($messages); + } + + if (!$imapMessages['all']) { + // We might need more attempts to fill the cache + $loggingMailboxId = $account->getId() . ':' . $mailbox->getName(); + $total = $imapMessages['total']; + $cached = count($this->dbMapper->findAllUids($mailbox)); + $perf->step('find number of cached UIDs'); + + $perf->end(); + throw new IncompleteSyncException("Initial sync is not complete for $loggingMailboxId ($cached of $total messages cached)."); + } + + $mailbox->setSyncNewToken($client->getSyncToken($mailbox->getName())); + $mailbox->setSyncChangedToken($client->getSyncToken($mailbox->getName())); + $mailbox->setSyncVanishedToken($client->getSyncToken($mailbox->getName())); + $this->mailboxMapper->update($mailbox); + + $perf->end(); + } + + /** + * @param int[] $knownUids + * + * @throws ServiceException + * @throws UidValidityChangedException + * @return bool whether there are new or vanished messages + */ + private function runPartialSync( + Horde_Imap_Client_Base $client, + MailAccount $account, + Mailbox $mailbox, + LoggerInterface $logger, + int $criteria, + ?array $knownUids = null): bool { + $newOrVanished = false; + $perf = $this->performanceLogger->startWithLogger( + 'partial sync ' . $account->getId() . ':' . $mailbox->getName(), + $logger + ); + + $uids = $knownUids ?? $this->dbMapper->findAllUids($mailbox); + $perf->step('get all known UIDs'); + + if ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS) { + $response = $this->synchronizer->sync( + $client, + new Request( + $mailbox->getName(), + $mailbox->getSyncNewToken(), + $uids + ), + $account->getUserId(), + Horde_Imap_Client::SYNC_NEWMSGSUIDS + ); + $perf->step('get new messages via Horde'); + + $highestKnownUid = $this->dbMapper->findHighestUid($mailbox); + if ($highestKnownUid === null) { + // Everything is relevant + $newMessages = $response->getNewMessages(); + } else { + // Filter out anything that is already in the DB. Ideally this never happens, but if there is an error + // during a consecutive chunk INSERT, the sync token won't be updated. In that case the same message(s) + // will be seen as *new* and therefore cause conflicts. + $newMessages = array_filter($response->getNewMessages(), static function (IMAPMessage $imapMessage) use ($highestKnownUid) { + return $imapMessage->getUid() > $highestKnownUid; + }); + } + + foreach (array_chunk($newMessages, 500) as $chunk) { + $dbMessages = array_map(static function (IMAPMessage $imapMessage) use ($mailbox, $account) { + return $imapMessage->toDbMessage($mailbox->getId(), $account); + }, $chunk); + + $this->dbMapper->insertBulk($account, ...$dbMessages); + + $this->dispatcher->dispatch( + NewMessagesSynchronized::class, + new NewMessagesSynchronized($account, $mailbox, $dbMessages) + ); + $perf->step('classified a chunk of new messages'); + } + $perf->step('persist new messages'); + + $mailbox->setSyncNewToken($client->getSyncToken($mailbox->getName())); + $newOrVanished = $newMessages !== []; + } + if ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS) { + $response = $this->synchronizer->sync( + $client, + new Request( + $mailbox->getName(), + $mailbox->getSyncChangedToken(), + $uids + ), + $account->getUserId(), + Horde_Imap_Client::SYNC_FLAGSUIDS + ); + $perf->step('get changed messages via Horde'); + + $permflagsEnabled = $this->mailManager->isPermflagsEnabled($client, $account, $mailbox->getName()); + + foreach (array_chunk($response->getChangedMessages(), 500) as $chunk) { + $this->dbMapper->updateBulk($account, $permflagsEnabled, ...array_map(static function (IMAPMessage $imapMessage) use ($mailbox, $account) { + return $imapMessage->toDbMessage($mailbox->getId(), $account); + }, $chunk)); + } + $perf->step('persist changed messages'); + + // If a list of UIDs was *provided* (as opposed to loaded from the DB, + // we can not assume that all changes were detected, hence this is kinda + // a silent sync and we don't update the change token until the next full + // mailbox sync + if ($knownUids === null) { + $mailbox->setSyncChangedToken($client->getSyncToken($mailbox->getName())); + } + } + if ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS) { + $response = $this->synchronizer->sync( + $client, + new Request( + $mailbox->getName(), + $mailbox->getSyncVanishedToken(), + $uids + ), + $account->getUserId(), + Horde_Imap_Client::SYNC_VANISHEDUIDS + ); + $perf->step('get vanished messages via Horde'); + + foreach (array_chunk($response->getVanishedMessageUids(), 500) as $chunk) { + $this->dbMapper->deleteByUid($mailbox, ...$chunk); + } + $perf->step('delete vanished messages'); + + // If a list of UIDs was *provided* (as opposed to loaded from the DB, + // we can not assume that all changes were detected, hence this is kinda + // a silent sync and we don't update the vanish token until the next full + // mailbox sync + if ($knownUids === null) { + $mailbox->setSyncVanishedToken($client->getSyncToken($mailbox->getName())); + } + $newOrVanished = $newOrVanished || !empty($response->getVanishedMessageUids()); + } + $this->mailboxMapper->update($mailbox); + $perf->end(); + + return $newOrVanished; + } +} diff --git a/lib/Service/Sync/SyncService.php b/lib/Service/Sync/SyncService.php index e4bed5f96a..30908b12e7 100644 --- a/lib/Service/Sync/SyncService.php +++ b/lib/Service/Sync/SyncService.php @@ -9,8 +9,8 @@ namespace OCA\Mail\Service\Sync; -use OCA\Mail\Account; use OCA\Mail\Contracts\IMailSearch; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Mailbox; use OCA\Mail\Db\MailboxMapper; use OCA\Mail\Db\Message; @@ -30,7 +30,7 @@ use function array_map; class SyncService { - + private IMAPClientFactory $clientFactory; /** @var ImapToDbSynchronizer */ @@ -74,19 +74,17 @@ public function __construct( } /** - * @param Account $account * @param Mailbox $mailbox * * @throws MailboxLockedException * @throws ServiceException */ - public function clearCache(Account $account, + public function clearCache(MailAccount $account, Mailbox $mailbox): void { $this->synchronizer->clearCache($account, $mailbox); } /** - * @param Account $account * @param Mailbox $mailbox * @param int $criteria * @param bool $partialOnly @@ -99,7 +97,7 @@ public function clearCache(Account $account, * @throws MailboxNotCachedException * @throws ServiceException */ - public function syncMailbox(Account $account, + public function syncMailbox(MailAccount $account, Mailbox $mailbox, int $criteria, bool $partialOnly, @@ -110,9 +108,9 @@ public function syncMailbox(Account $account, if ($partialOnly && !$mailbox->isCached()) { throw MailboxNotCachedException::from($mailbox); } - + $client = $this->clientFactory->getClient($account); - + $this->synchronizer->sync( $account, $client, @@ -139,7 +137,6 @@ public function syncMailbox(Account $account, } /** - * @param Account $account * @param Mailbox $mailbox * @param int[] $knownIds * @param SearchQuery $query @@ -148,7 +145,7 @@ public function syncMailbox(Account $account, * @todo does not work with text token search queries * */ - private function getDatabaseSyncChanges(Account $account, + private function getDatabaseSyncChanges(MailAccount $account, Mailbox $mailbox, array $knownIds, ?int $lastMessageTimestamp, diff --git a/lib/Service/TransmissionService.php b/lib/Service/TransmissionService.php index 1b6ccb6c06..bbe1e7c11f 100644 --- a/lib/Service/TransmissionService.php +++ b/lib/Service/TransmissionService.php @@ -7,11 +7,11 @@ */ namespace OCA\Mail\Service; -use OCA\Mail\Account; use OCA\Mail\Address; use OCA\Mail\AddressList; use OCA\Mail\Db\LocalAttachment; use OCA\Mail\Db\LocalMessage; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\Recipient; use OCA\Mail\Exception\AttachmentNotFoundException; use OCA\Mail\Exception\ServiceException; @@ -68,18 +68,17 @@ public function getAttachments(LocalMessage $message): array { } /** - * @param Account $account * @param array $attachment * @return \Horde_Mime_Part|null */ - public function handleAttachment(Account $account, array $attachment): ?\Horde_Mime_Part { + public function handleAttachment(MailAccount $account, array $attachment): ?\Horde_Mime_Part { if (!isset($attachment['id'])) { $this->logger->warning('ignoring local attachment because its id is unknown'); return null; } try { - [$localAttachment, $file] = $this->attachmentService->getAttachment($account->getMailAccount()->getUserId(), (int)$attachment['id']); + [$localAttachment, $file] = $this->attachmentService->getAttachment($account->getUserId(), (int)$attachment['id']); $part = new \Horde_Mime_Part(); $part->setCharset('us-ascii'); $part->setDisposition('attachment'); @@ -110,12 +109,11 @@ public function handleAttachment(Account $account, array $attachment): ?\Horde_M /** * @param LocalMessage $localMessage - * @param Account $account * @param \Horde_Mime_Part $mimePart * @return \Horde_Mime_Part * @throws ServiceException */ - public function getSignMimePart(LocalMessage $localMessage, Account $account, \Horde_Mime_Part $mimePart): \Horde_Mime_Part { + public function getSignMimePart(LocalMessage $localMessage, MailAccount $account, \Horde_Mime_Part $mimePart): \Horde_Mime_Part { if ($localMessage->getSmimeSign()) { if ($localMessage->getSmimeCertificateId() === null) { $localMessage->setStatus(LocalMessage::STATUS_SMIME_SIGN_NO_CERT_ID); @@ -152,12 +150,11 @@ public function getSignMimePart(LocalMessage $localMessage, Account $account, \H * @param AddressList $to * @param AddressList $cc * @param AddressList $bcc - * @param Account $account * @param \Horde_Mime_Part $mimePart * @return \Horde_Mime_Part * @throws ServiceException */ - public function getEncryptMimePart(LocalMessage $localMessage, AddressList $to, AddressList $cc, AddressList $bcc, Account $account, \Horde_Mime_Part $mimePart): \Horde_Mime_Part { + public function getEncryptMimePart(LocalMessage $localMessage, AddressList $to, AddressList $cc, AddressList $bcc, MailAccount $account, \Horde_Mime_Part $mimePart): \Horde_Mime_Part { if ($localMessage->getSmimeEncrypt()) { if ($localMessage->getSmimeCertificateId() === null) { $localMessage->setStatus(LocalMessage::STATUS_SMIME_ENCRYPT_NO_CERT_ID); diff --git a/lib/Sieve/SieveClientFactory.php b/lib/Sieve/SieveClientFactory.php index 127513c6e3..04676a51fe 100644 --- a/lib/Sieve/SieveClientFactory.php +++ b/lib/Sieve/SieveClientFactory.php @@ -10,7 +10,7 @@ namespace OCA\Mail\Sieve; use Horde\ManageSieve; -use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCP\IConfig; use OCP\Security\ICrypto; @@ -33,31 +33,30 @@ public function __construct(ICrypto $crypto, IConfig $config) { } /** - * @param Account $account * @return ManageSieve * @throws ManageSieve\Exception */ - public function getClient(Account $account): ManageSieve { - if (!isset($this->cache[$account->getId()])) { - $user = $account->getMailAccount()->getSieveUser(); + public function getClient(MailAccount $account): ManageSieve { + if (!isset($this->cache[($account->getId())])) { + $user = $account->getSieveUser(); if (empty($user)) { - $user = $account->getMailAccount()->getInboundUser(); + $user = $account->getInboundUser(); } - $password = $account->getMailAccount()->getSievePassword(); + $password = $account->getSievePassword(); if (empty($password)) { - $password = $account->getMailAccount()->getInboundPassword(); + $password = $account->getInboundPassword(); } - $this->cache[$account->getId()] = $this->createClient( - $account->getMailAccount()->getSieveHost(), - $account->getMailAccount()->getSievePort(), + $this->cache[($account->getId())] = $this->createClient( + $account->getSieveHost(), + $account->getSievePort(), $user, $password, - $account->getMailAccount()->getSieveSslMode() + $account->getSieveSslMode() ); } - return $this->cache[$account->getId()]; + return $this->cache[($account->getId())]; } /** diff --git a/tests/Integration/Migration/MigrateImportantFromImapAndDbTest.php b/tests/Integration/Migration/MigrateImportantFromImapAndDbTest.php index b6c141f572..d03fd63d1a 100644 --- a/tests/Integration/Migration/MigrateImportantFromImapAndDbTest.php +++ b/tests/Integration/Migration/MigrateImportantFromImapAndDbTest.php @@ -58,7 +58,7 @@ public function testMigrateImportantOnImap() { $this->logger->expects($this->never()) ->method('debug'); - $this->migration->migrateImportantOnImap($this->client, $account, $mailbox); + $this->migration->migrateImportantOnImap($this->client, $mailbox); } public function testMigrateImportantOnImapNoUids() { @@ -75,7 +75,7 @@ public function testMigrateImportantOnImapNoUids() { $this->logger->expects($this->never()) ->method('debug'); - $this->migration->migrateImportantOnImap($this->client, $account, $mailbox); + $this->migration->migrateImportantOnImap($this->client, $mailbox); } public function testMigrateImportantOnImapExceptionGetFlagged() { @@ -93,7 +93,7 @@ public function testMigrateImportantOnImapExceptionGetFlagged() { ->method('debug'); $this->expectException(ServiceException::class); - $this->migration->migrateImportantOnImap($this->client, $account, $mailbox); + $this->migration->migrateImportantOnImap($this->client, $mailbox); } public function testMigrateImportantOnImapExceptionOnFlag() { @@ -116,7 +116,7 @@ public function testMigrateImportantOnImapExceptionOnFlag() { ->with('Could not flag messages in mailbox <' . $mailbox->getId() . '>'); $this->expectException(ServiceException::class); - $this->migration->migrateImportantOnImap($this->client, $account, $mailbox); + $this->migration->migrateImportantOnImap($this->client, $mailbox); } public function migrateImportantFromDb() { @@ -135,7 +135,7 @@ public function migrateImportantFromDb() { $this->logger->expects($this->never()) ->method('debug'); - $this->migration->migrateImportantFromDb($this->client, $account, $mailbox); + $this->migration->migrateImportantFromDb($this->client, $mailbox); } public function testMigrateImportantFromDbNoUids() { @@ -153,7 +153,7 @@ public function testMigrateImportantFromDbNoUids() { $this->logger->expects($this->never()) ->method('debug'); - $this->migration->migrateImportantFromDb($this->client, $account, $mailbox); + $this->migration->migrateImportantFromDb($this->client, $mailbox); } public function testMigrateImportantFromDbExceptionOnFlag() { @@ -177,6 +177,6 @@ public function testMigrateImportantFromDbExceptionOnFlag() { ->with('Could not flag messages in mailbox <' . $mailbox->getId() . '>'); $this->expectException(ServiceException::class); - $this->migration->migrateImportantFromDb($this->client, $account, $mailbox); + $this->migration->migrateImportantFromDb($this->client, $mailbox); } } diff --git a/tests/Integration/Service/MailTransmissionIntegrationTest.php b/tests/Integration/Service/MailTransmissionIntegrationTest.php index 2f23543851..b60a4d21a8 100644 --- a/tests/Integration/Service/MailTransmissionIntegrationTest.php +++ b/tests/Integration/Service/MailTransmissionIntegrationTest.php @@ -107,7 +107,8 @@ protected function setUp(): void { $this->localMessageMapper = Server::get(LocalMessageMapper::class); $this->message = new LocalMessage(); - $this->message->setAccountId($this->account->getId()); + $account = $this->account; + $this->message->setAccountId($account->getId()); $this->message->setSubject('greetings'); $this->message->setBody('hello there'); $this->message->setType(LocalMessage::TYPE_OUTGOING); diff --git a/tests/Integration/Sieve/SieveClientFactoryTest.php b/tests/Integration/Sieve/SieveClientFactoryTest.php index 407ebefbb0..9ccfbe1df6 100644 --- a/tests/Integration/Sieve/SieveClientFactoryTest.php +++ b/tests/Integration/Sieve/SieveClientFactoryTest.php @@ -53,10 +53,7 @@ protected function setUp(): void { $this->factory = new SieveClientFactory($this->crypto, $this->config); } - /** - * @return Account - */ - private function getTestAccount() { + private function getTestAccount(): MailAccount { $mailAccount = new MailAccount(); $mailAccount->setId(123); $mailAccount->setEmail('user@domain.tld'); @@ -70,14 +67,14 @@ private function getTestAccount() { $mailAccount->setSieveSslMode(''); $mailAccount->setSieveUser(''); $mailAccount->setSievePassword(''); - return new Account($mailAccount); + return $mailAccount; } public function testClientConnectivity() { $account = $this->getTestAccount(); $this->crypto->expects($this->once()) ->method('decrypt') - ->with($account->getMailAccount()->getInboundPassword()) + ->with($account->getInboundPassword()) ->willReturn('mypassword'); $client = $this->factory->getClient($account); @@ -88,7 +85,7 @@ public function testClientInstallScript() { $account = $this->getTestAccount(); $this->crypto->expects($this->once()) ->method('decrypt') - ->with($account->getMailAccount()->getInboundPassword()) + ->with($account->getInboundPassword()) ->willReturn('mypassword'); $client = $this->factory->getClient($account); diff --git a/tests/Unit/Controller/DraftsControllerTest.php b/tests/Unit/Controller/DraftsControllerTest.php index 7e75bb728e..e61975fd60 100644 --- a/tests/Unit/Controller/DraftsControllerTest.php +++ b/tests/Unit/Controller/DraftsControllerTest.php @@ -205,7 +205,7 @@ public function testCreate(): void { $to = [['label' => 'Lewis', 'email' => 'tent@stardewvalley.com']]; $cc = [['label' => 'Pierre', 'email' => 'generalstore@stardewvalley.com']]; - $account = new Account(new MailAccount()); + $account = new MailAccount(); $this->accountService->expects(self::once()) ->method('find') ->with($this->userId, $message->getAccountId()) diff --git a/tests/Unit/Controller/MessageApiControllerTest.php b/tests/Unit/Controller/MessageApiControllerTest.php index 5f243c4fc3..2ad3e7042b 100644 --- a/tests/Unit/Controller/MessageApiControllerTest.php +++ b/tests/Unit/Controller/MessageApiControllerTest.php @@ -402,9 +402,10 @@ public function testMailboxNotFound(): void { public function testSend($messageStatus, $expected): void { $this->message->setStatus($messageStatus); + $account = $this->account; $this->accountService->expects(self::once()) ->method('find') - ->with($this->userId, $this->account->getId()) + ->with($this->userId, $account->getId()) ->willReturn($this->account); $this->aliasesService->expects(self::never()) ->method('findByAliasAndUserId'); @@ -436,9 +437,10 @@ public function testSend($messageStatus, $expected): void { public function testSendNoRecipient(): void { $this->message->setStatus(LocalMessage::STATUS_RAW); + $account = $this->account; $this->accountService->expects(self::once()) ->method('find') - ->with($this->userId, $this->account->getId()) + ->with($this->userId, $account->getId()) ->willReturn($this->account); $this->aliasesService->expects(self::never()) ->method('findByAliasAndUserId'); @@ -481,9 +483,10 @@ public function mailData() { * @dataProvider exceptionData */ public function testSendException($exception, $expected): void { + $account = $this->account; $this->accountService->expects(self::once()) ->method('find') - ->with($this->userId, $this->account->getId()) + ->with($this->userId, $account->getId()) ->willReturn($this->account); $this->aliasesService->expects(self::never()) ->method('findByAliasAndUserId'); @@ -546,9 +549,10 @@ public function testWithAttachment(): void { $localAttachment = new LocalAttachment(); $localAttachment->setId(1); + $account = $this->account; $this->accountService->expects(self::once()) ->method('find') - ->with($this->userId, $this->account->getId()) + ->with($this->userId, $account->getId()) ->willReturn($this->account); $this->aliasesService->expects(self::never()) ->method('findByAliasAndUserId'); @@ -603,9 +607,10 @@ public function testWithAttachmentError(): void { ], ]; + $account = $this->account; $this->accountService->expects(self::once()) ->method('find') - ->with($this->userId, $this->account->getId()) + ->with($this->userId, $account->getId()) ->willReturn($this->account); $this->aliasesService->expects(self::never()) ->method('findByAliasAndUserId'); @@ -686,9 +691,10 @@ public function testAlias(): void { public function testNoAlias(): void { $aliasMail = 'john-alias@test.com'; + $account = $this->account; $this->accountService->expects(self::once()) ->method('find') - ->with($this->userId, $this->account->getId()) + ->with($this->userId, $account->getId()) ->willReturn($this->account); $this->aliasesService->expects(self::once()) ->method('findByAliasAndUserId') diff --git a/tests/Unit/Migration/MigrateImportantFromImapAndDbTest.php b/tests/Unit/Migration/MigrateImportantFromImapAndDbTest.php index 5e9285fcc4..7ba8c7c85e 100644 --- a/tests/Unit/Migration/MigrateImportantFromImapAndDbTest.php +++ b/tests/Unit/Migration/MigrateImportantFromImapAndDbTest.php @@ -66,7 +66,7 @@ public function testMigrateImportantOnImap() { $this->logger->expects($this->never()) ->method('debug'); - $this->migration->migrateImportantOnImap($this->client, $account, $mailbox); + $this->migration->migrateImportantOnImap($this->client, $mailbox); } public function testMigrateImportantOnImapNoUids() { @@ -83,7 +83,7 @@ public function testMigrateImportantOnImapNoUids() { $this->logger->expects($this->never()) ->method('debug'); - $this->migration->migrateImportantOnImap($this->client, $account, $mailbox); + $this->migration->migrateImportantOnImap($this->client, $mailbox); } public function testMigrateImportantOnImapExceptionGetFlagged() { @@ -101,7 +101,7 @@ public function testMigrateImportantOnImapExceptionGetFlagged() { ->method('debug'); $this->expectException(ServiceException::class); - $this->migration->migrateImportantOnImap($this->client, $account, $mailbox); + $this->migration->migrateImportantOnImap($this->client, $mailbox); } public function testMigrateImportantOnImapExceptionOnFlag() { @@ -124,7 +124,7 @@ public function testMigrateImportantOnImapExceptionOnFlag() { ->with('Could not flag messages in mailbox <' . $mailbox->getId() . '>'); $this->expectException(ServiceException::class); - $this->migration->migrateImportantOnImap($this->client, $account, $mailbox); + $this->migration->migrateImportantOnImap($this->client, $mailbox); } public function migrateImportantFromDb() { @@ -143,7 +143,7 @@ public function migrateImportantFromDb() { $this->logger->expects($this->never()) ->method('debug'); - $this->migration->migrateImportantFromDb($this->client, $account, $mailbox); + $this->migration->migrateImportantFromDb($this->client, $mailbox); } public function testMigrateImportantFromDbNoUids() { @@ -161,7 +161,7 @@ public function testMigrateImportantFromDbNoUids() { $this->logger->expects($this->never()) ->method('debug'); - $this->migration->migrateImportantFromDb($this->client, $account, $mailbox); + $this->migration->migrateImportantFromDb($this->client, $mailbox); } public function testMigrateImportantFromDbExceptionOnFlag() { @@ -185,6 +185,6 @@ public function testMigrateImportantFromDbExceptionOnFlag() { ->with('Could not flag messages in mailbox <' . $mailbox->getId() . '>'); $this->expectException(ServiceException::class); - $this->migration->migrateImportantFromDb($this->client, $account, $mailbox); + $this->migration->migrateImportantFromDb($this->client, $mailbox); } } diff --git a/tests/Unit/Service/Attachment/AttachmentServiceTest.php b/tests/Unit/Service/Attachment/AttachmentServiceTest.php index c849985c7d..9689fd420a 100644 --- a/tests/Unit/Service/Attachment/AttachmentServiceTest.php +++ b/tests/Unit/Service/Attachment/AttachmentServiceTest.php @@ -396,7 +396,7 @@ public function testHandleAttachmentsCloudAttachmentNoDownloadPermission(): void $storage->expects(self::once()) ->method('getShare') ->willReturn($share); - + $file = $this->createConfiguredMock(File::class, [ 'getName' => 'cat.jpg', 'getMimeType' => 'text/plain',