Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions benches/decrypting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use deltachat::internals_for_benches::create_broadcast_secret;
use deltachat::internals_for_benches::save_broadcast_secret;
use deltachat::securejoin::get_securejoin_qr;
use deltachat::{
Events, chat::ChatId, config::Config, context::Context, internals_for_benches::key_from_asc,
Events, chat::ChatId, context::Context, internals_for_benches::key_from_asc,
internals_for_benches::parse_and_get_text, internals_for_benches::store_self_keypair,
stock_str::StockStrings,
};
Expand All @@ -57,10 +57,6 @@ async fn create_context() -> Context {
.await
.unwrap();

context
.set_config(Config::ConfiguredAddr, Some("bob@example.net"))
.await
.unwrap();
let secret = key_from_asc(include_str!("../test-data/key/bob-secret.asc")).unwrap();
store_self_keypair(&context, &secret)
.await
Expand Down
11 changes: 0 additions & 11 deletions benches/receive_emails.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use std::path::PathBuf;
use criterion::{Criterion, criterion_group, criterion_main};
use deltachat::{
Events,
config::Config,
context::Context,
imex::{ImexMode, imex},
receive_imf::receive_imf,
Expand Down Expand Up @@ -109,16 +108,6 @@ async fn create_context() -> Context {
.unwrap();
}

let addr = "alice@example.com";
context.set_config(Config::Addr, Some(addr)).await.unwrap();
context
.set_config(Config::ConfiguredAddr, Some(addr))
.await
.unwrap();
context
.set_config(Config::Configured, Some("1"))
.await
.unwrap();
context
}

Expand Down
7 changes: 1 addition & 6 deletions deltachat-ffi/deltachat.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,9 +389,6 @@ char* dc_get_blobdir (const dc_context_t* context);
/**
* Configure the context. The configuration is handled by key=value pairs as:
*
* - `configured_addr` = Email address in use.
* Unless for testing, do not set this value using dc_set_config().
* Instead, set `addr` and call dc_configure().
* - `displayname` = Own name to use when sending messages. MUAs are allowed to spread this way e.g. using CC, defaults to empty
* - `selfstatus` = Own status to display, e.g. in e-mail footers, defaults to empty
* - `selfavatar` = File containing avatar. Will immediately be copied to the
Expand Down Expand Up @@ -478,8 +475,6 @@ char* dc_get_blobdir (const dc_context_t* context);
* if you want to use the deprecated dc_configure() API, such as:
*
* - `addr` = Email address to use for configuration.
* If dc_configure() fails this is not the email address actually in use.
* Use `configured_addr` to find out the email address actually in use.
* - `mail_server` = IMAP-server, guessed if left out
* - `mail_user` = IMAP-username, guessed if left out
* - `mail_pw` = IMAP-password (always needed)
Expand Down Expand Up @@ -6471,7 +6466,7 @@ void dc_event_unref(dc_event_t* event);
* The event is emitted on the device modifying the transports
* as well as on other devices applying the synced change,
* for the JSON-RPC calls `add_or_update_transport`, `add_transport_from_qr`,
* `delete_transport` or `set_config(configured_addr)`.
* `delete_transport`.
*/
#define DC_EVENT_TRANSPORTS_MODIFIED 2600

Expand Down
29 changes: 27 additions & 2 deletions deltachat-rpc-client/tests/test_cross_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,31 @@ def test_second_device(acf, alice_and_remote_bob) -> None:
assert new_account.get_config("addr") == remote_eval("bob.get_config('addr')")


def test_old_device_delete_transport(acf, alice_and_remote_bob) -> None:
"""Test setting up old core as the second device for the new core and deleting a transport.

Old core unfortunately expects that deprecated configured_addr config value is set
and fails to delete a transport otherwise. The test makes sure new core sets some configured_addr
for backwards compatibility."""
alice, _alice_contact_bob, remote_eval = alice_and_remote_bob("2.62.0")

alice.set_config("displayname", "Alice123")
qr = acf.get_account_qr()
alice.add_transport_from_qr(qr)

alice_provide_backup_future = alice._rpc.provide_backup.future(alice.id)
qr = alice._rpc.get_backup_qr(alice.id)

remote_eval("locals().setdefault('new_account', bob.manager.add_account())")
remote_eval(f"new_account._rpc.get_backup(new_account.id, {qr!r})")
alice_provide_backup_future()

assert alice.get_config("displayname") == remote_eval("new_account.get_config('displayname')")

first_transport_addr = alice.list_transports()[0]["addr"]
remote_eval(f"new_account.delete_transport({first_transport_addr!r})")


@pytest.mark.parametrize("replace_relay", [False, True], ids=["add", "replace"])
def test_keyupdate_against_core_2_48_march_2026(acf, alice_and_remote_bob, replace_relay):
"""Test 2.48 Bob learns a relay change of Alice from a keyupdate, and is shown nothing."""
Expand All @@ -104,7 +129,6 @@ def bob_sees():
# an accepted chat alone is not enough, a message must have flowed.
alice_chat = alice_contact_bob.create_chat()
alice.set_config("keyupdate_debounce", "1")
old_addr = alice.get_config("configured_addr")
alice_chat.send_text("hi")
assert remote_eval("bob.wait_for_incoming_msg().get_snapshot().text") == "hi"
before = bob_sees()
Expand All @@ -113,8 +137,9 @@ def bob_sees():
# and signature timestamps have one-second resolution:
# without waiting, the re-signed key can tie with the copy Bob holds, keeping his.
time.sleep(2)
old_addr = alice.list_transports()[0]["addr"]
alice.add_transport_from_qr(acf.get_account_qr())
(new_addr,) = [t["addr"] for t in alice.list_transports() if t["addr"] != old_addr]
new_addr = alice.list_transports()[1]["addr"]
if replace_relay:
alice.delete_transport(old_addr)
alice.bring_online()
Expand Down
34 changes: 2 additions & 32 deletions deltachat-rpc-client/tests/test_multitransport.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,8 @@ def test_add_second_address(acf) -> None:
second_addr = account.list_transports()[1]["addr"]
third_addr = account.list_transports()[2]["addr"]

assert account.get_config("configured_addr") == first_addr
account.delete_transport(first_addr)
assert len(account.list_transports()) == 2
assert account.get_config("configured_addr") != first_addr

account.delete_transport(second_addr)
assert len(account.list_transports()) == 1
Expand Down Expand Up @@ -187,17 +185,13 @@ def wait_transports(ac, n):
wait_for_io_started(ac1)
[transport1, transport3] = ac1.list_transports()

log.section("ac1 changes the sending transport")
ac1.set_config("configured_addr", transport3["addr"])

log.section("ac1 removes the first transport")
ac1.delete_transport(transport1["addr"])

wait_transports(ac1_clone, 1)
wait_for_io_started(ac1_clone)
[transport3] = ac1_clone.list_transports()
assert transport3["addr"] == addr3
assert ac1_clone.get_config("configured_addr") == addr3

ac2_chat = ac2.create_chat(ac1)
ac2_chat.send_text("Hello!")
Expand All @@ -206,8 +200,8 @@ def wait_transports(ac, n):
assert ac1_clone.wait_for_incoming_msg().get_snapshot().text == "Hello!"


def test_transport_sync_new_as_primary(acf, log) -> None:
"""Test that a transport promoted on one device is usable on other devices."""
def test_receive_message_after_transport_sync(acf) -> None:
"""Test that second device can receive messages after transport synchronization."""
ac1, bob = acf.get_online_accounts(2)
ac1_clone = ac1.clone()
ac1_clone.bring_online()
Expand All @@ -221,12 +215,7 @@ def test_transport_sync_new_as_primary(acf, log) -> None:
[transport1, transport2] = ac1_transports
ac1_clone.wait_for_event(EventType.TRANSPORTS_MODIFIED)
assert len(ac1_clone.list_transports()) == 2
assert ac1_clone.get_config("configured_addr") == transport1["addr"]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test now doesn't test a lot anymore, it only does some very basic things:

  • ac1 and ac1_clone is a multi-device profile
  • ac1 adds a transport
  • ac1 sends a message, the test doesn't control which transport is used for this
  • Bob answers
  • ac1_clone receives the answer

Until we have functional end-to-end tests that can control the network (i.e. a test that can block the first transport in order to ensure that the message is sent via the second transport), I guess we can't do much here, but we need to update the test name and comments. And then we need to make sure to quickly make functional bad-network tests possible, because right now we wouldn't notice any regressions in this area until DC is deployed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test name and comments need to be updated, because they say "new_as_primary" and "a transport promoted on one device", which is not true anymore

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed it into test_receive_message_after_transport_sync and updated the documentation comment to "Test that second device can receive messages after transport synchronization."

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And then we need to make sure to quickly make functional bad-network tests possible, because right now we wouldn't notice any regressions in this area until DC is deployed.

I opened #8867 (currently WIP) for an idea of how we can test most of the failover code offline in Rust.


log.section("ac1 changes the primary transport")
ac1.set_config("configured_addr", transport2["addr"])

log.section("ac1_clone receives a message via the new transport")
ac1_chat = ac1.create_chat(bob)
ac1_chat.send_text("Hello!")
bob_chat_id = bob.wait_for_incoming_msg_event().chat_id
Expand All @@ -236,22 +225,6 @@ def test_transport_sync_new_as_primary(acf, log) -> None:
assert ac1_clone.wait_for_incoming_msg().get_snapshot().text == "hello back"


def test_recognize_self_address(acf) -> None:
alice, bob = acf.get_online_accounts(2)

bob_chat = bob.create_chat(alice)

qr = acf.get_account_qr()
alice.add_transport_from_qr(qr)

new_alice_addr = alice.list_transports()[1]["addr"]
alice.set_config("configured_addr", new_alice_addr)

bob_chat.send_text("Hello!")
msg = alice.wait_for_incoming_msg().get_snapshot()
assert msg.chat == alice.create_chat(bob)


def test_transport_limit(acf) -> None:
"""Test transports limit."""
account = acf.get_online_account()
Expand Down Expand Up @@ -294,7 +267,6 @@ def test_message_info_imap_urls(acf) -> None:

# Alice switches to another transport and removes the rest of the transports.
new_alice_addr = alice.list_transports()[1]["addr"]
alice.set_config("configured_addr", new_alice_addr)
removed_addrs = []
for transport in alice.list_transports():
if transport["addr"] != new_alice_addr:
Expand Down Expand Up @@ -326,7 +298,6 @@ def test_remove_primary_transport(acf, log) -> None:

log.section("Alice removes the primary relay")
alice.delete_transport(transport1["addr"])
assert alice.get_config("configured_addr") == transport2["addr"]
alice.stop_io()
alice.start_io()

Expand Down Expand Up @@ -369,7 +340,6 @@ def test_qr_works_after_removing_primary_transport(acf, log) -> None:
def test_background_fetch_from_second_transport(acf, direct_imap, dc):
alice, alice_chat, bob_chat = alice_with_two_transports_and_bob(acf)
[transport1, transport2] = alice.list_transports()
assert alice.get_config("configured_addr") == transport1["addr"]

alice.stop_io()
bob_chat.send_text("hello")
Expand Down
3 changes: 1 addition & 2 deletions deltachat-rpc-client/tests/test_securejoin.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,9 +647,8 @@ def test_qr_scan_updates_new_relay_address(acf):
bob.wait_for_securejoin_joiner_success()

for ac in [alice, bob]:
old_addr = ac.get_config("configured_addr")
old_addr = ac.list_transports()[0]["addr"]
ac.add_transport_from_qr(acf.get_account_qr())
ac.set_config("configured_addr", ac.list_transports()[1]["addr"])
ac.delete_transport(old_addr)

bob.secure_join(alice.get_qr_code())
Expand Down
5 changes: 2 additions & 3 deletions deltachat-rpc-client/tests/test_something.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ def test_lowercase_address(acf) -> None:
)
assert account.is_configured()
assert addr_upper != addr
assert account.get_config("configured_addr") == addr
assert account.list_transports()[0]["addr"] == addr

