Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tagging to messages #4665

Merged
merged 1 commit into from
Mar 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
- **🙈 We’re not reinventing the wheel!** Based on the great [Horde](http://horde.org) libraries.
- **📬 Want to host your own mail server?** We don’t have to reimplement this as you could set up [Mail-in-a-Box](https://mailinabox.email)!
]]></description>
<version>1.10.0-alpha.1</version>
<version>1.10.0-alpha.2</version>
<licence>agpl</licence>
<author>Christoph Wurst</author>
<author>Greta Doçi</author>
Expand Down
10 changes: 10 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,16 @@
'url' => '/api/messages/{id}/flags',
'verb' => 'PUT'
],
[
'name' => 'messages#setTag',
'url' => '/api/messages/{id}/tags/{imapLabel}',
'verb' => 'PUT'
],
[
'name' => 'messages#removeTag',
'url' => '/api/messages/{id}/tags/{imapLabel}',
'verb' => 'DELETE'
],
[
'name' => 'messages#move',
'url' => '/api/messages/{id}/move',
Expand Down
7 changes: 7 additions & 0 deletions lib/Account.php
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,13 @@ public function getEmail() {
return $this->account->getEmail();
}

/**
* @return string
*/
public function getUserId() {
return $this->account->getUserId();
}

/**
* @deprecated
*
Expand Down
29 changes: 25 additions & 4 deletions lib/Contracts/IMailManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@

namespace OCA\Mail\Contracts;

use OCA\Mail\Db\Tag;
use OCA\Mail\Folder;
use OCA\Mail\Account;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\Message;
use OCA\Mail\Exception\ClientException;
use OCA\Mail\Exception\ServiceException;
use OCA\Mail\Folder;
use OCA\Mail\Service\Quota;
use OCA\Mail\IMAP\FolderStats;
use OCA\Mail\Model\IMAPMessage;
use OCA\Mail\Service\Quota;
use OCA\Mail\Exception\ClientException;
use OCA\Mail\Exception\ServiceException;
use OCP\AppFramework\Db\DoesNotExistException;

interface IMailManager {
Expand Down Expand Up @@ -170,6 +171,18 @@ public function markFolderAsRead(Account $account, Mailbox $mailbox): void;
*/
public function flagMessage(Account $account, string $mailbox, int $uid, string $flag, bool $value): void;

/**
* @param Account $account
* @param string $mailbox
* @param int $uid
* @param Tag $tag
* @param bool $value
*
* @throws ClientException
* @throws ServiceException
*/
public function tagMessage(Account $account, string $mailbox, Message $message, Tag $tag, bool $value): void;

/**
* @param Account $account
*
Expand Down Expand Up @@ -229,4 +242,12 @@ public function enableMailboxBackgroundSync(Mailbox $mailbox,
* @return array
*/
public function getMailAttachments(Account $account, Mailbox $mailbox, Message $message) : array;

/**
* @param string $imapLabel
* @param string $userId
* @return Tag
* @throws DoesNotExistException
*/
public function getTagByImapLabel(string $imapLabel, string $userId): Tag;
}
67 changes: 64 additions & 3 deletions lib/Controller/MessagesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
use OCA\Mail\Exception\ServiceException;
use OCA\Mail\Http\AttachmentDownloadResponse;
use OCA\Mail\Http\HtmlResponse;
use OCA\Mail\Model\IMAPMessage;
use OCA\Mail\Service\AccountService;
use OCA\Mail\Service\ItineraryService;
use OCP\AppFramework\Controller;
Expand Down Expand Up @@ -649,6 +648,68 @@ public function setFlags(int $id, array $flags): JSONResponse {
return new JSONResponse();
}

/**
* @NoAdminRequired
* @TrapError
*
* @param int $id
* @param string $imapLabel
*
* @return JSONResponse
*
* @throws ClientException
* @throws ServiceException
*/
public function setTag(int $id, string $imapLabel): JSONResponse {
try {
$message = $this->mailManager->getMessage($this->currentUserId, $id);
$mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
$account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
} catch (DoesNotExistException $e) {
return new JSONResponse([], Http::STATUS_FORBIDDEN);
}

try {
$tag = $this->mailManager->getTagByImapLabel($imapLabel, $this->currentUserId);
} catch (DoesNotExistException $e) {
return new JSONResponse([], Http::STATUS_FORBIDDEN);
}

$this->mailManager->tagMessage($account, $mailbox->getName(), $message, $tag, true);
return new JSONResponse();
}

