mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-30 18:27:45 -05:00
Runs the pre-commit hooks over all the Python files
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
from django.contrib import admin
|
||||
from django import forms
|
||||
from paperless_mail.models import MailAccount, MailRule
|
||||
|
||||
from django.contrib import admin
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from paperless_mail.models import MailAccount
|
||||
from paperless_mail.models import MailRule
|
||||
|
||||
|
||||
class MailAccountAdminForm(forms.ModelForm):
|
||||
@@ -48,7 +48,7 @@ class MailRuleAdmin(admin.ModelAdmin):
|
||||
{
|
||||
"description": _(
|
||||
"Paperless will only process mails that match ALL of the "
|
||||
"filters given below."
|
||||
"filters given below.",
|
||||
),
|
||||
"fields": (
|
||||
"filter_from",
|
||||
@@ -66,7 +66,7 @@ class MailRuleAdmin(admin.ModelAdmin):
|
||||
"description": _(
|
||||
"The action applied to the mail. This action is only "
|
||||
"performed when documents were consumed from the mail. "
|
||||
"Mails without attachments will remain entirely untouched."
|
||||
"Mails without attachments will remain entirely untouched.",
|
||||
),
|
||||
"fields": ("action", "action_parameter"),
|
||||
},
|
||||
@@ -78,7 +78,7 @@ class MailRuleAdmin(admin.ModelAdmin):
|
||||
"Assign metadata to documents consumed from this rule "
|
||||
"automatically. If you do not assign tags, types or "
|
||||
"correspondents here, paperless will still process all "
|
||||
"matching rules that you have defined."
|
||||
"matching rules that you have defined.",
|
||||
),
|
||||
"fields": (
|
||||
"assign_title_from",
|
||||
|
@@ -1,5 +1,4 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import tempfile
|
||||
from datetime import timedelta, date
|
||||
from datetime import date
|
||||
from datetime import timedelta
|
||||
from fnmatch import fnmatch
|
||||
|
||||
import magic
|
||||
@@ -8,18 +9,16 @@ import pathvalidate
|
||||
from django.conf import settings
|
||||
from django.db import DatabaseError
|
||||
from django_q.tasks import async_task
|
||||
from imap_tools import (
|
||||
MailBox,
|
||||
MailBoxUnencrypted,
|
||||
AND,
|
||||
MailMessageFlags,
|
||||
MailboxFolderSelectError,
|
||||
)
|
||||
|
||||
from documents.loggers import LoggingMixin
|
||||
from documents.models import Correspondent
|
||||
from documents.parsers import is_mime_type_supported
|
||||
from paperless_mail.models import MailAccount, MailRule
|
||||
from imap_tools import AND
|
||||
from imap_tools import MailBox
|
||||
from imap_tools import MailboxFolderSelectError
|
||||
from imap_tools import MailBoxUnencrypted
|
||||
from imap_tools import MailMessageFlags
|
||||
from paperless_mail.models import MailAccount
|
||||
from paperless_mail.models import MailRule
|
||||
|
||||
|
||||
class MailError(Exception):
|
||||
@@ -120,8 +119,8 @@ class MailAccountHandler(LoggingMixin):
|
||||
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
"Unknown title selector."
|
||||
) # pragma: nocover # NOQA: E501
|
||||
"Unknown title selector.",
|
||||
) # pragma: nocover
|
||||
|
||||
def get_correspondent(self, message, rule):
|
||||
c_from = rule.assign_correspondent_from
|
||||
@@ -137,7 +136,7 @@ class MailAccountHandler(LoggingMixin):
|
||||
message.from_values
|
||||
and "name" in message.from_values
|
||||
and message.from_values["name"]
|
||||
): # NOQA: E501
|
||||
):
|
||||
return self._correspondent_from_name(message.from_values["name"])
|
||||
else:
|
||||
return self._correspondent_from_name(message.from_)
|
||||
@@ -147,8 +146,8 @@ class MailAccountHandler(LoggingMixin):
|
||||
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
"Unknwown correspondent selector"
|
||||
) # pragma: nocover # NOQA: E501
|
||||
"Unknwown correspondent selector",
|
||||
) # pragma: nocover
|
||||
|
||||
def handle_mail_account(self, account):
|
||||
|
||||
@@ -159,7 +158,9 @@ class MailAccountHandler(LoggingMixin):
|
||||
total_processed_files = 0
|
||||
|
||||
with get_mailbox(
|
||||
account.imap_server, account.imap_port, account.imap_security
|
||||
account.imap_server,
|
||||
account.imap_port,
|
||||
account.imap_security,
|
||||
) as M:
|
||||
|
||||
try:
|
||||
@@ -193,7 +194,7 @@ class MailAccountHandler(LoggingMixin):
|
||||
except MailboxFolderSelectError:
|
||||
raise MailError(
|
||||
f"Rule {rule}: Folder {rule.folder} "
|
||||
f"does not exist in account {rule.account}"
|
||||
f"does not exist in account {rule.account}",
|
||||
)
|
||||
|
||||
criterias = make_criterias(rule)
|
||||
@@ -242,12 +243,14 @@ class MailAccountHandler(LoggingMixin):
|
||||
|
||||
try:
|
||||
get_rule_action(rule).post_consume(
|
||||
M, post_consume_messages, rule.action_parameter
|
||||
M,
|
||||
post_consume_messages,
|
||||
rule.action_parameter,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
raise MailError(
|
||||
f"Rule {rule}: Error while processing post-consume actions: " f"{e}"
|
||||
f"Rule {rule}: Error while processing post-consume actions: " f"{e}",
|
||||
)
|
||||
|
||||
return total_processed_files
|
||||
@@ -274,7 +277,7 @@ class MailAccountHandler(LoggingMixin):
|
||||
if (
|
||||
not att.content_disposition == "attachment"
|
||||
and rule.attachment_type == MailRule.ATTACHMENT_TYPE_ATTACHMENTS_ONLY
|
||||
): # NOQA: E501
|
||||
):
|
||||
self.log(
|
||||
"debug",
|
||||
f"Rule {rule}: "
|
||||
@@ -297,7 +300,8 @@ class MailAccountHandler(LoggingMixin):
|
||||
|
||||
os.makedirs(settings.SCRATCH_DIR, exist_ok=True)
|
||||
_, temp_filename = tempfile.mkstemp(
|
||||
prefix="paperless-mail-", dir=settings.SCRATCH_DIR
|
||||
prefix="paperless-mail-",
|
||||
dir=settings.SCRATCH_DIR,
|
||||
)
|
||||
with open(temp_filename, "wb") as f:
|
||||
f.write(att.payload)
|
||||
@@ -313,15 +317,13 @@ class MailAccountHandler(LoggingMixin):
|
||||
"documents.tasks.consume_file",
|
||||
path=temp_filename,
|
||||
override_filename=pathvalidate.sanitize_filename(
|
||||
att.filename
|
||||
), # NOQA: E501
|
||||
att.filename,
|
||||
),
|
||||
override_title=title,
|
||||
override_correspondent_id=correspondent.id
|
||||
if correspondent
|
||||
else None, # NOQA: E501
|
||||
override_document_type_id=doc_type.id
|
||||
if doc_type
|
||||
else None, # NOQA: E501
|
||||
else None,
|
||||
override_document_type_id=doc_type.id if doc_type else None,
|
||||
override_tag_ids=[tag.id] if tag else None,
|
||||
task_name=att.filename[:100],
|
||||
)
|
||||
|
@@ -1,5 +1,4 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from paperless_mail import tasks
|
||||
|
||||
|
||||
@@ -7,7 +6,8 @@ class Command(BaseCommand):
|
||||
|
||||
help = """
|
||||
""".replace(
|
||||
" ", ""
|
||||
" ",
|
||||
"",
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
|
@@ -1,7 +1,5 @@
|
||||
from django.db import models
|
||||
|
||||
import documents.models as document_models
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
@@ -30,12 +28,14 @@ class MailAccount(models.Model):
|
||||
null=True,
|
||||
help_text=_(
|
||||
"This is usually 143 for unencrypted and STARTTLS "
|
||||
"connections, and 993 for SSL connections."
|
||||
"connections, and 993 for SSL connections.",
|
||||
),
|
||||
)
|
||||
|
||||
imap_security = models.PositiveIntegerField(
|
||||
_("IMAP security"), choices=IMAP_SECURITY_OPTIONS, default=IMAP_SECURITY_SSL
|
||||
_("IMAP security"),
|
||||
choices=IMAP_SECURITY_OPTIONS,
|
||||
default=IMAP_SECURITY_SSL,
|
||||
)
|
||||
|
||||
username = models.CharField(_("username"), max_length=256)
|
||||
@@ -48,7 +48,7 @@ class MailAccount(models.Model):
|
||||
default="UTF-8",
|
||||
help_text=_(
|
||||
"The character set to use when communicating with the "
|
||||
"mail server, such as 'UTF-8' or 'US-ASCII'."
|
||||
"mail server, such as 'UTF-8' or 'US-ASCII'.",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -123,13 +123,22 @@ class MailRule(models.Model):
|
||||
)
|
||||
|
||||
filter_from = models.CharField(
|
||||
_("filter from"), max_length=256, null=True, blank=True
|
||||
_("filter from"),
|
||||
max_length=256,
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
filter_subject = models.CharField(
|
||||
_("filter subject"), max_length=256, null=True, blank=True
|
||||
_("filter subject"),
|
||||
max_length=256,
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
filter_body = models.CharField(
|
||||
_("filter body"), max_length=256, null=True, blank=True
|
||||
_("filter body"),
|
||||
max_length=256,
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
filter_attachment_filename = models.CharField(
|
||||
@@ -140,12 +149,14 @@ class MailRule(models.Model):
|
||||
help_text=_(
|
||||
"Only consume documents which entirely match this "
|
||||
"filename if specified. Wildcards such as *.pdf or "
|
||||
"*invoice* are allowed. Case insensitive."
|
||||
"*invoice* are allowed. Case insensitive.",
|
||||
),
|
||||
)
|
||||
|
||||
maximum_age = models.PositiveIntegerField(
|
||||
_("maximum age"), default=30, help_text=_("Specified in days.")
|
||||
_("maximum age"),
|
||||
default=30,
|
||||
help_text=_("Specified in days."),
|
||||
)
|
||||
|
||||
attachment_type = models.PositiveIntegerField(
|
||||
@@ -154,7 +165,7 @@ class MailRule(models.Model):
|
||||
default=ATTACHMENT_TYPE_ATTACHMENTS_ONLY,
|
||||
help_text=_(
|
||||
"Inline attachments include embedded images, so it's best "
|
||||
"to combine this option with a filename filter."
|
||||
"to combine this option with a filename filter.",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -173,12 +184,14 @@ class MailRule(models.Model):
|
||||
"Additional parameter for the action selected above, "
|
||||
"i.e., "
|
||||
"the target folder of the move to folder action. "
|
||||
"Subfolders must be separated by dots."
|
||||
"Subfolders must be separated by dots.",
|
||||
),
|
||||
)
|
||||
|
||||
assign_title_from = models.PositiveIntegerField(
|
||||
_("assign title from"), choices=TITLE_SELECTOR, default=TITLE_FROM_SUBJECT
|
||||
_("assign title from"),
|
||||
choices=TITLE_SELECTOR,
|
||||
default=TITLE_FROM_SUBJECT,
|
||||
)
|
||||
|
||||
assign_tag = models.ForeignKey(
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import logging
|
||||
|
||||
from paperless_mail.mail import MailAccountHandler, MailError
|
||||
from paperless_mail.mail import MailAccountHandler
|
||||
from paperless_mail.mail import MailError
|
||||
from paperless_mail.models import MailAccount
|
||||
|
||||
|
||||
|
@@ -7,13 +7,15 @@ from unittest import mock
|
||||
from django.core.management import call_command
|
||||
from django.db import DatabaseError
|
||||
from django.test import TestCase
|
||||
from imap_tools import MailMessageFlags, MailboxFolderSelectError
|
||||
|
||||
from documents.models import Correspondent
|
||||
from documents.tests.utils import DirectoriesMixin
|
||||
from imap_tools import MailboxFolderSelectError
|
||||
from imap_tools import MailMessageFlags
|
||||
from paperless_mail import tasks
|
||||
from paperless_mail.mail import MailError, MailAccountHandler
|
||||
from paperless_mail.models import MailRule, MailAccount
|
||||
from paperless_mail.mail import MailAccountHandler
|
||||
from paperless_mail.mail import MailError
|
||||
from paperless_mail.models import MailAccount
|
||||
from paperless_mail.models import MailRule
|
||||
|
||||
|
||||
class BogusFolderManager:
|
||||
@@ -83,7 +85,7 @@ class BogusMailBox(ContextManager):
|
||||
def move(self, uid_list, folder):
|
||||
if folder == "spam":
|
||||
self.messages_spam.append(
|
||||
filter(lambda m: m.uid in uid_list, self.messages)
|
||||
filter(lambda m: m.uid in uid_list, self.messages),
|
||||
)
|
||||
self.messages = list(filter(lambda m: m.uid not in uid_list, self.messages))
|
||||
else:
|
||||
@@ -115,7 +117,9 @@ def create_message(
|
||||
|
||||
|
||||
def create_attachment(
|
||||
filename="the_file.pdf", content_disposition="attachment", payload=b"a PDF document"
|
||||
filename="the_file.pdf",
|
||||
content_disposition="attachment",
|
||||
payload=b"a PDF document",
|
||||
):
|
||||
attachment = namedtuple("Attachment", [])
|
||||
attachment.filename = filename
|
||||
@@ -163,7 +167,7 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
body="cables",
|
||||
seen=True,
|
||||
flagged=False,
|
||||
)
|
||||
),
|
||||
)
|
||||
self.bogus_mailbox.messages.append(
|
||||
create_message(
|
||||
@@ -171,14 +175,14 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
body="from my favorite electronic store",
|
||||
seen=False,
|
||||
flagged=True,
|
||||
)
|
||||
),
|
||||
)
|
||||
self.bogus_mailbox.messages.append(
|
||||
create_message(
|
||||
subject="Claim your $10M price now!",
|
||||
from_="amazon@amazon-some-indian-site.org",
|
||||
seen=False,
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
def test_get_correspondent(self):
|
||||
@@ -196,12 +200,14 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
handler = MailAccountHandler()
|
||||
|
||||
rule = MailRule(
|
||||
name="a", assign_correspondent_from=MailRule.CORRESPONDENT_FROM_NOTHING
|
||||
name="a",
|
||||
assign_correspondent_from=MailRule.CORRESPONDENT_FROM_NOTHING,
|
||||
)
|
||||
self.assertIsNone(handler.get_correspondent(message, rule))
|
||||
|
||||
rule = MailRule(
|
||||
name="b", assign_correspondent_from=MailRule.CORRESPONDENT_FROM_EMAIL
|
||||
name="b",
|
||||
assign_correspondent_from=MailRule.CORRESPONDENT_FROM_EMAIL,
|
||||
)
|
||||
c = handler.get_correspondent(message, rule)
|
||||
self.assertIsNotNone(c)
|
||||
@@ -212,7 +218,8 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
self.assertEqual(c.id, me_localhost.id)
|
||||
|
||||
rule = MailRule(
|
||||
name="c", assign_correspondent_from=MailRule.CORRESPONDENT_FROM_NAME
|
||||
name="c",
|
||||
assign_correspondent_from=MailRule.CORRESPONDENT_FROM_NAME,
|
||||
)
|
||||
c = handler.get_correspondent(message, rule)
|
||||
self.assertIsNotNone(c)
|
||||
@@ -244,7 +251,9 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
|
||||
def test_handle_message(self):
|
||||
message = create_message(
|
||||
subject="the message title", from_="Myself", num_attachments=2
|
||||
subject="the message title",
|
||||
from_="Myself",
|
||||
num_attachments=2,
|
||||
)
|
||||
|
||||
account = MailAccount()
|
||||
@@ -376,11 +385,16 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
def test_handle_mail_account_mark_read(self):
|
||||
|
||||
account = MailAccount.objects.create(
|
||||
name="test", imap_server="", username="admin", password="secret"
|
||||
name="test",
|
||||
imap_server="",
|
||||
username="admin",
|
||||
password="secret",
|
||||
)
|
||||
|
||||
rule = MailRule.objects.create(
|
||||
name="testrule", account=account, action=MailRule.ACTION_MARK_READ
|
||||
name="testrule",
|
||||
account=account,
|
||||
action=MailRule.ACTION_MARK_READ,
|
||||
)
|
||||
|
||||
self.assertEqual(len(self.bogus_mailbox.messages), 3)
|
||||
@@ -394,7 +408,10 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
def test_handle_mail_account_delete(self):
|
||||
|
||||
account = MailAccount.objects.create(
|
||||
name="test", imap_server="", username="admin", password="secret"
|
||||
name="test",
|
||||
imap_server="",
|
||||
username="admin",
|
||||
password="secret",
|
||||
)
|
||||
|
||||
rule = MailRule.objects.create(
|
||||
@@ -412,7 +429,10 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
|
||||
def test_handle_mail_account_flag(self):
|
||||
account = MailAccount.objects.create(
|
||||
name="test", imap_server="", username="admin", password="secret"
|
||||
name="test",
|
||||
imap_server="",
|
||||
username="admin",
|
||||
password="secret",
|
||||
)
|
||||
|
||||
rule = MailRule.objects.create(
|
||||
@@ -432,7 +452,10 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
|
||||
def test_handle_mail_account_move(self):
|
||||
account = MailAccount.objects.create(
|
||||
name="test", imap_server="", username="admin", password="secret"
|
||||
name="test",
|
||||
imap_server="",
|
||||
username="admin",
|
||||
password="secret",
|
||||
)
|
||||
|
||||
rule = MailRule.objects.create(
|
||||
@@ -453,7 +476,10 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
|
||||
def test_error_login(self):
|
||||
account = MailAccount.objects.create(
|
||||
name="test", imap_server="", username="admin", password="wrong"
|
||||
name="test",
|
||||
imap_server="",
|
||||
username="admin",
|
||||
password="wrong",
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -465,11 +491,17 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
|
||||
def test_error_skip_account(self):
|
||||
account_faulty = MailAccount.objects.create(
|
||||
name="test", imap_server="", username="admin", password="wroasdng"
|
||||
name="test",
|
||||
imap_server="",
|
||||
username="admin",
|
||||
password="wroasdng",
|
||||
)
|
||||
|
||||
account = MailAccount.objects.create(
|
||||
name="test2", imap_server="", username="admin", password="secret"
|
||||
name="test2",
|
||||
imap_server="",
|
||||
username="admin",
|
||||
password="secret",
|
||||
)
|
||||
rule = MailRule.objects.create(
|
||||
name="testrule",
|
||||
@@ -487,7 +519,10 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
def test_error_skip_rule(self):
|
||||
|
||||
account = MailAccount.objects.create(
|
||||
name="test2", imap_server="", username="admin", password="secret"
|
||||
name="test2",
|
||||
imap_server="",
|
||||
username="admin",
|
||||
password="secret",
|
||||
)
|
||||
rule = MailRule.objects.create(
|
||||
name="testrule",
|
||||
@@ -523,7 +558,10 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
m.side_effect = get_correspondent_fake
|
||||
|
||||
account = MailAccount.objects.create(
|
||||
name="test2", imap_server="", username="admin", password="secret"
|
||||
name="test2",
|
||||
imap_server="",
|
||||
username="admin",
|
||||
password="secret",
|
||||
)
|
||||
rule = MailRule.objects.create(
|
||||
name="testrule",
|
||||
@@ -544,7 +582,10 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
def test_error_create_correspondent(self):
|
||||
|
||||
account = MailAccount.objects.create(
|
||||
name="test2", imap_server="", username="admin", password="secret"
|
||||
name="test2",
|
||||
imap_server="",
|
||||
username="admin",
|
||||
password="secret",
|
||||
)
|
||||
rule = MailRule.objects.create(
|
||||
name="testrule",
|
||||
@@ -579,7 +620,10 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
def test_filters(self):
|
||||
|
||||
account = MailAccount.objects.create(
|
||||
name="test3", imap_server="", username="admin", password="secret"
|
||||
name="test3",
|
||||
imap_server="",
|
||||
username="admin",
|
||||
password="secret",
|
||||
)
|
||||
rule = MailRule.objects.create(
|
||||
name="testrule3",
|
||||
@@ -629,7 +673,7 @@ class TestMail(DirectoriesMixin, TestCase):
|
||||
|
||||
class TestManagementCommand(TestCase):
|
||||
@mock.patch(
|
||||
"paperless_mail.management.commands.mail_fetcher.tasks.process_mail_accounts"
|
||||
"paperless_mail.management.commands.mail_fetcher.tasks.process_mail_accounts",
|
||||
)
|
||||
def test_mail_fetcher(self, m):
|
||||
|
||||
@@ -644,10 +688,16 @@ class TestTasks(TestCase):
|
||||
m.side_effect = lambda account: 6
|
||||
|
||||
MailAccount.objects.create(
|
||||
name="A", imap_server="A", username="A", password="A"
|
||||
name="A",
|
||||
imap_server="A",
|
||||
username="A",
|
||||
password="A",
|
||||
)
|
||||
MailAccount.objects.create(
|
||||
name="B", imap_server="A", username="A", password="A"
|
||||
name="B",
|
||||
imap_server="A",
|
||||
username="A",
|
||||
password="A",
|
||||
)
|
||||
|
||||
result = tasks.process_mail_accounts()
|
||||
@@ -663,7 +713,10 @@ class TestTasks(TestCase):
|
||||
def test_single_accounts(self, m):
|
||||
|
||||
MailAccount.objects.create(
|
||||
name="A", imap_server="A", username="A", password="A"
|
||||
name="A",
|
||||
imap_server="A",
|
||||
username="A",
|
||||
password="A",
|
||||
)
|
||||
|
||||
tasks.process_mail_account("A")
|
||||
|
Reference in New Issue
Block a user