Merge pull request #767 from paperless-ngx/bug-fix-list-folders

List Email Account Folders In Event of Error Changing Folder
This commit is contained in:
Quinn Casey 2022-04-19 15:57:31 -07:00 committed by GitHub
commit 0bff3891bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 5 deletions

View File

@ -182,9 +182,10 @@ These are as follows:
When defining a mail rule with a folder, you may need to try different characters to When defining a mail rule with a folder, you may need to try different characters to
define how the sub-folders are separated. Common values include ".", "/" or "|", but define how the sub-folders are separated. Common values include ".", "/" or "|", but
this varies by the mail server. Unfortunately, this isn't a value we can determine this varies by the mail server. Check the documentation for your mail server. In the
automatically. Either check the documentation for your mail server, or check for event of an error fetching mail from a certain folder, check the Paperless logs. When
errors in the logs and try different folder separator values. a folder is not located, Paperless will attempt to list all folders found in the account
to the Paperless logs.
.. note:: .. note::

View File

@ -190,6 +190,21 @@ class MailAccountHandler(LoggingMixin):
try: try:
M.folder.set(rule.folder) M.folder.set(rule.folder)
except MailboxFolderSelectError: except MailboxFolderSelectError:
self.log(
"error",
f"Unable to access folder {rule.folder}, attempting folder listing",
)
try:
for folder_info in M.folder.list():
self.log("info", f"Located folder: {folder_info.name}")
except Exception as e:
self.log(
"error",
"Exception during folder listing, unable to provide list folders: "
+ str(e),
)
raise MailError( raise MailError(
f"Rule {rule}: Folder {rule.folder} " f"Rule {rule}: Folder {rule.folder} "
f"does not exist in account {rule.account}", f"does not exist in account {rule.account}",

View File

@ -15,6 +15,7 @@ from django.test import TestCase
from documents.models import Correspondent from documents.models import Correspondent
from documents.tests.utils import DirectoriesMixin from documents.tests.utils import DirectoriesMixin
from imap_tools import EmailAddress from imap_tools import EmailAddress
from imap_tools import FolderInfo
from imap_tools import MailboxFolderSelectError from imap_tools import MailboxFolderSelectError
from imap_tools import MailMessage from imap_tools import MailMessage
from imap_tools import MailMessageFlags from imap_tools import MailMessageFlags
@ -53,13 +54,12 @@ class BogusMailBox(ContextManager):
def __init__(self): def __init__(self):
self.messages: List[MailMessage] = [] self.messages: List[MailMessage] = []
self.messages_spam: List[MailMessage] = [] self.messages_spam: List[MailMessage] = []
self.folder = BogusFolderManager()
def login(self, username, password): def login(self, username, password):
if not (username == "admin" and password == "secret"): if not (username == "admin" and password == "secret"):
raise Exception() raise Exception()
folder = BogusFolderManager()
def fetch(self, criteria, mark_seen, charset=""): def fetch(self, criteria, mark_seen, charset=""):
msg = self.messages msg = self.messages
@ -621,6 +621,72 @@ 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_error_folder_set(self):
"""
GIVEN:
- Mail rule with non-existent folder
THEN:
- Should call list to output all folders in the account
- Should not process any messages
"""
account = MailAccount.objects.create(
name="test2",
imap_server="",
username="admin",
password="secret",
)
_ = MailRule.objects.create(
name="testrule",
account=account,
action=MailRule.AttachmentAction.MOVE,
action_parameter="spam",
filter_subject="Claim",
order=1,
folder="uuuhhhh", # Invalid folder name
)
self.bogus_mailbox.folder.list = mock.Mock(
return_value=[FolderInfo("SomeFoldername", "|", ())],
)
self.mail_account_handler.handle_mail_account(account)
self.bogus_mailbox.folder.list.assert_called_once()
self.assertEqual(self.async_task.call_count, 0)
def test_error_folder_set_error_listing(self):
"""
GIVEN:
- Mail rule with non-existent folder
- Mail account folder listing raises exception
THEN:
- Should not process any messages
"""
account = MailAccount.objects.create(
name="test2",
imap_server="",
username="admin",
password="secret",
)
_ = MailRule.objects.create(
name="testrule",
account=account,
action=MailRule.AttachmentAction.MOVE,
action_parameter="spam",
filter_subject="Claim",
order=1,
folder="uuuhhhh", # Invalid folder name
)
self.bogus_mailbox.folder.list = mock.Mock(
side_effect=MailboxFolderSelectError(None, "uhm"),
)
self.mail_account_handler.handle_mail_account(account)
self.bogus_mailbox.folder.list.assert_called_once()
self.assertEqual(self.async_task.call_count, 0)
@mock.patch("paperless_mail.mail.MailAccountHandler.get_correspondent") @mock.patch("paperless_mail.mail.MailAccountHandler.get_correspondent")
def test_error_skip_mail(self, m): def test_error_skip_mail(self, m):
def get_correspondent_fake(message, rule): def get_correspondent_fake(message, rule):