deltachat-rpc-client 2.25.0__tar.gz → 2.27.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {deltachat_rpc_client-2.25.0/src/deltachat_rpc_client.egg-info → deltachat_rpc_client-2.27.0}/PKG-INFO +1 -1
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/pyproject.toml +1 -1
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/account.py +12 -2
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/const.py +6 -8
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/deltachat.py +10 -1
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/pytestplugin.py +8 -2
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0/src/deltachat_rpc_client.egg-info}/PKG-INFO +1 -1
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client.egg-info/SOURCES.txt +1 -0
- deltachat_rpc_client-2.27.0/tests/test_folders.py +538 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/tests/test_iroh_webxdc.py +3 -3
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/tests/test_multidevice.py +35 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/tests/test_securejoin.py +25 -28
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/tests/test_something.py +95 -106
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/LICENSE +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/README.md +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/setup.cfg +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/__init__.py +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/_utils.py +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/chat.py +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/client.py +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/contact.py +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/events.py +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/message.py +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/py.typed +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/rpc.py +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client.egg-info/dependency_links.txt +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client.egg-info/entry_points.txt +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client.egg-info/top_level.txt +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/tests/test_account_events.py +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/tests/test_calls.py +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/tests/test_chatlist_events.py +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/tests/test_key_transfer.py +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/tests/test_vcard.py +0 -0
- {deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/tests/test_webxdc.py +0 -0
{deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/account.py
RENAMED
|
@@ -399,9 +399,10 @@ class Account:
|
|
|
399
399
|
next_msg_ids = self._rpc.get_next_msgs(self.id)
|
|
400
400
|
return [Message(self, msg_id) for msg_id in next_msg_ids]
|
|
401
401
|
|
|
402
|
+
@futuremethod
|
|
402
403
|
def wait_next_messages(self) -> list[Message]:
|
|
403
404
|
"""Wait for new messages and return a list of them."""
|
|
404
|
-
next_msg_ids = self._rpc.wait_next_msgs(self.id)
|
|
405
|
+
next_msg_ids = yield self._rpc.wait_next_msgs.future(self.id)
|
|
405
406
|
return [Message(self, msg_id) for msg_id in next_msg_ids]
|
|
406
407
|
|
|
407
408
|
def wait_for_incoming_msg_event(self):
|
|
@@ -416,12 +417,21 @@ class Account:
|
|
|
416
417
|
"""Wait for messages noticed event and return it."""
|
|
417
418
|
return self.wait_for_event(EventType.MSGS_NOTICED)
|
|
418
419
|
|
|
420
|
+
def wait_for_msg(self, event_type) -> Message:
|
|
421
|
+
"""Wait for an event about the message.
|
|
422
|
+
|
|
423
|
+
Consumes all events before the matching event.
|
|
424
|
+
Returns a message corresponding to the msg_id field of the event.
|
|
425
|
+
"""
|
|
426
|
+
event = self.wait_for_event(event_type)
|
|
427
|
+
return self.get_message_by_id(event.msg_id)
|
|
428
|
+
|
|
419
429
|
def wait_for_incoming_msg(self):
|
|
420
430
|
"""Wait for incoming message and return it.
|
|
421
431
|
|
|
422
432
|
Consumes all events before the next incoming message event.
|
|
423
433
|
"""
|
|
424
|
-
return self.
|
|
434
|
+
return self.wait_for_msg(EventType.INCOMING_MSG)
|
|
425
435
|
|
|
426
436
|
def wait_for_securejoin_inviter_success(self):
|
|
427
437
|
"""Wait until SecureJoin process finishes successfully on the inviter side."""
|
{deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/const.py
RENAMED
|
@@ -91,19 +91,17 @@ class ChatId(IntEnum):
|
|
|
91
91
|
LAST_SPECIAL = 9
|
|
92
92
|
|
|
93
93
|
|
|
94
|
-
class ChatType(
|
|
94
|
+
class ChatType(str, Enum):
|
|
95
95
|
"""Chat type."""
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
SINGLE = 100
|
|
97
|
+
SINGLE = "Single"
|
|
100
98
|
"""1:1 chat, i.e. a direct chat with a single contact"""
|
|
101
99
|
|
|
102
|
-
GROUP =
|
|
100
|
+
GROUP = "Group"
|
|
103
101
|
|
|
104
|
-
MAILINGLIST =
|
|
102
|
+
MAILINGLIST = "Mailinglist"
|
|
105
103
|
|
|
106
|
-
OUT_BROADCAST =
|
|
104
|
+
OUT_BROADCAST = "OutBroadcast"
|
|
107
105
|
"""Outgoing broadcast channel, called "Channel" in the UI.
|
|
108
106
|
|
|
109
107
|
The user can send into this channel,
|
|
@@ -115,7 +113,7 @@ class ChatType(IntEnum):
|
|
|
115
113
|
which would make it hard to grep for it.
|
|
116
114
|
"""
|
|
117
115
|
|
|
118
|
-
IN_BROADCAST =
|
|
116
|
+
IN_BROADCAST = "InBroadcast"
|
|
119
117
|
"""Incoming broadcast channel, called "Channel" in the UI.
|
|
120
118
|
|
|
121
119
|
This channel is read-only,
|
{deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/deltachat.py
RENAMED
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
|
-
from ._utils import AttrDict
|
|
7
|
+
from ._utils import AttrDict, futuremethod
|
|
8
8
|
from .account import Account
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
@@ -39,6 +39,15 @@ class DeltaChat:
|
|
|
39
39
|
"""Stop the I/O of all accounts."""
|
|
40
40
|
self.rpc.stop_io_for_all_accounts()
|
|
41
41
|
|
|
42
|
+
@futuremethod
|
|
43
|
+
def background_fetch(self, timeout_in_seconds: int) -> None:
|
|
44
|
+
"""Run background fetch for all accounts."""
|
|
45
|
+
yield self.rpc.background_fetch.future(timeout_in_seconds)
|
|
46
|
+
|
|
47
|
+
def stop_background_fetch(self) -> None:
|
|
48
|
+
"""Stop ongoing background fetch."""
|
|
49
|
+
self.rpc.stop_background_fetch()
|
|
50
|
+
|
|
42
51
|
def maybe_network(self) -> None:
|
|
43
52
|
"""Indicate that the network conditions might have changed."""
|
|
44
53
|
self.rpc.maybe_network()
|
{deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/pytestplugin.py
RENAMED
|
@@ -135,9 +135,15 @@ def rpc(tmp_path) -> AsyncGenerator:
|
|
|
135
135
|
|
|
136
136
|
|
|
137
137
|
@pytest.fixture
|
|
138
|
-
def
|
|
138
|
+
def dc(rpc) -> DeltaChat:
|
|
139
|
+
"""Return account manager."""
|
|
140
|
+
return DeltaChat(rpc)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@pytest.fixture
|
|
144
|
+
def acfactory(dc) -> AsyncGenerator:
|
|
139
145
|
"""Return account factory fixture."""
|
|
140
|
-
return ACFactory(
|
|
146
|
+
return ACFactory(dc)
|
|
141
147
|
|
|
142
148
|
|
|
143
149
|
@pytest.fixture
|
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import re
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
from imap_tools import AND, U
|
|
7
|
+
|
|
8
|
+
from deltachat_rpc_client import Contact, EventType, Message
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_move_works(acfactory):
|
|
12
|
+
ac1, ac2 = acfactory.get_online_accounts(2)
|
|
13
|
+
ac2.set_config("mvbox_move", "1")
|
|
14
|
+
ac2.bring_online()
|
|
15
|
+
|
|
16
|
+
chat = ac1.create_chat(ac2)
|
|
17
|
+
chat.send_text("message1")
|
|
18
|
+
|
|
19
|
+
# Message is moved to the movebox
|
|
20
|
+
ac2.wait_for_event(EventType.IMAP_MESSAGE_MOVED)
|
|
21
|
+
|
|
22
|
+
# Message is downloaded
|
|
23
|
+
msg = ac2.wait_for_incoming_msg().get_snapshot()
|
|
24
|
+
assert msg.text == "message1"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_move_avoids_loop(acfactory, direct_imap):
|
|
28
|
+
"""Test that the message is only moved from INBOX to DeltaChat.
|
|
29
|
+
|
|
30
|
+
This is to avoid busy loop if moved message reappears in the Inbox
|
|
31
|
+
or some scanned folder later.
|
|
32
|
+
For example, this happens on servers that alias `INBOX.DeltaChat` to `DeltaChat` folder,
|
|
33
|
+
so the message moved to `DeltaChat` appears as a new message in the `INBOX.DeltaChat` folder.
|
|
34
|
+
We do not want to move this message from `INBOX.DeltaChat` to `DeltaChat` again.
|
|
35
|
+
"""
|
|
36
|
+
ac1, ac2 = acfactory.get_online_accounts(2)
|
|
37
|
+
ac2.set_config("mvbox_move", "1")
|
|
38
|
+
ac2.set_config("delete_server_after", "0")
|
|
39
|
+
ac2.bring_online()
|
|
40
|
+
|
|
41
|
+
# Create INBOX.DeltaChat folder and make sure
|
|
42
|
+
# it is detected by full folder scan.
|
|
43
|
+
ac2_direct_imap = direct_imap(ac2)
|
|
44
|
+
ac2_direct_imap.create_folder("INBOX.DeltaChat")
|
|
45
|
+
ac2.stop_io()
|
|
46
|
+
ac2.start_io()
|
|
47
|
+
|
|
48
|
+
while True:
|
|
49
|
+
event = ac2.wait_for_event()
|
|
50
|
+
# Wait until the end of folder scan.
|
|
51
|
+
if event.kind == EventType.INFO and "Found folders:" in event.msg:
|
|
52
|
+
break
|
|
53
|
+
|
|
54
|
+
ac1_chat = acfactory.get_accepted_chat(ac1, ac2)
|
|
55
|
+
ac1_chat.send_text("Message 1")
|
|
56
|
+
|
|
57
|
+
# Message is moved to the DeltaChat folder and downloaded.
|
|
58
|
+
ac2_msg1 = ac2.wait_for_incoming_msg().get_snapshot()
|
|
59
|
+
assert ac2_msg1.text == "Message 1"
|
|
60
|
+
|
|
61
|
+
# Move the message to the INBOX.DeltaChat again.
|
|
62
|
+
# We assume that test server uses "." as the delimiter.
|
|
63
|
+
ac2_direct_imap.select_folder("DeltaChat")
|
|
64
|
+
ac2_direct_imap.conn.move(["*"], "INBOX.DeltaChat")
|
|
65
|
+
|
|
66
|
+
ac1_chat.send_text("Message 2")
|
|
67
|
+
ac2_msg2 = ac2.wait_for_incoming_msg().get_snapshot()
|
|
68
|
+
assert ac2_msg2.text == "Message 2"
|
|
69
|
+
|
|
70
|
+
# Stop and start I/O to trigger folder scan.
|
|
71
|
+
ac2.stop_io()
|
|
72
|
+
ac2.start_io()
|
|
73
|
+
while True:
|
|
74
|
+
event = ac2.wait_for_event()
|
|
75
|
+
# Wait until the end of folder scan.
|
|
76
|
+
if event.kind == EventType.INFO and "Found folders:" in event.msg:
|
|
77
|
+
break
|
|
78
|
+
|
|
79
|
+
# Check that Message 1 is still in the INBOX.DeltaChat folder
|
|
80
|
+
# and Message 2 is in the DeltaChat folder.
|
|
81
|
+
ac2_direct_imap.select_folder("INBOX")
|
|
82
|
+
assert len(ac2_direct_imap.get_all_messages()) == 0
|
|
83
|
+
ac2_direct_imap.select_folder("DeltaChat")
|
|
84
|
+
assert len(ac2_direct_imap.get_all_messages()) == 1
|
|
85
|
+
ac2_direct_imap.select_folder("INBOX.DeltaChat")
|
|
86
|
+
assert len(ac2_direct_imap.get_all_messages()) == 1
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def test_reactions_for_a_reordering_move(acfactory, direct_imap):
|
|
90
|
+
"""When a batch of messages is moved from Inbox to DeltaChat folder with a single MOVE command,
|
|
91
|
+
their UIDs may be reordered (e.g. Gmail is known for that) which led to that messages were
|
|
92
|
+
processed by receive_imf in the wrong order, and, particularly, reactions were processed before
|
|
93
|
+
messages they refer to and thus dropped.
|
|
94
|
+
"""
|
|
95
|
+
(ac1,) = acfactory.get_online_accounts(1)
|
|
96
|
+
|
|
97
|
+
addr, password = acfactory.get_credentials()
|
|
98
|
+
ac2 = acfactory.get_unconfigured_account()
|
|
99
|
+
ac2.add_or_update_transport({"addr": addr, "password": password})
|
|
100
|
+
ac2.set_config("mvbox_move", "1")
|
|
101
|
+
assert ac2.is_configured()
|
|
102
|
+
|
|
103
|
+
ac2.bring_online()
|
|
104
|
+
chat1 = acfactory.get_accepted_chat(ac1, ac2)
|
|
105
|
+
ac2.stop_io()
|
|
106
|
+
|
|
107
|
+
logging.info("sending message + reaction from ac1 to ac2")
|
|
108
|
+
msg1 = chat1.send_text("hi")
|
|
109
|
+
msg1.wait_until_delivered()
|
|
110
|
+
# It's is sad, but messages must differ in their INTERNALDATEs to be processed in the correct
|
|
111
|
+
# order by DC, and most (if not all) mail servers provide only seconds precision.
|
|
112
|
+
time.sleep(1.1)
|
|
113
|
+
react_str = "\N{THUMBS UP SIGN}"
|
|
114
|
+
msg1.send_reaction(react_str).wait_until_delivered()
|
|
115
|
+
|
|
116
|
+
logging.info("moving messages to ac2's DeltaChat folder in the reverse order")
|
|
117
|
+
ac2_direct_imap = direct_imap(ac2)
|
|
118
|
+
ac2_direct_imap.connect()
|
|
119
|
+
for uid in sorted([m.uid for m in ac2_direct_imap.get_all_messages()], reverse=True):
|
|
120
|
+
ac2_direct_imap.conn.move(uid, "DeltaChat")
|
|
121
|
+
|
|
122
|
+
logging.info("receiving messages by ac2")
|
|
123
|
+
ac2.start_io()
|
|
124
|
+
msg2 = Message(ac2, ac2.wait_for_reactions_changed().msg_id)
|
|
125
|
+
assert msg2.get_snapshot().text == msg1.get_snapshot().text
|
|
126
|
+
reactions = msg2.get_reactions()
|
|
127
|
+
contacts = [Contact(ac2, int(i)) for i in reactions.reactions_by_contact]
|
|
128
|
+
assert len(contacts) == 1
|
|
129
|
+
assert contacts[0].get_snapshot().address == ac1.get_config("addr")
|
|
130
|
+
assert list(reactions.reactions_by_contact.values())[0] == [react_str]
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_delete_deltachat_folder(acfactory, direct_imap):
|
|
134
|
+
"""Test that DeltaChat folder is recreated if user deletes it manually."""
|
|
135
|
+
ac1 = acfactory.new_configured_account()
|
|
136
|
+
ac1.set_config("mvbox_move", "1")
|
|
137
|
+
ac1.bring_online()
|
|
138
|
+
|
|
139
|
+
ac1_direct_imap = direct_imap(ac1)
|
|
140
|
+
ac1_direct_imap.conn.folder.delete("DeltaChat")
|
|
141
|
+
assert "DeltaChat" not in ac1_direct_imap.list_folders()
|
|
142
|
+
|
|
143
|
+
# Wait until new folder is created and UIDVALIDITY is updated.
|
|
144
|
+
while True:
|
|
145
|
+
event = ac1.wait_for_event()
|
|
146
|
+
if event.kind == EventType.INFO and "uid/validity change folder DeltaChat" in event.msg:
|
|
147
|
+
break
|
|
148
|
+
|
|
149
|
+
ac2 = acfactory.get_online_account()
|
|
150
|
+
ac2.create_chat(ac1).send_text("hello")
|
|
151
|
+
msg = ac1.wait_for_incoming_msg().get_snapshot()
|
|
152
|
+
assert msg.text == "hello"
|
|
153
|
+
|
|
154
|
+
assert "DeltaChat" in ac1_direct_imap.list_folders()
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def test_dont_show_emails(acfactory, direct_imap, log):
|
|
158
|
+
"""Most mailboxes have a "Drafts" folder where constantly new emails appear but we don't actually want to show them.
|
|
159
|
+
So: If it's outgoing AND there is no Received header, then ignore the email.
|
|
160
|
+
|
|
161
|
+
If the draft email is sent out and received later (i.e. it's in "Inbox"), it must be shown.
|
|
162
|
+
|
|
163
|
+
Also, test that unknown emails in the Spam folder are not shown."""
|
|
164
|
+
ac1 = acfactory.new_configured_account()
|
|
165
|
+
ac1.stop_io()
|
|
166
|
+
ac1.set_config("show_emails", "2")
|
|
167
|
+
|
|
168
|
+
ac1.create_contact("alice@example.org").create_chat()
|
|
169
|
+
|
|
170
|
+
ac1_direct_imap = direct_imap(ac1)
|
|
171
|
+
ac1_direct_imap.create_folder("Drafts")
|
|
172
|
+
ac1_direct_imap.create_folder("Spam")
|
|
173
|
+
ac1_direct_imap.create_folder("Junk")
|
|
174
|
+
|
|
175
|
+
# Learn UID validity for all folders.
|
|
176
|
+
ac1.set_config("scan_all_folders_debounce_secs", "0")
|
|
177
|
+
ac1.start_io()
|
|
178
|
+
ac1.wait_for_event(EventType.IMAP_INBOX_IDLE)
|
|
179
|
+
ac1.stop_io()
|
|
180
|
+
|
|
181
|
+
ac1_direct_imap.append(
|
|
182
|
+
"Drafts",
|
|
183
|
+
"""
|
|
184
|
+
From: ac1 <{}>
|
|
185
|
+
Subject: subj
|
|
186
|
+
To: alice@example.org
|
|
187
|
+
Message-ID: <aepiors@example.org>
|
|
188
|
+
Content-Type: text/plain; charset=utf-8
|
|
189
|
+
|
|
190
|
+
message in Drafts received later
|
|
191
|
+
""".format(
|
|
192
|
+
ac1.get_config("configured_addr"),
|
|
193
|
+
),
|
|
194
|
+
)
|
|
195
|
+
ac1_direct_imap.append(
|
|
196
|
+
"Spam",
|
|
197
|
+
"""
|
|
198
|
+
From: unknown.address@junk.org
|
|
199
|
+
Subject: subj
|
|
200
|
+
To: {}
|
|
201
|
+
Message-ID: <spam.message@junk.org>
|
|
202
|
+
Content-Type: text/plain; charset=utf-8
|
|
203
|
+
|
|
204
|
+
Unknown message in Spam
|
|
205
|
+
""".format(
|
|
206
|
+
ac1.get_config("configured_addr"),
|
|
207
|
+
),
|
|
208
|
+
)
|
|
209
|
+
ac1_direct_imap.append(
|
|
210
|
+
"Spam",
|
|
211
|
+
"""
|
|
212
|
+
From: unknown.address@junk.org, unkwnown.add@junk.org
|
|
213
|
+
Subject: subj
|
|
214
|
+
To: {}
|
|
215
|
+
Message-ID: <spam.message2@junk.org>
|
|
216
|
+
Content-Type: text/plain; charset=utf-8
|
|
217
|
+
|
|
218
|
+
Unknown & malformed message in Spam
|
|
219
|
+
""".format(
|
|
220
|
+
ac1.get_config("configured_addr"),
|
|
221
|
+
),
|
|
222
|
+
)
|
|
223
|
+
ac1_direct_imap.append(
|
|
224
|
+
"Spam",
|
|
225
|
+
"""
|
|
226
|
+
From: delta<address: inbox@nhroy.com>
|
|
227
|
+
Subject: subj
|
|
228
|
+
To: {}
|
|
229
|
+
Message-ID: <spam.message99@junk.org>
|
|
230
|
+
Content-Type: text/plain; charset=utf-8
|
|
231
|
+
|
|
232
|
+
Unknown & malformed message in Spam
|
|
233
|
+
""".format(
|
|
234
|
+
ac1.get_config("configured_addr"),
|
|
235
|
+
),
|
|
236
|
+
)
|
|
237
|
+
ac1_direct_imap.append(
|
|
238
|
+
"Spam",
|
|
239
|
+
"""
|
|
240
|
+
From: alice@example.org
|
|
241
|
+
Subject: subj
|
|
242
|
+
To: {}
|
|
243
|
+
Message-ID: <spam.message3@junk.org>
|
|
244
|
+
Content-Type: text/plain; charset=utf-8
|
|
245
|
+
|
|
246
|
+
Actually interesting message in Spam
|
|
247
|
+
""".format(
|
|
248
|
+
ac1.get_config("configured_addr"),
|
|
249
|
+
),
|
|
250
|
+
)
|
|
251
|
+
ac1_direct_imap.append(
|
|
252
|
+
"Junk",
|
|
253
|
+
"""
|
|
254
|
+
From: unknown.address@junk.org
|
|
255
|
+
Subject: subj
|
|
256
|
+
To: {}
|
|
257
|
+
Message-ID: <spam.message@junk.org>
|
|
258
|
+
Content-Type: text/plain; charset=utf-8
|
|
259
|
+
|
|
260
|
+
Unknown message in Junk
|
|
261
|
+
""".format(
|
|
262
|
+
ac1.get_config("configured_addr"),
|
|
263
|
+
),
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
ac1.set_config("scan_all_folders_debounce_secs", "0")
|
|
267
|
+
log.section("All prepared, now let DC find the message")
|
|
268
|
+
ac1.start_io()
|
|
269
|
+
|
|
270
|
+
# Wait until each folder was scanned, this is necessary for this test to test what it should test:
|
|
271
|
+
ac1.wait_for_event(EventType.IMAP_INBOX_IDLE)
|
|
272
|
+
|
|
273
|
+
fresh_msgs = list(ac1.get_fresh_messages())
|
|
274
|
+
msg = fresh_msgs[0].get_snapshot()
|
|
275
|
+
chat_msgs = msg.chat.get_messages()
|
|
276
|
+
assert len(chat_msgs) == 1
|
|
277
|
+
assert msg.text == "subj – Actually interesting message in Spam"
|
|
278
|
+
|
|
279
|
+
assert not any("unknown.address" in c.get_full_snapshot().name for c in ac1.get_chatlist())
|
|
280
|
+
ac1_direct_imap.select_folder("Spam")
|
|
281
|
+
assert ac1_direct_imap.get_uid_by_message_id("spam.message@junk.org")
|
|
282
|
+
|
|
283
|
+
ac1.stop_io()
|
|
284
|
+
log.section("'Send out' the draft by moving it to Inbox, and wait for DC to display it this time")
|
|
285
|
+
ac1_direct_imap.select_folder("Drafts")
|
|
286
|
+
uid = ac1_direct_imap.get_uid_by_message_id("aepiors@example.org")
|
|
287
|
+
ac1_direct_imap.conn.move(uid, "Inbox")
|
|
288
|
+
|
|
289
|
+
ac1.start_io()
|
|
290
|
+
event = ac1.wait_for_event(EventType.MSGS_CHANGED)
|
|
291
|
+
msg2 = Message(ac1, event.msg_id).get_snapshot()
|
|
292
|
+
|
|
293
|
+
assert msg2.text == "subj – message in Drafts received later"
|
|
294
|
+
assert len(msg.chat.get_messages()) == 2
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def test_move_works_on_self_sent(acfactory):
|
|
298
|
+
ac1, ac2 = acfactory.get_online_accounts(2)
|
|
299
|
+
|
|
300
|
+
# Enable movebox and wait until it is created.
|
|
301
|
+
ac1.set_config("mvbox_move", "1")
|
|
302
|
+
ac1.set_config("bcc_self", "1")
|
|
303
|
+
ac1.bring_online()
|
|
304
|
+
|
|
305
|
+
chat = ac1.create_chat(ac2)
|
|
306
|
+
chat.send_text("message1")
|
|
307
|
+
ac1.wait_for_event(EventType.IMAP_MESSAGE_MOVED)
|
|
308
|
+
chat.send_text("message2")
|
|
309
|
+
ac1.wait_for_event(EventType.IMAP_MESSAGE_MOVED)
|
|
310
|
+
chat.send_text("message3")
|
|
311
|
+
ac1.wait_for_event(EventType.IMAP_MESSAGE_MOVED)
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def test_moved_markseen(acfactory, direct_imap):
|
|
315
|
+
"""Test that message already moved to DeltaChat folder is marked as seen."""
|
|
316
|
+
ac1, ac2 = acfactory.get_online_accounts(2)
|
|
317
|
+
ac2.set_config("mvbox_move", "1")
|
|
318
|
+
ac2.set_config("delete_server_after", "0")
|
|
319
|
+
ac2.set_config("sync_msgs", "0") # Do not send a sync message when accepting a contact request.
|
|
320
|
+
ac2.bring_online()
|
|
321
|
+
|
|
322
|
+
ac2.stop_io()
|
|
323
|
+
ac2_direct_imap = direct_imap(ac2)
|
|
324
|
+
with ac2_direct_imap.idle() as idle2:
|
|
325
|
+
ac1.create_chat(ac2).send_text("Hello!")
|
|
326
|
+
idle2.wait_for_new_message()
|
|
327
|
+
|
|
328
|
+
# Emulate moving of the message to DeltaChat folder by Sieve rule.
|
|
329
|
+
ac2_direct_imap.conn.move(["*"], "DeltaChat")
|
|
330
|
+
ac2_direct_imap.select_folder("DeltaChat")
|
|
331
|
+
assert len(list(ac2_direct_imap.conn.fetch("*", mark_seen=False))) == 1
|
|
332
|
+
|
|
333
|
+
with ac2_direct_imap.idle() as idle2:
|
|
334
|
+
ac2.start_io()
|
|
335
|
+
|
|
336
|
+
ev = ac2.wait_for_event(EventType.MSGS_CHANGED)
|
|
337
|
+
msg = ac2.get_message_by_id(ev.msg_id)
|
|
338
|
+
assert msg.get_snapshot().text == "Messages are end-to-end encrypted."
|
|
339
|
+
|
|
340
|
+
ev = ac2.wait_for_event(EventType.INCOMING_MSG)
|
|
341
|
+
msg = ac2.get_message_by_id(ev.msg_id)
|
|
342
|
+
chat = ac2.get_chat_by_id(ev.chat_id)
|
|
343
|
+
|
|
344
|
+
# Accept the contact request.
|
|
345
|
+
chat.accept()
|
|
346
|
+
msg.mark_seen()
|
|
347
|
+
idle2.wait_for_seen()
|
|
348
|
+
|
|
349
|
+
assert len(list(ac2_direct_imap.conn.fetch(AND(seen=True, uid=U(1, "*")), mark_seen=False))) == 1
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
@pytest.mark.parametrize("mvbox_move", [True, False])
|
|
353
|
+
def test_markseen_message_and_mdn(acfactory, direct_imap, mvbox_move):
|
|
354
|
+
ac1, ac2 = acfactory.get_online_accounts(2)
|
|
355
|
+
|
|
356
|
+
for ac in ac1, ac2:
|
|
357
|
+
ac.set_config("delete_server_after", "0")
|
|
358
|
+
if mvbox_move:
|
|
359
|
+
ac.set_config("mvbox_move", "1")
|
|
360
|
+
ac.bring_online()
|
|
361
|
+
|
|
362
|
+
# Do not send BCC to self, we only want to test MDN on ac1.
|
|
363
|
+
ac1.set_config("bcc_self", "0")
|
|
364
|
+
|
|
365
|
+
acfactory.get_accepted_chat(ac1, ac2).send_text("hi")
|
|
366
|
+
msg = ac2.wait_for_incoming_msg()
|
|
367
|
+
msg.mark_seen()
|
|
368
|
+
|
|
369
|
+
if mvbox_move:
|
|
370
|
+
rex = re.compile("Marked messages [0-9]+ in folder DeltaChat as seen.")
|
|
371
|
+
else:
|
|
372
|
+
rex = re.compile("Marked messages [0-9]+ in folder INBOX as seen.")
|
|
373
|
+
|
|
374
|
+
for ac in ac1, ac2:
|
|
375
|
+
while True:
|
|
376
|
+
event = ac.wait_for_event()
|
|
377
|
+
if event.kind == EventType.INFO and rex.search(event.msg):
|
|
378
|
+
break
|
|
379
|
+
|
|
380
|
+
folder = "mvbox" if mvbox_move else "inbox"
|
|
381
|
+
ac1_direct_imap = direct_imap(ac1)
|
|
382
|
+
ac2_direct_imap = direct_imap(ac2)
|
|
383
|
+
|
|
384
|
+
ac1_direct_imap.select_config_folder(folder)
|
|
385
|
+
ac2_direct_imap.select_config_folder(folder)
|
|
386
|
+
|
|
387
|
+
# Check that the mdn is marked as seen
|
|
388
|
+
assert len(list(ac1_direct_imap.conn.fetch(AND(seen=True), mark_seen=False))) == 1
|
|
389
|
+
# Check original message is marked as seen
|
|
390
|
+
assert len(list(ac2_direct_imap.conn.fetch(AND(seen=True), mark_seen=False))) == 1
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def test_mvbox_and_trash(acfactory, direct_imap, log):
|
|
394
|
+
log.section("ac1: start with mvbox")
|
|
395
|
+
ac1 = acfactory.get_online_account()
|
|
396
|
+
ac1.set_config("mvbox_move", "1")
|
|
397
|
+
ac1.bring_online()
|
|
398
|
+
|
|
399
|
+
log.section("ac2: start without a mvbox")
|
|
400
|
+
ac2 = acfactory.get_online_account()
|
|
401
|
+
|
|
402
|
+
log.section("ac1: create trash")
|
|
403
|
+
ac1_direct_imap = direct_imap(ac1)
|
|
404
|
+
ac1_direct_imap.create_folder("Trash")
|
|
405
|
+
ac1.set_config("scan_all_folders_debounce_secs", "0")
|
|
406
|
+
ac1.stop_io()
|
|
407
|
+
ac1.start_io()
|
|
408
|
+
|
|
409
|
+
log.section("ac1: send message and wait for ac2 to receive it")
|
|
410
|
+
acfactory.get_accepted_chat(ac1, ac2).send_text("message1")
|
|
411
|
+
assert ac2.wait_for_incoming_msg().get_snapshot().text == "message1"
|
|
412
|
+
|
|
413
|
+
assert ac1.get_config("configured_mvbox_folder") == "DeltaChat"
|
|
414
|
+
while ac1.get_config("configured_trash_folder") != "Trash":
|
|
415
|
+
ac1.wait_for_event(EventType.CONNECTIVITY_CHANGED)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
@pytest.mark.parametrize(
|
|
419
|
+
("folder", "move", "expected_destination"),
|
|
420
|
+
[
|
|
421
|
+
(
|
|
422
|
+
"xyz",
|
|
423
|
+
False,
|
|
424
|
+
"xyz",
|
|
425
|
+
), # Test that emails aren't found in a random folder
|
|
426
|
+
(
|
|
427
|
+
"xyz",
|
|
428
|
+
True,
|
|
429
|
+
"xyz",
|
|
430
|
+
), # ...emails are found in a random folder and downloaded without moving
|
|
431
|
+
(
|
|
432
|
+
"Spam",
|
|
433
|
+
False,
|
|
434
|
+
"INBOX",
|
|
435
|
+
), # ...emails are moved from the spam folder to the Inbox
|
|
436
|
+
],
|
|
437
|
+
)
|
|
438
|
+
# Testrun.org does not support the CREATE-SPECIAL-USE capability, which means that we can't create a folder with
|
|
439
|
+
# the "\Junk" flag (see https://tools.ietf.org/html/rfc6154). So, we can't test spam folder detection by flag.
|
|
440
|
+
def test_scan_folders(acfactory, log, direct_imap, folder, move, expected_destination):
|
|
441
|
+
"""Delta Chat periodically scans all folders for new messages to make sure we don't miss any."""
|
|
442
|
+
variant = folder + "-" + str(move) + "-" + expected_destination
|
|
443
|
+
log.section("Testing variant " + variant)
|
|
444
|
+
ac1, ac2 = acfactory.get_online_accounts(2)
|
|
445
|
+
ac1.set_config("delete_server_after", "0")
|
|
446
|
+
if move:
|
|
447
|
+
ac1.set_config("mvbox_move", "1")
|
|
448
|
+
ac1.bring_online()
|
|
449
|
+
|
|
450
|
+
ac1.stop_io()
|
|
451
|
+
ac1_direct_imap = direct_imap(ac1)
|
|
452
|
+
ac1_direct_imap.create_folder(folder)
|
|
453
|
+
|
|
454
|
+
# Wait until each folder was selected once and we are IDLEing:
|
|
455
|
+
ac1.start_io()
|
|
456
|
+
ac1.bring_online()
|
|
457
|
+
|
|
458
|
+
ac1.stop_io()
|
|
459
|
+
assert folder in ac1_direct_imap.list_folders()
|
|
460
|
+
|
|
461
|
+
log.section("Send a message from ac2 to ac1 and manually move it to `folder`")
|
|
462
|
+
ac1_direct_imap.select_config_folder("inbox")
|
|
463
|
+
with ac1_direct_imap.idle() as idle1:
|
|
464
|
+
acfactory.get_accepted_chat(ac2, ac1).send_text("hello")
|
|
465
|
+
idle1.wait_for_new_message()
|
|
466
|
+
ac1_direct_imap.conn.move(["*"], folder) # "*" means "biggest UID in mailbox"
|
|
467
|
+
|
|
468
|
+
log.section("start_io() and see if DeltaChat finds the message (" + variant + ")")
|
|
469
|
+
ac1.set_config("scan_all_folders_debounce_secs", "0")
|
|
470
|
+
ac1.start_io()
|
|
471
|
+
chat = ac1.create_chat(ac2)
|
|
472
|
+
n_msgs = 1 # "Messages are end-to-end encrypted."
|
|
473
|
+
if folder == "Spam":
|
|
474
|
+
msg = ac1.wait_for_incoming_msg().get_snapshot()
|
|
475
|
+
assert msg.text == "hello"
|
|
476
|
+
n_msgs += 1
|
|
477
|
+
else:
|
|
478
|
+
ac1.wait_for_event(EventType.IMAP_INBOX_IDLE)
|
|
479
|
+
assert len(chat.get_messages()) == n_msgs
|
|
480
|
+
|
|
481
|
+
# The message has reached its destination.
|
|
482
|
+
ac1_direct_imap.select_folder(expected_destination)
|
|
483
|
+
assert len(ac1_direct_imap.get_all_messages()) == 1
|
|
484
|
+
if folder != expected_destination:
|
|
485
|
+
ac1_direct_imap.select_folder(folder)
|
|
486
|
+
assert len(ac1_direct_imap.get_all_messages()) == 0
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def test_trash_multiple_messages(acfactory, direct_imap, log):
|
|
490
|
+
ac1, ac2 = acfactory.get_online_accounts(2)
|
|
491
|
+
ac2.stop_io()
|
|
492
|
+
|
|
493
|
+
# Create the Trash folder on IMAP server and configure deletion to it. There was a bug that if
|
|
494
|
+
# Trash wasn't configured initially, it can't be configured later, let's check this.
|
|
495
|
+
log.section("Creating trash folder")
|
|
496
|
+
ac2_direct_imap = direct_imap(ac2)
|
|
497
|
+
ac2_direct_imap.create_folder("Trash")
|
|
498
|
+
ac2.set_config("delete_server_after", "0")
|
|
499
|
+
ac2.set_config("sync_msgs", "0")
|
|
500
|
+
ac2.set_config("delete_to_trash", "1")
|
|
501
|
+
|
|
502
|
+
log.section("Check that Trash can be configured initially as well")
|
|
503
|
+
ac3 = ac2.clone()
|
|
504
|
+
ac3.bring_online()
|
|
505
|
+
assert ac3.get_config("configured_trash_folder")
|
|
506
|
+
ac3.stop_io()
|
|
507
|
+
|
|
508
|
+
ac2.start_io()
|
|
509
|
+
chat12 = acfactory.get_accepted_chat(ac1, ac2)
|
|
510
|
+
|
|
511
|
+
log.section("ac1: sending 3 messages")
|
|
512
|
+
texts = ["first", "second", "third"]
|
|
513
|
+
for text in texts:
|
|
514
|
+
chat12.send_text(text)
|
|
515
|
+
|
|
516
|
+
log.section("ac2: waiting for all messages on the other side")
|
|
517
|
+
to_delete = []
|
|
518
|
+
for text in texts:
|
|
519
|
+
msg = ac2.wait_for_incoming_msg().get_snapshot()
|
|
520
|
+
assert msg.text in texts
|
|
521
|
+
if text != "second":
|
|
522
|
+
to_delete.append(msg)
|
|
523
|
+
# ac2 has received some messages, this is impossible w/o the trash folder configured, let's
|
|
524
|
+
# check the configuration.
|
|
525
|
+
assert ac2.get_config("configured_trash_folder") == "Trash"
|
|
526
|
+
|
|
527
|
+
log.section("ac2: deleting all messages except second")
|
|
528
|
+
assert len(to_delete) == len(texts) - 1
|
|
529
|
+
ac2.delete_messages(to_delete)
|
|
530
|
+
|
|
531
|
+
log.section("ac2: test that only one message is left")
|
|
532
|
+
while 1:
|
|
533
|
+
ac2.wait_for_event(EventType.IMAP_MESSAGE_MOVED)
|
|
534
|
+
ac2_direct_imap.select_config_folder("inbox")
|
|
535
|
+
nr_msgs = len(ac2_direct_imap.get_all_messages())
|
|
536
|
+
assert nr_msgs > 0
|
|
537
|
+
if nr_msgs == 1:
|
|
538
|
+
break
|
|
@@ -84,7 +84,7 @@ def test_realtime_sequentially(acfactory, path_to_webxdc):
|
|
|
84
84
|
|
|
85
85
|
# share a webxdc app between ac1 and ac2
|
|
86
86
|
ac1_webxdc_msg = acfactory.send_message(from_account=ac1, to_account=ac2, text="play", file=path_to_webxdc)
|
|
87
|
-
ac2_webxdc_msg = ac2.
|
|
87
|
+
ac2_webxdc_msg = ac2.wait_for_incoming_msg()
|
|
88
88
|
snapshot = ac2_webxdc_msg.get_snapshot()
|
|
89
89
|
assert snapshot.text == "play"
|
|
90
90
|
|
|
@@ -94,7 +94,7 @@ def test_realtime_sequentially(acfactory, path_to_webxdc):
|
|
|
94
94
|
acfactory.send_message(from_account=ac1, to_account=ac2, text="ping1")
|
|
95
95
|
|
|
96
96
|
log("waiting for incoming message on ac2")
|
|
97
|
-
snapshot = ac2.
|
|
97
|
+
snapshot = ac2.wait_for_incoming_msg().get_snapshot()
|
|
98
98
|
assert snapshot.text == "ping1"
|
|
99
99
|
|
|
100
100
|
log("sending ac2 -> ac1 realtime advertisement and additional message")
|
|
@@ -102,7 +102,7 @@ def test_realtime_sequentially(acfactory, path_to_webxdc):
|
|
|
102
102
|
acfactory.send_message(from_account=ac2, to_account=ac1, text="ping2")
|
|
103
103
|
|
|
104
104
|
log("waiting for incoming message on ac1")
|
|
105
|
-
snapshot = ac1.
|
|
105
|
+
snapshot = ac1.wait_for_incoming_msg().get_snapshot()
|
|
106
106
|
assert snapshot.text == "ping2"
|
|
107
107
|
|
|
108
108
|
log("sending realtime data ac1 -> ac2")
|
|
@@ -4,6 +4,41 @@ from deltachat_rpc_client import EventType
|
|
|
4
4
|
from deltachat_rpc_client.const import MessageState
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
def test_bcc_self_delete_server_after_defaults(acfactory):
|
|
8
|
+
"""Test default values for bcc_self and delete_server_after."""
|
|
9
|
+
ac = acfactory.get_online_account()
|
|
10
|
+
|
|
11
|
+
# Initially after getting online
|
|
12
|
+
# the setting bcc_self is set to 0 because there is only one device
|
|
13
|
+
# and delete_server_after is "1", meaning immediate deletion.
|
|
14
|
+
assert ac.get_config("bcc_self") == "0"
|
|
15
|
+
assert ac.get_config("delete_server_after") == "1"
|
|
16
|
+
|
|
17
|
+
# Setup a second device.
|
|
18
|
+
ac_clone = ac.clone()
|
|
19
|
+
ac_clone.bring_online()
|
|
20
|
+
|
|
21
|
+
# Second device setup
|
|
22
|
+
# enables bcc_self and changes default delete_server_after.
|
|
23
|
+
assert ac.get_config("bcc_self") == "1"
|
|
24
|
+
assert ac.get_config("delete_server_after") == "0"
|
|
25
|
+
|
|
26
|
+
assert ac_clone.get_config("bcc_self") == "1"
|
|
27
|
+
assert ac_clone.get_config("delete_server_after") == "0"
|
|
28
|
+
|
|
29
|
+
# Manually disabling bcc_self
|
|
30
|
+
# also restores the default for delete_server_after.
|
|
31
|
+
ac.set_config("bcc_self", "0")
|
|
32
|
+
assert ac.get_config("bcc_self") == "0"
|
|
33
|
+
assert ac.get_config("delete_server_after") == "1"
|
|
34
|
+
|
|
35
|
+
# Cloning the account again enables bcc_self
|
|
36
|
+
# even though it was manually disabled.
|
|
37
|
+
ac_clone = ac.clone()
|
|
38
|
+
assert ac.get_config("bcc_self") == "1"
|
|
39
|
+
assert ac.get_config("delete_server_after") == "0"
|
|
40
|
+
|
|
41
|
+
|
|
7
42
|
def test_one_account_send_bcc_setting(acfactory, log, direct_imap):
|
|
8
43
|
ac1, ac2 = acfactory.get_online_accounts(2)
|
|
9
44
|
ac1_clone = ac1.clone()
|
|
@@ -86,7 +86,7 @@ def test_qr_securejoin(acfactory):
|
|
|
86
86
|
alice_contact_bob_snapshot = alice_contact_bob.get_snapshot()
|
|
87
87
|
assert alice_contact_bob_snapshot.is_verified
|
|
88
88
|
|
|
89
|
-
snapshot = bob.
|
|
89
|
+
snapshot = bob.wait_for_incoming_msg().get_snapshot()
|
|
90
90
|
assert snapshot.text == "Member Me added by {}.".format(alice.get_config("addr"))
|
|
91
91
|
|
|
92
92
|
# Test that Bob verified Alice's profile.
|
|
@@ -140,15 +140,15 @@ def test_qr_securejoin_broadcast(acfactory, all_devices_online):
|
|
|
140
140
|
return chat
|
|
141
141
|
|
|
142
142
|
def wait_for_broadcast_messages(ac):
|
|
143
|
-
|
|
143
|
+
snapshot1 = ac.wait_for_incoming_msg().get_snapshot()
|
|
144
|
+
assert snapshot1.text == "You joined the channel."
|
|
144
145
|
|
|
145
|
-
|
|
146
|
-
assert
|
|
147
|
-
assert snapshot.chat_id == chat.id
|
|
146
|
+
snapshot2 = ac.wait_for_incoming_msg().get_snapshot()
|
|
147
|
+
assert snapshot2.text == "Hello everyone!"
|
|
148
148
|
|
|
149
|
-
|
|
150
|
-
assert
|
|
151
|
-
assert
|
|
149
|
+
chat = get_broadcast(ac)
|
|
150
|
+
assert snapshot1.chat_id == chat.id
|
|
151
|
+
assert snapshot2.chat_id == chat.id
|
|
152
152
|
|
|
153
153
|
def check_account(ac, contact, inviter_side, please_wait_info_msg=False):
|
|
154
154
|
# Check that the chat partner is verified.
|
|
@@ -255,7 +255,7 @@ def test_qr_securejoin_contact_request(acfactory) -> None:
|
|
|
255
255
|
alice_chat_bob = alice_contact_bob.create_chat()
|
|
256
256
|
alice_chat_bob.send_text("Hello!")
|
|
257
257
|
|
|
258
|
-
snapshot = bob.
|
|
258
|
+
snapshot = bob.wait_for_incoming_msg().get_snapshot()
|
|
259
259
|
assert snapshot.text == "Hello!"
|
|
260
260
|
bob_chat_alice = snapshot.chat
|
|
261
261
|
assert bob_chat_alice.get_basic_snapshot().is_contact_request
|
|
@@ -299,8 +299,7 @@ def test_qr_readreceipt(acfactory) -> None:
|
|
|
299
299
|
|
|
300
300
|
logging.info("Bob and Charlie receive a group")
|
|
301
301
|
|
|
302
|
-
|
|
303
|
-
bob_message = bob.get_message_by_id(bob_msg_id)
|
|
302
|
+
bob_message = bob.wait_for_incoming_msg()
|
|
304
303
|
bob_snapshot = bob_message.get_snapshot()
|
|
305
304
|
assert bob_snapshot.text == "Hello"
|
|
306
305
|
|
|
@@ -311,8 +310,7 @@ def test_qr_readreceipt(acfactory) -> None:
|
|
|
311
310
|
|
|
312
311
|
bob_out_message = bob_snapshot.chat.send_message(text="Hi from Bob!")
|
|
313
312
|
|
|
314
|
-
|
|
315
|
-
charlie_message = charlie.get_message_by_id(charlie_msg_id)
|
|
313
|
+
charlie_message = charlie.wait_for_incoming_msg()
|
|
316
314
|
charlie_snapshot = charlie_message.get_snapshot()
|
|
317
315
|
assert charlie_snapshot.text == "Hi from Bob!"
|
|
318
316
|
|
|
@@ -387,7 +385,7 @@ def test_verified_group_member_added_recovery(acfactory) -> None:
|
|
|
387
385
|
ac3_contact_ac2 = ac3.create_contact(ac2)
|
|
388
386
|
ac3_chat.remove_contact(ac3_contact_ac2_old)
|
|
389
387
|
|
|
390
|
-
snapshot = ac1.
|
|
388
|
+
snapshot = ac1.wait_for_incoming_msg().get_snapshot()
|
|
391
389
|
assert "removed" in snapshot.text
|
|
392
390
|
|
|
393
391
|
ac3_chat.add_contact(ac3_contact_ac2)
|
|
@@ -400,18 +398,17 @@ def test_verified_group_member_added_recovery(acfactory) -> None:
|
|
|
400
398
|
logging.info("ac2 got event message: %s", snapshot.text)
|
|
401
399
|
assert "added" in snapshot.text
|
|
402
400
|
|
|
403
|
-
snapshot = ac1.
|
|
401
|
+
snapshot = ac1.wait_for_incoming_msg().get_snapshot()
|
|
404
402
|
assert "added" in snapshot.text
|
|
405
403
|
|
|
406
404
|
chat = Chat(ac2, chat_id)
|
|
407
405
|
chat.send_text("Works again!")
|
|
408
406
|
|
|
409
|
-
|
|
410
|
-
message = ac3.get_message_by_id(msg_id)
|
|
407
|
+
message = ac3.wait_for_incoming_msg()
|
|
411
408
|
snapshot = message.get_snapshot()
|
|
412
409
|
assert snapshot.text == "Works again!"
|
|
413
410
|
|
|
414
|
-
snapshot = ac1.
|
|
411
|
+
snapshot = ac1.wait_for_incoming_msg().get_snapshot()
|
|
415
412
|
assert snapshot.text == "Works again!"
|
|
416
413
|
|
|
417
414
|
ac1_contact_ac2 = ac1.create_contact(ac2)
|
|
@@ -447,7 +444,7 @@ def test_qr_join_chat_with_pending_bobstate_issue4894(acfactory):
|
|
|
447
444
|
# ensure ac1 can write and ac2 receives messages in verified chat
|
|
448
445
|
ch1.send_text("ac1 says hello")
|
|
449
446
|
while 1:
|
|
450
|
-
snapshot = ac2.
|
|
447
|
+
snapshot = ac2.wait_for_incoming_msg().get_snapshot()
|
|
451
448
|
if snapshot.text == "ac1 says hello":
|
|
452
449
|
break
|
|
453
450
|
|
|
@@ -468,7 +465,7 @@ def test_qr_join_chat_with_pending_bobstate_issue4894(acfactory):
|
|
|
468
465
|
# ensure ac2 receives message in VG
|
|
469
466
|
vg.send_text("hello")
|
|
470
467
|
while 1:
|
|
471
|
-
msg = ac2.
|
|
468
|
+
msg = ac2.wait_for_incoming_msg().get_snapshot()
|
|
472
469
|
if msg.text == "hello":
|
|
473
470
|
break
|
|
474
471
|
|
|
@@ -505,7 +502,7 @@ def test_qr_new_group_unblocked(acfactory):
|
|
|
505
502
|
ac2.wait_for_incoming_msg_event()
|
|
506
503
|
|
|
507
504
|
ac1_new_chat.send_text("Hello!")
|
|
508
|
-
ac2_msg = ac2.
|
|
505
|
+
ac2_msg = ac2.wait_for_incoming_msg().get_snapshot()
|
|
509
506
|
assert ac2_msg.text == "Hello!"
|
|
510
507
|
assert ac2_msg.chat.get_basic_snapshot().is_contact_request
|
|
511
508
|
|
|
@@ -530,7 +527,7 @@ def test_aeap_flow_verified(acfactory):
|
|
|
530
527
|
|
|
531
528
|
logging.info("receiving first message")
|
|
532
529
|
ac2.wait_for_incoming_msg_event() # member added message
|
|
533
|
-
msg_in_1 = ac2.
|
|
530
|
+
msg_in_1 = ac2.wait_for_incoming_msg().get_snapshot()
|
|
534
531
|
assert msg_in_1.text == msg_out.text
|
|
535
532
|
|
|
536
533
|
logging.info("changing email account")
|
|
@@ -544,7 +541,7 @@ def test_aeap_flow_verified(acfactory):
|
|
|
544
541
|
msg_out = chat.send_text("changed address").get_snapshot()
|
|
545
542
|
|
|
546
543
|
logging.info("receiving second message")
|
|
547
|
-
msg_in_2 = ac2.
|
|
544
|
+
msg_in_2 = ac2.wait_for_incoming_msg()
|
|
548
545
|
msg_in_2_snapshot = msg_in_2.get_snapshot()
|
|
549
546
|
assert msg_in_2_snapshot.text == msg_out.text
|
|
550
547
|
assert msg_in_2_snapshot.chat.id == msg_in_1.chat.id
|
|
@@ -576,7 +573,7 @@ def test_gossip_verification(acfactory) -> None:
|
|
|
576
573
|
bob_group_chat.add_contact(bob_contact_carol)
|
|
577
574
|
bob_group_chat.send_message(text="Hello Autocrypt group")
|
|
578
575
|
|
|
579
|
-
snapshot = carol.
|
|
576
|
+
snapshot = carol.wait_for_incoming_msg().get_snapshot()
|
|
580
577
|
assert snapshot.text == "Hello Autocrypt group"
|
|
581
578
|
assert snapshot.show_padlock
|
|
582
579
|
|
|
@@ -592,7 +589,7 @@ def test_gossip_verification(acfactory) -> None:
|
|
|
592
589
|
bob_group_chat.add_contact(bob_contact_carol)
|
|
593
590
|
bob_group_chat.send_message(text="Hello Securejoin group")
|
|
594
591
|
|
|
595
|
-
snapshot = carol.
|
|
592
|
+
snapshot = carol.wait_for_incoming_msg().get_snapshot()
|
|
596
593
|
assert snapshot.text == "Hello Securejoin group"
|
|
597
594
|
assert snapshot.show_padlock
|
|
598
595
|
|
|
@@ -620,7 +617,7 @@ def test_securejoin_after_contact_resetup(acfactory) -> None:
|
|
|
620
617
|
ac1.wait_for_securejoin_joiner_success()
|
|
621
618
|
|
|
622
619
|
# ac1 waits for member added message and creates a QR code.
|
|
623
|
-
snapshot = ac1.
|
|
620
|
+
snapshot = ac1.wait_for_incoming_msg().get_snapshot()
|
|
624
621
|
assert snapshot.text == "Member Me added by {}.".format(ac3.get_config("addr"))
|
|
625
622
|
ac1_qr_code = snapshot.chat.get_qr_code()
|
|
626
623
|
|
|
@@ -657,7 +654,7 @@ def test_securejoin_after_contact_resetup(acfactory) -> None:
|
|
|
657
654
|
|
|
658
655
|
# Wait for member added.
|
|
659
656
|
logging.info("ac2 waits for member added message")
|
|
660
|
-
snapshot = ac2.
|
|
657
|
+
snapshot = ac2.wait_for_incoming_msg().get_snapshot()
|
|
661
658
|
assert snapshot.is_info
|
|
662
659
|
ac2_chat = snapshot.chat
|
|
663
660
|
assert len(ac2_chat.get_contacts()) == 3
|
|
@@ -679,7 +676,7 @@ def test_withdraw_securejoin_qr(acfactory):
|
|
|
679
676
|
|
|
680
677
|
alice.clear_all_events()
|
|
681
678
|
|
|
682
|
-
snapshot = bob.
|
|
679
|
+
snapshot = bob.wait_for_incoming_msg().get_snapshot()
|
|
683
680
|
assert snapshot.text == "Member Me added by {}.".format(alice.get_config("addr"))
|
|
684
681
|
bob_chat.leave()
|
|
685
682
|
|
|
@@ -352,9 +352,7 @@ def test_receive_imf_failure(acfactory) -> None:
|
|
|
352
352
|
# The failed message doesn't break the IMAP loop.
|
|
353
353
|
bob.set_config("fail_on_receiving_full_msg", "0")
|
|
354
354
|
alice_chat_bob.send_text("Hello again!")
|
|
355
|
-
|
|
356
|
-
msg_id = event.msg_id
|
|
357
|
-
message = bob.get_message_by_id(msg_id)
|
|
355
|
+
message = bob.wait_for_incoming_msg()
|
|
358
356
|
snapshot = message.get_snapshot()
|
|
359
357
|
assert snapshot.text == "Hello again!"
|
|
360
358
|
assert snapshot.download_state == DownloadState.DONE
|
|
@@ -423,10 +421,7 @@ def test_is_bot(acfactory) -> None:
|
|
|
423
421
|
alice.set_config("bot", "1")
|
|
424
422
|
alice_chat_bob.send_text("Hello!")
|
|
425
423
|
|
|
426
|
-
|
|
427
|
-
message = bob.get_message_by_id(event.msg_id)
|
|
428
|
-
snapshot = message.get_snapshot()
|
|
429
|
-
assert snapshot.chat_id == event.chat_id
|
|
424
|
+
snapshot = bob.wait_for_incoming_msg().get_snapshot()
|
|
430
425
|
assert snapshot.text == "Hello!"
|
|
431
426
|
assert snapshot.is_bot
|
|
432
427
|
|
|
@@ -484,22 +479,21 @@ def test_wait_next_messages(acfactory) -> None:
|
|
|
484
479
|
# There are no old messages and the call returns immediately.
|
|
485
480
|
assert not bot.wait_next_messages()
|
|
486
481
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
next_messages_task = executor.submit(bot.wait_next_messages)
|
|
482
|
+
# Bot starts waiting for messages.
|
|
483
|
+
next_messages_task = bot.wait_next_messages.future()
|
|
490
484
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
485
|
+
alice_contact_bot = alice.create_contact(bot, "Bot")
|
|
486
|
+
alice_chat_bot = alice_contact_bot.create_chat()
|
|
487
|
+
alice_chat_bot.send_text("Hello!")
|
|
494
488
|
|
|
495
|
-
|
|
489
|
+
next_messages = next_messages_task()
|
|
496
490
|
|
|
497
|
-
|
|
498
|
-
|
|
491
|
+
if len(next_messages) == E2EE_INFO_MSGS:
|
|
492
|
+
next_messages += bot.wait_next_messages()
|
|
499
493
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
494
|
+
assert len(next_messages) == 1 + E2EE_INFO_MSGS
|
|
495
|
+
snapshot = next_messages[0 + E2EE_INFO_MSGS].get_snapshot()
|
|
496
|
+
assert snapshot.text == "Hello!"
|
|
503
497
|
|
|
504
498
|
|
|
505
499
|
def test_import_export_backup(acfactory, tmp_path) -> None:
|
|
@@ -519,7 +513,7 @@ def test_import_export_keys(acfactory, tmp_path) -> None:
|
|
|
519
513
|
alice_chat_bob = alice.create_chat(bob)
|
|
520
514
|
alice_chat_bob.send_text("Hello Bob!")
|
|
521
515
|
|
|
522
|
-
snapshot = bob.
|
|
516
|
+
snapshot = bob.wait_for_incoming_msg().get_snapshot()
|
|
523
517
|
assert snapshot.text == "Hello Bob!"
|
|
524
518
|
|
|
525
519
|
# Alice resetups account, but keeps the key.
|
|
@@ -531,7 +525,7 @@ def test_import_export_keys(acfactory, tmp_path) -> None:
|
|
|
531
525
|
|
|
532
526
|
snapshot.chat.accept()
|
|
533
527
|
snapshot.chat.send_text("Hello Alice!")
|
|
534
|
-
snapshot = alice.
|
|
528
|
+
snapshot = alice.wait_for_incoming_msg().get_snapshot()
|
|
535
529
|
assert snapshot.text == "Hello Alice!"
|
|
536
530
|
assert snapshot.show_padlock
|
|
537
531
|
|
|
@@ -576,18 +570,13 @@ def test_mdn_doesnt_break_autocrypt(acfactory) -> None:
|
|
|
576
570
|
|
|
577
571
|
# Alice sends a message to Bob.
|
|
578
572
|
alice_chat_bob.send_text("Hello Bob!")
|
|
579
|
-
|
|
580
|
-
msg_id = event.msg_id
|
|
581
|
-
message = bob.get_message_by_id(msg_id)
|
|
582
|
-
snapshot = message.get_snapshot()
|
|
573
|
+
snapshot = bob.wait_for_incoming_msg().get_snapshot()
|
|
583
574
|
|
|
584
575
|
# Bob sends a message to Alice.
|
|
585
576
|
bob_chat_alice = snapshot.chat
|
|
586
577
|
bob_chat_alice.accept()
|
|
587
578
|
bob_chat_alice.send_text("Hello Alice!")
|
|
588
|
-
|
|
589
|
-
msg_id = event.msg_id
|
|
590
|
-
message = alice.get_message_by_id(msg_id)
|
|
579
|
+
message = alice.wait_for_incoming_msg()
|
|
591
580
|
snapshot = message.get_snapshot()
|
|
592
581
|
assert snapshot.show_padlock
|
|
593
582
|
|
|
@@ -597,10 +586,7 @@ def test_mdn_doesnt_break_autocrypt(acfactory) -> None:
|
|
|
597
586
|
|
|
598
587
|
# Bob sends a message to Alice, it should also be encrypted.
|
|
599
588
|
bob_chat_alice.send_text("Hi Alice!")
|
|
600
|
-
|
|
601
|
-
msg_id = event.msg_id
|
|
602
|
-
message = alice.get_message_by_id(msg_id)
|
|
603
|
-
snapshot = message.get_snapshot()
|
|
589
|
+
snapshot = alice.wait_for_incoming_msg().get_snapshot()
|
|
604
590
|
assert snapshot.show_padlock
|
|
605
591
|
|
|
606
592
|
|
|
@@ -658,50 +644,6 @@ def test_reaction_to_partially_fetched_msg(acfactory, tmp_path):
|
|
|
658
644
|
assert list(reactions.reactions_by_contact.values())[0] == [react_str]
|
|
659
645
|
|
|
660
646
|
|
|
661
|
-
def test_reactions_for_a_reordering_move(acfactory, direct_imap):
|
|
662
|
-
"""When a batch of messages is moved from Inbox to DeltaChat folder with a single MOVE command,
|
|
663
|
-
their UIDs may be reordered (e.g. Gmail is known for that) which led to that messages were
|
|
664
|
-
processed by receive_imf in the wrong order, and, particularly, reactions were processed before
|
|
665
|
-
messages they refer to and thus dropped.
|
|
666
|
-
"""
|
|
667
|
-
(ac1,) = acfactory.get_online_accounts(1)
|
|
668
|
-
|
|
669
|
-
addr, password = acfactory.get_credentials()
|
|
670
|
-
ac2 = acfactory.get_unconfigured_account()
|
|
671
|
-
ac2.add_or_update_transport({"addr": addr, "password": password})
|
|
672
|
-
ac2.set_config("mvbox_move", "1")
|
|
673
|
-
assert ac2.is_configured()
|
|
674
|
-
|
|
675
|
-
ac2.bring_online()
|
|
676
|
-
chat1 = acfactory.get_accepted_chat(ac1, ac2)
|
|
677
|
-
ac2.stop_io()
|
|
678
|
-
|
|
679
|
-
logging.info("sending message + reaction from ac1 to ac2")
|
|
680
|
-
msg1 = chat1.send_text("hi")
|
|
681
|
-
msg1.wait_until_delivered()
|
|
682
|
-
# It's is sad, but messages must differ in their INTERNALDATEs to be processed in the correct
|
|
683
|
-
# order by DC, and most (if not all) mail servers provide only seconds precision.
|
|
684
|
-
time.sleep(1.1)
|
|
685
|
-
react_str = "\N{THUMBS UP SIGN}"
|
|
686
|
-
msg1.send_reaction(react_str).wait_until_delivered()
|
|
687
|
-
|
|
688
|
-
logging.info("moving messages to ac2's DeltaChat folder in the reverse order")
|
|
689
|
-
ac2_direct_imap = direct_imap(ac2)
|
|
690
|
-
ac2_direct_imap.connect()
|
|
691
|
-
for uid in sorted([m.uid for m in ac2_direct_imap.get_all_messages()], reverse=True):
|
|
692
|
-
ac2_direct_imap.conn.move(uid, "DeltaChat")
|
|
693
|
-
|
|
694
|
-
logging.info("receiving messages by ac2")
|
|
695
|
-
ac2.start_io()
|
|
696
|
-
msg2 = Message(ac2, ac2.wait_for_reactions_changed().msg_id)
|
|
697
|
-
assert msg2.get_snapshot().text == msg1.get_snapshot().text
|
|
698
|
-
reactions = msg2.get_reactions()
|
|
699
|
-
contacts = [Contact(ac2, int(i)) for i in reactions.reactions_by_contact]
|
|
700
|
-
assert len(contacts) == 1
|
|
701
|
-
assert contacts[0].get_snapshot().address == ac1.get_config("addr")
|
|
702
|
-
assert list(reactions.reactions_by_contact.values())[0] == [react_str]
|
|
703
|
-
|
|
704
|
-
|
|
705
647
|
@pytest.mark.parametrize("n_accounts", [3, 2])
|
|
706
648
|
def test_download_limit_chat_assignment(acfactory, tmp_path, n_accounts):
|
|
707
649
|
download_limit = 300000
|
|
@@ -713,7 +655,7 @@ def test_download_limit_chat_assignment(acfactory, tmp_path, n_accounts):
|
|
|
713
655
|
for account in others:
|
|
714
656
|
chat = account.create_chat(alice)
|
|
715
657
|
chat.send_text("Hello Alice!")
|
|
716
|
-
assert alice.
|
|
658
|
+
assert alice.wait_for_incoming_msg().get_snapshot().text == "Hello Alice!"
|
|
717
659
|
|
|
718
660
|
contact = alice.create_contact(account)
|
|
719
661
|
alice_group.add_contact(contact)
|
|
@@ -723,7 +665,7 @@ def test_download_limit_chat_assignment(acfactory, tmp_path, n_accounts):
|
|
|
723
665
|
bob.set_config("download_limit", str(download_limit))
|
|
724
666
|
|
|
725
667
|
alice_group.send_text("hi")
|
|
726
|
-
snapshot = bob.
|
|
668
|
+
snapshot = bob.wait_for_incoming_msg().get_snapshot()
|
|
727
669
|
assert snapshot.text == "hi"
|
|
728
670
|
bob_group = snapshot.chat
|
|
729
671
|
|
|
@@ -733,7 +675,7 @@ def test_download_limit_chat_assignment(acfactory, tmp_path, n_accounts):
|
|
|
733
675
|
for i in range(10):
|
|
734
676
|
logging.info("Sending message %s", i)
|
|
735
677
|
alice_group.send_file(str(path))
|
|
736
|
-
snapshot = bob.
|
|
678
|
+
snapshot = bob.wait_for_incoming_msg().get_snapshot()
|
|
737
679
|
assert snapshot.download_state == DownloadState.AVAILABLE
|
|
738
680
|
if n_accounts > 2:
|
|
739
681
|
assert snapshot.chat == bob_group
|
|
@@ -760,8 +702,8 @@ def test_markseen_contact_request(acfactory):
|
|
|
760
702
|
alice_chat_bob = alice.create_chat(bob)
|
|
761
703
|
alice_chat_bob.send_text("Hello Bob!")
|
|
762
704
|
|
|
763
|
-
message = bob.
|
|
764
|
-
message2 = bob2.
|
|
705
|
+
message = bob.wait_for_incoming_msg()
|
|
706
|
+
message2 = bob2.wait_for_incoming_msg()
|
|
765
707
|
assert message2.get_snapshot().state == MessageState.IN_FRESH
|
|
766
708
|
|
|
767
709
|
message.mark_seen()
|
|
@@ -783,7 +725,7 @@ def test_read_receipt(acfactory):
|
|
|
783
725
|
msg = bob.wait_for_incoming_msg()
|
|
784
726
|
msg.mark_seen()
|
|
785
727
|
|
|
786
|
-
read_msg = alice.
|
|
728
|
+
read_msg = alice.wait_for_msg(EventType.MSG_READ)
|
|
787
729
|
read_receipts = read_msg.get_read_receipts()
|
|
788
730
|
assert len(read_receipts) == 1
|
|
789
731
|
assert read_receipts[0].contact_id == alice_contact_bob.id
|
|
@@ -889,30 +831,6 @@ def test_get_all_accounts_deadlock(rpc):
|
|
|
889
831
|
all_accounts()
|
|
890
832
|
|
|
891
833
|
|
|
892
|
-
def test_delete_deltachat_folder(acfactory, direct_imap):
|
|
893
|
-
"""Test that DeltaChat folder is recreated if user deletes it manually."""
|
|
894
|
-
ac1 = acfactory.new_configured_account()
|
|
895
|
-
ac1.set_config("mvbox_move", "1")
|
|
896
|
-
ac1.bring_online()
|
|
897
|
-
|
|
898
|
-
ac1_direct_imap = direct_imap(ac1)
|
|
899
|
-
ac1_direct_imap.conn.folder.delete("DeltaChat")
|
|
900
|
-
assert "DeltaChat" not in ac1_direct_imap.list_folders()
|
|
901
|
-
|
|
902
|
-
# Wait until new folder is created and UIDVALIDITY is updated.
|
|
903
|
-
while True:
|
|
904
|
-
event = ac1.wait_for_event()
|
|
905
|
-
if event.kind == EventType.INFO and "uid/validity change folder DeltaChat" in event.msg:
|
|
906
|
-
break
|
|
907
|
-
|
|
908
|
-
ac2 = acfactory.get_online_account()
|
|
909
|
-
ac2.create_chat(ac1).send_text("hello")
|
|
910
|
-
msg = ac1.wait_for_incoming_msg().get_snapshot()
|
|
911
|
-
assert msg.text == "hello"
|
|
912
|
-
|
|
913
|
-
assert "DeltaChat" in ac1_direct_imap.list_folders()
|
|
914
|
-
|
|
915
|
-
|
|
916
834
|
@pytest.mark.parametrize("all_devices_online", [True, False])
|
|
917
835
|
def test_leave_broadcast(acfactory, all_devices_online):
|
|
918
836
|
alice, bob = acfactory.get_online_accounts(2)
|
|
@@ -1013,3 +931,74 @@ def test_leave_broadcast(acfactory, all_devices_online):
|
|
|
1013
931
|
bob2.wait_for_event(EventType.CHAT_MODIFIED)
|
|
1014
932
|
|
|
1015
933
|
check_account(bob2, bob2.create_contact(alice), inviter_side=False)
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
def test_immediate_autodelete(acfactory, direct_imap, log):
|
|
937
|
+
ac1, ac2 = acfactory.get_online_accounts(2)
|
|
938
|
+
|
|
939
|
+
# "1" means delete immediately, while "0" means do not delete
|
|
940
|
+
ac2.set_config("delete_server_after", "1")
|
|
941
|
+
|
|
942
|
+
log.section("ac1: create chat with ac2")
|
|
943
|
+
chat1 = ac1.create_chat(ac2)
|
|
944
|
+
ac2.create_chat(ac1)
|
|
945
|
+
|
|
946
|
+
log.section("ac1: send message to ac2")
|
|
947
|
+
sent_msg = chat1.send_text("hello")
|
|
948
|
+
|
|
949
|
+
msg = ac2.wait_for_incoming_msg()
|
|
950
|
+
assert msg.get_snapshot().text == "hello"
|
|
951
|
+
|
|
952
|
+
log.section("ac2: wait for close/expunge on autodelete")
|
|
953
|
+
ac2.wait_for_event(EventType.IMAP_MESSAGE_DELETED)
|
|
954
|
+
while True:
|
|
955
|
+
event = ac2.wait_for_event()
|
|
956
|
+
if event.kind == EventType.INFO and "Close/expunge succeeded." in event.msg:
|
|
957
|
+
break
|
|
958
|
+
|
|
959
|
+
log.section("ac2: check that message was autodeleted on server")
|
|
960
|
+
ac2_direct_imap = direct_imap(ac2)
|
|
961
|
+
assert len(ac2_direct_imap.get_all_messages()) == 0
|
|
962
|
+
|
|
963
|
+
log.section("ac2: Mark deleted message as seen and check that read receipt arrives")
|
|
964
|
+
msg.mark_seen()
|
|
965
|
+
ev = ac1.wait_for_event(EventType.MSG_READ)
|
|
966
|
+
assert ev.chat_id == chat1.id
|
|
967
|
+
assert ev.msg_id == sent_msg.id
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
def test_background_fetch(acfactory, dc):
|
|
971
|
+
ac1, ac2 = acfactory.get_online_accounts(2)
|
|
972
|
+
ac1.stop_io()
|
|
973
|
+
|
|
974
|
+
ac1_chat = ac1.create_chat(ac2)
|
|
975
|
+
|
|
976
|
+
ac2_chat = ac2.create_chat(ac1)
|
|
977
|
+
ac2_chat.send_text("Hello!")
|
|
978
|
+
|
|
979
|
+
while True:
|
|
980
|
+
dc.background_fetch(300)
|
|
981
|
+
messages = ac1_chat.get_messages()
|
|
982
|
+
snapshot = messages[-1].get_snapshot()
|
|
983
|
+
if snapshot.text == "Hello!":
|
|
984
|
+
break
|
|
985
|
+
|
|
986
|
+
# Stopping background fetch immediately after starting
|
|
987
|
+
# does not result in any errors.
|
|
988
|
+
background_fetch_future = dc.background_fetch.future(300)
|
|
989
|
+
dc.stop_background_fetch()
|
|
990
|
+
background_fetch_future()
|
|
991
|
+
|
|
992
|
+
# Starting background fetch with zero timeout is ok,
|
|
993
|
+
# it should terminate immediately.
|
|
994
|
+
dc.background_fetch(0)
|
|
995
|
+
|
|
996
|
+
# Background fetch can still be used to send and receive messages.
|
|
997
|
+
ac2_chat.send_text("Hello again!")
|
|
998
|
+
|
|
999
|
+
while True:
|
|
1000
|
+
dc.background_fetch(300)
|
|
1001
|
+
messages = ac1_chat.get_messages()
|
|
1002
|
+
snapshot = messages[-1].get_snapshot()
|
|
1003
|
+
if snapshot.text == "Hello again!":
|
|
1004
|
+
break
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/__init__.py
RENAMED
|
File without changes
|
{deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/_utils.py
RENAMED
|
File without changes
|
{deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/chat.py
RENAMED
|
File without changes
|
{deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/client.py
RENAMED
|
File without changes
|
{deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/contact.py
RENAMED
|
File without changes
|
{deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/events.py
RENAMED
|
File without changes
|
{deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/message.py
RENAMED
|
File without changes
|
{deltachat_rpc_client-2.25.0 → deltachat_rpc_client-2.27.0}/src/deltachat_rpc_client/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|