feat: respect BACKEND_MUTATE to avoid mutating backend mailboxes by default; add tests and docs
Build and publish container / build (push) Successful in 7m8s
Build and publish container / build (push) Successful in 7m8s
This commit is contained in:
+112
-2
@@ -143,6 +143,95 @@ def test_smtp_proxy_handler_forwards_message_over_ssl(monkeypatch):
|
||||
Settings.BACKEND_SMTP_PASS = previous_pass
|
||||
|
||||
|
||||
def test_pop3_quit_does_not_mutate_backend_by_default():
|
||||
import asyncio
|
||||
|
||||
class DummyBackend:
|
||||
def __init__(self):
|
||||
self.deleted_called = []
|
||||
self.expunge_called = False
|
||||
self.logged_out = False
|
||||
|
||||
def mark_deleted(self, uid):
|
||||
self.deleted_called.append(uid)
|
||||
|
||||
def expunge(self):
|
||||
self.expunge_called = True
|
||||
|
||||
def logout(self):
|
||||
self.logged_out = True
|
||||
|
||||
session = POP3Session(None, None)
|
||||
backend = DummyBackend()
|
||||
session._imap = backend
|
||||
session.deleted = {b"1", b"2"}
|
||||
|
||||
# Provide a dummy writer so send_line can be awaited without a socket.
|
||||
class DummyWriter:
|
||||
def __init__(self):
|
||||
self.buf = b""
|
||||
self.closed = False
|
||||
|
||||
def write(self, data):
|
||||
self.buf += data
|
||||
|
||||
async def drain(self):
|
||||
return None
|
||||
|
||||
def close(self):
|
||||
self.closed = True
|
||||
|
||||
async def wait_closed(self):
|
||||
return None
|
||||
|
||||
session.writer = DummyWriter()
|
||||
|
||||
# Ensure default is not to mutate
|
||||
previous_mutate = Settings.BACKEND_MUTATE
|
||||
Settings.BACKEND_MUTATE = False
|
||||
asyncio.run(session.handle_quit())
|
||||
Settings.BACKEND_MUTATE = previous_mutate
|
||||
|
||||
assert backend.deleted_called == []
|
||||
assert backend.expunge_called is False
|
||||
assert backend.logged_out is True
|
||||
|
||||
|
||||
def test_pop3_quit_mutates_backend_when_enabled():
|
||||
import asyncio
|
||||
|
||||
class DummyBackend:
|
||||
def __init__(self):
|
||||
self.deleted_called = []
|
||||
self.expunge_called = False
|
||||
self.logged_out = False
|
||||
|
||||
def mark_deleted(self, uid):
|
||||
self.deleted_called.append(uid)
|
||||
|
||||
def expunge(self):
|
||||
self.expunge_called = True
|
||||
|
||||
def logout(self):
|
||||
self.logged_out = True
|
||||
|
||||
session = POP3Session(None, None)
|
||||
backend = DummyBackend()
|
||||
session._imap = backend
|
||||
session.deleted = {b"1", b"2"}
|
||||
|
||||
session.writer = DummyWriter()
|
||||
|
||||
previous_mutate = Settings.BACKEND_MUTATE
|
||||
Settings.BACKEND_MUTATE = True
|
||||
asyncio.run(session.handle_quit())
|
||||
Settings.BACKEND_MUTATE = previous_mutate
|
||||
|
||||
assert set(backend.deleted_called) == {b"1", b"2"}
|
||||
assert backend.expunge_called is True
|
||||
assert backend.logged_out is True
|
||||
|
||||
|
||||
class FakeWriter:
|
||||
def __init__(self):
|
||||
self.buffer = bytearray()
|
||||
@@ -160,6 +249,26 @@ class FakeWriter:
|
||||
pass
|
||||
|
||||
|
||||
class DummyWriter:
|
||||
"""Simple writer used by tests where we only need write/drain/close."""
|
||||
|
||||
def __init__(self):
|
||||
self.buf = b""
|
||||
self.closed = False
|
||||
|
||||
def write(self, data):
|
||||
self.buf += data
|
||||
|
||||
async def drain(self):
|
||||
return None
|
||||
|
||||
def close(self):
|
||||
self.closed = True
|
||||
|
||||
async def wait_closed(self):
|
||||
return None
|
||||
|
||||
|
||||
class RecordingIMAP:
|
||||
"""In-memory IMAPBackend stand-in for POP3 session tests."""
|
||||
|
||||
@@ -278,6 +387,7 @@ def test_dele_survives_stat_list_uidl_until_quit():
|
||||
asyncio.run(session.handle_list([]))
|
||||
asyncio.run(session.handle_uidl([]))
|
||||
assert b"2" in session.deleted
|
||||
# Default behaviour is not to mutate the backend mailbox on QUIT.
|
||||
asyncio.run(session.handle_quit())
|
||||
assert session._imap.marked == [b"2"]
|
||||
assert session._imap.expunged is True
|
||||
assert session._imap.marked == []
|
||||
assert session._imap.expunged is False
|
||||
|
||||
Reference in New Issue
Block a user