/**
* @NoAdminRequired
* @TrapError
*
* @param int $id
* @param string $imapLabel
*
* @return JSONResponse
*
* @throws ClientException
* @throws ServiceException
*/
public function removeTag(int $id, string $imapLabel): JSONResponse {
try {
$message = $this->mailManager->getMessage($this->currentUserId, $id);
$mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
$account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
} catch (DoesNotExistException $e) {
return new JSONResponse([], Http::STATUS_FORBIDDEN);
}

try {
$tag = $this->mailManager->getTagByImapLabel($imapLabel, $this->currentUserId);
} catch (DoesNotExistException $e) {
return new JSONResponse([], Http::STATUS_FORBIDDEN);
}

$this->mailManager->tagMessage($account, $mailbox->getName(), $message, $tag, false);
return new JSONResponse();
}

/**
* @NoAdminRequired
* @TrapError
Expand Down Expand Up @@ -705,10 +766,10 @@ private function enrichDownloadUrl(int $id,
}

/**
* @param array $attachment
*
* Determines if the content of this attachment is an image
*
* @param array $attachment
*
* @return boolean
*/
private function attachmentIsImage(array $attachment): bool {
Expand Down
9 changes: 9 additions & 0 deletions lib/Db/MailAccountMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,13 @@ public function getAllAccounts(): array {

return $this->findEntities($query);
}

public function getAllUserIdsWithAccounts(): array {
$qb = $this->db->getQueryBuilder();
$query = $qb
->selectDistinct('user_id')
->from($this->getTableName());

return $this->findEntities($query);
}
}
46 changes: 38 additions & 8 deletions lib/Db/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@ class Message extends Entity implements JsonSerializable {
'forwarded',
'junk',
'notjunk',
'important',
'mdnsent'
'mdnsent',
Tag::LABEL_IMPORTANT,
'$important' // @todo remove this when we have removed all references on IMAP to $important @link https://github.com/nextcloud/mail/issues/25
];

protected $uid;
Expand Down Expand Up @@ -125,6 +126,9 @@ class Message extends Entity implements JsonSerializable {
/** @var AddressList */
private $bcc;

/** @var Tag[] */
private $tags = [];

public function __construct() {
$this->from = new AddressList([]);
$this->to = new AddressList([]);
Expand Down Expand Up @@ -199,6 +203,20 @@ public function setTo(AddressList $to): void {
$this->to = $to;
}

/**
* @return Tag[]
*/
public function getTags(): array {
return $this->tags;
}

/**
* @param array $tags
miaulalala marked this conversation as resolved.
Show resolved Hide resolved
*/
public function setTags(array $tags): void {
$this->tags = $tags;
}

/**
* @return AddressList
*/
Expand Down Expand Up @@ -232,14 +250,26 @@ public function setFlag(string $flag, bool $value = true) {
// Ignore
return;
}

$this->setter(
$this->columnToProperty("flag_$flag"),
[$value]
);
if ($flag === Tag::LABEL_IMPORTANT) {
$this->setFlagImportant($value);
} else {
$this->setter(
$this->columnToProperty("flag_$flag"),
[$value]
);
}
}

public function jsonSerialize() {
$tags = $this->getTags();
$indexed = array_combine(
array_map(
function (Tag $tag) {
return $tag->getImapLabel();
}, $tags),
$tags
);

return [
'databaseId' => $this->getId(),
'uid' => $this->getUid(),
Expand All @@ -253,10 +283,10 @@ public function jsonSerialize() {
'draft' => $this->getFlagDraft(),
'forwarded' => $this->getFlagForwarded(),
'hasAttachments' => $this->getFlagAttachments() ?? false,
'important' => $this->getFlagImportant(),
'junk' => $this->getFlagJunk(),
'mdnsent' => $this->getFlagMdnsent(),
],
'tags' => $indexed,
'from' => $this->getFrom()->jsonSerialize(),
'to' => $this->getTo()->jsonSerialize(),
'cc' => $this->getCc()->jsonSerialize(),
Expand Down
Loading