param = account.get_info()["used_transport_settings"]
Expand Down Expand Up @@ -168,7 +167,7 @@ def test_list_transports(acf) -> None:
def test_account(acf) -> None:
alice, bob = acf.get_online_accounts(2)

bob_addr = bob.get_config("configured_addr")
bob_addr = bob.list_transports()[0]["addr"]
alice_contact_bob = alice.create_contact(bob, "Bob")
alice_chat_bob = alice_contact_bob.create_chat()
alice_chat_bob.send_text("Hello!")
Expand Down Expand Up @@ -331,7 +330,7 @@ def test_chat(acf) -> None:
def test_contact(acf) -> None:
alice, bob = acf.get_online_accounts(2)

bob_addr = bob.get_config("configured_addr")
bob_addr = bob.list_transports()[0]["addr"]
alice_contact_bob = alice.create_contact(bob, "Bob")

assert alice_contact_bob == alice.get_contact_by_id(alice_contact_bob.id)
Expand Down
7 changes: 1 addition & 6 deletions python/src/deltachat/testplugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,12 +370,7 @@ def get_pseudo_configured_account(self, passphrase: Optional[str] = None) -> Acc
acname = ac._logid
addr = f"{acname}@offline.org"
lib.dc_add_pseudo_transport(ac._dc_context, as_dc_charpointer(addr))
ac.update_config(
{
"configured_addr": addr,
"displayname": acname,
},
)
ac.set_config("displayname", acname)
self._preconfigure_key(ac)
self._acsetup.init_logging(ac)
assert ac.is_configured(), "Pseudo configured account should look like if it is configured"
Expand Down
1 change: 0 additions & 1 deletion python/tests/test_0_complex_or_slow.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ def test_group_many_members_add_leave_remove(self, acfactory, lp):

