from imap_tools import MailBoxUnencrypted
from imap_tools import MailMessage
from imap_tools import MailMessageFlags
+from imap_tools import errors
from imap_tools.mailbox import MailBoxTls
from imap_tools.query import LogicOperator
M.folder.set(rule.folder)
action = get_rule_action(rule, supports_gmail_labels)
- action.post_consume(M, message_uid, rule.action_parameter)
+ try:
+ action.post_consume(M, message_uid, rule.action_parameter)
+ except errors.ImapToolsError:
+ logger = logging.getLogger("paperless_mail")
+ logger.exception(
+ "Error while processing mail action during post_consume",
+ )
+ raise
ProcessedMail.objects.create(
owner=rule.owner,
rule: MailRule,
supports_gmail_labels: bool,
):
- self.log.debug(f"Rule {rule}: Selecting folder {rule.folder}")
-
+ folders = [rule.folder]
+ # In case of MOVE, make sure also the destination exists
+ if rule.action == MailRule.MailAction.MOVE:
+ folders.insert(0, rule.action_parameter)
try:
- M.folder.set(rule.folder)
+ for folder in folders:
+ self.log.debug(f"Rule {rule}: Selecting folder {folder}")
+ M.folder.set(folder)
except MailboxFolderSelectError as err:
self.log.error(
- f"Unable to access folder {rule.folder}, attempting folder listing",
+ f"Unable to access folder {folder}, attempting folder listing",
)
try:
for folder_info in M.folder.list():
)
raise MailError(
- f"Rule {rule}: Folder {rule.folder} "
+ f"Rule {rule}: Folder {folder} "
f"does not exist in account {rule.account}",
) from err
from django.core.management import call_command
from django.db import DatabaseError
from django.test import TestCase
+from django.utils import timezone
from imap_tools import NOT
from imap_tools import EmailAddress
from imap_tools import FolderInfo
from imap_tools import MailboxLoginError
from imap_tools import MailMessage
from imap_tools import MailMessageFlags
+from imap_tools import errors
from documents.models import Correspondent
from documents.tests.utils import DirectoriesMixin
from paperless_mail.mail import apply_mail_action
from paperless_mail.models import MailAccount
from paperless_mail.models import MailRule
+from paperless_mail.models import ProcessedMail
@dataclasses.dataclass
) # still 2
+class TestPostConsumeAction(TestCase):
+ def setUp(self):
+ self.account = MailAccount.objects.create(
+ name="test",
+ imap_server="imap.test.com",
+ imap_port=993,
+ imap_security=MailAccount.ImapSecurity.SSL,
+ username="testuser",
+ password="password",
+ )
+ self.rule = MailRule.objects.create(
+ name="testrule",
+ account=self.account,
+ action=MailRule.MailAction.MARK_READ,
+ action_parameter="",
+ folder="INBOX",
+ )
+ self.message_uid = "12345"
+ self.message_subject = "Test Subject"
+ self.message_date = timezone.make_aware(timezone.datetime(2023, 1, 1, 12, 0, 0))
+
+ @mock.patch("paperless_mail.mail.get_mailbox")
+ @mock.patch("paperless_mail.mail.mailbox_login")
+ @mock.patch("paperless_mail.mail.get_rule_action")
+ def test_post_consume_success(
+ self,
+ mock_get_rule_action,
+ mock_mailbox_login,
+ mock_get_mailbox,
+ ):
+ mock_mailbox = mock.MagicMock()
+ mock_get_mailbox.return_value.__enter__.return_value = mock_mailbox
+ mock_action = mock.MagicMock()
+ mock_get_rule_action.return_value = mock_action
+
+ apply_mail_action(
+ result=[],
+ rule_id=self.rule.pk,
+ message_uid=self.message_uid,
+ message_subject=self.message_subject,
+ message_date=self.message_date,
+ )
+
+ mock_mailbox_login.assert_called_once_with(mock_mailbox, self.account)
+ mock_mailbox.folder.set.assert_called_once_with(self.rule.folder)
+ mock_action.post_consume.assert_called_once_with(
+ mock_mailbox,
+ self.message_uid,
+ self.rule.action_parameter,
+ )
+
+ processed_mail = ProcessedMail.objects.get(uid=self.message_uid)
+ self.assertEqual(processed_mail.status, "SUCCESS")
+
+ @mock.patch("paperless_mail.mail.get_mailbox")
+ @mock.patch("paperless_mail.mail.mailbox_login")
+ @mock.patch("paperless_mail.mail.get_rule_action")
+ def test_post_consume_failure(
+ self,
+ mock_get_rule_action,
+ mock_mailbox_login,
+ mock_get_mailbox,
+ ):
+ mock_mailbox = mock.MagicMock()
+ mock_get_mailbox.return_value.__enter__.return_value = mock_mailbox
+ mock_action = mock.MagicMock()
+ mock_get_rule_action.return_value = mock_action
+ mock_action.post_consume.side_effect = errors.ImapToolsError("Test Exception")
+
+ with (
+ self.assertRaises(errors.ImapToolsError),
+ self.assertLogs("paperless.mail", level="ERROR") as cm,
+ ):
+ apply_mail_action(
+ result=[],
+ rule_id=self.rule.pk,
+ message_uid=self.message_uid,
+ message_subject=self.message_subject,
+ message_date=self.message_date,
+ )
+ error_str = cm.output[0]
+ expected_str = "Error while processing mail action during post_consume"
+ self.assertIn(expected_str, error_str)
+
+ processed_mail = ProcessedMail.objects.get(uid=self.message_uid)
+ self.assertEqual(processed_mail.status, "FAILED")
+ self.assertIn("Test Exception", processed_mail.error)
+
+
class TestManagementCommand(TestCase):
@mock.patch(
"paperless_mail.management.commands.mail_fetcher.tasks.process_mail_accounts",