diff --git a/appinfo/info.xml b/appinfo/info.xml
index d964279f3d271a169a00dd8ee13f299ed0d6ca71..c7037f13f4cd1f29f71d80bcbfd3b41c094840b1 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -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.3.3</version>
+	<version>1.4.0</version>
 	<licence>agpl</licence>
 	<author>Christoph Wurst</author>
 	<author>Roeland Jago Douma</author>
diff --git a/img/important.svg b/img/important.svg
new file mode 100644
index 0000000000000000000000000000000000000000..026d5dfb7e10ea9aba4d89149bf6955517fd3f84
--- /dev/null
+++ b/img/important.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"><path d="M2 13h7.8a1.4 1.4 0 001.1-.6L14 8l-3.1-4.4A1.4 1.4 0 009.8 3H2l3.4 5z" stroke="#000" stroke-width="2"/></svg>
diff --git a/lib/AppInfo/BootstrapSingleton.php b/lib/AppInfo/BootstrapSingleton.php
index 1e605b7942ea37929ab32c58acfad8583b2163a3..9d074e3c4e0b15532dbb09e4475ee99373636086 100644
--- a/lib/AppInfo/BootstrapSingleton.php
+++ b/lib/AppInfo/BootstrapSingleton.php
@@ -36,6 +36,7 @@ use OCA\Mail\Events\DraftSavedEvent;
 use OCA\Mail\Events\MessageDeletedEvent;
 use OCA\Mail\Events\MessageFlaggedEvent;
 use OCA\Mail\Events\MessageSentEvent;
+use OCA\Mail\Events\NewMessagesSynchronized;
 use OCA\Mail\Events\SaveDraftEvent;
 use OCA\Mail\Http\Middleware\ErrorMiddleware;
 use OCA\Mail\Http\Middleware\ProvisioningMiddleware;
@@ -45,6 +46,7 @@ use OCA\Mail\Listener\DraftMailboxCreatorListener;
 use OCA\Mail\Listener\FlagRepliedMessageListener;
 use OCA\Mail\Listener\InteractionListener;
 use OCA\Mail\Listener\MessageCacheUpdaterListener;
+use OCA\Mail\Listener\NewMessageClassificationListener;
 use OCA\Mail\Listener\SaveSentMessageListener;
 use OCA\Mail\Listener\TrashMailboxCreatorListener;
 use OCA\Mail\Service\Attachment\AttachmentService;
@@ -135,6 +137,7 @@ class BootstrapSingleton {
 		$dispatcher->addServiceListener(MessageSentEvent::class, FlagRepliedMessageListener::class);
 		$dispatcher->addServiceListener(MessageSentEvent::class, InteractionListener::class);
 		$dispatcher->addServiceListener(MessageSentEvent::class, SaveSentMessageListener::class);
+		$dispatcher->addServiceListener(NewMessagesSynchronized::class, NewMessageClassificationListener::class);
 		$dispatcher->addServiceListener(SaveDraftEvent::class, DraftMailboxCreatorListener::class);
 	}
 }
diff --git a/lib/Db/Message.php b/lib/Db/Message.php
index e2c0bbb4bb0ea59c90b97c45527ea931e55c81bb..55e096315447aa6a2e039c1dea83f0eb40a7fbd0 100644
--- a/lib/Db/Message.php
+++ b/lib/Db/Message.php
@@ -61,6 +61,8 @@ use function in_array;
  * @method bool getStructureAnalyzed()
  * @method void setFlagAttachments(?bool $hasAttachments)
  * @method null|bool getFlagAttachments()
+ * @method void setFlagImportant(bool $important)
+ * @method bool getFlagImportant()
  * @method void setPreviewText(?string $subject)
  * @method null|string getPreviewText()
  * @method void setUpdatedAt(int $time)
@@ -76,6 +78,7 @@ class Message extends Entity implements JsonSerializable {
 		'forwarded',
 		'junk',
 		'notjunk',
+		'important',
 	];
 
 	protected $uid;
