|
13 | 13 | delete_label, |
14 | 14 | mark_starred, |
15 | 15 | mark_unread, |
| 16 | + move, |
16 | 17 | save_draft, |
17 | 18 | update_draft, |
18 | 19 | update_folder, |
@@ -275,3 +276,44 @@ def test_failed_event_creation( |
275 | 276 | assert all(a.status == "failed" for a in q) |
276 | 277 |
|
277 | 278 | service.stop() |
| 279 | + |
| 280 | + |
| 281 | +def test_move_uses_imap_move_when_supported( |
| 282 | + db, default_account, message, folder, mock_imapclient |
| 283 | +) -> None: |
| 284 | + """Test that IMAP MOVE command is used when the server supports it.""" |
| 285 | + mock_imapclient.add_folder_data(folder.name, {}) |
| 286 | + mock_imapclient.add_folder_data("Archive", {}) |
| 287 | + mock_imapclient.capabilities = mock.Mock(return_value=[b"IMAP4rev1", b"MOVE"]) |
| 288 | + mock_imapclient.move = mock.Mock() |
| 289 | + mock_imapclient.copy = mock.Mock() |
| 290 | + mock_imapclient.delete_messages = mock.Mock() |
| 291 | + add_fake_imapuid(db.session, default_account.id, message, folder, 42) |
| 292 | + |
| 293 | + with writable_connection_pool(default_account.id).get() as crispin_client: |
| 294 | + move(crispin_client, default_account.id, message.id, {"destination": "Archive"}) |
| 295 | + |
| 296 | + mock_imapclient.move.assert_called_once_with([42], "Archive") |
| 297 | + mock_imapclient.copy.assert_not_called() |
| 298 | + |
| 299 | + |
| 300 | +def test_move_falls_back_to_copy_delete_when_move_not_supported( |
| 301 | + db, default_account, message, folder, mock_imapclient |
| 302 | +) -> None: |
| 303 | + """Test fallback to COPY+DELETE when MOVE is not supported.""" |
| 304 | + mock_imapclient.add_folder_data(folder.name, {}) |
| 305 | + mock_imapclient.add_folder_data("Archive", {}) |
| 306 | + mock_imapclient.capabilities = mock.Mock(return_value=[b"IMAP4rev1"]) |
| 307 | + mock_imapclient.move = mock.Mock() |
| 308 | + mock_imapclient.copy = mock.Mock() |
| 309 | + mock_imapclient.delete_messages = mock.Mock() |
| 310 | + mock_imapclient.expunge = mock.Mock() |
| 311 | + add_fake_imapuid(db.session, default_account.id, message, folder, 42) |
| 312 | + |
| 313 | + with writable_connection_pool(default_account.id).get() as crispin_client: |
| 314 | + move(crispin_client, default_account.id, message.id, {"destination": "Archive"}) |
| 315 | + |
| 316 | + mock_imapclient.move.assert_not_called() |
| 317 | + mock_imapclient.copy.assert_called_once_with([42], "Archive") |
| 318 | + # delete_uids converts UIDs to strings before calling delete_messages |
| 319 | + mock_imapclient.delete_messages.assert_called_once_with(["42"], silent=True) |
0 commit comments