Description
The MailBox.move() method catches all exceptions when attempting UID MOVE, then silently falls back to COPY + DELETE + EXPUNGE. This means real errors — network failures, authentication issues, quota exceeded, permission denied — are swallowed, and the user has no idea the operation didn't succeed as expected.
Location
email_profile/clients/imap/mailbox.py — lines 189–196
Current Behavior
def move(self, target: MessageLike, destination: str) -> None:
_state(self._client.select(_quote(self.name)))
uid = _uid_of(target)
try:
_state(self._client.uid("MOVE", uid, destination))
except Exception: # ← catches EVERYTHING
_state(self._client.uid("COPY", uid, destination))
_state(self._client.uid("STORE", uid, "+FLAGS", "\\Deleted"))
_state(self._client.expunge())
Example of masked failure
with Email("user@gmail.com", "pw") as app:
# Server is rate-limiting, but move() catches the RateLimited
# exception and tries COPY — which also fails silently
app.inbox.move(uid, "Archive")
# No error raised, but the message was never moved
Another scenario
# Network drops mid-operation: MOVE fails, COPY fails too,
# but the exception from COPY is raised — confusing traceback
# points to COPY instead of the real issue (network)
Expected Behavior
Only catch the specific exception that indicates the server doesn't support MOVE (RFC 6851). Let all other errors propagate normally.
Suggested Fix
import imaplib
def move(self, target: MessageLike, destination: str) -> None:
_state(self._client.select(_quote(self.name)))
uid = _uid_of(target)
try:
_state(self._client.uid("MOVE", uid, destination))
except imaplib.IMAP4.error:
# Server doesn't support MOVE — fall back to COPY + DELETE
_state(self._client.uid("COPY", uid, destination))
_state(self._client.uid("STORE", uid, "+FLAGS", "\\Deleted"))
_state(self._client.expunge())
Impact
Who: Any user calling move(), MailBox.move(), or any code path that triggers a move operation.
Severity: Critical — silent data loss. Users believe the message was moved, but it may still be in the original mailbox (or worse, deleted from source without being copied).
Priority
Critical
Description
The
MailBox.move()method catches all exceptions when attemptingUID MOVE, then silently falls back toCOPY + DELETE + EXPUNGE. This means real errors — network failures, authentication issues, quota exceeded, permission denied — are swallowed, and the user has no idea the operation didn't succeed as expected.Location
email_profile/clients/imap/mailbox.py— lines 189–196Current Behavior
Example of masked failure
Another scenario
Expected Behavior
Only catch the specific exception that indicates the server doesn't support
MOVE(RFC 6851). Let all other errors propagate normally.Suggested Fix
Impact
Who: Any user calling
move(),MailBox.move(), or any code path that triggers a move operation.Severity: Critical — silent data loss. Users believe the message was moved, but it may still be in the original mailbox (or worse, deleted from source without being copied).
Priority
Critical