From f358eda5c5045bd6859f17062e1afcb865d7426e Mon Sep 17 00:00:00 2001 From: Trenton Holmes Date: Mon, 28 Mar 2022 10:41:18 -0700 Subject: [PATCH] Updates the mail db model to use the built-in enum capabilities and runs the migrations --- src/paperless_mail/mail.py | 29 +++--- ...r_mailrule_action_alter_mailrule_folder.py | 37 ++++++++ src/paperless_mail/models.py | 90 +++++++------------ src/paperless_mail/tests/test_mail.py | 61 ++++++++----- 4 files changed, 121 insertions(+), 96 deletions(-) create mode 100644 src/paperless_mail/migrations/0009_alter_mailrule_action_alter_mailrule_folder.py diff --git a/src/paperless_mail/mail.py b/src/paperless_mail/mail.py index a7e455829..190f1e7bf 100644 --- a/src/paperless_mail/mail.py +++ b/src/paperless_mail/mail.py @@ -61,13 +61,13 @@ class FlagMailAction(BaseMailAction): def get_rule_action(rule): - if rule.action == MailRule.ACTION_FLAG: + if rule.action == MailRule.AttachmentAction.FLAG: return FlagMailAction() - elif rule.action == MailRule.ACTION_DELETE: + elif rule.action == MailRule.AttachmentAction.DELETE: return DeleteMailAction() - elif rule.action == MailRule.ACTION_MOVE: + elif rule.action == MailRule.AttachmentAction.MOVE: return MoveMailAction() - elif rule.action == MailRule.ACTION_MARK_READ: + elif rule.action == MailRule.AttachmentAction.MARK_READ: return MarkReadMailAction() else: raise NotImplementedError("Unknown action.") # pragma: nocover @@ -89,11 +89,11 @@ def make_criterias(rule): def get_mailbox(server, port, security): - if security == MailAccount.IMAP_SECURITY_NONE: + if security == MailAccount.ImapSecurity.NONE: mailbox = MailBoxUnencrypted(server, port) - elif security == MailAccount.IMAP_SECURITY_STARTTLS: + elif security == MailAccount.ImapSecurity.STARTTLS: mailbox = MailBox(server, port, starttls=True) - elif security == MailAccount.IMAP_SECURITY_SSL: + elif security == MailAccount.ImapSecurity.SSL: mailbox = MailBox(server, port) else: raise NotImplementedError("Unknown IMAP security") # pragma: nocover @@ -112,10 +112,10 @@ class MailAccountHandler(LoggingMixin): return None def get_title(self, message, att, rule): - if rule.assign_title_from == MailRule.TITLE_FROM_SUBJECT: + if rule.assign_title_from == MailRule.TitleSource.FROM_SUBJECT: return message.subject - elif rule.assign_title_from == MailRule.TITLE_FROM_FILENAME: + elif rule.assign_title_from == MailRule.TitleSource.FROM_FILENAME: return os.path.splitext(os.path.basename(att.filename))[0] else: @@ -126,20 +126,20 @@ class MailAccountHandler(LoggingMixin): def get_correspondent(self, message: MailMessage, rule): c_from = rule.assign_correspondent_from - if c_from == MailRule.CORRESPONDENT_FROM_NOTHING: + if c_from == MailRule.CorrespondentSource.FROM_NOTHING: return None - elif c_from == MailRule.CORRESPONDENT_FROM_EMAIL: + elif c_from == MailRule.CorrespondentSource.FROM_EMAIL: return self._correspondent_from_name(message.from_) - elif c_from == MailRule.CORRESPONDENT_FROM_NAME: + elif c_from == MailRule.CorrespondentSource.FROM_NAME: from_values = message.from_values if from_values is not None and len(from_values.name) > 0: return self._correspondent_from_name(from_values.name) else: return self._correspondent_from_name(message.from_) - elif c_from == MailRule.CORRESPONDENT_FROM_CUSTOM: + elif c_from == MailRule.CorrespondentSource.FROM_CUSTOM: return rule.assign_correspondent else: @@ -274,7 +274,8 @@ class MailAccountHandler(LoggingMixin): if ( not att.content_disposition == "attachment" - and rule.attachment_type == MailRule.ATTACHMENT_TYPE_ATTACHMENTS_ONLY + and rule.attachment_type + == MailRule.AttachmentProcessing.ATTACHMENTS_ONLY ): self.log( "debug", diff --git a/src/paperless_mail/migrations/0009_alter_mailrule_action_alter_mailrule_folder.py b/src/paperless_mail/migrations/0009_alter_mailrule_action_alter_mailrule_folder.py new file mode 100644 index 000000000..7eff52691 --- /dev/null +++ b/src/paperless_mail/migrations/0009_alter_mailrule_action_alter_mailrule_folder.py @@ -0,0 +1,37 @@ +# Generated by Django 4.0.3 on 2022-03-28 17:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("paperless_mail", "0008_auto_20210516_0940"), + ] + + operations = [ + migrations.AlterField( + model_name="mailrule", + name="action", + field=models.PositiveIntegerField( + choices=[ + (1, "Mark as read, don't process read mails"), + (2, "Flag the mail, don't process flagged mails"), + (3, "Move to specified folder"), + (4, "Delete"), + ], + default=3, + verbose_name="action", + ), + ), + migrations.AlterField( + model_name="mailrule", + name="folder", + field=models.CharField( + default="INBOX", + help_text="Subfolders must be separated by a delimiter, often a dot ('.') or slash ('/'), but it varies by mail server.", + max_length=256, + verbose_name="folder", + ), + ), + ] diff --git a/src/paperless_mail/models.py b/src/paperless_mail/models.py index 59d4827a4..2c7b9fb6d 100644 --- a/src/paperless_mail/models.py +++ b/src/paperless_mail/models.py @@ -8,15 +8,10 @@ class MailAccount(models.Model): verbose_name = _("mail account") verbose_name_plural = _("mail accounts") - IMAP_SECURITY_NONE = 1 - IMAP_SECURITY_SSL = 2 - IMAP_SECURITY_STARTTLS = 3 - - IMAP_SECURITY_OPTIONS = ( - (IMAP_SECURITY_NONE, _("No encryption")), - (IMAP_SECURITY_SSL, _("Use SSL")), - (IMAP_SECURITY_STARTTLS, _("Use STARTTLS")), - ) + class ImapSecurity(models.IntegerChoices): + NONE = 1, _("No encryption") + SSL = 2, _("Use SSL") + STARTTLS = 3, _("Use STARTTLS") name = models.CharField(_("name"), max_length=256, unique=True) @@ -34,8 +29,8 @@ class MailAccount(models.Model): imap_security = models.PositiveIntegerField( _("IMAP security"), - choices=IMAP_SECURITY_OPTIONS, - default=IMAP_SECURITY_SSL, + choices=ImapSecurity.choices, + default=ImapSecurity.SSL, ) username = models.CharField(_("username"), max_length=256) @@ -61,48 +56,25 @@ class MailRule(models.Model): verbose_name = _("mail rule") verbose_name_plural = _("mail rules") - ATTACHMENT_TYPE_ATTACHMENTS_ONLY = 1 - ATTACHMENT_TYPE_EVERYTHING = 2 + class AttachmentProcessing(models.IntegerChoices): + ATTACHMENTS_ONLY = 1, _("Only process attachments.") + EVERYTHING = 2, _("Process all files, including 'inline' " "attachments.") - ATTACHMENT_TYPES = ( - (ATTACHMENT_TYPE_ATTACHMENTS_ONLY, _("Only process attachments.")), - ( - ATTACHMENT_TYPE_EVERYTHING, - _("Process all files, including 'inline' " "attachments."), - ), - ) + class AttachmentAction(models.IntegerChoices): + DELETE = 1, _("Mark as read, don't process read mails") + MOVE = 2, _("Flag the mail, don't process flagged mails") + MARK_READ = 3, _("Move to specified folder") + FLAG = 4, _("Delete") - ACTION_DELETE = 1 - ACTION_MOVE = 2 - ACTION_MARK_READ = 3 - ACTION_FLAG = 4 + class TitleSource(models.IntegerChoices): + FROM_SUBJECT = 1, _("Use subject as title") + FROM_FILENAME = 2, _("Use attachment filename as title") - ACTIONS = ( - (ACTION_MARK_READ, _("Mark as read, don't process read mails")), - (ACTION_FLAG, _("Flag the mail, don't process flagged mails")), - (ACTION_MOVE, _("Move to specified folder")), - (ACTION_DELETE, _("Delete")), - ) - - TITLE_FROM_SUBJECT = 1 - TITLE_FROM_FILENAME = 2 - - TITLE_SELECTOR = ( - (TITLE_FROM_SUBJECT, _("Use subject as title")), - (TITLE_FROM_FILENAME, _("Use attachment filename as title")), - ) - - CORRESPONDENT_FROM_NOTHING = 1 - CORRESPONDENT_FROM_EMAIL = 2 - CORRESPONDENT_FROM_NAME = 3 - CORRESPONDENT_FROM_CUSTOM = 4 - - CORRESPONDENT_SELECTOR = ( - (CORRESPONDENT_FROM_NOTHING, _("Do not assign a correspondent")), - (CORRESPONDENT_FROM_EMAIL, _("Use mail address")), - (CORRESPONDENT_FROM_NAME, _("Use name (or mail address if not available)")), - (CORRESPONDENT_FROM_CUSTOM, _("Use correspondent selected below")), - ) + class CorrespondentSource(models.IntegerChoices): + FROM_NOTHING = 1, _("Do not assign a correspondent") + FROM_EMAIL = 2, _("Use mail address") + FROM_NAME = 3, _("Use name (or mail address if not available)") + FROM_CUSTOM = 4, _("Use correspondent selected below") name = models.CharField(_("name"), max_length=256, unique=True) @@ -120,7 +92,7 @@ class MailRule(models.Model): default="INBOX", max_length=256, help_text=_( - "Subfolders must be separated by a delimiter, often a dot ('.') or " + "Subfolders must be separated by a delimiter, often a dot ('.') or" " slash ('/'), but it varies by mail server.", ), ) @@ -164,8 +136,8 @@ class MailRule(models.Model): attachment_type = models.PositiveIntegerField( _("attachment type"), - choices=ATTACHMENT_TYPES, - default=ATTACHMENT_TYPE_ATTACHMENTS_ONLY, + choices=AttachmentProcessing.choices, + default=AttachmentProcessing.ATTACHMENTS_ONLY, help_text=_( "Inline attachments include embedded images, so it's best " "to combine this option with a filename filter.", @@ -174,8 +146,8 @@ class MailRule(models.Model): action = models.PositiveIntegerField( _("action"), - choices=ACTIONS, - default=ACTION_MARK_READ, + choices=AttachmentAction.choices, + default=AttachmentAction.MARK_READ, ) action_parameter = models.CharField( @@ -193,8 +165,8 @@ class MailRule(models.Model): assign_title_from = models.PositiveIntegerField( _("assign title from"), - choices=TITLE_SELECTOR, - default=TITLE_FROM_SUBJECT, + choices=TitleSource.choices, + default=TitleSource.FROM_SUBJECT, ) assign_tag = models.ForeignKey( @@ -215,8 +187,8 @@ class MailRule(models.Model): assign_correspondent_from = models.PositiveIntegerField( _("assign correspondent from"), - choices=CORRESPONDENT_SELECTOR, - default=CORRESPONDENT_FROM_NOTHING, + choices=CorrespondentSource.choices, + default=CorrespondentSource.FROM_NOTHING, ) assign_correspondent = models.ForeignKey( diff --git a/src/paperless_mail/tests/test_mail.py b/src/paperless_mail/tests/test_mail.py index 5d7e2a3b6..1ef8c759e 100644 --- a/src/paperless_mail/tests/test_mail.py +++ b/src/paperless_mail/tests/test_mail.py @@ -246,13 +246,13 @@ class TestMail(DirectoriesMixin, TestCase): rule = MailRule( name="a", - assign_correspondent_from=MailRule.CORRESPONDENT_FROM_NOTHING, + assign_correspondent_from=MailRule.CorrespondentSource.FROM_NOTHING, ) self.assertIsNone(handler.get_correspondent(message, rule)) rule = MailRule( name="b", - assign_correspondent_from=MailRule.CORRESPONDENT_FROM_EMAIL, + assign_correspondent_from=MailRule.CorrespondentSource.FROM_EMAIL, ) c = handler.get_correspondent(message, rule) self.assertIsNotNone(c) @@ -264,7 +264,7 @@ class TestMail(DirectoriesMixin, TestCase): rule = MailRule( name="c", - assign_correspondent_from=MailRule.CORRESPONDENT_FROM_NAME, + assign_correspondent_from=MailRule.CorrespondentSource.FROM_NAME, ) c = handler.get_correspondent(message, rule) self.assertIsNotNone(c) @@ -275,7 +275,7 @@ class TestMail(DirectoriesMixin, TestCase): rule = MailRule( name="d", - assign_correspondent_from=MailRule.CORRESPONDENT_FROM_CUSTOM, + assign_correspondent_from=MailRule.CorrespondentSource.FROM_CUSTOM, assign_correspondent=someone_else, ) c = handler.get_correspondent(message, rule) @@ -289,9 +289,15 @@ class TestMail(DirectoriesMixin, TestCase): handler = MailAccountHandler() - rule = MailRule(name="a", assign_title_from=MailRule.TITLE_FROM_FILENAME) + rule = MailRule( + name="a", + assign_title_from=MailRule.TitleSource.FROM_FILENAME, + ) self.assertEqual(handler.get_title(message, att, rule), "this_is_the_file") - rule = MailRule(name="b", assign_title_from=MailRule.TITLE_FROM_SUBJECT) + rule = MailRule( + name="b", + assign_title_from=MailRule.TitleSource.FROM_SUBJECT, + ) self.assertEqual(handler.get_title(message, att, rule), "the message title") def test_handle_message(self): @@ -302,7 +308,10 @@ class TestMail(DirectoriesMixin, TestCase): ) account = MailAccount() - rule = MailRule(assign_title_from=MailRule.TITLE_FROM_FILENAME, account=account) + rule = MailRule( + assign_title_from=MailRule.TitleSource.FROM_FILENAME, + account=account, + ) result = self.mail_account_handler.handle_message(message, rule) @@ -346,7 +355,10 @@ class TestMail(DirectoriesMixin, TestCase): ) account = MailAccount() - rule = MailRule(assign_title_from=MailRule.TITLE_FROM_FILENAME, account=account) + rule = MailRule( + assign_title_from=MailRule.TitleSource.FROM_FILENAME, + account=account, + ) result = self.mail_account_handler.handle_message(message, rule) @@ -369,7 +381,10 @@ class TestMail(DirectoriesMixin, TestCase): ) account = MailAccount() - rule = MailRule(assign_title_from=MailRule.TITLE_FROM_FILENAME, account=account) + rule = MailRule( + assign_title_from=MailRule.TitleSource.FROM_FILENAME, + account=account, + ) result = self.mail_account_handler.handle_message(message, rule) @@ -392,9 +407,9 @@ class TestMail(DirectoriesMixin, TestCase): account = MailAccount() rule = MailRule( - assign_title_from=MailRule.TITLE_FROM_FILENAME, + assign_title_from=MailRule.TitleSource.FROM_FILENAME, account=account, - attachment_type=MailRule.ATTACHMENT_TYPE_EVERYTHING, + attachment_type=MailRule.AttachmentProcessing.EVERYTHING, ) result = self.mail_account_handler.handle_message(message, rule) @@ -424,7 +439,7 @@ class TestMail(DirectoriesMixin, TestCase): self.async_task.reset_mock() account = MailAccount() rule = MailRule( - assign_title_from=MailRule.TITLE_FROM_FILENAME, + assign_title_from=MailRule.TitleSource.FROM_FILENAME, account=account, filter_attachment_filename=pattern, ) @@ -449,7 +464,7 @@ class TestMail(DirectoriesMixin, TestCase): _ = MailRule.objects.create( name="testrule", account=account, - action=MailRule.ACTION_MARK_READ, + action=MailRule.AttachmentAction.MARK_READ, ) self.assertEqual(len(self.bogus_mailbox.messages), 3) @@ -472,7 +487,7 @@ class TestMail(DirectoriesMixin, TestCase): _ = MailRule.objects.create( name="testrule", account=account, - action=MailRule.ACTION_DELETE, + action=MailRule.AttachmentAction.DELETE, filter_subject="Invoice", ) @@ -493,7 +508,7 @@ class TestMail(DirectoriesMixin, TestCase): _ = MailRule.objects.create( name="testrule", account=account, - action=MailRule.ACTION_FLAG, + action=MailRule.AttachmentAction.FLAG, filter_subject="Invoice", ) @@ -516,7 +531,7 @@ class TestMail(DirectoriesMixin, TestCase): _ = MailRule.objects.create( name="testrule", account=account, - action=MailRule.ACTION_MOVE, + action=MailRule.AttachmentAction.MOVE, action_parameter="spam", filter_subject="Claim", ) @@ -562,7 +577,7 @@ class TestMail(DirectoriesMixin, TestCase): _ = MailRule.objects.create( name="testrule", account=account, - action=MailRule.ACTION_MOVE, + action=MailRule.AttachmentAction.MOVE, action_parameter="spam", filter_subject="Claim", ) @@ -583,7 +598,7 @@ class TestMail(DirectoriesMixin, TestCase): _ = MailRule.objects.create( name="testrule", account=account, - action=MailRule.ACTION_MOVE, + action=MailRule.AttachmentAction.MOVE, action_parameter="spam", filter_subject="Claim", order=1, @@ -592,7 +607,7 @@ class TestMail(DirectoriesMixin, TestCase): _ = MailRule.objects.create( name="testrule2", account=account, - action=MailRule.ACTION_MOVE, + action=MailRule.AttachmentAction.MOVE, action_parameter="spam", filter_subject="Claim", order=2, @@ -622,7 +637,7 @@ class TestMail(DirectoriesMixin, TestCase): _ = MailRule.objects.create( name="testrule", account=account, - action=MailRule.ACTION_MOVE, + action=MailRule.AttachmentAction.MOVE, action_parameter="spam", ) @@ -647,9 +662,9 @@ class TestMail(DirectoriesMixin, TestCase): name="testrule", filter_from="amazon@amazon.de", account=account, - action=MailRule.ACTION_MOVE, + action=MailRule.AttachmentAction.MOVE, action_parameter="spam", - assign_correspondent_from=MailRule.CORRESPONDENT_FROM_EMAIL, + assign_correspondent_from=MailRule.CorrespondentSource.FROM_EMAIL, ) self.mail_account_handler.handle_mail_account(account) @@ -684,7 +699,7 @@ class TestMail(DirectoriesMixin, TestCase): rule = MailRule.objects.create( name="testrule3", account=account, - action=MailRule.ACTION_DELETE, + action=MailRule.AttachmentAction.DELETE, filter_subject="Claim", )