mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-09 09:58:20 -05:00
Merge pull request #1032 from pheerai/feature-mailActionCustomTag
Feature mail action custom tag
This commit is contained in:
commit
4db3f366ef
@ -161,6 +161,9 @@ These are as follows:
|
|||||||
will not consume flagged mails.
|
will not consume flagged mails.
|
||||||
* **Move to folder:** Moves consumed mails out of the way so that paperless wont
|
* **Move to folder:** Moves consumed mails out of the way so that paperless wont
|
||||||
consume them again.
|
consume them again.
|
||||||
|
* **Add custom Tag:** Adds a custom tag to mails with consumed documents (the IMAP
|
||||||
|
standard calls these "keywords"). Paperless will not consume mails already tagged.
|
||||||
|
Not all mail servers support this feature!
|
||||||
|
|
||||||
.. caution::
|
.. caution::
|
||||||
|
|
||||||
|
@ -62,6 +62,17 @@ class FlagMailAction(BaseMailAction):
|
|||||||
M.flag(message_uids, [MailMessageFlags.FLAGGED], True)
|
M.flag(message_uids, [MailMessageFlags.FLAGGED], True)
|
||||||
|
|
||||||
|
|
||||||
|
class TagMailAction(BaseMailAction):
|
||||||
|
def __init__(self, parameter):
|
||||||
|
self.keyword = parameter
|
||||||
|
|
||||||
|
def get_criteria(self):
|
||||||
|
return {"no_keyword": self.keyword}
|
||||||
|
|
||||||
|
def post_consume(self, M: MailBox, message_uids, parameter):
|
||||||
|
M.flag(message_uids, [self.keyword], True)
|
||||||
|
|
||||||
|
|
||||||
def get_rule_action(rule):
|
def get_rule_action(rule):
|
||||||
if rule.action == MailRule.MailAction.FLAG:
|
if rule.action == MailRule.MailAction.FLAG:
|
||||||
return FlagMailAction()
|
return FlagMailAction()
|
||||||
@ -71,6 +82,8 @@ def get_rule_action(rule):
|
|||||||
return MoveMailAction()
|
return MoveMailAction()
|
||||||
elif rule.action == MailRule.MailAction.MARK_READ:
|
elif rule.action == MailRule.MailAction.MARK_READ:
|
||||||
return MarkReadMailAction()
|
return MarkReadMailAction()
|
||||||
|
elif rule.action == MailRule.MailAction.TAG:
|
||||||
|
return TagMailAction(rule.action_parameter)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError("Unknown action.") # pragma: nocover
|
raise NotImplementedError("Unknown action.") # pragma: nocover
|
||||||
|
|
||||||
|
28
src/paperless_mail/migrations/0015_alter_mailrule_action.py
Normal file
28
src/paperless_mail/migrations/0015_alter_mailrule_action.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Generated by Django 4.0.4 on 2022-05-29 13:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("paperless_mail", "0014_alter_mailrule_action"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="mailrule",
|
||||||
|
name="action",
|
||||||
|
field=models.PositiveIntegerField(
|
||||||
|
choices=[
|
||||||
|
(1, "Delete"),
|
||||||
|
(2, "Move to specified folder"),
|
||||||
|
(3, "Mark as read, don't process read mails"),
|
||||||
|
(4, "Flag the mail, don't process flagged mails"),
|
||||||
|
(5, "Tag the mail with specified tag, don't process tagged mails"),
|
||||||
|
],
|
||||||
|
default=3,
|
||||||
|
verbose_name="action",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
@ -65,6 +65,7 @@ class MailRule(models.Model):
|
|||||||
MOVE = 2, _("Move to specified folder")
|
MOVE = 2, _("Move to specified folder")
|
||||||
MARK_READ = 3, _("Mark as read, don't process read mails")
|
MARK_READ = 3, _("Mark as read, don't process read mails")
|
||||||
FLAG = 4, _("Flag the mail, don't process flagged mails")
|
FLAG = 4, _("Flag the mail, don't process flagged mails")
|
||||||
|
TAG = 5, _("Tag the mail with specified tag, don't process tagged mails")
|
||||||
|
|
||||||
class TitleSource(models.IntegerChoices):
|
class TitleSource(models.IntegerChoices):
|
||||||
FROM_SUBJECT = 1, _("Use subject as title")
|
FROM_SUBJECT = 1, _("Use subject as title")
|
||||||
|
@ -96,6 +96,10 @@ class BogusMailBox(ContextManager):
|
|||||||
if "UNFLAGGED" in criteria:
|
if "UNFLAGGED" in criteria:
|
||||||
msg = filter(lambda m: not m.flagged, msg)
|
msg = filter(lambda m: not m.flagged, msg)
|
||||||
|
|
||||||
|
if "UNKEYWORD" in criteria:
|
||||||
|
tag = criteria[criteria.index("UNKEYWORD") + 1].strip("'")
|
||||||
|
msg = filter(lambda m: "processed" not in m.flags, msg)
|
||||||
|
|
||||||
return list(msg)
|
return list(msg)
|
||||||
|
|
||||||
def delete(self, uid_list):
|
def delete(self, uid_list):
|
||||||
@ -109,6 +113,9 @@ class BogusMailBox(ContextManager):
|
|||||||
message.flagged = value
|
message.flagged = value
|
||||||
if flag == MailMessageFlags.SEEN:
|
if flag == MailMessageFlags.SEEN:
|
||||||
message.seen = value
|
message.seen = value
|
||||||
|
if flag == "processed":
|
||||||
|
message._raw_flag_data.append(f"+FLAGS (processed)".encode())
|
||||||
|
MailMessage.flags.fget.cache_clear()
|
||||||
|
|
||||||
def move(self, uid_list, folder):
|
def move(self, uid_list, folder):
|
||||||
if folder == "spam":
|
if folder == "spam":
|
||||||
@ -130,6 +137,7 @@ def create_message(
|
|||||||
from_: str = "noone@mail.com",
|
from_: str = "noone@mail.com",
|
||||||
seen: bool = False,
|
seen: bool = False,
|
||||||
flagged: bool = False,
|
flagged: bool = False,
|
||||||
|
processed: bool = False,
|
||||||
) -> MailMessage:
|
) -> MailMessage:
|
||||||
email_msg = email.message.EmailMessage()
|
email_msg = email.message.EmailMessage()
|
||||||
# TODO: This does NOT set the UID
|
# TODO: This does NOT set the UID
|
||||||
@ -175,6 +183,9 @@ def create_message(
|
|||||||
|
|
||||||
imap_msg.seen = seen
|
imap_msg.seen = seen
|
||||||
imap_msg.flagged = flagged
|
imap_msg.flagged = flagged
|
||||||
|
if processed:
|
||||||
|
imap_msg._raw_flag_data.append(f"+FLAGS (processed)".encode())
|
||||||
|
MailMessage.flags.fget.cache_clear()
|
||||||
|
|
||||||
return imap_msg
|
return imap_msg
|
||||||
|
|
||||||
@ -217,6 +228,7 @@ class TestMail(DirectoriesMixin, TestCase):
|
|||||||
body="cables",
|
body="cables",
|
||||||
seen=True,
|
seen=True,
|
||||||
flagged=False,
|
flagged=False,
|
||||||
|
processed=False,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.bogus_mailbox.messages.append(
|
self.bogus_mailbox.messages.append(
|
||||||
@ -225,6 +237,7 @@ class TestMail(DirectoriesMixin, TestCase):
|
|||||||
body="from my favorite electronic store",
|
body="from my favorite electronic store",
|
||||||
seen=False,
|
seen=False,
|
||||||
flagged=True,
|
flagged=True,
|
||||||
|
processed=True,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.bogus_mailbox.messages.append(
|
self.bogus_mailbox.messages.append(
|
||||||
@ -571,6 +584,29 @@ class TestMail(DirectoriesMixin, TestCase):
|
|||||||
self.assertEqual(len(self.bogus_mailbox.messages), 2)
|
self.assertEqual(len(self.bogus_mailbox.messages), 2)
|
||||||
self.assertEqual(len(self.bogus_mailbox.messages_spam), 1)
|
self.assertEqual(len(self.bogus_mailbox.messages_spam), 1)
|
||||||
|
|
||||||
|
def test_handle_mail_account_tag(self):
|
||||||
|
account = MailAccount.objects.create(
|
||||||
|
name="test",
|
||||||
|
imap_server="",
|
||||||
|
username="admin",
|
||||||
|
password="secret",
|
||||||
|
)
|
||||||
|
|
||||||
|
_ = MailRule.objects.create(
|
||||||
|
name="testrule",
|
||||||
|
account=account,
|
||||||
|
action=MailRule.MailAction.TAG,
|
||||||
|
action_parameter="processed",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(len(self.bogus_mailbox.messages), 3)
|
||||||
|
self.assertEqual(self.async_task.call_count, 0)
|
||||||
|
self.assertEqual(len(self.bogus_mailbox.fetch("UNKEYWORD processed", False)), 2)
|
||||||
|
self.mail_account_handler.handle_mail_account(account)
|
||||||
|
self.assertEqual(self.async_task.call_count, 2)
|
||||||
|
self.assertEqual(len(self.bogus_mailbox.fetch("UNKEYWORD processed", False)), 0)
|
||||||
|
self.assertEqual(len(self.bogus_mailbox.messages), 3)
|
||||||
|
|
||||||
def test_error_login(self):
|
def test_error_login(self):
|
||||||
account = MailAccount.objects.create(
|
account = MailAccount.objects.create(
|
||||||
name="test",
|
name="test",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user