@@ -94,6 +97,7 @@ class Message extends Entity implements JsonSerializable {
 	protected $updatedAt;
 	protected $structureAnalyzed;
 	protected $flagAttachments;
+	protected $flagImportant = false;
 	protected $previewText;
 
 	/** @var AddressList */
@@ -126,6 +130,7 @@ class Message extends Entity implements JsonSerializable {
 		$this->addType('flagNotjunk', 'bool');
 		$this->addType('structureAnalyzed', 'bool');
 		$this->addType('flagAttachments', 'bool');
+		$this->addType('flagImportant', 'bool');
 		$this->addType('updatedAt', 'integer');
 	}
 
@@ -210,6 +215,7 @@ class Message extends Entity implements JsonSerializable {
 				'draft' => $this->getFlagDraft(),
 				'forwarded' => $this->getFlagForwarded(),
 				'hasAttachments' => $this->getFlagAttachments() ?? false,
+				'important' => $this->getFlagImportant(),
 			],
 			'from' => $this->getFrom()->jsonSerialize(),
 			'to' => $this->getTo()->jsonSerialize(),
diff --git a/lib/Db/MessageMapper.php b/lib/Db/MessageMapper.php
index 1e0bde2adf2c1c016901c51673453b8b2e67a2de..f45ee0d7830d6f247141dc517ce6e9605da4e353 100644
--- a/lib/Db/MessageMapper.php
+++ b/lib/Db/MessageMapper.php
@@ -104,6 +104,7 @@ class MessageMapper extends QBMapper {
 		$qb1->setValue('flag_forwarded', $qb1->createParameter('flag_forwarded'));
 		$qb1->setValue('flag_junk', $qb1->createParameter('flag_junk'));
 		$qb1->setValue('flag_notjunk', $qb1->createParameter('flag_notjunk'));
+		$qb1->setValue('flag_important', $qb1->createParameter('flag_important'));
 		$qb2 = $this->db->getQueryBuilder();
 
 		$qb2->insert('mail_recipients')
@@ -126,6 +127,7 @@ class MessageMapper extends QBMapper {
 			$qb1->setParameter('flag_forwarded', $message->getFlagForwarded(), IQueryBuilder::PARAM_BOOL);
 			$qb1->setParameter('flag_junk', $message->getFlagJunk(), IQueryBuilder::PARAM_BOOL);
 			$qb1->setParameter('flag_notjunk', $message->getFlagNotjunk(), IQueryBuilder::PARAM_BOOL);
+			$qb1->setParameter('flag_important', $message->getFlagImportant(), IQueryBuilder::PARAM_BOOL);
 
 			$qb1->execute();
 
diff --git a/lib/Events/NewMessagesSynchronized.php b/lib/Events/NewMessagesSynchronized.php
new file mode 100644
index 0000000000000000000000000000000000000000..beda723a111383165491342b9d726b6de69141d9
--- /dev/null
+++ b/lib/Events/NewMessagesSynchronized.php
@@ -0,0 +1,72 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCA\Mail\Events;
+
+use OCA\Mail\Account;
+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;
+
+	/** @var array|Message[] */
+	private $messages;
+
+	/**
+	 * @param Account $account
+	 * @param Mailbox $mailbox
+	 * @param Message[] $messages
+	 */
+	public function __construct(Account $account,
+								Mailbox $mailbox,
+								array $messages) {
+		parent::__construct();
+		$this->account = $account;
+		$this->mailbox = $mailbox;
+		$this->messages = $messages;
+	}
+
+	public function getAccount(): Account {
+		return $this->account;
+	}
+
+	public function getMailbox(): Mailbox {
+		return $this->mailbox;
+	}
+
+	/**
+	 * @return Message[]
+	 */
+	public function getMessages() {
+		return $this->messages;
+	}
+}
diff --git a/lib/Listener/NewMessageClassificationListener.php b/lib/Listener/NewMessageClassificationListener.php
new file mode 100644
index 0000000000000000000000000000000000000000..1605a60b2693247b5c5849cb12c83711ba74419f
--- /dev/null
+++ b/lib/Listener/NewMessageClassificationListener.php
@@ -0,0 +1,53 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCA\Mail\Listener;
+
+use OCA\Mail\Events\NewMessagesSynchronized;
+use OCA\Mail\Service\Classification\MessageClassifier;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+
+class NewMessageClassificationListener implements IEventListener {
+
+	/** @var MessageClassifier */
+	private $classifier;
+
+	public function __construct(MessageClassifier $classifier) {
+		$this->classifier = $classifier;
+	}
+
+	public function handle(Event $event): void {
+		if (!($event instanceof NewMessagesSynchronized)) {
+			return;
+		}
+
+		foreach ($event->getMessages() as $message) {
+			if ($this->classifier->isImportant($event->getAccount(), $event->getMailbox(), $message)) {
+				$message->setFlagImportant(true);
+			}
+		}
+	}
+}
diff --git a/lib/Migration/Version1040Date20200422130220.php b/lib/Migration/Version1040Date20200422130220.php
new file mode 100644
index 0000000000000000000000000000000000000000..17377e460292bee65a89a621bac3716553b629f0
--- /dev/null
+++ b/lib/Migration/Version1040Date20200422130220.php
@@ -0,0 +1,55 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OCA\Mail\Migration;
+
+use Closure;
+use OCP\DB\ISchemaWrapper;
+use OCP\IDBConnection;
+use OCP\Migration\IOutput;
+use OCP\Migration\SimpleMigrationStep;
+
+class Version1040Date20200422130220 extends SimpleMigrationStep {
+
+	/** @var IDBConnection */
+	protected $connection;
+
+	public function __construct(IDBConnection $connection) {
+		$this->connection = $connection;
+	}
+
+	/**
+	 * @param IOutput $output
+	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+	 * @param array $options
+	 *
+	 * @return ISchemaWrapper
+	 */
+	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ISchemaWrapper {
+		/** @var ISchemaWrapper $schema */
+		$schema = $schemaClosure();
+
+		$schema->dropTable('mail_messages');
+
+		return $schema;
+	}
+
+	public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
+		// Reset locks and sync tokens
+		$qb1 = $this->connection->getQueryBuilder();
+		$updateMailboxes = $qb1->update('mail_mailboxes')
+			->set('sync_new_lock', $qb1->createNamedParameter(null))
+			->set('sync_new_token', $qb1->createNamedParameter(null))
+			->set('sync_changed_lock', $qb1->createNamedParameter(null))
+			->set('sync_changed_token', $qb1->createNamedParameter(null))
+			->set('sync_vanished_lock', $qb1->createNamedParameter(null))
+			->set('sync_vanished_token', $qb1->createNamedParameter(null));
+		$updateMailboxes->execute();
+
+		// Clean up some orphaned data
+		$qb2 = $this->connection->getQueryBuilder();
+		$deleteRecipients = $qb2->delete('mail_recipients');
+		$deleteRecipients->execute();
+	}
+}
diff --git a/lib/Migration/Version1040Date20200422142920.php b/lib/Migration/Version1040Date20200422142920.php
new file mode 100644
index 0000000000000000000000000000000000000000..ee8a39be4dfa16c37c08539470150a7bfeffd886
--- /dev/null
+++ b/lib/Migration/Version1040Date20200422142920.php
@@ -0,0 +1,116 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OCA\Mail\Migration;
+
+use Closure;
+use OCP\DB\ISchemaWrapper;
+use OCP\Migration\IOutput;
+use OCP\Migration\SimpleMigrationStep;
+
+class Version1040Date20200422142920 extends SimpleMigrationStep {
+
+	/**
+	 * @param IOutput $output
+	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+	 * @param array $options
+	 *
+	 * @return null|ISchemaWrapper
+	 */
+	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
+		/** @var ISchemaWrapper $schema */
+		$schema = $schemaClosure();
+
+		$messagesTable = $schema->createTable('mail_messages');
+		$messagesTable->addColumn('id', 'integer', [
+			'autoincrement' => true,
+			'notnull' => true,
+			'length' => 20,
+		]);
+		$messagesTable->addColumn('uid', 'integer', [
+			'notnull' => true,
+			'length' => 4,
+		]);
+		$messagesTable->addColumn('message_id', 'string', [
+			'notnull' => false,
+			'length' => 255,
+		]);
+		$messagesTable->addColumn('mailbox_id', 'integer', [
+			'notnull' => true,
+			'length' => 20,
+		]);
+		$messagesTable->addColumn('subject', 'string', [
+			'notnull' => true,
+			'length' => 255,
+			'default' => '',
+		]);
+		$messagesTable->addColumn('sent_at', 'integer', [
+			'notnull' => true,
+			'length' => 4,
+		]);
+		$messagesTable->addColumn('flag_answered', 'boolean', [
+			'notnull' => true,
+			'default' => false,
+		]);
+		$messagesTable->addColumn('flag_deleted', 'boolean', [
+			'notnull' => true,
+			'default' => false,
+		]);
+		$messagesTable->addColumn('flag_draft', 'boolean', [
+			'notnull' => true,
+			'default' => false,
+		]);
+		$messagesTable->addColumn('flag_flagged', 'boolean', [
+			'notnull' => true,
+			'default' => false,
+		]);
+		$messagesTable->addColumn('flag_seen', 'boolean', [
+			'notnull' => true,
+			'default' => false,
+		]);
+		$messagesTable->addColumn('flag_forwarded', 'boolean', [
+			'notnull' => true,
+			'default' => false,
+		]);
+		$messagesTable->addColumn('flag_junk', 'boolean', [
+			'notnull' => true,
+			'default' => false,
+		]);
+		$messagesTable->addColumn('flag_notjunk', 'boolean', [
+			'notnull' => true,
+			'default' => false,
+		]);
+		$messagesTable->addColumn('flag_attachments', 'boolean', [
+			'notnull' => false,
+		]);
+		$messagesTable->addColumn('flag_important', 'boolean', [
+			'notnull' => true,
+			'default' => false,
+		]);
+		$messagesTable->addColumn('structure_analyzed', 'boolean', [
+			'notnull' => true,
+			'default' => false,
+		]);
+		$messagesTable->addColumn('preview_text', 'string', [
+			'notnull' => false,
+			'length' => 255,
+		]);
+		$messagesTable->addColumn('updated_at', 'integer', [
+			'notnull' => false,
+			'length' => 4,
+		]);
+		$messagesTable->setPrimaryKey(['id']);
+		// We allow each UID just once
+		$messagesTable->addUniqueIndex(
+			[
+				'uid',
+				'mailbox_id',
+			],
+			'mail_msg_mb_uid_idx'
+		);
+		$messagesTable->addIndex(['sent_at'], 'mail_msg_sent_idx');
+
+		return $schema;
+	}
+}
diff --git a/lib/Model/IMAPMessage.php b/lib/Model/IMAPMessage.php
index 3b7be1060692c78c73cf634f54e1a3d89f8690cb..3e055f2ccccf8a6f640fa7338c02b441d8b41db1 100644
--- a/lib/Model/IMAPMessage.php
+++ b/lib/Model/IMAPMessage.php
@@ -646,6 +646,7 @@ class IMAPMessage implements IMessage, JsonSerializable {
 		$msg->setFlagForwarded(in_array(Horde_Imap_Client::FLAG_FORWARDED, $flags, true));
 		$msg->setFlagJunk(in_array(Horde_Imap_Client::FLAG_JUNK, $flags, true));
 		$msg->setFlagNotjunk(in_array(Horde_Imap_Client::FLAG_NOTJUNK, $flags, true));
+		$msg->setFlagImportant(false);
 		$msg->setFlagAttachments(false);
 
 		return $msg;
diff --git a/lib/Service/Classification/AClassifier.php b/lib/Service/Classification/AClassifier.php
new file mode 100644
index 0000000000000000000000000000000000000000..a9d4ec50889f61b6e0c7525ec3028ac4c1fb2f5d
--- /dev/null
+++ b/lib/Service/Classification/AClassifier.php
@@ -0,0 +1,53 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCA\Mail\Service\Classification;
+
+use OCA\Mail\Account;
+use OCA\Mail\Db\Mailbox;
+use OCA\Mail\Db\Message;
+
+abstract class AClassifier {
+	abstract public function isImportant(Account $account, Mailbox $mailbox, Message $message): bool;
+
+	final public function or(AClassifier $next): AClassifier {
+		return new class($this, $next) extends AClassifier {
+			/** @var AClassifier */
+			private $outer;
+
+			/** @var AClassifier */
+			private $next;
+
+			public function __construct(AClassifier $outer, AClassifier $next) {
+				$this->outer = $outer;
+				$this->next = $next;
+			}
+
+			public function isImportant(Account $account, Mailbox $mailbox, Message $message): bool {
+				return $this->outer->isImportant($account, $mailbox, $message) || $this->next->isImportant($account, $mailbox, $message);
+			}
+		};
+	}
+}
diff --git a/lib/Service/Classification/MessageClassifier.php b/lib/Service/Classification/MessageClassifier.php
new file mode 100644
index 0000000000000000000000000000000000000000..8efe202abc26272169c9bf31e9ae8e35e2c5fb0c
--- /dev/null
+++ b/lib/Service/Classification/MessageClassifier.php
@@ -0,0 +1,65 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCA\Mail\Service\Classification;
+
+use OCA\Mail\Account;
+use OCA\Mail\Db\Mailbox;
+use OCA\Mail\Db\Message;
+
+class MessageClassifier {
+
+	/** @var AClassifier */
+	private $oftenImportantSenderClassifier;
+
+	/** @var AClassifier */
+	private $oftenContactedSenderClassifier;
+
+	/** @var AClassifier */
+	private $oftenReadSenderClassifier;
+
+	/** @var AClassifier */
+	private $oftenRepliedSenderClassifier;
+
+	public function __construct(OftenImportantSenderClassifier $oftenImportantSenderClassifier,
+								OftenContactedSenderClassifier $oftenContactedSenderClassifier,
+								OftenReadSenderClassifier $oftenReadSenderClassifier,
+								OftenRepliedSenderClassifier $oftenRepliedSenderClassifier) {
+		$this->oftenImportantSenderClassifier = $oftenImportantSenderClassifier;
+		$this->oftenContactedSenderClassifier = $oftenContactedSenderClassifier;
+		$this->oftenReadSenderClassifier = $oftenReadSenderClassifier;
+		$this->oftenRepliedSenderClassifier = $oftenRepliedSenderClassifier;
+	}
+
+	public function isImportant(Account $account,
+								Mailbox $mailbox,
+								Message $message): bool {
+		return $this->oftenImportantSenderClassifier
+			->or($this->oftenContactedSenderClassifier)
+			->or($this->oftenReadSenderClassifier)
+			->or($this->oftenRepliedSenderClassifier)
+			->isImportant($account, $mailbox, $message);
+	}
+}
diff --git a/lib/Service/Classification/OftenContactedSenderClassifier.php b/lib/Service/Classification/OftenContactedSenderClassifier.php
new file mode 100644
index 0000000000000000000000000000000000000000..fd54124e9478d98143466e97248f34ff16e18410
--- /dev/null
+++ b/lib/Service/Classification/OftenContactedSenderClassifier.php
@@ -0,0 +1,102 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCA\Mail\Service\Classification;
+
+use OCA\Mail\Account;
+use OCA\Mail\Address;
+use OCA\Mail\Db\Mailbox;
+use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Db\Message;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+class OftenContactedSenderClassifier extends AClassifier {
+	use SafeRatio;
+
+	/** @var MailboxMapper */
+	private $mailboxMapper;
+
+	/** @var IDBConnection */
+	private $db;
+
+	public function __construct(MailboxMapper $mailboxMapper,
+								IDBConnection $db) {
+		$this->mailboxMapper = $mailboxMapper;
+		$this->db = $db;
+	}
+
+	public function isImportant(Account $account, Mailbox $mailbox, Message $message): bool {
+		$sender = $message->getTo()->first();
+		if ($sender === null) {
+			return false;
+		}
+
+		try {
+			$mb = $this->mailboxMapper->findSpecial($account, 'sent');
+		} catch (DoesNotExistException $e) {
+			return false;
+		}
+
+		return $this->greater(
+			$this->getMessagesSentTo($mb, $sender->getEmail()),
+			$this->getMessagesSentTotal($mb),
+			0.1,
+			true // The very first message is important
+		);
+	}
+
+	private function getMessagesSentTotal(Mailbox $mb): int {
+		$qb = $this->db->getQueryBuilder();
+
+		$select = $qb->select($qb->func()->count('*'))
+			->from('mail_recipients', 'r')
+			->join('r', 'mail_messages', 'm', $qb->expr()->eq('m.id', 'r.message_id'))
+			->join('r', 'mail_mailboxes', 'mb', $qb->expr()->eq('mb.id', 'm.mailbox_id'))
+			->where($qb->expr()->eq('r.id', $qb->createNamedParameter(Address::TYPE_FROM), IQueryBuilder::PARAM_INT))
+			->andWhere($qb->expr()->eq('mb.id', $qb->createNamedParameter($mb->getId(), IQueryBuilder::PARAM_INT)));
+		$result = $select->execute();
+		$cnt = $result->fetchColumn();
+		$result->closeCursor();
+		return (int)$cnt;
+	}
+
+	private function getMessagesSentTo(Mailbox $mb, string $email): int {
+		$qb = $this->db->getQueryBuilder();
+
+		$select = $qb->select($qb->func()->count('*'))
+			->from('mail_recipients', 'r')
+			->join('r', 'mail_messages', 'm', $qb->expr()->eq('m.id', 'r.message_id', IQueryBuilder::PARAM_INT))
+			->join('r', 'mail_mailboxes', 'mb', $qb->expr()->eq('mb.id', $qb->expr()->castColumn('m.mailbox_id', IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT))
+			->where($qb->expr()->eq('r.id', $qb->createNamedParameter(Address::TYPE_FROM), IQueryBuilder::PARAM_INT))
+			->andWhere($qb->expr()->eq('r.email', $qb->createNamedParameter($email)))
+			->andWhere($qb->expr()->eq('mb.id', $qb->createNamedParameter($mb->getId(), IQueryBuilder::PARAM_INT)));
+		$result = $select->execute();
+		$cnt = $result->fetchColumn();
+		$result->closeCursor();
+		return (int)$cnt;
+	}
+}
diff --git a/lib/Service/Classification/OftenImportantSenderClassifier.php b/lib/Service/Classification/OftenImportantSenderClassifier.php
new file mode 100644
index 0000000000000000000000000000000000000000..fb95cda04b21ba953d8a7242c53123b04d8e04bd
--- /dev/null
+++ b/lib/Service/Classification/OftenImportantSenderClassifier.php
@@ -0,0 +1,103 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCA\Mail\Service\Classification;
+
+use OCA\Mail\Account;
+use OCA\Mail\Address;
+use OCA\Mail\Db\Mailbox;
+use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Db\Message;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+class OftenImportantSenderClassifier extends AClassifier {
+	use SafeRatio;
+
+	/** @var MailboxMapper */
+	private $mailboxMapper;
+
+	/** @var IDBConnection */
+	private $db;
+
+	public function __construct(MailboxMapper $mailboxMapper,
+								IDBConnection $db) {
+		$this->mailboxMapper = $mailboxMapper;
+		$this->db = $db;
+	}
+
+	public function isImportant(Account $account, Mailbox $mailbox, Message $message): bool {
+		$sender = $message->getTo()->first();
+		if ($sender === null) {
+			return false;
+		}
+
+		try {
+			$mb = $this->mailboxMapper->findSpecial($account, 'inbox');
+		} catch (DoesNotExistException $e) {
+			return false;
+		}
+
+		return $this->greater(
+			$this->getNrOfImportantMessages($mb, $sender->getEmail()),
+			$this->getNumberOfMessages($mb, $sender->getEmail()),
+			0.3
+		);
+	}
+
+	private function getNrOfImportantMessages(Mailbox $mb, string $email): int {
+		$qb = $this->db->getQueryBuilder();
+
+		$select = $qb->select($qb->func()->count('*'))
+			->from('mail_recipients', 'r')
+			->join('r', 'mail_messages', 'm', $qb->expr()->eq('m.id', 'r.message_id', IQueryBuilder::PARAM_INT))
+			->join('r', 'mail_mailboxes', 'mb', $qb->expr()->eq('mb.id', $qb->expr()->castColumn('m.mailbox_id', IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT))
+			->where($qb->expr()->eq('r.type', $qb->createNamedParameter(Address::TYPE_FROM), IQueryBuilder::PARAM_INT))
+			->andWhere($qb->expr()->eq('mb.id', $qb->createNamedParameter($mb->getId(), IQueryBuilder::PARAM_INT)))
+			->andWhere($qb->expr()->eq('m.flag_important', $qb->createNamedParameter(true, IQueryBuilder::PARAM_BOOL)))
+			->andWhere($qb->expr()->eq('r.email', $qb->createNamedParameter($email)));
+		$result = $select->execute();
+		$cnt = $result->fetchColumn();
+		$result->closeCursor();
+		return (int)$cnt;
+	}
+
+	private function getNumberOfMessages(Mailbox $mb, string $email): int {
+		$qb = $this->db->getQueryBuilder();
+
+		$select = $qb->select($qb->func()->count('*'))
+			->from('mail_recipients', 'r')
+			->join('r', 'mail_messages', 'm', $qb->expr()->eq('m.id', 'r.message_id', IQueryBuilder::PARAM_INT))
+			->join('r', 'mail_mailboxes', 'mb', $qb->expr()->eq('mb.id', $qb->expr()->castColumn('m.mailbox_id', IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT))
+			->where($qb->expr()->eq('r.type', $qb->createNamedParameter(Address::TYPE_FROM), IQueryBuilder::PARAM_INT))
+			->andWhere($qb->expr()->eq('mb.id', $qb->createNamedParameter($mb->getId(), IQueryBuilder::PARAM_INT)))
+			->andWhere($qb->expr()->eq('r.email', $qb->createNamedParameter($email)));
+		$result = $select->execute();
+		$cnt = $result->fetchColumn();
+		$result->closeCursor();
+		return (int)$cnt;
+	}
+}
diff --git a/lib/Service/Classification/OftenReadSenderClassifier.php b/lib/Service/Classification/OftenReadSenderClassifier.php
new file mode 100644
index 0000000000000000000000000000000000000000..7eaf86e5766d044921b3136c71461d0c8a0119bf
--- /dev/null
+++ b/lib/Service/Classification/OftenReadSenderClassifier.php
@@ -0,0 +1,103 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCA\Mail\Service\Classification;
+
+use OCA\Mail\Account;
+use OCA\Mail\Address;
+use OCA\Mail\Db\Mailbox;
+use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Db\Message;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+class OftenReadSenderClassifier extends AClassifier {
+	use SafeRatio;
+
+	/** @var MailboxMapper */
+	private $mailboxMapper;
+
+	/** @var IDBConnection */
+	private $db;
+
+	public function __construct(MailboxMapper $mailboxMapper,
+								IDBConnection $db) {
+		$this->mailboxMapper = $mailboxMapper;
+		$this->db = $db;
+	}
+
+	public function isImportant(Account $account, Mailbox $mailbox, Message $message): bool {
+		$sender = $message->getTo()->first();
+		if ($sender === null) {
+			return false;
+		}
+
+		try {
+			$mb = $this->mailboxMapper->findSpecial($account, 'inbox');
+		} catch (DoesNotExistException $e) {
+			return false;
+		}
+
+		return $this->greater(
+			$this->getNrOfReadMessages($mb, $sender->getEmail()),
+			$this->getNumberOfMessages($mb, $sender->getEmail()),
+			0.9
+		);
+	}
+
+	private function getNrOfReadMessages(Mailbox $mb, string $email): int {
+		$qb = $this->db->getQueryBuilder();
+
+		$select = $qb->select($qb->func()->count('*'))
+			->from('mail_recipients', 'r')
+			->join('r', 'mail_messages', 'm', $qb->expr()->eq('m.id', 'r.message_id', IQueryBuilder::PARAM_INT))
+			->join('r', 'mail_mailboxes', 'mb', $qb->expr()->eq('mb.id', $qb->expr()->castColumn('m.mailbox_id', IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT))
+			->where($qb->expr()->eq('r.type', $qb->createNamedParameter(Address::TYPE_FROM), IQueryBuilder::PARAM_INT))
+			->andWhere($qb->expr()->eq('mb.id', $qb->createNamedParameter($mb->getId(), IQueryBuilder::PARAM_INT)))
+			->andWhere($qb->expr()->eq('m.flag_seen', $qb->createNamedParameter(true, IQueryBuilder::PARAM_BOOL)))
+			->andWhere($qb->expr()->eq('r.email', $qb->createNamedParameter($email)));
+		$result = $select->execute();
+		$cnt = $result->fetchColumn();
+		$result->closeCursor();
+		return (int)$cnt;
+	}
+
+	private function getNumberOfMessages(Mailbox $mb, string $email): int {
+		$qb = $this->db->getQueryBuilder();
+
+		$select = $qb->select($qb->func()->count('*'))
+			->from('mail_recipients', 'r')
+			->join('r', 'mail_messages', 'm', $qb->expr()->eq('m.id', 'r.message_id', IQueryBuilder::PARAM_INT))
+			->join('r', 'mail_mailboxes', 'mb', $qb->expr()->eq('mb.id', $qb->expr()->castColumn('m.mailbox_id', IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT))
+			->where($qb->expr()->eq('r.type', $qb->createNamedParameter(Address::TYPE_FROM), IQueryBuilder::PARAM_INT))
+			->andWhere($qb->expr()->eq('mb.id', $qb->createNamedParameter($mb->getId(), IQueryBuilder::PARAM_INT)))
+			->andWhere($qb->expr()->eq('r.email', $qb->createNamedParameter($email)));
+		$result = $select->execute();
+		$cnt = $result->fetchColumn();
+		$result->closeCursor();
+		return (int)$cnt;
+	}
+}
diff --git a/lib/Service/Classification/OftenRepliedSenderClassifier.php b/lib/Service/Classification/OftenRepliedSenderClassifier.php
new file mode 100644
index 0000000000000000000000000000000000000000..2f3f8692703cb4517e09bfe34ab229414ec365b9
--- /dev/null
+++ b/lib/Service/Classification/OftenRepliedSenderClassifier.php
@@ -0,0 +1,103 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCA\Mail\Service\Classification;
+
+use OCA\Mail\Account;
+use OCA\Mail\Address;
+use OCA\Mail\Db\Mailbox;
+use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Db\Message;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+class OftenRepliedSenderClassifier extends AClassifier {
+	use SafeRatio;
+
+	/** @var MailboxMapper */
+	private $mailboxMapper;
+
+	/** @var IDBConnection */
+	private $db;
+
+	public function __construct(MailboxMapper $mailboxMapper,
+								IDBConnection $db) {
+		$this->mailboxMapper = $mailboxMapper;
+		$this->db = $db;
+	}
+
+	public function isImportant(Account $account, Mailbox $mailbox, Message $message): bool {
+		$sender = $message->getTo()->first();
+		if ($sender === null) {
+			return false;
+		}
+
+		try {
+			$mb = $this->mailboxMapper->findSpecial($account, 'inbox');
+		} catch (DoesNotExistException $e) {
+			return false;
+		}
+
+		return $this->greater(
+			$this->getNrOfRepliedMessages($mb, $sender->getEmail()),
+			$this->getNumberOfMessages($mb, $sender->getEmail()),
+			0.1
+		);
+	}
+
+	private function getNrOfRepliedMessages(Mailbox $mb, string $email): int {
+		$qb = $this->db->getQueryBuilder();
+
+		$select = $qb->select($qb->func()->count('*'))
+			->from('mail_recipients', 'r')
+			->join('r', 'mail_messages', 'm', $qb->expr()->eq('m.id', 'r.message_id', IQueryBuilder::PARAM_INT))
+			->join('r', 'mail_mailboxes', 'mb', $qb->expr()->eq('mb.id', $qb->expr()->castColumn('m.mailbox_id', IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT))
+			->where($qb->expr()->eq('r.type', $qb->createNamedParameter(Address::TYPE_FROM), IQueryBuilder::PARAM_INT))
+			->andWhere($qb->expr()->eq('mb.id', $qb->createNamedParameter($mb->getId(), IQueryBuilder::PARAM_INT)))
+			->andWhere($qb->expr()->eq('m.flag_answered', $qb->createNamedParameter(true, IQueryBuilder::PARAM_BOOL)))
+			->andWhere($qb->expr()->eq('r.email', $qb->createNamedParameter($email)));
+		$result = $select->execute();
+		$cnt = $result->fetchColumn();
+		$result->closeCursor();
+		return (int)$cnt;
+	}
+
+	private function getNumberOfMessages(Mailbox $mb, string $email): int {
+		$qb = $this->db->getQueryBuilder();
+
+		$select = $qb->select($qb->func()->count('*'))
+			->from('mail_recipients', 'r')
+			->join('r', 'mail_messages', 'm', $qb->expr()->eq('m.id', 'r.message_id', IQueryBuilder::PARAM_INT))
+			->join('r', 'mail_mailboxes', 'mb', $qb->expr()->eq('mb.id', $qb->expr()->castColumn('m.mailbox_id', IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT))
+			->where($qb->expr()->eq('r.type', $qb->createNamedParameter(Address::TYPE_FROM), IQueryBuilder::PARAM_INT))
+			->andWhere($qb->expr()->eq('mb.id', $qb->createNamedParameter($mb->getId(), IQueryBuilder::PARAM_INT)))
+			->andWhere($qb->expr()->eq('r.email', $qb->createNamedParameter($email)));
+		$result = $select->execute();
+		$cnt = $result->fetchColumn();
+		$result->closeCursor();
+		return (int)$cnt;
+	}
+}
diff --git a/lib/Service/Classification/SafeRatio.php b/lib/Service/Classification/SafeRatio.php
new file mode 100644
index 0000000000000000000000000000000000000000..f3fdf3df02eb011e83f3f7fd9131a76fc3514268
--- /dev/null
+++ b/lib/Service/Classification/SafeRatio.php
@@ -0,0 +1,38 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCA\Mail\Service\Classification;
+
+trait SafeRatio {
+	protected function greater(int $num,
+							   int $of,
+							   float $threshold,
+							   bool $default = false): bool {
+		if ($of === 0) {
+			return $default;
+		}
+		return $num / $of > $threshold;
+	}
+}
diff --git a/lib/Service/Sync/ImapToDbSynchronizer.php b/lib/Service/Sync/ImapToDbSynchronizer.php
index c0f19e96a86a0d4def19ad37ce3fd9a973ea2508..4378270c6e735b8d4026c5e7f8b7b586a77d032f 100644
--- a/lib/Service/Sync/ImapToDbSynchronizer.php
+++ b/lib/Service/Sync/ImapToDbSynchronizer.php
@@ -31,6 +31,7 @@ use OCA\Mail\Account;
 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\Exception\ClientException;
 use OCA\Mail\Exception\IncompleteSyncException;
 use OCA\Mail\Exception\MailboxLockedException;
@@ -43,6 +44,7 @@ use OCA\Mail\IMAP\Sync\Synchronizer;
 use OCA\mail\lib\Exception\UidValidityChangedException;
 use OCA\Mail\Model\IMAPMessage;
 use OCA\Mail\Support\PerformanceLogger;
+use OCP\EventDispatcher\IEventDispatcher;
 use OCP\ILogger;
 use Throwable;
 use function array_chunk;
@@ -71,6 +73,9 @@ class ImapToDbSynchronizer {
 	/** @var Synchronizer */
 	private $synchronizer;
 
+	/** @var IEventDispatcher */
+	private $dispatcher;
+
 	/** @var PerformanceLogger */
 	private $performanceLogger;
 
@@ -83,6 +88,7 @@ class ImapToDbSynchronizer {
 								MailboxMapper $mailboxMapper,
 								DatabaseMessageMapper $messageMapper,
 								Synchronizer $synchronizer,
+								IEventDispatcher $dispatcher,
 								PerformanceLogger $performanceLogger,
 								ILogger $logger) {
 		$this->dbMapper = $dbMapper;
@@ -91,6 +97,7 @@ class ImapToDbSynchronizer {
 		$this->mailboxMapper = $mailboxMapper;
 		$this->messageMapper = $messageMapper;
 		$this->synchronizer = $synchronizer;
+		$this->dispatcher = $dispatcher;
 		$this->performanceLogger = $performanceLogger;
 		$this->logger = $logger;
 	}
@@ -275,9 +282,17 @@ class ImapToDbSynchronizer {
 			$perf->step('get new messages via Horde');
 
 			foreach (array_chunk($response->getNewMessages(), 500) as $chunk) {
-				$this->dbMapper->insertBulk(...array_map(function (IMAPMessage $imapMessage) use ($mailbox) {
+				$dbMessages = array_map(function (IMAPMessage $imapMessage) use ($mailbox) {
 					return $imapMessage->toDbMessage($mailbox->getId());
-				}, $chunk));
+				}, $chunk);
+
+				$this->dispatcher->dispatch(
+					NewMessagesSynchronized::class,
+					new NewMessagesSynchronized($account, $mailbox, $dbMessages)
+				);
+				$perf->step('classified a chunk of new messages');
+
+				$this->dbMapper->insertBulk(...$dbMessages);
 			}
 			$perf->step('persist new messages');
 
diff --git a/package-lock.json b/package-lock.json
index 6b32d9bcc865c38169543d718409c6d13c165218..ade7787f67209b079d59a8b9da015504761146d4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11360,6 +11360,12 @@
         "simple-concat": "^1.0.0"
       }
     },
+    "simple-html-tokenizer": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.1.1.tgz",
+      "integrity": "sha1-BcLuxXn//+FFoDCsJs/qYbmA+r4=",
+      "dev": true
+    },
     "simple-swizzle": {
       "version": "0.2.2",
       "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
@@ -11865,6 +11871,17 @@
         "has-flag": "^3.0.0"
       }
     },
+    "svg-inline-loader": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/svg-inline-loader/-/svg-inline-loader-0.8.2.tgz",
+      "integrity": "sha512-kbrcEh5n5JkypaSC152eGfGcnT4lkR0eSfvefaUJkLqgGjRQJyKDvvEE/CCv5aTSdfXuc+N98w16iAojhShI3g==",
+      "dev": true,
+      "requires": {
+        "loader-utils": "^1.1.0",
+        "object-assign": "^4.0.1",
+        "simple-html-tokenizer": "^0.1.1"
+      }
+    },
     "svg-tags": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
diff --git a/package.json b/package.json
index caf30f00615e713727ca6f02009056cc9bac70ef..adc59a250e1633dd2e6397cea3f79560c29c5031 100644
--- a/package.json
+++ b/package.json
@@ -97,6 +97,7 @@
     "sass-loader": "^8.0.2",
     "sinon": "^9.0.2",
     "sinon-chai": "^3.4.0",
+    "svg-inline-loader": "^0.8.2",
     "url-loader": "^4.1.0",
     "vue-loader": "^15.9.1",
     "vue-server-renderer": "^2.6.11",
diff --git a/src/components/Envelope.vue b/src/components/Envelope.vue
index 5b76fa32a7ba983d8a47e15406230f8229bfb373..a8073649eed7e18d5dc6274ddb1a677150abd99b 100644
--- a/src/components/Envelope.vue
+++ b/src/components/Envelope.vue
@@ -11,6 +11,13 @@
 			:data-starred="data.flags.flagged ? 'true' : 'false'"
 			@click.prevent="onToggleFlagged"
 		></div>
+		<div
+			v-if="data.flags.important"
+			class="app-content-list-item-star icon-important"
+			:data-starred="data.flags.important ? 'true' : 'false'"
+			@click.prevent="onToggleImportant"
+			v-html="importantSvg"
+		></div>
 		<div class="app-content-list-item-icon">
 			<Avatar :display-name="addresses" :email="avatarEmail" />
 		</div>
@@ -32,6 +39,9 @@
 			<ActionButton icon="icon-starred" @click.prevent="onToggleFlagged">{{
 				data.flags.flagged ? t('mail', 'Unfavorite') : t('mail', 'Favorite')
 			}}</ActionButton>
+			<ActionButton icon="icon-info" @click.prevent="onToggleImportant">{{
+				data.flags.important ? t('mail', 'Mark unimportant') : t('mail', 'Mark important')
+			}}</ActionButton>
 			<ActionButton icon="icon-mail" @click.prevent="onToggleSeen">{{
 				data.flags.unseen ? t('mail', 'Mark read') : t('mail', 'Mark unread')
 			}}</ActionButton>
@@ -44,6 +54,7 @@
 import Actions from '@nextcloud/vue/dist/Components/Actions'
 import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
 import Moment from './Moment'
+import importantSvg from '../../img/important.svg'
 
 import Avatar from './Avatar'
 import {calculateAccountColor} from '../util/AccountColor'
@@ -66,6 +77,11 @@ export default {
 			required: true,
 		},
 	},
+	data() {
+		return {
+			importantSvg,
+		}
+	},
 	computed: {
 		accountColor() {
 			return calculateAccountColor(this.$store.getters.getAccount(this.data.accountId).emailAddress)
@@ -134,6 +150,9 @@ export default {
 		onToggleFlagged() {
 			this.$store.dispatch('toggleEnvelopeFlagged', this.data)
 		},
+		onToggleImportant() {
+			this.$store.dispatch('toggleEnvelopeImportant', this.data)
+		},
 		onToggleSeen() {
 			this.$store.dispatch('toggleEnvelopeSeen', this.data)
 		},
@@ -158,6 +177,18 @@ export default {
 	z-index: 1;
 }
 
+.app-content-list-item-star.icon-important {
+	left: 7px;
+	top: 13px;
+	opacity: 1;
+	&:hover {
+		opacity: 0.5;
+	}
+	::v-deep path {
+		fill: #ffcc00;
+		stroke: var(--color-main-background);
+	}
+}
 .app-content-list-item.unseen {
 	font-weight: bold;
 }
diff --git a/src/store/actions.js b/src/store/actions.js
index 12d586eb18b78b96401a02f9cf58c2c2b0ca6707..6063c9ab6d8ada68200fc821abc5d25319fada68 100644
--- a/src/store/actions.js
+++ b/src/store/actions.js
@@ -493,6 +493,26 @@ export default {
 			})
 		})
 	},
+	toggleEnvelopeImportant({commit, getters}, envelope) {
+		// Change immediately and switch back on error
+		const oldState = envelope.flags.important
+		commit('flagEnvelope', {
+			envelope,
+			flag: 'important',
+			value: !oldState,
+		})
+
+		setEnvelopeFlag(envelope.accountId, envelope.folderId, envelope.id, 'important', !oldState).catch((e) => {
+			console.error('could not toggle message important state', e)
+
+			// Revert change
+			commit('flagEnvelope', {
+				envelope,
+				flag: 'important',
+				value: oldState,
+			})
+		})
+	},
 	toggleEnvelopeSeen({commit, getters}, envelope) {
 		// Change immediately and switch back on error
 		const oldState = envelope.flags.unseen
diff --git a/tests/Unit/Service/Classification/ClassifierTest.php b/tests/Unit/Service/Classification/ClassifierTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..22cc85037e53617f2730a70dfd0388cf9f29ab5f
--- /dev/null
+++ b/tests/Unit/Service/Classification/ClassifierTest.php
@@ -0,0 +1,74 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCA\Mail\Tests\Unit\Service\Classification;
+
+use ChristophWurst\Nextcloud\Testing\TestCase;
+use OCA\Mail\Account;
+use OCA\Mail\Db\Mailbox;
+use OCA\Mail\Db\Message;
+use OCA\Mail\Service\Classification\AClassifier;
+
+class ClassifierTest extends TestCase {
+	public function testShortcut(): void {
+		$c1 = $this->createMock(AClassifier::class);
+		$c1->method('isImportant')->willReturn(true);
+		$c2 = $this->createMock(AClassifier::class);
+		$c2->expects($this->never())
+			->method('isImportant');
+		$account = $this->createMock(Account::class);
+		$mailbox = $this->createMock(Mailbox::class);
+		$message = $this->createMock(Message::class);
+
+		$result = $c1->or($c2)->isImportant($account, $mailbox, $message);
+
+		$this->assertTrue($result);
+	}
+
+	public function testOr(): void {
+		$c1 = $this->createMock(AClassifier::class);
+		$c2 = $this->createMock(AClassifier::class);
+		$c2->method('isImportant')->willReturn(true);
+		$account = $this->createMock(Account::class);
+		$mailbox = $this->createMock(Mailbox::class);
+		$message = $this->createMock(Message::class);
+
+		$result = $c1->or($c2)->isImportant($account, $mailbox, $message);
+
+		$this->assertTrue($result);
+	}
+
+	public function testNone(): void {
+		$c1 = $this->createMock(AClassifier::class);
+		$c2 = $this->createMock(AClassifier::class);
+		$account = $this->createMock(Account::class);
+		$mailbox = $this->createMock(Mailbox::class);
+		$message = $this->createMock(Message::class);
+
+		$result = $c1->or($c2)->isImportant($account, $mailbox, $message);
+
+		$this->assertFalse($result);
+	}
+}
diff --git a/webpack.common.js b/webpack.common.js
index 42a0777c04402ef9d3e8a2735dfcdea0802ea197..010f19b084633f739deca4f74370abac6c39ee3c 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -62,7 +62,7 @@ module.exports = {
 				test: /\.(svg)$/i,
 				use: [
 					{
-						loader: 'url-loader'
+						loader: 'svg-inline-loader'
 					}
 				],
 				exclude: path.join(__dirname, 'node_modules', '@ckeditor')