refactor: Consolidate account classes

Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
This commit is contained in:
Christoph Wurst 2024-09-17 09:04:05 +02:00
Родитель b1c5609ec9
Коммит 880e2f8beb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: CC42AC2A7F0E56D8
101 изменённых файлов: 1621 добавлений и 1235 удалений

Просмотреть файл

@ -9,12 +9,9 @@ declare(strict_types=1);
*/
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 @@ class Account implements JsonSerializable {
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();
}
}

Просмотреть файл

@ -9,7 +9,6 @@ declare(strict_types=1);
namespace OCA\Mail\BackgroundJob;
use OCA\Mail\Account;
use OCA\Mail\Db\MailAccountMapper;
use OCA\Mail\Db\MailboxMapper;
@ -65,27 +64,25 @@ class MigrateImportantJob extends QueuedJob {
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 . '>.');
}

Просмотреть файл

@ -57,7 +57,7 @@ class PreviewEnhancementProcessingJob extends TimedJob {
return;
}
if (!$account->getMailAccount()->canAuthenticateImap()) {
if (!$account->canAuthenticateImap()) {
$this->logger->info('Ignoring preprocessing job for provisioned account as athentication on IMAP not possible');
return;
}

Просмотреть файл

@ -8,7 +8,6 @@ declare(strict_types=1);
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\BackgroundJob\TimedJob;
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 @@ class QuotaJob extends TimedJob {
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 @@ class QuotaJob extends TimedJob {
return;
}
if(!$account->getMailAccount()->canAuthenticateImap()) {
if(!$account->canAuthenticateImap()) {
$this->logger->debug('No authentication on IMAP possible, skipping quota job');
return;
}
@ -82,9 +81,14 @@ class QuotaJob extends TimedJob {
$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

Просмотреть файл

@ -73,7 +73,7 @@ class SyncJob extends TimedJob {
return;
}
if(!$account->getMailAccount()->canAuthenticateImap()) {
if(!$account->canAuthenticateImap()) {
$this->logger->debug('No authentication on IMAP possible, skipping background sync job');
return;
}

Просмотреть файл

@ -58,7 +58,7 @@ class TrainImportanceClassifierJob extends TimedJob {
return;
}
if(!$account->getMailAccount()->canAuthenticateImap()) {
if(!$account->canAuthenticateImap()) {
$this->logger->debug('Cron importance classifier training not possible: no authentication on IMAP possible');
return;
}

Просмотреть файл

@ -9,8 +9,8 @@ declare(strict_types=1);
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 @@ class TrashRetentionJob extends TimedJob {
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 @@ class TrashRetentionJob extends TimedJob {
'exception' => $e,
'userId' => $account->getUserId(),
'accountId' => $account->getId(),
'trashMailboxId' => $account->getMailAccount()->getTrashMailboxId(),
'trashMailboxId' => $account->getTrashMailboxId(),
]);
}
}
@ -73,8 +71,8 @@ class TrashRetentionJob extends TimedJob {
* @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;
}

Просмотреть файл

@ -9,7 +9,7 @@ declare(strict_types=1);
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 @@ class DeleteAccount extends Command {
}
$output->writeLn('<info>Found account with email: ' . $account->getEmail() . '</info>');
if (!is_null($account->getMailAccount()->getProvisioningId())) {
if (!is_null($account->getProvisioningId())) {
$output->writeLn('<error>This is a provisioned account which can not be deleted from CLI. Use the Provisioning UI instead.</error>');
return 2;
}
@ -63,7 +63,7 @@ class DeleteAccount extends Command {
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());

Просмотреть файл

@ -61,7 +61,7 @@ class DiagnoseAccount extends Command {
return 1;
}
if ($account->getMailAccount()->getInboundPassword() === null) {
if ($account->getInboundPassword() === null) {
$output->writeln('<error>No IMAP passwort set. The user might have to log into their account to set it.</error>');
}
$imapClient = $this->clientFactory->getClient($account);

Просмотреть файл

@ -1,96 +1,96 @@
<?php
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Mail\Command;
use OCA\Mail\Service\AccountService;
use OCP\Security\ICrypto;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class ExportAccount extends Command {
public const ARGUMENT_USER_ID = 'user-id';
public const ARGUMENT_OUTPUT_FORMAT = 'output';
private AccountService $accountService;
private ICrypto $crypto;
public function __construct(AccountService $service, ICrypto $crypto) {
parent::__construct();
$this->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('<info>Account ' . $account->getId() . ':</info>');
$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;
}
}
<?php

/**
 * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
 * SPDX-License-Identifier: AGPL-3.0-only
 */

namespace OCA\Mail\Command;

use OCA\Mail\Service\AccountService;
use OCP\Security\ICrypto;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class ExportAccount extends Command {
 public const ARGUMENT_USER_ID = 'user-id';
 public const ARGUMENT_OUTPUT_FORMAT = 'output';

 private AccountService $accountService;
 private ICrypto $crypto;

 public function __construct(AccountService $service, ICrypto $crypto) {
 parent::__construct();

 $this->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('<info>Account ' . $account->getId() . ':</info>');
 $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;
 }
}

Просмотреть файл

@ -0,0 +1,103 @@
<?php
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Mail\Command;
use OCA\Mail\Service\AccountService;
use OCP\Security\ICrypto;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class ExportAccount extends Command {
public const ARGUMENT_USER_ID = 'user-id';
public const ARGUMENT_OUTPUT_FORMAT = 'output';
private AccountService $accountService;
private ICrypto $crypto;
public function __construct(AccountService $service, ICrypto $crypto) {
parent::__construct();
$this->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('<info>Account ' . $account->getId() . ':</info>');
$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('<info>Account ' . $account->getId() . ':</info>');
$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;
}
}

Просмотреть файл

@ -9,7 +9,7 @@ declare(strict_types=1);
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 @@ class SyncAccount extends Command {
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

Просмотреть файл

@ -9,10 +9,10 @@ declare(strict_types=1);
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;
}

Просмотреть файл

@ -10,8 +10,8 @@ declare(strict_types=1);
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 @@ interface IMailManager {
/**
* @param Horde_Imap_Client_Socket $client
* @param Account $account
* @param string $mailbox
* @param int $uid
*
@ -81,13 +76,12 @@ interface IMailManager {
* @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 @@ interface IMailManager {
* @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 @@ interface IMailManager {
* @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 @@ interface IMailManager {
/**
* 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 @@ interface IMailManager {
* @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 @@ interface IMailManager {
* @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 @@ interface IMailManager {
*
* @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 @@ interface IMailManager {
* @throws ClientException
* @throws ServiceException
*/
public function updateSubscription(Account $account,
public function updateSubscription(MailAccount $account,
Mailbox $mailbox,
bool $subscribed): Mailbox;
@ -246,21 +226,19 @@ interface IMailManager {
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 @@ interface IMailManager {
/**
* 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 @@ interface IMailManager {
*
* @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;
}

Просмотреть файл

@ -9,7 +9,7 @@ declare(strict_types=1);
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 @@ interface IMailSearch {
* @throws ClientException
* @throws ServiceException
*/
public function findMessages(Account $account,
public function findMessages(MailAccount $account,
Mailbox $mailbox,
string $sortOrder,
?string $filter,

Просмотреть файл

@ -9,8 +9,8 @@ declare(strict_types=1);
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 @@ interface IMailTransmission {
/**
* 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;
}

Просмотреть файл

@ -35,6 +35,7 @@ use OCP\IL10N;
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 @@ class AccountsController extends Controller {
$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 @@ class AccountsController extends Controller {
?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 @@ class AccountsController extends Controller {
* @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();

Просмотреть файл

@ -142,7 +142,7 @@ class GoogleIntegrationController extends Controller {
$account,
$code,
);
$this->accountService->update($updated->getMailAccount());
$this->accountService->update($updated);
try {
$this->mailboxSync->sync($account, $this->logger);
} catch (ServiceException $e) {

Просмотреть файл

@ -140,7 +140,7 @@ class MicrosoftIntegrationController extends Controller {
$account,
$code,
);
$this->accountService->update($updated->getMailAccount());
$this->accountService->update($updated);
return new StandaloneTemplateResponse(
Application::APP_ID,

Просмотреть файл

@ -53,7 +53,7 @@ class OutOfOfficeController extends Controller {
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 @@ class OutOfOfficeController extends Controller {
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 @@ class OutOfOfficeController extends Controller {
throw new ServiceException('Missing start date');
}
$mailAccount = $account->getMailAccount();
$mailAccount = $account;
if ($mailAccount->getOutOfOfficeFollowsSystem()) {
$mailAccount->setOutOfOfficeFollowsSystem(false);
$this->accountService->update($mailAccount);

Просмотреть файл

@ -45,6 +45,7 @@ use OCP\User\IAvailabilityCoordinator;
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 @@ class PageController extends Controller {
$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 {

Просмотреть файл

@ -9,7 +9,6 @@ declare(strict_types=1);
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 @@ class MailboxMapper extends QBMapper {
}
/**
* @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 @@ class MailboxMapper extends QBMapper {
* @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('*')

Просмотреть файл

@ -9,7 +9,6 @@ declare(strict_types=1);
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 @@ class MessageMapper extends QBMapper {
}
/**
* @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 @@ class MessageMapper extends QBMapper {
* @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 @@ class MessageMapper extends QBMapper {
}
/**
* @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 @@ class MessageMapper extends QBMapper {
}
/**
* @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 @@ class MessageMapper extends QBMapper {
}
/**
* @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 @@ class MessageMapper extends QBMapper {
}
/**
* @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 @@ class MessageMapper extends QBMapper {
/**
* 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

Просмотреть файл

@ -9,22 +9,17 @@ declare(strict_types=1);
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;
}
}

Просмотреть файл

@ -9,12 +9,11 @@ declare(strict_types=1);
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;
}

Просмотреть файл

@ -9,7 +9,7 @@ declare(strict_types=1);
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 @@ use OCP\EventDispatcher\Event;
* @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;
}

Просмотреть файл

@ -9,31 +9,27 @@ declare(strict_types=1);
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;
}

Просмотреть файл

@ -9,22 +9,18 @@ declare(strict_types=1);
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;
}
}

Просмотреть файл

@ -9,30 +9,26 @@ declare(strict_types=1);
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;
}

Просмотреть файл

@ -9,14 +9,11 @@ declare(strict_types=1);
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;
}

Просмотреть файл

@ -9,24 +9,21 @@ declare(strict_types=1);
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;
}

Просмотреть файл

@ -9,14 +9,12 @@ declare(strict_types=1);
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;
}

Просмотреть файл

@ -9,7 +9,7 @@ declare(strict_types=1);
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 @@ use OCP\EventDispatcher\Event;
* @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;
}

Просмотреть файл

@ -9,31 +9,27 @@ declare(strict_types=1);
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;
}

Просмотреть файл

@ -9,13 +9,11 @@ declare(strict_types=1);
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;
}

Просмотреть файл

@ -12,7 +12,7 @@ namespace OCA\Mail\IMAP;
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 @@ class FolderMapper {
];
/**
* @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 @@ class FolderMapper {
}
public function createFolder(Horde_Imap_Client_Socket $client,
Account $account,
MailAccount $account,
string $name): Folder {
$client->createMailbox($name);

Просмотреть файл

@ -12,8 +12,8 @@ namespace OCA\Mail\IMAP;
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 @@ class IMAPClientFactory {
* 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 @@ class IMAPClientFactory {
],
],
];
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(

Просмотреть файл

@ -13,7 +13,7 @@ use Horde_Imap_Client;
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 @@ class MailboxSync {
/**
* @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 @@ class MailboxSync {
'ob_return' => true,
]);
$personalNamespace = $this->getPersonalNamespace($namespaces);
$account->getMailAccount()->setPersonalNamespace(
$account->setPersonalNamespace(
$personalNamespace
);
} catch (Horde_Imap_Client_Exception $e) {
@ -139,12 +139,11 @@ class MailboxSync {
/**
* 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 @@ class MailboxSync {
/**
* @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 @@ class MailboxSync {
$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 @@ class MailboxSync {
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());

Просмотреть файл

@ -10,7 +10,7 @@ declare(strict_types=1);
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 @@ class PreviewEnhancer {
*
* @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

Просмотреть файл

@ -11,7 +11,7 @@ namespace OCA\Mail\IMAP\Search;
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 @@ class Provider {
* @return int[]
* @throws ServiceException
*/
public function findMatches(Account $account,
public function findMatches(MailAccount $account,
Mailbox $mailbox,
SearchQuery $searchQuery): array {
$client = $this->clientFactory->getClient($account);

Просмотреть файл

@ -10,8 +10,8 @@ declare(strict_types=1);
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 @@ class GoogleIntegration {
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 @@ class GoogleIntegration {
$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 @@ class GoogleIntegration {
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 @@ class GoogleIntegration {
$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;
}

Просмотреть файл

@ -10,8 +10,8 @@ declare(strict_types=1);
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 @@ class MicrosoftIntegration {
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 @@ class MicrosoftIntegration {
$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 @@ class MicrosoftIntegration {
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 @@ class MicrosoftIntegration {
$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;
}

Просмотреть файл

@ -50,7 +50,8 @@ class AccountSynchronizedThreadUpdaterListener implements IEventListener {
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');

Просмотреть файл

@ -45,7 +45,8 @@ class AddressCollectionListener implements IEventListener {
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 @@ class AddressCollectionListener implements IEventListener {
$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,

Просмотреть файл

@ -11,7 +11,7 @@ namespace OCA\Mail\Listener;
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 @@ class DeleteDraftListener implements IEventListener {
}
/**
* @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 @@ class DeleteDraftListener implements IEventListener {
/**
* @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');
}

Просмотреть файл

@ -36,7 +36,7 @@ class FollowUpClassifierListener implements IEventListener {
}
if (!$event->getMailbox()->isSpecialUse('sent')
&& $event->getAccount()->getMailAccount()->getSentMailboxId() !== $event->getMailbox()->getId()
&& $event->getAccount()->getSentMailboxId() !== $event->getMailbox()->getId()
) {
return;
}
@ -52,7 +52,8 @@ class FollowUpClassifierListener implements IEventListener {
// 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;

Просмотреть файл

@ -51,7 +51,7 @@ class MailboxesSynchronizedSpecialMailboxesUpdater implements IEventListener {
public function handle(Event $event): void {
/** @var MailboxesSynchronizedEvent $event */
$account = $event->getAccount();
$mailAccount = $account->getMailAccount();
$mailAccount = $account;
$mailboxes = $this->indexMailboxes(
$this->mailboxMapper->findAll($account)
);

Просмотреть файл

@ -32,12 +32,12 @@ class MessageKnownSinceListener implements IEventListener {
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;
}

Просмотреть файл

@ -33,7 +33,7 @@ class MoveJunkListener implements IEventListener {
}
$account = $event->getAccount();
$mailAccount = $account->getMailAccount();
$mailAccount = $account;
$junkMailboxId = $mailAccount->getJunkMailboxId();
if ($junkMailboxId === null) {

Просмотреть файл

@ -65,7 +65,8 @@ class NewMessageClassificationListener implements IEventListener {
return;
}
if (!$this->classificationSettingsService->isClassificationEnabled($event->getAccount()->getUserId())) {
$account3 = $event->getAccount();
if (!$this->classificationSettingsService->isClassificationEnabled($account3->getUserId())) {
return;
}
@ -79,9 +80,10 @@ class NewMessageClassificationListener implements IEventListener {
$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 @@ class NewMessageClassificationListener implements IEventListener {
});
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;

Просмотреть файл

@ -43,6 +43,6 @@ class OauthTokenRefreshListener implements IEventListener {
return;
}
$this->accountService->update($updated->getMailAccount());
$this->accountService->update($updated);
}
}

Просмотреть файл

@ -61,7 +61,7 @@ class OutOfOfficeListener implements IEventListener {
$accounts = $this->accountService->findByUserId($event->getData()->getUser()->getUID());
foreach ($accounts as $account) {
if (!$account->getMailAccount()->getOutOfOfficeFollowsSystem()) {
if (!$account->getOutOfOfficeFollowsSystem()) {
continue;
}
@ -73,7 +73,7 @@ class OutOfOfficeListener implements IEventListener {
$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,

Просмотреть файл

@ -11,7 +11,6 @@ namespace OCA\Mail\Migration;
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 @@ class MigrateImportantFromImapAndDb {
$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 @@ class MigrateImportantFromImapAndDb {
}
}
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 !== []) {

Просмотреть файл

@ -9,8 +9,8 @@ declare(strict_types=1);
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 @@ class NewMessageData {
}
/**
* @param Account $account
* @param string $subject
* @param string $body
* @param string|null $to
@ -102,7 +99,7 @@ class NewMessageData {
* @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 @@ class NewMessageData {
);
}
/**
* @return Account
*/
public function getAccount(): Account {
public function getAccount(): MailAccount {
return $this->account;
}

Просмотреть файл

@ -9,7 +9,7 @@ declare(strict_types=1);
namespace OCA\Mail\Model;
use OCA\Mail\Account;
use OCA\Mail\Db\MailAccount;
use OCA\Mail\Db\Message;
/**
@ -18,18 +18,17 @@ use OCA\Mail\Db\Message;
* @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;
}

Просмотреть файл

@ -8,7 +8,7 @@ declare(strict_types=1);
*/
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 @@ class MailProvider implements IProvider {
* @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();

Просмотреть файл

@ -13,7 +13,7 @@ use Horde_Mail_Transport;
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 @@ class SmtpClientFactory {
}
/**
* @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 @@ class SmtpClientFactory {
],
],
];
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(

Просмотреть файл

@ -7,8 +7,8 @@ declare(strict_types=1);
*/
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 @@ abstract class 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);
}

Просмотреть файл

@ -7,8 +7,8 @@ declare(strict_types=1);
*/
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 @@ class AntiAbuseHandler extends AHandler {
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);

Просмотреть файл

@ -7,9 +7,9 @@ declare(strict_types=1);
*/
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 @@ class Chain {
* @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)

Просмотреть файл

@ -8,8 +8,8 @@ declare(strict_types=1);
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 @@ class CopySentMessageHandler extends AHandler {
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 @@ class CopySentMessageHandler extends AHandler {
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.

Просмотреть файл

@ -9,8 +9,8 @@ namespace OCA\Mail\Send;
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 @@ class FlagRepliedMessageHandler extends AHandler {
) {
}
public function process(Account $account, LocalMessage $localMessage): LocalMessage {
public function process(MailAccount $account, LocalMessage $localMessage): LocalMessage {
if ($localMessage->getStatus() !== LocalMessage::STATUS_PROCESSED) {
return $localMessage;
}

Просмотреть файл

@ -7,16 +7,16 @@ declare(strict_types=1);
*/
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);

Просмотреть файл

@ -7,12 +7,12 @@ declare(strict_types=1);
*/
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;
}

Просмотреть файл

@ -10,7 +10,6 @@ declare(strict_types=1);
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<string, Account[]>
* @var array<string, MailAccount[]>
*/
private array $accounts = [];
@ -56,13 +55,11 @@ class AccountService {
/**
* @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 @@ class AccountService {
/**
* @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 @@ class AccountService {
* @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 @@ class AccountService {
}
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 @@ class AccountService {
*/
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);
}

Просмотреть файл

@ -10,9 +10,9 @@ declare(strict_types=1);
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 @@ PROMPT;
$this->config = $config;
}
/**
* @param Account $account
* @param string $threadId
* @param array $messages
* @param string $currentUserId
@ -71,7 +70,7 @@ PROMPT;
*
* @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 @@ PROMPT;
/**
* @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 @@ PROMPT;
* @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 @@ PROMPT;
* @throws ServiceException
*/
public function requiresFollowUp(
Account $account,
MailAccount $account,
Mailbox $mailbox,
Message $message,
string $currentUserId,

Просмотреть файл

@ -12,9 +12,9 @@ namespace OCA\Mail\Service;
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 @@ class AntiSpamService {
}
/**
* @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 @@ class AntiSpamService {
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 @@ class AntiSpamService {
$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 @@ class AntiSpamService {
);
}
$sentMailboxId = $account->getMailAccount()->getSentMailboxId();
$sentMailboxId = $account->getSentMailboxId();
if ($sentMailboxId === null) {
$this->logger->warning("No sent mailbox exists, can't save sent message");
return;

Просмотреть файл

@ -12,12 +12,12 @@ namespace OCA\Mail\Service\Attachment;
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 @@ class AttachmentService implements IAttachmentService {
* @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 @@ class AttachmentService implements IAttachmentService {
/**
* 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 @@ class AttachmentService implements IAttachmentService {
/**
* 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 @@ class AttachmentService implements IAttachmentService {
}
/**
* @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;
}

Просмотреть файл

@ -9,7 +9,7 @@ declare(strict_types=1);
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 @@ class CompositeExtractor implements IExtractor {
];
}
public function prepare(Account $account,
public function prepare(MailAccount $account,
array $incomingMailboxes,
array $outgoingMailboxes,
array $messages): void {

Просмотреть файл

@ -9,7 +9,7 @@ declare(strict_types=1);
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;

Просмотреть файл

@ -9,7 +9,7 @@ declare(strict_types=1);
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 @@ class ImportantMessagesExtractor implements IExtractor {
$this->statisticsDao = $statisticsDao;
}
public function prepare(Account $account,
public function prepare(MailAccount $account,
array $incomingMailboxes,
array $outgoingMailboxes,
array $messages): void {

Просмотреть файл

@ -9,7 +9,7 @@ declare(strict_types=1);
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 @@ class ReadMessagesExtractor implements IExtractor {
$this->statisticsDao = $statisticsDao;
}
public function prepare(Account $account,
public function prepare(MailAccount $account,
array $incomingMailboxes,
array $outgoingMailboxes,
array $messages): void {

Просмотреть файл

@ -9,7 +9,7 @@ declare(strict_types=1);
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 @@ class RepliedMessagesExtractor implements IExtractor {
$this->statisticsDao = $statisticsDao;
}
public function prepare(Account $account,
public function prepare(MailAccount $account,
array $incomingMailboxes,
array $outgoingMailboxes,
array $messages): void {

Просмотреть файл

@ -9,7 +9,7 @@ declare(strict_types=1);
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 @@ class SentMessagesExtractor implements IExtractor {
$this->statisticsDao = $statisticsDao;
}
public function prepare(Account $account,
public function prepare(MailAccount $account,
array $incomingMailboxes,
array $outgoingMailboxes,
array $messages): void {

Просмотреть файл

@ -10,8 +10,8 @@ declare(strict_types=1);
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 @@ class ImportanceClassifier {
*
* 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 @@ class ImportanceClassifier {
}
/**
* @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 @@ class ImportanceClassifier {
}
/**
* @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 @@ class ImportanceClassifier {
/**
* 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 @@ class ImportanceClassifier {
}
/**
* @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);

Просмотреть файл

@ -9,7 +9,7 @@ declare(strict_types=1);
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 @@ class ImportanceRulesClassifier {
}
/**
* @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 {

Просмотреть файл

@ -9,10 +9,10 @@ declare(strict_types=1);
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 @@ class PersistenceService {
}
/**
* @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) {

Просмотреть файл

@ -9,9 +9,9 @@ declare(strict_types=1);
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 @@ class DkimService implements IDkimService {
$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 @@ class DkimService implements IDkimService {
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;
}
}

Просмотреть файл

@ -9,11 +9,11 @@ declare(strict_types=1);
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 @@ class DraftsService {
}
/**
* @param Account $account
* @param LocalMessage $message
* @param array<int, string[]> $to
* @param array<int, string[]> $cc
@ -91,7 +90,7 @@ class DraftsService {
* @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 @@ class DraftsService {
}
/**
* @param Account $account
* @param LocalMessage $message
* @param array<int, string[]> $to
* @param array<int, string[]> $cc
@ -133,7 +131,7 @@ class DraftsService {
* @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 @@ class DraftsService {
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 @@ class DraftsService {
* "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) {

Просмотреть файл

@ -9,7 +9,6 @@ declare(strict_types=1);
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 @@ class IMipService {
/** @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 @@ class IMipService {
// 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) {

Просмотреть файл

@ -10,7 +10,7 @@ declare(strict_types=1);
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 @@ class ItineraryService {
$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 @@ class ItineraryService {
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;
}

Просмотреть файл

@ -14,9 +14,9 @@ use Horde_Imap_Client_Exception;
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 @@ class MailManager implements IMailManager {
}
/**
* @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 @@ class MailManager implements IMailManager {
/**
* @param Horde_Imap_Client_Socket $client
* @param Account $account
* @param Mailbox $mailbox
* @param int $uid
* @param bool $loadBody
@ -177,7 +173,7 @@ class MailManager implements IMailManager {
* @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 @@ class MailManager implements IMailManager {
}
/**
* @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 @@ class MailManager implements IMailManager {
}
}
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 @@ class MailManager implements IMailManager {
/**
* @param Horde_Imap_Client_Socket $client
* @param Account $account
* @param string $mailbox
* @param int $uid
*
@ -251,7 +245,7 @@ class MailManager implements IMailManager {
* @throws ServiceException
*/
public function getSource(Horde_Imap_Client_Socket $client,
Account $account,
MailAccount $account,
string $mailbox,
int $uid): ?string {
try {
@ -268,19 +262,17 @@ class MailManager implements IMailManager {
}
/**
* @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 @@ class MailManager implements IMailManager {
* @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 @@ class MailManager implements IMailManager {
* @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 @@ class MailManager implements IMailManager {
);
try {
$trashMailboxId = $account->getMailAccount()->getTrashMailboxId();
$trashMailboxId = $account->getTrashMailboxId();
if ($trashMailboxId === null) {
throw new TrashMailboxNotSetException();
}
@ -379,7 +371,6 @@ class MailManager implements IMailManager {
}
/**
* @param Account $account
* @param string $sourceFolderId
* @param string $destFolderId
* @param int $messageId
@ -388,7 +379,7 @@ class MailManager implements IMailManager {
* @throws ServiceException
*
*/
private function moveMessageOnSameAccount(Account $account,
private function moveMessageOnSameAccount(MailAccount $account,
string $sourceFolderId,
string $destFolderId,
int $messageId): int {
@ -400,7 +391,7 @@ class MailManager implements IMailManager {
}
}
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 @@ class MailManager implements IMailManager {
}
}
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 @@ class MailManager implements IMailManager {
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 @@ class MailManager implements IMailManager {
* @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 @@ class MailManager implements IMailManager {
/**
* Tag (flag) a message on IMAP
*
* @param Account $account
* @param string $mailbox
* @param Message $message
* @param Tag $tag
@ -543,7 +533,7 @@ class MailManager implements IMailManager {
*
* @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 @@ class MailManager implements IMailManager {
}
/**
* @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 @@ class MailManager implements IMailManager {
);
}
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 @@ class MailManager implements IMailManager {
}
/**
* @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 @@ class MailManager implements IMailManager {
/**
* Clear messages in folder
*
* @param Account $account
* @param Mailbox $mailbox
*
* @throws DoesNotExistException
@ -666,10 +652,10 @@ class MailManager implements IMailManager {
* @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 @@ class MailManager implements IMailManager {
}
/**
* @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 @@ class MailManager implements IMailManager {
}
/**
* @param Account $account
* @param Mailbox $mailbox
* @param Message $message
* @param string $attachmentId
@ -721,7 +705,7 @@ class MailManager implements IMailManager {
* @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 @@ class MailManager implements IMailManager {
* @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 @@ class MailManager implements IMailManager {
/**
* 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 @@ class MailManager implements IMailManager {
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 @@ class MailManager implements IMailManager {
}
}
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 @@ class MailManager implements IMailManager {
* @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 @@ class MailManager implements IMailManager {
/**
* @return Message[]
*/
public function getByMessageId(Account $account, string $messageId): array {
public function getByMessageId(MailAccount $account, string $messageId): array {
return $this->dbMessageMapper->findByMessageId($account, $messageId);
}
}

Просмотреть файл

@ -25,11 +25,11 @@ use Horde_Mime_Headers_Subject;
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 @@ class MailTransmission implements IMailTransmission {
) {
}
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 @@ class MailTransmission implements IMailTransmission {
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 @@ class MailTransmission implements IMailTransmission {
);
}
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 @@ class MailTransmission implements IMailTransmission {
$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 @@ class MailTransmission implements IMailTransmission {
$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 @@ class MailTransmission implements IMailTransmission {
$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 @@ class MailTransmission implements IMailTransmission {
$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 @@ class MailTransmission implements IMailTransmission {
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 @@ class MailTransmission implements IMailTransmission {
true,
true,
'displayed',
$account->getMailAccount()->getOutboundHost(),
$account->getOutboundHost(),
$smtpClient,
[
'from_addr' => $account->getEMailAddress(),
'from_addr' => $account->getEmail(),
'charset' => 'UTF-8',
]
);

Просмотреть файл

@ -9,11 +9,11 @@ declare(strict_types=1);
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 @@ class OutboxService {
* @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<int, array{email: string, label?: string}> $to
* @param array<int, array{email: string, label?: string}> $cc
@ -135,7 +134,7 @@ class OutboxService {
* @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 @@ class OutboxService {
}
/**
* @param Account $account
* @param LocalMessage $message
* @param array<int, array{email: string, label?: string}> $to
* @param array<int, array{email: string, label?: string}> $cc
@ -166,7 +164,7 @@ class OutboxService {
* @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 @@ class OutboxService {
}
/**
* @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,

Просмотреть файл

@ -7,7 +7,7 @@ declare(strict_types=1);
*/
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 @@ class PreprocessingService {
$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.');

Просмотреть файл

@ -10,8 +10,8 @@ declare(strict_types=1);
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 @@ class MailSearch implements IMailSearch {
$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 @@ class MailSearch implements IMailSearch {
}
/**
* @param Account $account
* @param Mailbox $mailbox
* @param string $sortOrder
* @param string|null $filter
@ -86,7 +85,7 @@ class MailSearch implements IMailSearch {
* @throws ClientException
* @throws ServiceException
*/
public function findMessages(Account $account,
public function findMessages(MailAccount $account,
Mailbox $mailbox,
string $sortOrder,
?string $filter,
@ -152,7 +151,7 @@ class MailSearch implements IMailSearch {
*
* @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);
}

Просмотреть файл

@ -13,7 +13,6 @@ use Horde_Imap_Client_Exception;
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 @@ class SetupService {
/**
* @throws CouldNotConnectException
* @throws ServiceException
*
* @return Account
*/
public function createNewAccount(string $accountName,
string $emailAddress,
@ -77,7 +74,7 @@ class SetupService {
?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 @@ class SetupService {
}
$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 @@ class SetupService {
$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 {

Просмотреть файл

@ -63,14 +63,14 @@ class SieveService {
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;

Просмотреть файл

@ -9,8 +9,8 @@ declare(strict_types=1);
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 @@ class SnoozeService {
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 @@ class SnoozeService {
'exception' => $e,
'userId' => $account->getUserId(),
'accountId' => $account->getId(),
'snoozeMailboxId' => $account->getMailAccount()->getSnoozeMailboxId(),
'snoozeMailboxId' => $account->getSnoozeMailboxId(),
]);
}
}
@ -68,9 +66,7 @@ class SnoozeService {
/**
* @param Message $message
* @param int $unixTimestamp
* @param Account $srcAccount
* @param Mailbox $srcMailbox
* @param Account $dstAccount
* @param Mailbox $dstMailbox
*
* @return void
@ -80,9 +76,9 @@ class SnoozeService {
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 @@ class SnoozeService {
/**
* @param Message $selectedMessage
* @param int $unixTimestamp
* @param Account $srcAccount
* @param Mailbox $srcMailbox
* @param Account $dstAccount
* @param Mailbox $dstMailbox
*
* @return void
@ -158,9 +152,9 @@ class SnoozeService {
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 @@ class SnoozeService {
/**
* @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;
}

Просмотреть файл

@ -1,488 +1,486 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Mail\Service\Sync;
use Horde_Imap_Client;
use Horde_Imap_Client_Base;
use Horde_Imap_Client_Exception;
use OCA\Mail\Account;
use OCA\Mail\Contracts\IMailManager;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\MailboxMapper;
use OCA\Mail\Db\MessageMapper as DatabaseMessageMapper;
use OCA\Mail\Events\NewMessagesSynchronized;
use OCA\Mail\Events\SynchronizationEvent;
use OCA\Mail\Exception\ClientException;
use OCA\Mail\Exception\IncompleteSyncException;
use OCA\Mail\Exception\MailboxDoesNotSupportModSequencesException;
use OCA\Mail\Exception\MailboxLockedException;
use OCA\Mail\Exception\MailboxNotCachedException;
use OCA\Mail\Exception\ServiceException;
use OCA\Mail\Exception\UidValidityChangedException;
use OCA\Mail\IMAP\IMAPClientFactory;
use OCA\Mail\IMAP\MessageMapper as ImapMessageMapper;
use OCA\Mail\IMAP\Sync\Request;
use OCA\Mail\IMAP\Sync\Synchronizer;
use OCA\Mail\Model\IMAPMessage;
use OCA\Mail\Support\PerformanceLogger;
use OCP\EventDispatcher\IEventDispatcher;
use Psr\Log\LoggerInterface;
use Throwable;
use function array_chunk;
use function array_filter;
use function array_map;
use function sprintf;
class ImapToDbSynchronizer {
/** @var int */
public const MAX_NEW_MESSAGES = 5000;
/** @var DatabaseMessageMapper */
private $dbMapper;
/** @var IMAPClientFactory */
private $clientFactory;
/** @var ImapMessageMapper */
private $imapMapper;
/** @var MailboxMapper */
private $mailboxMapper;
/** @var Synchronizer */
private $synchronizer;
/** @var IEventDispatcher */
private $dispatcher;
/** @var PerformanceLogger */
private $performanceLogger;
/** @var LoggerInterface */
private $logger;
/** @var IMailManager */
private $mailManager;
public function __construct(DatabaseMessageMapper $dbMapper,
IMAPClientFactory $clientFactory,
ImapMessageMapper $imapMapper,
MailboxMapper $mailboxMapper,
Synchronizer $synchronizer,
IEventDispatcher $dispatcher,
PerformanceLogger $performanceLogger,
LoggerInterface $logger,
IMailManager $mailManager) {
$this->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;
}
}
<?php

declare(strict_types=1);

/**
 * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

namespace OCA\Mail\Service\Sync;

use Horde_Imap_Client;
use Horde_Imap_Client_Base;
use Horde_Imap_Client_Exception;
use OCA\Mail\Contracts\IMailManager;
use OCA\Mail\Db\MailAccount;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\MailboxMapper;
use OCA\Mail\Db\MessageMapper as DatabaseMessageMapper;
use OCA\Mail\Events\NewMessagesSynchronized;
use OCA\Mail\Events\SynchronizationEvent;
use OCA\Mail\Exception\ClientException;
use OCA\Mail\Exception\IncompleteSyncException;
use OCA\Mail\Exception\MailboxDoesNotSupportModSequencesException;
use OCA\Mail\Exception\MailboxLockedException;
use OCA\Mail\Exception\MailboxNotCachedException;
use OCA\Mail\Exception\ServiceException;
use OCA\Mail\Exception\UidValidityChangedException;
use OCA\Mail\IMAP\IMAPClientFactory;
use OCA\Mail\IMAP\MessageMapper as ImapMessageMapper;
use OCA\Mail\IMAP\Sync\Request;
use OCA\Mail\IMAP\Sync\Synchronizer;
use OCA\Mail\Model\IMAPMessage;
use OCA\Mail\Support\PerformanceLogger;
use OCP\EventDispatcher\IEventDispatcher;
use Psr\Log\LoggerInterface;
use Throwable;
use function array_chunk;
use function array_filter;
use function array_map;
use function sprintf;

class ImapToDbSynchronizer {
 /** @var int */
 public const MAX_NEW_MESSAGES = 5000;

 /** @var DatabaseMessageMapper */
 private $dbMapper;

 /** @var IMAPClientFactory */
 private $clientFactory;

 /** @var ImapMessageMapper */
 private $imapMapper;

 /** @var MailboxMapper */
 private $mailboxMapper;

 /** @var Synchronizer */
 private $synchronizer;

 /** @var IEventDispatcher */
 private $dispatcher;

 /** @var PerformanceLogger */
 private $performanceLogger;

 /** @var LoggerInterface */
 private $logger;

 /** @var IMailManager */
 private $mailManager;

 public function __construct(DatabaseMessageMapper $dbMapper,
 IMAPClientFactory $clientFactory,
 ImapMessageMapper $imapMapper,
 MailboxMapper $mailboxMapper,
 Synchronizer $synchronizer,
 IEventDispatcher $dispatcher,
 PerformanceLogger $performanceLogger,
 LoggerInterface $logger,
 IMailManager $mailManager) {
 $this->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;
 }
}

Просмотреть файл

@ -0,0 +1,497 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Mail\Service\Sync;
use Horde_Imap_Client;
use Horde_Imap_Client_Base;
use Horde_Imap_Client_Exception;
use OCA\Mail\Contracts\IMailManager;
use OCA\Mail\Db\MailAccount;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\MailboxMapper;
use OCA\Mail\Db\MessageMapper as DatabaseMessageMapper;
use OCA\Mail\Events\NewMessagesSynchronized;
use OCA\Mail\Events\SynchronizationEvent;
use OCA\Mail\Exception\ClientException;
use OCA\Mail\Exception\IncompleteSyncException;
use OCA\Mail\Exception\MailboxDoesNotSupportModSequencesException;
use OCA\Mail\Exception\MailboxLockedException;
use OCA\Mail\Exception\MailboxNotCachedException;
use OCA\Mail\Exception\ServiceException;
use OCA\Mail\Exception\UidValidityChangedException;
use OCA\Mail\IMAP\IMAPClientFactory;
use OCA\Mail\IMAP\MessageMapper as ImapMessageMapper;
use OCA\Mail\IMAP\Sync\Request;
use OCA\Mail\IMAP\Sync\Synchronizer;
use OCA\Mail\Model\IMAPMessage;
use OCA\Mail\Support\PerformanceLogger;
use OCP\EventDispatcher\IEventDispatcher;
use Psr\Log\LoggerInterface;
use Throwable;
use function array_chunk;
use function array_filter;
use function array_map;
use function sprintf;
class ImapToDbSynchronizer {
/** @var int */
public const MAX_NEW_MESSAGES = 5000;
/** @var DatabaseMessageMapper */
private $dbMapper;
/** @var IMAPClientFactory */
private $clientFactory;
/** @var ImapMessageMapper */
private $imapMapper;
/** @var MailboxMapper */
private $mailboxMapper;
/** @var Synchronizer */
private $synchronizer;
/** @var IEventDispatcher */
private $dispatcher;
/** @var PerformanceLogger */
private $performanceLogger;
/** @var LoggerInterface */
private $logger;
/** @var IMailManager */
private $mailManager;
public function __construct(DatabaseMessageMapper $dbMapper,
IMAPClientFactory $clientFactory,
ImapMessageMapper $imapMapper,
MailboxMapper $mailboxMapper,
Synchronizer $synchronizer,
IEventDispatcher $dispatcher,
PerformanceLogger $performanceLogger,
LoggerInterface $logger,
IMailManager $mailManager) {
$this->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;
}
}

Просмотреть файл

@ -9,8 +9,8 @@ declare(strict_types=1);
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_diff;
use function array_map;
class SyncService {
private IMAPClientFactory $clientFactory;
/** @var ImapToDbSynchronizer */
@ -74,19 +74,17 @@ class SyncService {
}
/**
* @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 @@ class SyncService {
* @throws MailboxNotCachedException
* @throws ServiceException
*/
public function syncMailbox(Account $account,
public function syncMailbox(MailAccount $account,
Mailbox $mailbox,
int $criteria,
bool $partialOnly,
@ -110,9 +108,9 @@ class SyncService {
if ($partialOnly && !$mailbox->isCached()) {
throw MailboxNotCachedException::from($mailbox);
}
$client = $this->clientFactory->getClient($account);
$this->synchronizer->sync(
$account,
$client,
@ -139,7 +137,6 @@ class SyncService {
}
/**
* @param Account $account
* @param Mailbox $mailbox
* @param int[] $knownIds
* @param SearchQuery $query
@ -148,7 +145,7 @@ class SyncService {
* @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,

Просмотреть файл

@ -7,11 +7,11 @@ declare(strict_types=1);
*/
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 @@ class TransmissionService {
}
/**
* @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 @@ class TransmissionService {
/**
* @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 @@ class TransmissionService {
* @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);

Просмотреть файл

@ -10,7 +10,7 @@ declare(strict_types=1);
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 @@ class SieveClientFactory {
}
/**
* @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())];
}
/**

Просмотреть файл

@ -58,7 +58,7 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
$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 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
$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 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
->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 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
->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 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
$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 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
$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 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
->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);
}
}

Просмотреть файл

@ -107,7 +107,8 @@ class MailTransmissionIntegrationTest extends TestCase {
$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);

Просмотреть файл

@ -53,10 +53,7 @@ class SieveClientFactoryTest extends TestCase {
$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 @@ class SieveClientFactoryTest extends TestCase {
$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 @@ class SieveClientFactoryTest extends TestCase {
$account = $this->getTestAccount();
$this->crypto->expects($this->once())
->method('decrypt')
->with($account->getMailAccount()->getInboundPassword())
->with($account->getInboundPassword())
->willReturn('mypassword');
$client = $this->factory->getClient($account);

Просмотреть файл

@ -205,7 +205,7 @@ class DraftsControllerTest extends TestCase {
$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())

Просмотреть файл

@ -402,9 +402,10 @@ class MessageApiControllerTest extends TestCase {
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 @@ class MessageApiControllerTest extends TestCase {
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 @@ class MessageApiControllerTest extends TestCase {
* @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 @@ class MessageApiControllerTest extends TestCase {
$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 @@ class MessageApiControllerTest extends TestCase {
],
];
$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 @@ class MessageApiControllerTest extends TestCase {
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')

Просмотреть файл

@ -66,7 +66,7 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
$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 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
$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 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
->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 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
->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 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
$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 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
$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 @@ class MigrateImportantFromImapAndDbTest extends TestCase {
->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);
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше