Add settings for email decryption preprocessor
This commit is contained in:
parent
243daf7469
commit
c134ce9025
@ -1171,6 +1171,15 @@ if DEBUG: # pragma: no cover
|
||||
EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend"
|
||||
EMAIL_FILE_PATH = BASE_DIR / "sent_emails"
|
||||
|
||||
###############################################################################
|
||||
# Email Preprocessors #
|
||||
###############################################################################
|
||||
|
||||
EMAIL_GNUPG_HOME: Final[Optional[str]] = os.getenv("PAPERLESS_EMAIL_GNUPG_HOME")
|
||||
EMAIL_ENABLE_GPG_DECRYPTOR: Final[bool] = __get_boolean(
|
||||
"PAPERLESS_ENABLE_GPG_DECRYPTOR",
|
||||
)
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Soft Delete
|
||||
|
@ -10,7 +10,6 @@ from datetime import timedelta
|
||||
from fnmatch import fnmatch
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import Callable
|
||||
from typing import Optional
|
||||
from typing import Union
|
||||
|
||||
@ -45,6 +44,7 @@ from paperless_mail.models import MailAccount
|
||||
from paperless_mail.models import MailRule
|
||||
from paperless_mail.models import ProcessedMail
|
||||
from paperless_mail.preprocessor import MailMessageDecryptor
|
||||
from paperless_mail.preprocessor import MailMessagePreprocessor
|
||||
|
||||
# Apple Mail sets multiple IMAP KEYWORD and the general "\Flagged" FLAG
|
||||
# imaplib => conn.fetch(b"<message_id>", "FLAGS")
|
||||
@ -428,12 +428,22 @@ class MailAccountHandler(LoggingMixin):
|
||||
|
||||
logging_name = "paperless_mail"
|
||||
|
||||
_message_preprocessors: list[Callable[[MailMessage], MailMessage]] = []
|
||||
_message_preprocessor_types: list[type[MailMessagePreprocessor]] = [
|
||||
MailMessageDecryptor,
|
||||
]
|
||||
|
||||
def __init__(self, *gpgArgs, **gpgkwArgs) -> None:
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._message_preprocessors.append(MailMessageDecryptor(*gpgArgs, **gpgkwArgs))
|
||||
self.renew_logging_group()
|
||||
self._init_preprocessors()
|
||||
|
||||
def _init_preprocessors(self):
|
||||
self._message_preprocessors: list[MailMessagePreprocessor] = []
|
||||
for preprocessor_type in self._message_preprocessor_types:
|
||||
if preprocessor_type.able_to_run():
|
||||
self._message_preprocessors.append(preprocessor_type())
|
||||
else:
|
||||
self.log.debug(f"Skipping mail preprocessor {preprocessor_type.NAME}")
|
||||
|
||||
def _correspondent_from_name(self, name: str) -> Optional[Correspondent]:
|
||||
try:
|
||||
@ -542,7 +552,7 @@ class MailAccountHandler(LoggingMixin):
|
||||
|
||||
def _preprocess_message(self, message: MailMessage):
|
||||
for preprocessor in self._message_preprocessors:
|
||||
message = preprocessor(message)
|
||||
message = preprocessor.run(message)
|
||||
return message
|
||||
|
||||
def _handle_mail_rule(
|
||||
|
@ -1,22 +1,53 @@
|
||||
import abc
|
||||
from email import message_from_bytes
|
||||
from email import policy
|
||||
from email.message import Message
|
||||
|
||||
from django.conf import settings
|
||||
from gnupg import GPG
|
||||
from imap_tools import MailMessage
|
||||
|
||||
from documents.loggers import LoggingMixin
|
||||
|
||||
|
||||
class MailMessageDecryptor(LoggingMixin):
|
||||
class MailMessagePreprocessor(abc.ABC):
|
||||
"""
|
||||
Defines the interface for preprocessors that alter messages before they are handled in MailAccountHandler
|
||||
"""
|
||||
|
||||
NAME: str = "MailMessagePreprocessor"
|
||||
|
||||
@staticmethod
|
||||
@abc.abstractmethod
|
||||
def able_to_run() -> bool:
|
||||
"""
|
||||
Return True if the conditions are met for the preprocessor to run, False otherwise
|
||||
|
||||
If False, run(message) will not be called
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def run(self, message: MailMessage) -> MailMessage:
|
||||
"""
|
||||
Performs the actual preprocessing task
|
||||
"""
|
||||
|
||||
|
||||
class MailMessageDecryptor(MailMessagePreprocessor, LoggingMixin):
|
||||
logging_name = "paperless_mail_message_decryptor"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
NAME = "MailMessageDecryptor"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.renew_logging_group()
|
||||
self._gpg = GPG(*args, **kwargs)
|
||||
self._gpg = GPG(gnupghome=settings.EMAIL_GNUPG_HOME)
|
||||
|
||||
def __call__(self, message: MailMessage) -> MailMessage:
|
||||
@staticmethod
|
||||
def able_to_run() -> bool:
|
||||
return settings.EMAIL_ENABLE_GPG_DECRYPTOR
|
||||
|
||||
def run(self, message: MailMessage) -> MailMessage:
|
||||
if not hasattr(message, "obj"):
|
||||
self.log.debug("Message does not have 'obj' attribute")
|
||||
return message
|
||||
|
@ -16,6 +16,7 @@ import pytest
|
||||
from django.core.management import call_command
|
||||
from django.db import DatabaseError
|
||||
from django.test import TestCase
|
||||
from django.test import override_settings
|
||||
from imap_tools import NOT
|
||||
from imap_tools import EmailAddress
|
||||
from imap_tools import FolderInfo
|
||||
@ -273,10 +274,11 @@ class TestMail(
|
||||
self.reset_bogus_mailbox()
|
||||
|
||||
self.messageEncryptor = MessageEncryptor()
|
||||
|
||||
self.mail_account_handler = MailAccountHandler(
|
||||
gnupghome=self.messageEncryptor.gpg_home,
|
||||
)
|
||||
with override_settings(
|
||||
EMAIL_GNUPG_HOME=self.messageEncryptor.gpg_home,
|
||||
EMAIL_ENABLE_GPG_DECRYPTOR=True,
|
||||
):
|
||||
self.mail_account_handler = MailAccountHandler()
|
||||
|
||||
super().setUp()
|
||||
|
||||
@ -1368,10 +1370,13 @@ class TestMail(
|
||||
self.assertEqual(encrypted_message.attachments[0].filename, "encrypted.asc")
|
||||
self.assertEqual(encrypted_message.text, "")
|
||||
|
||||
message_decryptor = MailMessageDecryptor(
|
||||
gnupghome=self.messageEncryptor.gpg_home,
|
||||
)
|
||||
decrypted_message = message_decryptor(encrypted_message)
|
||||
with override_settings(
|
||||
EMAIL_ENABLE_GPG_DECRYPTOR=True,
|
||||
EMAIL_GNUPG_HOME=self.messageEncryptor.gpg_home,
|
||||
):
|
||||
message_decryptor = MailMessageDecryptor()
|
||||
self.assertTrue(message_decryptor.able_to_run())
|
||||
decrypted_message = message_decryptor.run(encrypted_message)
|
||||
|
||||
self.assertEqual(len(decrypted_message.attachments), 2)
|
||||
self.assertEqual(decrypted_message.attachments[0].filename, "f1.pdf")
|
||||
|
Loading…
x
Reference in New Issue
Block a user