owenrusk.dev

errands

small jobs the runtime does for the studio.

git clone https://owenrusk.dev/errands.git

errands / tests/test_mail.py -rw-r--r-- · 3388 bytes

 1 import mailbox
 2 import tempfile
 3 import unittest
 4 from email.message import EmailMessage
 5 from pathlib import Path
 6 
 7 from errands import mail, settings
 8 from tests.fakes import FakeBox, FakeServer, raw
 9 
10 
11 class UnreadTest(unittest.TestCase):
12     def test_reads_every_unseen_message(self):
13         box = FakeBox({b"7": raw(subject="a question"), b"9": raw(sender="Ann <Ann@example.com>")})
14         got = mail.unread(lambda: box)
15         self.assertEqual([m.uid for m in got], ["7", "9"])
16         self.assertEqual(got[0].subject, "a question")
17         self.assertEqual(got[1].sender, "ann@example.com")
18         self.assertEqual(got[0].body, "hello\n")
19         self.assertTrue(box.closed)
20 
21     def test_plain_text_from_multipart(self):
22         msg = EmailMessage()
23         msg["From"] = "someone@example.com"
24         msg["Subject"] = "screenshot"
25         msg.set_content("it's attached\n")
26         msg.add_alternative("<p>it's attached</p>", subtype="html")
27         msg.add_attachment(b"\x89PNG", maintype="image", subtype="png", filename="shot.png")
28         self.assertEqual(mail.parse("3", bytes(msg)).body, "it's attached\n")
29 
30     def test_encoded_subject(self):
31         message = mail.parse("4", raw(subject="caf\u00e9 hours"))
32         self.assertEqual(message.subject, "caf\u00e9 hours")
33         self.assertIn(b"=?utf-8?", raw(subject="caf\u00e9 hours"))
34 
35     def test_skips_our_own(self):
36         box = FakeBox({b"1": raw(sender="Paper Moth Games <support@papermothgames.com>"), b"2": raw()})
37         self.assertEqual([m.uid for m in mail.unread(lambda: box)], ["2"])
38 
39     def test_nothing_unread(self):
40         self.assertEqual(mail.unread(lambda: FakeBox({})), [])
41 
42     def test_mark_read(self):
43         box = FakeBox({})
44         mail.mark_read("7", lambda: box)
45         self.assertEqual(box.stored, [("7", "+FLAGS", "(\\Seen)")])
46 
47 
48 class SendTest(unittest.TestCase):
49     def setUp(self):
50         self.dir = tempfile.TemporaryDirectory()
51         self.logs = settings.LOGS
52         settings.LOGS = Path(self.dir.name)
53 
54     def tearDown(self):
55         settings.LOGS = self.logs
56         self.dir.cleanup()
57 
58     def test_keeps_a_copy(self):
59         mail.send(mail.compose("someone@example.com", "hello", "hello\n"), FakeServer)
60         mail.send(mail.compose("ann@example.com", "again", "hello\n"), FakeServer)
61         kept = mailbox.mbox(settings.LOGS / "sent.mbox")
62         self.assertEqual([m["To"] for m in kept], ["someone@example.com", "ann@example.com"])
63         kept.close()
64 
65     def test_reply_keeps_the_subject_and_thread(self):
66         original = mail.parse("7", raw(subject="a question", message_id="<q@example.com>"))
67         server = FakeServer()
68         mail.reply(original, "thanks for writing.\n", lambda: server)
69         sent = server.sent[0]
70         self.assertEqual(sent["To"], "someone@example.com")
71         self.assertEqual(sent["Subject"], "Re: a question")
72         self.assertEqual(sent["In-Reply-To"], "<q@example.com>")
73         self.assertEqual(sent["References"], "<q@example.com>")
74         self.assertEqual(sent["From"], "Paper Moth Games <support@papermothgames.com>")
75         self.assertTrue(server.quit_called)
76 
77     def test_no_second_re(self):
78         original = mail.parse("7", raw(subject="Re: a question"))
79         server = FakeServer()
80         mail.reply(original, "ok\n", lambda: server)
81         self.assertEqual(server.sent[0]["Subject"], "Re: a question")