diff --git a/deltachat-rpc-client/tests/test_securejoin.py b/deltachat-rpc-client/tests/test_securejoin.py index 54799adf1..238eff840 100644 --- a/deltachat-rpc-client/tests/test_securejoin.py +++ b/deltachat-rpc-client/tests/test_securejoin.py @@ -704,3 +704,21 @@ def test_withdraw_securejoin_qr(acfactory): and "Ignoring RequestWithAuth message because of invalid auth code." in event.msg ): break + + +def test_qr_scan_updates_new_relay_address(acfactory): + alice, bob = acfactory.get_online_accounts(2) + + bob.secure_join(alice.get_qr_code()) + alice.wait_for_securejoin_inviter_success() + bob.wait_for_securejoin_joiner_success() + + for ac in [alice, bob]: + old_addr = ac.get_config("configured_addr") + ac.add_transport_from_qr(acfactory.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()) + alice.wait_for_securejoin_inviter_success() + bob.wait_for_securejoin_joiner_success() diff --git a/src/contact.rs b/src/contact.rs index 310600c96..df4367cf1 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -1026,7 +1026,9 @@ impl Contact { || row_authname.is_empty()); row_id = id; - if origin >= row_origin && addr != row_addr { + let qr_with_fingerprint = !fingerprint.is_empty() + && origin == Origin::UnhandledSecurejoinQrScan; + if (origin >= row_origin || qr_with_fingerprint) && addr != row_addr { update_addr = true; } if update_name || update_authname || update_addr || origin > row_origin { diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 07a899e7a..3be965e14 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -271,9 +271,7 @@ impl MimeFactory { let public_key = SignedPublicKey::from_slice(&public_key_bytes)?; - let relays = - addresses_from_public_key(&public_key).unwrap_or_else(|| vec![addr.clone()]); - recipients.extend(relays); + recipients.extend(relay_addrs(&public_key, &addr)); to.push((authname, addr.clone())); encryption_pubkeys = Some(vec![(addr, public_key)]); @@ -353,7 +351,7 @@ impl MimeFactory { }; if add_timestamp >= remove_timestamp { let relays = if let Some(public_key) = public_key_opt { - let addrs = addresses_from_public_key(&public_key); + let addrs = relay_addrs(&public_key, &addr); keys.push((addr.clone(), public_key)); addrs } else if id != ContactId::SELF && !should_encrypt_symmetrically(&msg, &chat) { @@ -361,10 +359,10 @@ impl MimeFactory { if is_encrypted { warn!(context, "Missing key for {addr}"); } - None + vec![addr.clone()] } else { - None - }.unwrap_or_else(|| vec![addr.clone()]); + vec![addr.clone()] + }; if !recipients_contain_addr(&to, &addr) { if id != ContactId::SELF { @@ -393,7 +391,7 @@ impl MimeFactory { if let Some(email_to_remove) = email_to_remove && email_to_remove == addr { let relays = if let Some(public_key) = public_key_opt { - let addrs = addresses_from_public_key(&public_key); + let addrs = relay_addrs(&public_key, &addr); keys.push((addr.clone(), public_key)); addrs } else if id != ContactId::SELF && !should_encrypt_symmetrically(&msg, &chat) { @@ -401,10 +399,10 @@ impl MimeFactory { if is_encrypted { warn!(context, "Missing key for {addr}"); } - None + vec![addr.clone()] } else { - None - }.unwrap_or_else(|| vec![addr.clone()]); + vec![addr.clone()] + }; // This is a "member removed" message, // we need to notify removed member @@ -2203,6 +2201,14 @@ async fn build_avatar_file(context: &Context, path: &str) -> Result { Ok(encoded_body) } +fn relay_addrs(public_key: &SignedPublicKey, addr: &str) -> Vec { + let mut addrs = addresses_from_public_key(public_key).unwrap_or_default(); + if !addrs.iter().any(|r| r == addr) { + addrs.push(addr.to_string()); + } + addrs +} + fn recipients_contain_addr(recipients: &[(String, String)], addr: &str) -> bool { let addr_lc = addr.to_lowercase(); recipients