120 lines
4.3 KiB
Python
120 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from govoplan_mail.backend.config import ImapConfig
|
|
from govoplan_mail.backend.sending.imap import (
|
|
_detect_sent_folder,
|
|
_extract_mailbox_name,
|
|
_normalize_mailbox_page,
|
|
_paged_descending_sequences,
|
|
_parse_fetch_sequence,
|
|
_select_readonly,
|
|
_sequence_set,
|
|
append_message_to_sent,
|
|
)
|
|
|
|
|
|
class ImapFolderParserTests(unittest.TestCase):
|
|
def test_extracts_quoted_mailbox_after_quoted_delimiter(self):
|
|
self.assertEqual(
|
|
_extract_mailbox_name(b'(\\HasNoChildren \\Sent) "/" "Sent Items"'),
|
|
("Sent Items", {"\\hasnochildren", "\\sent"}),
|
|
)
|
|
|
|
def test_extracts_atom_mailbox(self):
|
|
self.assertEqual(
|
|
_extract_mailbox_name('(\\HasNoChildren) "/" INBOX'),
|
|
("INBOX", {"\\hasnochildren"}),
|
|
)
|
|
|
|
def test_extracts_nil_delimiter_mailbox(self):
|
|
self.assertEqual(
|
|
_extract_mailbox_name('(\\HasNoChildren) NIL "INBOX.Sent"'),
|
|
("INBOX.Sent", {"\\hasnochildren"}),
|
|
)
|
|
|
|
def test_detects_sent_by_flag_before_name(self):
|
|
self.assertEqual(
|
|
_detect_sent_folder([("Archive", {"\\sent"}), ("Sent", set())]),
|
|
"Archive",
|
|
)
|
|
|
|
def test_detects_common_sent_name(self):
|
|
self.assertEqual(
|
|
_detect_sent_folder([("INBOX", set()), ("Gesendet", set())]),
|
|
"Gesendet",
|
|
)
|
|
|
|
|
|
class ImapMessagePaginationTests(unittest.TestCase):
|
|
def test_paginates_sequence_numbers_newest_first(self):
|
|
self.assertEqual(
|
|
_paged_descending_sequences(120, offset=0, limit=5),
|
|
["120", "119", "118", "117", "116"],
|
|
)
|
|
self.assertEqual(_paged_descending_sequences(120, offset=118, limit=5), ["2", "1"])
|
|
self.assertEqual(_paged_descending_sequences(120, offset=120, limit=5), [])
|
|
|
|
def test_compacts_contiguous_sequence_sets(self):
|
|
self.assertEqual(_sequence_set(["5", "4", "3"]), "3:5")
|
|
self.assertEqual(_sequence_set(["9", "7", "5"]), "5,7,9")
|
|
|
|
def test_extracts_fetch_sequence_number(self):
|
|
self.assertEqual(
|
|
_parse_fetch_sequence("42 (UID 123 FLAGS (\\Seen) RFC822.SIZE 100)"),
|
|
"42",
|
|
)
|
|
self.assertIsNone(_parse_fetch_sequence("UID 123 FLAGS ()"))
|
|
|
|
def test_normalizes_mailbox_pagination_request(self):
|
|
self.assertEqual(_normalize_mailbox_page(folder="", limit=0, offset=-5), ("INBOX", 1, 0))
|
|
self.assertEqual(_normalize_mailbox_page(folder=" Sent ", limit=500, offset=3), ("Sent", 100, 3))
|
|
|
|
|
|
class ImapMailboxCommandTests(unittest.TestCase):
|
|
def test_select_quotes_mailbox_name_with_spaces(self):
|
|
class Client:
|
|
untagged_responses = {"EXISTS": [b"0"], "UIDVALIDITY": [b"1"]}
|
|
|
|
def select(self, mailbox, readonly=False):
|
|
self.mailbox = mailbox
|
|
self.readonly = readonly
|
|
return "OK", [b"0"]
|
|
|
|
def response(self, code):
|
|
return "OK", [b"1"] if code == "UIDVALIDITY" else []
|
|
|
|
client = Client()
|
|
|
|
self.assertEqual(_select_readonly(client, "Gesendete Elemente"), (0, "1"))
|
|
self.assertEqual(client.mailbox, '"Gesendete Elemente"')
|
|
self.assertTrue(client.readonly)
|
|
|
|
def test_append_quotes_mailbox_name_with_spaces(self):
|
|
class Client:
|
|
def append(self, mailbox, flags, date_time, message):
|
|
self.mailbox = mailbox
|
|
self.flags = flags
|
|
self.date_time = date_time
|
|
self.message = message
|
|
return "OK", [b"APPEND completed"]
|
|
|
|
def logout(self):
|
|
return "BYE", [b"logged out"]
|
|
|
|
client = Client()
|
|
config = ImapConfig(host="imap.example.org", username="user", password="secret", sent_folder="auto")
|
|
|
|
with patch("govoplan_mail.backend.sending.imap._open_imap", return_value=client):
|
|
result = append_message_to_sent(b"Subject: test\r\n\r\nBody", imap_config=config, folder="Gesendete Elemente")
|
|
|
|
self.assertEqual(client.mailbox, '"Gesendete Elemente"')
|
|
self.assertEqual(result.folder, "Gesendete Elemente")
|
|
self.assertEqual(result.bytes_appended, len(b"Subject: test\r\n\r\nBody"))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|