lp.sec("ac2: receiving system message about contact addition")
sysmsg = ac2._evtracker.wait_next_incoming_message()
assert ac5.get_config("configured_addr") in sysmsg.text
assert sysmsg.chat.num_contacts() == 4

lp.sec("ac5: waiting for message about addition to the chat")
Expand Down
12 changes: 6 additions & 6 deletions python/tests/test_3_offline.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def test_get_blocked(self, acfactory):

def test_create_self_contact(self, acfactory):
ac1 = acfactory.get_pseudo_configured_account()
contact1 = ac1.create_contact(ac1.get_config("configured_addr"))
contact1 = ac1.create_contact(ac1.get_self_contact().addr)
assert contact1.id == 1

def test_get_contacts_and_delete(self, acfactory):
Expand Down Expand Up @@ -223,7 +223,7 @@ def test_group_chat_add_second_account(self, acfactory):
ac2 = acfactory.get_pseudo_configured_account()
chat = ac1.create_group_chat(name="title1")
contact = chat.add_contact(ac2)
assert contact.addr == ac2.get_config("configured_addr")
assert contact.addr == ac2.get_self_contact().addr
assert contact.name == ac2.get_config("displayname")
assert contact.account == ac1
chat.remove_contact(ac2)
Expand Down Expand Up @@ -456,7 +456,7 @@ def test_import_export_on_unencrypted_acct(self, acfactory, tmp_path):
contacts = ac2.get_contacts()
assert len(contacts) == 1
contact2 = contacts[0]
assert contact2.addr == ac_contact.get_config("configured_addr")
assert contact2.addr == ac_contact.get_self_contact().addr
chat2 = contact2.create_chat()
messages = chat2.get_messages()
assert len(messages) == 2 + E2EE_INFO_MSGS
Expand Down Expand Up @@ -552,7 +552,7 @@ def test_import_export_with_passphrase(self, acfactory, tmp_path):
contacts = ac2.get_contacts()
assert len(contacts) == 1
contact2 = contacts[0]
assert contact2.addr == ac_contact.get_config("configured_addr")
assert contact2.addr == ac_contact.get_self_contact().addr
chat2 = contact2.create_chat()
messages = chat2.get_messages()
assert len(messages) == 2 + E2EE_INFO_MSGS
Expand Down Expand Up @@ -604,7 +604,7 @@ def test_import_encrypted_bak_into_encrypted_acct(self, acfactory, tmp_path):
contacts = ac2.get_contacts()
assert len(contacts) == 1
contact2 = contacts[0]
assert contact2.addr == ac_contact.get_config("configured_addr")
Comment thread
Hocuri marked this conversation as resolved.
Resolved
assert contact2.addr == ac_contact.get_self_contact().addr
chat2 = contact2.create_chat()
messages = chat2.get_messages()
assert len(messages) == 2 + E2EE_INFO_MSGS
Expand All @@ -621,7 +621,7 @@ def test_import_encrypted_bak_into_encrypted_acct(self, acfactory, tmp_path):
contacts = ac2.get_contacts()
assert len(contacts) == 1
contact2 = contacts[0]
assert contact2.addr == ac_contact.get_config("configured_addr")
assert contact2.addr == ac_contact.get_self_contact().addr
chat2 = contact2.create_chat()
messages = chat2.get_messages()
assert len(messages) == 2 + E2EE_INFO_MSGS
Expand Down
12 changes: 3 additions & 9 deletions src/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2893,15 +2893,9 @@ async fn create_send_msg_jobs(context: &Context, msg: &mut Message) -> Result<Ve
let (queued_msg, side_effects) = queued_msg_pair;

if needs_encryption && !is_encrypted {
let addr = context.get_config(Config::ConfiguredAddr).await?;
let text = stock_str::unencrypted_email(
context,
addr.unwrap_or_default()
.split('@')
.nth(1)
.unwrap_or_default(),
)
.await;
let addr = context.get_primary_self_addr().await?;
let text =
stock_str::unencrypted_email(context, addr.split('@').nth(1).unwrap_or_default()).await;
message::set_msg_failed(context, msg, &text).await?;
add_info_msg_with_cmd(
context,
Expand Down
Loading
Loading