Skip to content

Commit

Permalink
fixup! Add imip processing
Browse files Browse the repository at this point in the history
  • Loading branch information
miaulalala committed Jul 14, 2022
1 parent 51f1c8f commit b43b7fe
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 23 deletions.
6 changes: 2 additions & 4 deletions lib/BackgroundJob/IMipMessageJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,14 @@
use function method_exists;

class IMipMessageJob extends TimedJob {

/** @var IMipService */
private $iMipService;
private IMipService $iMipService;

public function __construct(ITimeFactory $time,
IMipService $iMipService) {
parent::__construct($time);

// Run once per hour
$this->setInterval(60*60);
$this->setInterval(60 * 60);
/**
* @todo remove checks with 24+
*/
Expand Down
2 changes: 1 addition & 1 deletion lib/Db/MessageMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,7 @@ public function findIMipMessages(): array {
$qb->expr()->eq('imip_message', $qb->createNamedParameter(true, IQueryBuilder::PARAM_BOOL), IQueryBuilder::PARAM_BOOL),
$qb->expr()->eq('imip_processed', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL), IQueryBuilder::PARAM_BOOL),
$qb->expr()->eq('imip_error', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL), IQueryBuilder::PARAM_BOOL),
$qb->expr()->gt('sent_at', ($this->timeFactory->getTime() - 60*60*24*14), $qb->createNamedParameter(false, IQueryBuilder::PARAM_INT)),
$qb->expr()->gt('sent_at', ($this->timeFactory->getTime() - 60 * 60 * 24 * 14), $qb->createNamedParameter(false, IQueryBuilder::PARAM_INT)),
);

return $this->findEntities($select);
Expand Down
6 changes: 3 additions & 3 deletions lib/Migration/Version1140Date20220630113356.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,19 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
$schema = $schemaClosure();

$messagesTable = $schema->getTable('mail_messages');
if(!$messagesTable->hasColumn('imip_message')) {
if (!$messagesTable->hasColumn('imip_message')) {
$messagesTable->addColumn('imip_message', 'boolean', [
'notnull' => false,
'default' => false,
]);
}
if(!$messagesTable->hasColumn('imip_processed')) {
if (!$messagesTable->hasColumn('imip_processed')) {
$messagesTable->addColumn('imip_processed', 'boolean', [
'notnull' => false,
'default' => false,
]);
}
if(!$messagesTable->hasColumn('imip_error')) {
if (!$messagesTable->hasColumn('imip_error')) {
$messagesTable->addColumn('imip_error', 'boolean', [
'notnull' => false,
'default' => false,
Expand Down
67 changes: 52 additions & 15 deletions lib/Service/IMipService.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,52 +26,57 @@

namespace OCA\Mail\Service;

use OCA\Mail\Db\MailAccountMapper;
use OCA\Mail\Account;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\MailboxMapper;
use OCA\Mail\Db\Message;
use OCA\Mail\Db\MessageMapper;
use OCA\Mail\Exception\ServiceException;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\Calendar\IManager;
use Psr\Log\LoggerInterface;

class IMipService {

private MessageMapper $messageMapper;
private MailboxMapper $mailboxMapper;
private AccountService $accountService;
private MailManager $mailManager;
private IManager $calendarManager;
private LoggerInterface $logger;

public function __construct(
MessageMapper $messageMapper,
MailboxMapper $mailboxMapper,
AccountService $accountService,
MailManager $mailManager,
IManager $manager,
LoggerInterface $logger,
) {
$this->messageMapper = $messageMapper;
$this->mailboxMapper = $mailboxMapper;
$this->accountService = $accountService;
$this->mailManager = $mailManager;
$this->calendarManager = $manager;
$this->logger = $logger;
}

public function process() {
$messages = $this->messageMapper->findIMipMessages();

// Collect all mailboxes in memory
$mailboxIds = array_unique(array_map(function (Message $message) {
return $message->getMailboxId();
}, $messages));

$mailboxes = array_combine($mailboxIds, array_map(function (int $mailboxId) {
try {
$mailbox = $this->mailboxMapper->findById($mailboxId);
if ($mailbox->getSpecialUse() === '["sent"]' || $mailbox->getSpecialUse() === '["drafts"]') {
return null;
}
return $this->mailboxMapper->findById($mailboxId);
} catch (DoesNotExistException $e) {
return null;
}
}, $mailboxIds));

// Collect all accounts in memory
$accountIds = array_unique(array_map(function (Mailbox $mailbox) {
return $mailbox->getAccountId();
}, $mailboxes));
Expand All @@ -84,25 +89,57 @@ public function process() {
}
}, $accountIds));

// build the updated messages on a per-account basis, so we can bulk update for each account
$processedMessages = [];
foreach ($messages as $message) {
/** @var Mailbox $mailbox */
$mailbox = $mailboxes[$message->getMailboxId()];
/** @var Account $account */
$account = $accounts[$mailbox->getAccountId()];
// mailbox not in collated array, maybe specal use?
// no processing for drafts and sent items
if ($mailbox->getSpecialUse() === '["sent"]' || $mailbox->getSpecialUse() === '["drafts"]') { // does this need more use cases? Also probably won't work? @todo
$message->setImipProcessed(true); // Silently drop from passing to DAV and mark as processed, so we won't run into this message again.
$processedMessages[$account->getId()] = $message;
continue;
}


foreach ($messages as $message) {
$imapMessage = $this->mailManager->getImapMessage($accounts[$message->getAccountId()], $mailboxes[$message->getMailboxId()], $message->getUid());
try {
$imapMessage = $this->mailManager->getImapMessage($account, $mailbox, $message->getUid());
} catch (ServiceException $e) {
$message->setImipError(true);
$processedMessages[$account->getId()] = $message;
continue;
}

if(empty($imapMessage->scheduling)) {
if (empty($imapMessage->scheduling)) {
// No scheduling info, maybe the DB is wrong
$message->setImipError(true);
$this->messageMapper->update($message);
$processedMessages[$account->getId()] = $message;
continue;
}

if($imapMessage->scheduling['method'] === 'REPLY' || $imapMessage->scheduling['method'] == 'CANCEL') {
// automatically process this

$message->setImipProcessed(true);
$this->messageMapper->update($message);
$principalUri = '';
$sender = $imapMessage->getFrom()->first()->getEmail();
$recipient = $account->getEmail();
$processed = false;
if ($imapMessage->scheduling['method'] === 'REPLY') {
$processed = $this->calendarManager->handleIMipReply($principalUri, $sender, $recipient, $imapMessage->scheduling['content']);
} elseif ($imapMessage->scheduling['method'] === 'CANCEL') {
$processed = $this->calendarManager->handleIMipCancel($principalUri, $sender, $recipient, $imapMessage->scheduling['content']);
}
$message->setImipProcessed($processed);
$message->setImipError(!$processed);
$processedMessages[$account->getId()] = $message;
}

foreach ($processedMessages as $accountId => $messages) {
try {
$this->messageMapper->updateBulk($accounts[$accountId], false, $messages);
} catch (\Throwable $e) {
$this->logger->error('Could not update iMip messages for account ' . $accountId, ['exception' => $e]);
}
}
}
}

0 comments on commit b43b7fe

Please sign in to comment.