mirror of
https://github.com/chatmail/core.git
synced 2026-10-11 23:50:16 +03:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f25c3ac006 |
@@ -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,
|
||||
};
|
||||
@@ -57,10 +57,7 @@ async fn create_context() -> Context {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
context
|
||||
.set_config(Config::ConfiguredAddr, Some("bob@example.net"))
|
||||
.await
|
||||
.unwrap();
|
||||
// FIXME add_pseudo_transport
|
||||
let secret = key_from_asc(include_str!("../test-data/key/bob-secret.asc")).unwrap();
|
||||
store_self_keypair(&context, &secret)
|
||||
.await
|
||||
|
||||
@@ -110,11 +110,8 @@ async fn create_context() -> Context {
|
||||
}
|
||||
|
||||
let addr = "alice@example.com";
|
||||
// FIXME add_pseudo_transport()
|
||||
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
|
||||
|
||||
@@ -104,7 +104,6 @@ def test_keyupdate_against_core_2_48_march_2026(acf, alice_and_remote_bob, repla
|
||||
# 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()
|
||||
@@ -113,8 +112,9 @@ def test_keyupdate_against_core_2_48_march_2026(acf, alice_and_remote_bob, repla
|
||||
# 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()
|
||||
|
||||
@@ -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
|
||||
@@ -187,9 +185,6 @@ def test_transport_synchronization(acf, log) -> None:
|
||||
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"])
|
||||
|
||||
@@ -197,7 +192,6 @@ def test_transport_synchronization(acf, log) -> None:
|
||||
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!")
|
||||
@@ -221,10 +215,6 @@ 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"]
|
||||
|
||||
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)
|
||||
@@ -236,22 +226,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()
|
||||
@@ -294,7 +268,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:
|
||||
@@ -326,7 +299,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()
|
||||
|
||||
@@ -369,7 +341,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")
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -100,7 +100,7 @@ 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"]
|
||||
@@ -168,7 +168,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!")
|
||||
@@ -331,7 +331,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)
|
||||
|
||||
@@ -370,12 +370,7 @@ class ACFactory:
|
||||
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"
|
||||
|
||||
@@ -51,7 +51,6 @@ class TestGroupStressTests:
|
||||
|
||||
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")
|
||||
|
||||
@@ -130,11 +130,6 @@ class TestOfflineContact:
|
||||
contact2.unblock()
|
||||
assert ac1.get_blocked_contacts() == [contact1]
|
||||
|
||||
def test_create_self_contact(self, acfactory):
|
||||
ac1 = acfactory.get_pseudo_configured_account()
|
||||
contact1 = ac1.create_contact(ac1.get_config("configured_addr"))
|
||||
assert contact1.id == 1
|
||||
|
||||
def test_get_contacts_and_delete(self, acfactory):
|
||||
ac1 = acfactory.get_pseudo_configured_account()
|
||||
ac2 = acfactory.get_pseudo_configured_account()
|
||||
@@ -223,7 +218,6 @@ class TestOfflineChat:
|
||||
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.name == ac2.get_config("displayname")
|
||||
assert contact.account == ac1
|
||||
chat.remove_contact(ac2)
|
||||
@@ -456,7 +450,6 @@ class TestOfflineChat:
|
||||
contacts = ac2.get_contacts()
|
||||
assert len(contacts) == 1
|
||||
contact2 = contacts[0]
|
||||
assert contact2.addr == ac_contact.get_config("configured_addr")
|
||||
chat2 = contact2.create_chat()
|
||||
messages = chat2.get_messages()
|
||||
assert len(messages) == 2 + E2EE_INFO_MSGS
|
||||
@@ -552,7 +545,6 @@ class TestOfflineChat:
|
||||
contacts = ac2.get_contacts()
|
||||
assert len(contacts) == 1
|
||||
contact2 = contacts[0]
|
||||
assert contact2.addr == ac_contact.get_config("configured_addr")
|
||||
chat2 = contact2.create_chat()
|
||||
messages = chat2.get_messages()
|
||||
assert len(messages) == 2 + E2EE_INFO_MSGS
|
||||
@@ -604,7 +596,6 @@ class TestOfflineChat:
|
||||
contacts = ac2.get_contacts()
|
||||
assert len(contacts) == 1
|
||||
contact2 = contacts[0]
|
||||
assert contact2.addr == ac_contact.get_config("configured_addr")
|
||||
chat2 = contact2.create_chat()
|
||||
messages = chat2.get_messages()
|
||||
assert len(messages) == 2 + E2EE_INFO_MSGS
|
||||
@@ -621,7 +612,6 @@ class TestOfflineChat:
|
||||
contacts = ac2.get_contacts()
|
||||
assert len(contacts) == 1
|
||||
contact2 = contacts[0]
|
||||
assert contact2.addr == ac_contact.get_config("configured_addr")
|
||||
chat2 = contact2.create_chat()
|
||||
messages = chat2.get_messages()
|
||||
assert len(messages) == 2 + E2EE_INFO_MSGS
|
||||
|
||||
+4
-9
@@ -2893,15 +2893,10 @@ 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;
|
||||
// FIXME: remove this message? We don't know yet which provider we are going to send the message through.
|
||||
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,
|
||||
|
||||
+4
-62
@@ -4,7 +4,7 @@ use std::env;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{Context as _, Result, bail, ensure};
|
||||
use anyhow::{Context as _, Result, ensure};
|
||||
use base64::Engine as _;
|
||||
use deltachat_contact_tools::{addr_cmp, sanitize_single_line};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -197,11 +197,6 @@ pub enum Config {
|
||||
#[strum(props(default = "0"))]
|
||||
DeleteDeviceAfter,
|
||||
|
||||
/// Deprecated(2026-09).
|
||||
///
|
||||
/// Use ConfiguredLoginParam and list_transports() instead.
|
||||
ConfiguredAddr,
|
||||
|
||||
/// Deprecated(2026-04).
|
||||
/// Use ConfiguredLoginParam and add_transport{from_qr}()/list_transports() instead.
|
||||
///
|
||||
@@ -752,34 +747,6 @@ impl Context {
|
||||
.set_raw_config(key.as_ref(), value.map(|s| s.to_lowercase()).as_deref())
|
||||
.await?;
|
||||
}
|
||||
Config::ConfiguredAddr => {
|
||||
let Some(addr) = value else {
|
||||
bail!("Cannot unset configured_addr");
|
||||
};
|
||||
|
||||
self.sql
|
||||
.transaction(|transaction| {
|
||||
if transaction.query_row(
|
||||
"SELECT COUNT(*) FROM transports WHERE addr=?",
|
||||
(addr,),
|
||||
|row| {
|
||||
let res: i64 = row.get(0)?;
|
||||
Ok(res)
|
||||
},
|
||||
)? == 0
|
||||
{
|
||||
bail!("Address does not belong to any transport.");
|
||||
}
|
||||
transaction.execute(
|
||||
"INSERT OR REPLACE INTO config (keyname, value) VALUES ('configured_addr', ?)",
|
||||
(addr,),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.await?;
|
||||
self.sql.uncache_raw_config("configured_addr").await;
|
||||
}
|
||||
_ => {
|
||||
self.sql.set_raw_config(key.as_ref(), value).await?;
|
||||
}
|
||||
@@ -854,18 +821,6 @@ impl Context {
|
||||
/// Determine whether the specified addr maps to the/a self addr.
|
||||
/// Returns `false` if no addresses are configured.
|
||||
pub(crate) async fn is_self_addr(&self, addr: &str) -> Result<bool> {
|
||||
// Employ the config cache to optimize for `ConfiguredAddr` passed.
|
||||
if !addr.is_empty()
|
||||
&& addr_cmp(
|
||||
addr,
|
||||
&self
|
||||
.get_config(Config::ConfiguredAddr)
|
||||
.await?
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
Ok(self
|
||||
.get_self_addrs()
|
||||
.await?
|
||||
@@ -873,20 +828,6 @@ impl Context {
|
||||
.any(|a| addr_cmp(addr, a)))
|
||||
}
|
||||
|
||||
/// Sets `primary_new` as the address used for sending.
|
||||
///
|
||||
/// This should only be used by test code and during configure.
|
||||
#[cfg(test)] // AEAP is disabled, but there are still tests for it
|
||||
pub(crate) async fn set_primary_self_addr(&self, primary_new: &str) -> Result<()> {
|
||||
self.quota.write().await.clear();
|
||||
|
||||
self.sql
|
||||
.set_raw_config(Config::ConfiguredAddr.as_ref(), Some(primary_new))
|
||||
.await?;
|
||||
self.emit_event(EventType::ConnectivityChanged);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns all self addresses, newest first.
|
||||
pub(crate) async fn get_self_addrs(&self) -> Result<Vec<String>> {
|
||||
let query_only = true;
|
||||
@@ -895,10 +836,11 @@ impl Context {
|
||||
.await
|
||||
}
|
||||
|
||||
/// Returns the address of the transport used for sending.
|
||||
/// Returns address of some transport.
|
||||
/// Returns an error if no self addr is configured.
|
||||
pub async fn get_primary_self_addr(&self) -> Result<String> {
|
||||
self.get_config(Config::ConfiguredAddr)
|
||||
self.sql
|
||||
.query_get_value("SELECT addr FROM transports ORDER BY id", ())
|
||||
.await?
|
||||
.context("No self addr configured")
|
||||
}
|
||||
|
||||
+4
-11
@@ -37,8 +37,8 @@ use crate::sync::Sync::Nosync;
|
||||
use crate::tools::time;
|
||||
use crate::transport::{
|
||||
ConfiguredCertificateChecks, ConfiguredLoginParam, ConfiguredServerLoginParam,
|
||||
ConnectionCandidate, delete_transport_row, maybe_update_sending_transport,
|
||||
purge_transport_caches, send_sync_transports, transport_addrs,
|
||||
ConnectionCandidate, delete_transport_row, purge_transport_caches, send_sync_transports,
|
||||
transport_addrs,
|
||||
};
|
||||
use crate::{EventType, autorelay, stock_str};
|
||||
|
||||
@@ -275,7 +275,7 @@ impl Context {
|
||||
/// another one is chosen automatically.
|
||||
pub async fn delete_transport(&self, addr: &str) -> Result<()> {
|
||||
let now = time();
|
||||
let (removed_transport_id, reelected) = self
|
||||
let removed_transport_id = self
|
||||
.sql
|
||||
.transaction(|transaction| {
|
||||
if transport_addrs(transaction)?.len() <= 1 {
|
||||
@@ -294,14 +294,9 @@ impl Context {
|
||||
let remove_timestamp = std::cmp::max(now, add_timestamp);
|
||||
let transport_id = delete_transport_row(transaction, addr, remove_timestamp)?
|
||||
.context("Transport disappeared")?;
|
||||
let reelected = maybe_update_sending_transport(transaction)?;
|
||||
Ok((transport_id, reelected))
|
||||
Ok(transport_id)
|
||||
})
|
||||
.await?;
|
||||
if let Some(new_addr) = reelected {
|
||||
info!(self, "Using transport {new_addr:?} for sending now.");
|
||||
self.sql.uncache_raw_config("configured_addr").await;
|
||||
}
|
||||
send_sync_transports(self).await?;
|
||||
purge_transport_caches(self, removed_transport_id).await;
|
||||
// Restarting all IO also stops the removed transport's IMAP loop.
|
||||
@@ -799,8 +794,6 @@ mod tests {
|
||||
let t = &tcm.unconfigured().await;
|
||||
|
||||
add_pseudo_transport(t, "primary@example.org").await?;
|
||||
t.set_config(Config::ConfiguredAddr, Some("primary@example.org"))
|
||||
.await?;
|
||||
assert_eq!(t.count_transports().await?, 1);
|
||||
t.check_relay_limit().await?;
|
||||
|
||||
|
||||
+10
-34
@@ -718,9 +718,9 @@ impl Contact {
|
||||
.await?
|
||||
.unwrap_or_default();
|
||||
contact.addr = context
|
||||
.get_config(Config::ConfiguredAddr)
|
||||
.await?
|
||||
.unwrap_or_default();
|
||||
.get_primary_self_addr()
|
||||
.await
|
||||
.context("Cannot get address for self-contact")?;
|
||||
if let Some(self_fp) = self_fingerprint_opt(context).await? {
|
||||
contact.fingerprint = Some(self_fp.to_string());
|
||||
}
|
||||
@@ -1421,10 +1421,6 @@ WHERE addr=?
|
||||
);
|
||||
|
||||
let contact = Contact::get_by_id(context, contact_id).await?;
|
||||
let addr = context
|
||||
.get_config(Config::ConfiguredAddr)
|
||||
.await?
|
||||
.unwrap_or_default();
|
||||
|
||||
let Some(fingerprint_other) = contact.fingerprint() else {
|
||||
return Ok(stock_str::encr_none(context));
|
||||
@@ -1444,32 +1440,12 @@ WHERE addr=?
|
||||
.await?
|
||||
.dc_fingerprint()
|
||||
.human_readable();
|
||||
if addr < contact.addr {
|
||||
cat_fingerprint(
|
||||
&mut ret,
|
||||
&stock_str::self_msg(context),
|
||||
&addr,
|
||||
&fingerprint_self,
|
||||
);
|
||||
cat_fingerprint(
|
||||
&mut ret,
|
||||
contact.get_display_name(),
|
||||
&contact.addr,
|
||||
&fingerprint_other,
|
||||
);
|
||||
if fingerprint_self < fingerprint_other {
|
||||
cat_fingerprint(&mut ret, &stock_str::self_msg(context), &fingerprint_self);
|
||||
cat_fingerprint(&mut ret, contact.get_display_name(), &fingerprint_other);
|
||||
} else {
|
||||
cat_fingerprint(
|
||||
&mut ret,
|
||||
contact.get_display_name(),
|
||||
&contact.addr,
|
||||
&fingerprint_other,
|
||||
);
|
||||
cat_fingerprint(
|
||||
&mut ret,
|
||||
&stock_str::self_msg(context),
|
||||
&addr,
|
||||
&fingerprint_self,
|
||||
);
|
||||
cat_fingerprint(&mut ret, contact.get_display_name(), &fingerprint_other);
|
||||
cat_fingerprint(&mut ret, &stock_str::self_msg(context), &fingerprint_self);
|
||||
}
|
||||
|
||||
if let Some(public_key) = contact.public_key(context).await?
|
||||
@@ -1968,8 +1944,8 @@ pub(crate) async fn update_last_seen(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cat_fingerprint(ret: &mut String, name: &str, addr: &str, fingerprint: &str) {
|
||||
*ret += &format!("\n\n{name} ({addr}):\n{fingerprint}");
|
||||
fn cat_fingerprint(ret: &mut String, name: &str, fingerprint: &str) {
|
||||
*ret += &format!("\n\n{name}:\n{fingerprint}");
|
||||
}
|
||||
|
||||
fn split_address_book(book: &str) -> Vec<(&str, &str)> {
|
||||
|
||||
@@ -887,11 +887,11 @@ async fn test_contact_get_encrinfo() -> Result<()> {
|
||||
"Messages are end-to-end encrypted.
|
||||
Fingerprints:
|
||||
|
||||
Me (alice@example.org):
|
||||
Me:
|
||||
2E6F A2CB 23B5 32D7 2863
|
||||
4B58 64B0 8F61 A9ED 9443
|
||||
|
||||
bob@example.net (bob@example.net):
|
||||
bob@example.net:
|
||||
CCCB 5AA9 F6E1 141C 9431
|
||||
65F1 DB18 B18C BCF7 0487
|
||||
|
||||
@@ -908,11 +908,11 @@ bob@example.net"
|
||||
"No encryption.
|
||||
Fingerprints:
|
||||
|
||||
Me (alice@example.org):
|
||||
Me:
|
||||
2E6F A2CB 23B5 32D7 2863
|
||||
4B58 64B0 8F61 A9ED 9443
|
||||
|
||||
bob@example.net (bob@example.net):
|
||||
bob@example.net:
|
||||
CCCB 5AA9 F6E1 141C 9431
|
||||
65F1 DB18 B18C BCF7 0487"
|
||||
);
|
||||
@@ -1252,7 +1252,7 @@ async fn test_make_n_import_vcard() -> Result<()> {
|
||||
tokio::fs::write(&avatar_path, avatar_bytes).await?;
|
||||
bob.set_config(Config::Selfavatar, Some(avatar_path.to_str().unwrap()))
|
||||
.await?;
|
||||
let bob_addr = bob.get_config(Config::ConfiguredAddr).await?.unwrap();
|
||||
let bob_addr = bob.get_primary_self_addr().await?;
|
||||
let bob_biography = bob.get_config(Config::Selfstatus).await?.unwrap();
|
||||
let chat = bob.create_chat(alice).await;
|
||||
let sent_msg = bob.send_text(chat.id, "moin").await;
|
||||
@@ -1348,7 +1348,7 @@ async fn test_make_n_import_vcard() -> Result<()> {
|
||||
async fn test_import_vcard_key_change() -> Result<()> {
|
||||
let alice = &TestContext::new_alice().await;
|
||||
let bob = &TestContext::new_bob().await;
|
||||
let bob_addr = &bob.get_config(Config::ConfiguredAddr).await?.unwrap();
|
||||
let bob_addr = &bob.get_primary_self_addr().await?;
|
||||
bob.set_config(Config::Displayname, Some("Bob")).await?;
|
||||
let vcard = make_vcard(bob, &[ContactId::SELF]).await?;
|
||||
alice.evtracker.clear_events();
|
||||
|
||||
@@ -961,10 +961,6 @@ mod tests {
|
||||
.await;
|
||||
|
||||
assert!(context2.is_configured().await?);
|
||||
assert_eq!(
|
||||
context2.get_config(Config::ConfiguredAddr).await?,
|
||||
Some("alice@example.org".to_string())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1074,7 +1070,6 @@ mod tests {
|
||||
.await;
|
||||
|
||||
assert!(!context2.is_configured().await?);
|
||||
assert_eq!(context2.get_config(Config::ConfiguredAddr).await?, None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
-10
@@ -660,7 +660,6 @@ mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
use super::*;
|
||||
use crate::config::Config;
|
||||
use crate::test_utils::{TestContext, TestContextManager, alice_keypair};
|
||||
use crate::tools::SystemTime;
|
||||
use crate::transport::add_pseudo_transport;
|
||||
@@ -814,9 +813,6 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD
|
||||
async fn test_load_self_generate_public() {
|
||||
let t = TestContext::new().await;
|
||||
add_pseudo_transport(&t, "alice@example.org").await.unwrap();
|
||||
t.set_config(Config::ConfiguredAddr, Some("alice@example.org"))
|
||||
.await
|
||||
.unwrap();
|
||||
let key = load_self_public_key(&t).await;
|
||||
assert!(key.is_ok());
|
||||
}
|
||||
@@ -825,9 +821,6 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD
|
||||
async fn test_load_self_generate_secret() {
|
||||
let t = TestContext::new().await;
|
||||
add_pseudo_transport(&t, "alice@example.org").await.unwrap();
|
||||
t.set_config(Config::ConfiguredAddr, Some("alice@example.org"))
|
||||
.await
|
||||
.unwrap();
|
||||
let key = load_self_secret_key(&t).await;
|
||||
assert!(key.is_ok());
|
||||
}
|
||||
@@ -838,9 +831,6 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD
|
||||
|
||||
let t = TestContext::new().await;
|
||||
add_pseudo_transport(&t, "alice@example.org").await.unwrap();
|
||||
t.set_config(Config::ConfiguredAddr, Some("alice@example.org"))
|
||||
.await
|
||||
.unwrap();
|
||||
let thr0 = {
|
||||
let ctx = t.clone();
|
||||
thread::spawn(move || {
|
||||
|
||||
@@ -260,10 +260,6 @@ async fn test_keyupdate_on_replacement() -> Result<()> {
|
||||
alice.add_transport("alice@relay.example.net").await;
|
||||
SystemTime::shift(Duration::from_secs(2));
|
||||
alice.delete_transport("alice@example.org").await?;
|
||||
assert_eq!(
|
||||
alice.get_config(Config::ConfiguredAddr).await?.as_deref(),
|
||||
Some("alice@relay.example.net")
|
||||
);
|
||||
|
||||
maybe_send_keyupdate_message(alice).await?;
|
||||
let keyupdate = alice.pop_sent_msg().await;
|
||||
|
||||
+7
-11
@@ -433,9 +433,9 @@ pub(crate) fn render_queued_mail(
|
||||
#[cfg(test)]
|
||||
pub(crate) async fn render_queued_mail_with_context(
|
||||
queued_mail: QueuedMail,
|
||||
context: &Context,
|
||||
context: &crate::test_utils::TestContext,
|
||||
) -> Result<RenderedEmail> {
|
||||
let from_addr = context.get_primary_self_addr().await?;
|
||||
let from_addr = context.sending_addr().await;
|
||||
let public_key = crate::key::load_self_public_key(context).await?;
|
||||
let secret_key = crate::key::load_self_secret_key(context).await?;
|
||||
|
||||
@@ -999,14 +999,10 @@ impl MimeFactory {
|
||||
true => context.get_config(Config::Displayname).await?,
|
||||
false => None,
|
||||
};
|
||||
let self_name = &match self_name {
|
||||
Some(name) => name,
|
||||
None => context
|
||||
.get_config(Config::ConfiguredAddr)
|
||||
.await?
|
||||
.unwrap_or_default(),
|
||||
};
|
||||
Ok(stock_str::subject_for_new_contact(context, self_name))
|
||||
Ok(stock_str::subject_for_new_contact(
|
||||
context,
|
||||
self_name.as_deref().unwrap_or("..."),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn recipients(&self) -> Vec<String> {
|
||||
@@ -1228,7 +1224,7 @@ impl MimeFactory {
|
||||
///
|
||||
/// Used only for tests.
|
||||
#[cfg(test)]
|
||||
pub async fn render(self, context: &Context) -> Result<RenderedEmail> {
|
||||
pub async fn render(self, context: &crate::test_utils::TestContext) -> Result<RenderedEmail> {
|
||||
// Does not matter, we are not going to return the QueuedMail.
|
||||
let bcc_self = false;
|
||||
let (queued_mail, _side_effects) =
|
||||
|
||||
@@ -185,7 +185,7 @@ async fn test_subject_outgoing() {
|
||||
let t = TestContext::new_alice().await;
|
||||
t.allow_unencrypted().await.unwrap();
|
||||
|
||||
assert_eq!(first_subject_str(t).await, "Message from alice@example.org");
|
||||
assert_eq!(first_subject_str(t).await, "Message from ...");
|
||||
|
||||
let t = TestContext::new_alice().await;
|
||||
t.allow_unencrypted().await.unwrap();
|
||||
@@ -732,9 +732,9 @@ async fn test_remove_member_bcc() -> Result<()> {
|
||||
let charlie = &tcm.charlie().await;
|
||||
alice.allow_unencrypted().await?;
|
||||
|
||||
let alice_addr = alice.get_config(Config::ConfiguredAddr).await?.unwrap();
|
||||
let bob_addr = bob.get_config(Config::ConfiguredAddr).await?.unwrap();
|
||||
let charlie_addr = charlie.get_config(Config::ConfiguredAddr).await?.unwrap();
|
||||
let alice_addr = alice.get_primary_self_addr().await?;
|
||||
let bob_addr = bob.get_primary_self_addr().await?;
|
||||
let charlie_addr = charlie.get_primary_self_addr().await?;
|
||||
|
||||
let bob_id = alice.add_or_lookup_address_contact_id(bob).await;
|
||||
let charlie_id = alice.add_or_lookup_address_contact_id(charlie).await;
|
||||
@@ -897,7 +897,7 @@ async fn test_new_member_is_first_recipient() -> Result<()> {
|
||||
assert!(
|
||||
sent_msg
|
||||
.recipients
|
||||
.starts_with(&charlie.get_config(Config::ConfiguredAddr).await?.unwrap())
|
||||
.starts_with(&charlie.get_primary_self_addr().await?)
|
||||
);
|
||||
|
||||
remove_contact_from_chat(alice, group, bob_id).await?;
|
||||
@@ -905,11 +905,8 @@ async fn test_new_member_is_first_recipient() -> Result<()> {
|
||||
SystemTime::shift(Duration::from_secs(60));
|
||||
add_contact_to_chat(alice, group, bob_id).await?;
|
||||
let sent_msg = alice.pop_sent_msg().await;
|
||||
assert!(
|
||||
sent_msg
|
||||
.recipients
|
||||
.starts_with(&bob.get_config(Config::ConfiguredAddr).await?.unwrap())
|
||||
);
|
||||
let bob_addr = bob.get_primary_self_addr().await?;
|
||||
assert!(sent_msg.recipients.starts_with(&bob_addr));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1117,7 +1114,7 @@ Autocrypt: addr=alice@example.org; prefer-encrypt=mutual;
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Date: DATE
|
||||
To: <bob@example.net>
|
||||
Subject: Message from alice@example.org
|
||||
Subject: Message from ...
|
||||
References: <MESSAGE_ID@localhost>
|
||||
Chat-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
@@ -1169,7 +1166,7 @@ Content-Type: multipart/mixed;
|
||||
boundary="BOUNDARY"
|
||||
Date: DATE
|
||||
To: <bob@example.net>
|
||||
Subject: Message from alice@example.org
|
||||
Subject: Message from ...
|
||||
References: <MESSAGE_ID@localhost>
|
||||
Chat-Version: 1.0
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ async fn test_broadcast_security_attacker_signature() -> Result<()> {
|
||||
|
||||
let secret = load_broadcast_secret(alice, alice_chat_id).await?.unwrap();
|
||||
|
||||
let charlie_addr = charlie.get_config(Config::ConfiguredAddr).await?.unwrap();
|
||||
let charlie_addr = charlie.get_primary_self_addr().await?;
|
||||
|
||||
test_shared_secret_decryption_ext(
|
||||
bob,
|
||||
@@ -183,7 +183,7 @@ async fn test_broadcast_security_happy_path() -> Result<()> {
|
||||
|
||||
let secret = load_broadcast_secret(alice, alice_chat_id).await?.unwrap();
|
||||
|
||||
let alice_addr = alice.get_config(Config::ConfiguredAddr).await?.unwrap();
|
||||
let alice_addr = alice.get_primary_self_addr().await?;
|
||||
|
||||
test_shared_secret_decryption_ext(bob, &alice_addr, &secret, Some(alice), None).await
|
||||
}
|
||||
@@ -202,7 +202,7 @@ async fn test_qr_code_security() -> Result<()> {
|
||||
// Start a securejoin process, but don't finish it:
|
||||
join_securejoin(bob, &qr).await?;
|
||||
|
||||
let charlie_addr = charlie.get_config(Config::ConfiguredAddr).await?.unwrap();
|
||||
let charlie_addr = charlie.get_primary_self_addr().await?;
|
||||
|
||||
let alice_fp = self_fingerprint(alice).await?;
|
||||
let secret_for_encryption = format!("securejoin/{alice_fp}/{authcode}");
|
||||
|
||||
@@ -4,7 +4,6 @@ use tokio::sync::OnceCell;
|
||||
use super::*;
|
||||
use crate::transport::add_pseudo_transport;
|
||||
use crate::{
|
||||
config::Config,
|
||||
decrypt,
|
||||
key::{load_self_public_key, self_fingerprint, store_self_keypair},
|
||||
mimefactory::{part_to_bytes, wrap_encrypted_part},
|
||||
@@ -23,9 +22,6 @@ async fn decrypt_bytes(
|
||||
add_pseudo_transport(t, "alice@example.org")
|
||||
.await
|
||||
.expect("Failed to add pseudo transport");
|
||||
t.set_config(Config::ConfiguredAddr, Some("alice@example.org"))
|
||||
.await
|
||||
.expect("Failed to configure address");
|
||||
|
||||
for secret in auth_tokens_for_decryption {
|
||||
token::save(t, token::Namespace::Auth, None, secret, 0).await?;
|
||||
|
||||
@@ -156,14 +156,6 @@ mod tests {
|
||||
};
|
||||
assert!(!t.quota_needs_update(0, TIMEOUT).await);
|
||||
|
||||
t.evtracker.clear_events();
|
||||
t.set_primary_self_addr("new@addr").await?;
|
||||
assert!(t.quota.read().await.is_empty());
|
||||
t.evtracker
|
||||
.get_matching(|evt| matches!(evt, EventType::ConnectivityChanged))
|
||||
.await;
|
||||
assert!(t.quota_needs_update(0, TIMEOUT).await);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3853,7 +3853,7 @@ async fn test_unsigned_chat_group_hdr() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
let alice = &tcm.alice().await;
|
||||
let bob = &tcm.bob().await;
|
||||
let bob_addr = bob.get_config(Config::ConfiguredAddr).await?.unwrap();
|
||||
let bob_addr = bob.get_primary_self_addr().await?;
|
||||
let bob_id = alice.add_or_lookup_contact_id(bob).await;
|
||||
let alice_chat_id = create_group(alice, "foos").await?;
|
||||
add_contact_to_chat(alice, alice_chat_id, bob_id).await?;
|
||||
@@ -4541,7 +4541,7 @@ async fn test_outgoing_msg_forgery() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
let export_dir = tempfile::tempdir().unwrap();
|
||||
let alice = &tcm.alice().await;
|
||||
let alice_addr = &alice.get_config(Config::ConfiguredAddr).await?.unwrap();
|
||||
let alice_addr = &alice.get_primary_self_addr().await?;
|
||||
imex(alice, ImexMode::ExportSelfKeys, export_dir.path(), None).await?;
|
||||
// We need Bob only to encrypt the forged message to Alice's key, actually Bob doesn't
|
||||
// participate in the scenario.
|
||||
@@ -5638,7 +5638,7 @@ async fn test_bcc_not_a_group() -> Result<()> {
|
||||
async fn test_lookup_key_contact_by_address_self() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
let t = &tcm.alice().await;
|
||||
let addr = &t.get_config(Config::ConfiguredAddr).await?.unwrap();
|
||||
let addr = &t.get_primary_self_addr().await?;
|
||||
assert_eq!(
|
||||
lookup_key_contact_by_address(t, addr, None).await?,
|
||||
Some(ContactId::SELF)
|
||||
@@ -5690,10 +5690,7 @@ async fn test_outgoing_determined_by_signature() -> Result<()> {
|
||||
let alice_dev2 = &tcm.unconfigured().await;
|
||||
alice_dev2.configure_addr(different_from).await;
|
||||
key::store_self_keypair(alice_dev2, &alice_keypair()).await?;
|
||||
assert_ne!(
|
||||
alice.get_config(Config::ConfiguredAddr).await?.unwrap(),
|
||||
different_from
|
||||
);
|
||||
assert_ne!(alice.get_primary_self_addr().await?, different_from);
|
||||
|
||||
// Send message from alice_dev2 and check alice sees it as outgoing
|
||||
let chat_id = alice_dev2.create_chat_id(bob).await;
|
||||
|
||||
@@ -50,11 +50,7 @@ async fn test_setup_contact_ext(case: SetupContactCase) -> (TestContext, TestCon
|
||||
|
||||
let mut tcm = TestContextManager::new();
|
||||
let alice = tcm.alice().await;
|
||||
let alice_addr = &alice
|
||||
.get_config(Config::ConfiguredAddr)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let alice_addr = alice.get_primary_self_addr().await.unwrap();
|
||||
if case == SetupContactCase::AliceHasName {
|
||||
alice
|
||||
.set_config(Config::Displayname, Some("Alice"))
|
||||
@@ -118,7 +114,7 @@ async fn test_setup_contact_ext(case: SetupContactCase) -> (TestContext, TestCon
|
||||
let contact_alice_id = bob.add_or_lookup_contact_no_key(&alice).await.id;
|
||||
let sent = bob.pop_sent_msg().await;
|
||||
assert!(!sent.payload.contains("Bob Examplenet"));
|
||||
assert_eq!(sent.recipient(), EmailAddress::new(alice_addr).unwrap());
|
||||
assert_eq!(sent.recipients, *alice_addr);
|
||||
let msg = alice.parse_msg(&sent).await;
|
||||
assert!(msg.signature.is_none());
|
||||
assert_eq!(
|
||||
|
||||
+5
-10
@@ -13,7 +13,6 @@ use rusqlite::OptionalExtension as _;
|
||||
use tokio::task;
|
||||
|
||||
use crate::chat::{ChatId, add_info_msg_with_cmd};
|
||||
use crate::config::Config;
|
||||
use crate::contact::{Contact, ContactId};
|
||||
use crate::context::Context;
|
||||
use crate::events::EventType;
|
||||
@@ -587,15 +586,11 @@ pub(crate) async fn send_msg_to_smtp(
|
||||
.await?;
|
||||
|
||||
if let Some((chat_id, timestamp_sort)) = res {
|
||||
let addr = context.get_config(Config::ConfiguredAddr).await?;
|
||||
let text = unencrypted_email(
|
||||
context,
|
||||
addr.unwrap_or_default()
|
||||
.split('@')
|
||||
.nth(1)
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
.await;
|
||||
// FIXME info message
|
||||
let addr = context.get_primary_self_addr().await?;
|
||||
let text =
|
||||
unencrypted_email(context, addr.split('@').nth(1).unwrap_or_default())
|
||||
.await;
|
||||
add_info_msg_with_cmd(
|
||||
context,
|
||||
chat_id,
|
||||
|
||||
File diff suppressed because one or more lines are too long
+29
-31
@@ -193,21 +193,11 @@ impl TestContextManager {
|
||||
to.recv_msg(&sent).await
|
||||
}
|
||||
|
||||
pub async fn change_addr(&self, test_context: &TestContext, new_addr: &str) {
|
||||
self.section(&format!(
|
||||
"{} changes her self address and reconfigures",
|
||||
test_context.name()
|
||||
));
|
||||
|
||||
pub async fn change_addr(&self, test_context: &mut TestContext, new_addr: &str) {
|
||||
test_context.add_transport(new_addr).await;
|
||||
test_context.set_primary_self_addr(new_addr).await.unwrap();
|
||||
test_context.set_sending_addr(new_addr);
|
||||
// ensure_secret_key_exists() is called during configure
|
||||
key::ensure_secret_key_exists(test_context).await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
test_context.get_primary_self_addr().await.unwrap(),
|
||||
new_addr
|
||||
);
|
||||
}
|
||||
|
||||
/// Executes SecureJoin protocol between `scanner` and `scanned`.
|
||||
@@ -252,10 +242,9 @@ impl TestContextManager {
|
||||
qr: &str,
|
||||
) -> ChatId {
|
||||
assert!(joiner.pop_sent_msg_opt().await.is_none());
|
||||
let inviter_addr = inviters[0].get_primary_self_addr().await.unwrap();
|
||||
let inviter_addr = inviters[0].sending_addr().await;
|
||||
for inviter in inviters {
|
||||
assert!(inviter.pop_sent_msg_opt().await.is_none());
|
||||
assert_eq!(inviter.get_primary_self_addr().await.unwrap(), inviter_addr);
|
||||
}
|
||||
|
||||
let chat_id = join_securejoin(&joiner.ctx, qr).await.unwrap();
|
||||
@@ -435,6 +424,9 @@ pub struct TestContext {
|
||||
pub evtracker: EventTracker,
|
||||
|
||||
log_sink: LogSink,
|
||||
|
||||
/// From address to be used when emulating sending.
|
||||
from: Option<String>,
|
||||
}
|
||||
|
||||
impl TestContext {
|
||||
@@ -530,6 +522,7 @@ impl TestContext {
|
||||
dir,
|
||||
evtracker: EventTracker::new(evtracker_receiver),
|
||||
log_sink,
|
||||
from: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -560,10 +553,6 @@ impl TestContext {
|
||||
add_pseudo_transport(&self.ctx, addr)
|
||||
.await
|
||||
.expect("Failed to add pseudo transport");
|
||||
self.ctx
|
||||
.set_config(Config::ConfiguredAddr, Some(addr))
|
||||
.await
|
||||
.expect("Failed to configure address");
|
||||
|
||||
if let Some(name) = addr.split('@').next() {
|
||||
self.set_name(name);
|
||||
@@ -586,6 +575,21 @@ impl TestContext {
|
||||
self.self_public_key.lock().await.take();
|
||||
}
|
||||
|
||||
pub fn set_sending_addr(&mut self, addr: &str) {
|
||||
// TODO: check if the address is configured
|
||||
self.from = Some(addr.to_string());
|
||||
}
|
||||
|
||||
pub async fn sending_addr(&self) -> String {
|
||||
if let Some(ref from) = self.from {
|
||||
from.clone()
|
||||
} else {
|
||||
self.get_primary_self_addr()
|
||||
.await
|
||||
.expect("Cannot get From address")
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves a sent message from the jobs table.
|
||||
///
|
||||
/// This retrieves and removes a message which has been scheduled to send from the jobs
|
||||
@@ -632,10 +636,7 @@ ORDER BY id"
|
||||
.await
|
||||
.expect("Failed to load queued mail");
|
||||
if queued_mail.bcc_self {
|
||||
let from = self
|
||||
.get_primary_self_addr()
|
||||
.await
|
||||
.expect("Cannot get From address");
|
||||
let from = self.sending_addr().await;
|
||||
smtp::add_self_recipients(
|
||||
&self.ctx,
|
||||
&mut queued_mail.recipients,
|
||||
@@ -734,10 +735,7 @@ ORDER BY id"
|
||||
.await
|
||||
.expect("Failed to load queued mail");
|
||||
if queued_mail.bcc_self {
|
||||
let from = self
|
||||
.get_primary_self_addr()
|
||||
.await
|
||||
.expect("Cannot get self address");
|
||||
let from = self.sending_addr().await;
|
||||
smtp::add_self_recipients(
|
||||
&self.ctx,
|
||||
&mut queued_mail.recipients,
|
||||
@@ -897,7 +895,7 @@ ORDER BY id"
|
||||
|
||||
/// Returns the [`ContactId`] for the other [`TestContext`], creating a contact if necessary.
|
||||
pub async fn add_or_lookup_address_contact_id(&self, other: &TestContext) -> ContactId {
|
||||
let primary_self_addr = other.ctx.get_primary_self_addr().await.unwrap();
|
||||
let primary_self_addr = other.sending_addr().await;
|
||||
let addr = ContactAddress::new(&primary_self_addr).unwrap();
|
||||
// MailinglistAddress is the lowest allowed origin, we'd prefer to not modify the
|
||||
// origin when creating this contact.
|
||||
@@ -952,7 +950,7 @@ ORDER BY id"
|
||||
/// If the contact does not exist yet, a new contact will be created
|
||||
/// with the correct fingerprint, but without the public key.
|
||||
pub async fn add_or_lookup_contact_id_no_key(&self, other: &TestContext) -> ContactId {
|
||||
let primary_self_addr = other.ctx.get_primary_self_addr().await.unwrap();
|
||||
let primary_self_addr = other.sending_addr().await;
|
||||
let addr = ContactAddress::new(&primary_self_addr).unwrap();
|
||||
let fingerprint = self_fingerprint(other).await.unwrap();
|
||||
|
||||
@@ -1242,13 +1240,14 @@ ORDER BY id"
|
||||
}
|
||||
|
||||
pub async fn encrypt_raw_message(
|
||||
context: &Context,
|
||||
context: &TestContext,
|
||||
receivers: &[&TestContext],
|
||||
payload: &[u8],
|
||||
) -> Result<String> {
|
||||
let public_key = key::load_self_public_key(context).await?;
|
||||
let from = context.sending_addr().await;
|
||||
let aheader = Aheader {
|
||||
addr: context.get_primary_self_addr().await?,
|
||||
addr: from.clone(),
|
||||
public_key: public_key.clone(),
|
||||
prefer_encrypt: EncryptPreference::Mutual,
|
||||
};
|
||||
@@ -1259,7 +1258,6 @@ pub async fn encrypt_raw_message(
|
||||
encryption_keyring.push(key::load_self_public_key(receiver).await?);
|
||||
}
|
||||
|
||||
let from = context.get_primary_self_addr().await?;
|
||||
let compress = false;
|
||||
|
||||
let mut cleartext = format!("Autocrypt: {aheader}").into_bytes();
|
||||
|
||||
+6
-8
@@ -20,13 +20,14 @@ use crate::test_utils::TestContextManager;
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_change_primary_self_addr() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
let alice = tcm.alice().await;
|
||||
let mut alice = tcm.alice().await;
|
||||
let bob = tcm.bob().await;
|
||||
|
||||
tcm.send_recv_accept(&alice, &bob, "Hi").await;
|
||||
let bob_alice_chat = bob.create_chat(&alice).await;
|
||||
|
||||
tcm.change_addr(&alice, "alice@someotherdomain.xyz").await;
|
||||
tcm.change_addr(&mut alice, "alice@someotherdomain.xyz")
|
||||
.await;
|
||||
|
||||
tcm.section("Bob sends a message to Alice, encrypting to her previous key");
|
||||
let sent = bob.send_text(bob_alice_chat.id, "hi back").await;
|
||||
@@ -63,7 +64,7 @@ async fn check_aeap_transition(chat_for_transition: ChatForTransition) {
|
||||
const ALICE_NEW_ADDR: &str = "alice2@example.net";
|
||||
|
||||
let mut tcm = TestContextManager::new();
|
||||
let alice = &tcm.alice().await;
|
||||
let alice = &mut tcm.alice().await;
|
||||
let bob = &tcm.bob().await;
|
||||
|
||||
tcm.send_recv_accept(alice, bob, "Hi").await;
|
||||
@@ -105,10 +106,7 @@ async fn check_aeap_transition(chat_for_transition: ChatForTransition) {
|
||||
check_that_transition_worked(bob, &groups, alice_contact, ALICE_NEW_ADDR).await;
|
||||
|
||||
tcm.section("Test switching back");
|
||||
alice
|
||||
.set_primary_self_addr("alice@example.org")
|
||||
.await
|
||||
.unwrap();
|
||||
alice.set_sending_addr("alice@example.org");
|
||||
let sent = alice
|
||||
.send_text(chat_to_send, "Hello from my old addr!")
|
||||
.await;
|
||||
@@ -205,7 +203,7 @@ async fn test_aeap_replay_attack() -> Result<()> {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_write_to_alice_after_aeap() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
let alice = &tcm.alice().await;
|
||||
let alice = &mut tcm.alice().await;
|
||||
let bob = &tcm.bob().await;
|
||||
|
||||
let alice_grp_id = chat::create_group(alice, "Group").await?;
|
||||
|
||||
+6
-46
@@ -276,14 +276,15 @@ impl ConfiguredLoginParam {
|
||||
.await
|
||||
}
|
||||
|
||||
/// Loads legacy configured param. Only used for tests and the migration.
|
||||
/// Loads legacy configured param. Only used for tests and migration 131.
|
||||
pub(crate) async fn load_legacy(context: &Context) -> Result<Option<Self>> {
|
||||
if !context.get_config_bool(Config::Configured).await? {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let addr = context
|
||||
.get_config(Config::ConfiguredAddr)
|
||||
.sql
|
||||
.get_raw_config("configured_addr")
|
||||
.await?
|
||||
.unwrap_or_default()
|
||||
.trim()
|
||||
@@ -480,8 +481,7 @@ pub(crate) async fn save_transport(
|
||||
);
|
||||
|
||||
let addr = addr_normalize(&configured.addr);
|
||||
let configured_addr = context.get_config(Config::ConfiguredAddr).await?;
|
||||
let mut modified = context
|
||||
let modified = context
|
||||
.sql
|
||||
.execute(
|
||||
"INSERT INTO transports (addr, entered_param, configured_param, add_timestamp)
|
||||
@@ -503,14 +503,6 @@ pub(crate) async fn save_transport(
|
||||
.await?
|
||||
> 0;
|
||||
|
||||
if configured_addr.is_none() {
|
||||
// If there is no transport yet, use the new transport for sending
|
||||
context
|
||||
.sql
|
||||
.set_raw_config(Config::ConfiguredAddr.as_ref(), Some(&addr))
|
||||
.await?;
|
||||
modified = true;
|
||||
}
|
||||
Ok(modified)
|
||||
}
|
||||
|
||||
@@ -625,7 +617,7 @@ pub(crate) async fn sync_transports(
|
||||
)
|
||||
.collect();
|
||||
|
||||
let (deleted_ids, reelected) = context
|
||||
let deleted_ids = context
|
||||
.sql
|
||||
.transaction(|transaction| {
|
||||
let mut deleted_ids = Vec::new();
|
||||
@@ -638,8 +630,7 @@ pub(crate) async fn sync_transports(
|
||||
}
|
||||
modified |= !deleted_ids.is_empty();
|
||||
|
||||
let reelected = maybe_update_sending_transport(transaction)?;
|
||||
Ok((deleted_ids, reelected))
|
||||
Ok(deleted_ids)
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -647,12 +638,6 @@ pub(crate) async fn sync_transports(
|
||||
purge_transport_caches(context, *transport_id).await;
|
||||
}
|
||||
|
||||
if let Some(new_addr) = reelected {
|
||||
info!(context, "Re-elected sending transport {new_addr:?}.");
|
||||
context.sql.uncache_raw_config("configured_addr").await;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if modified {
|
||||
context.self_public_key.lock().await.take();
|
||||
context
|
||||
@@ -711,31 +696,6 @@ pub(crate) async fn purge_transport_caches(context: &Context, transport_id: u32)
|
||||
context.metadata.write().await.remove(&transport_id);
|
||||
}
|
||||
|
||||
/// Elects another transport for sending if the current one vanished.
|
||||
/// Any remaining transport works and selection is anyway moving
|
||||
/// to the authority of the SMTP loop, see <https://github.com/chatmail/core/pull/8619>
|
||||
pub(crate) fn maybe_update_sending_transport(
|
||||
transaction: &mut rusqlite::Transaction,
|
||||
) -> Result<Option<String>> {
|
||||
let configured_addr: String = transaction.query_row(
|
||||
"SELECT value FROM config WHERE keyname='configured_addr'",
|
||||
(),
|
||||
|row| row.get(0),
|
||||
)?;
|
||||
let addrs = transport_addrs(transaction)?;
|
||||
if addrs.contains(&configured_addr) {
|
||||
return Ok(None);
|
||||
}
|
||||
let Some(new_addr) = addrs.into_iter().next() else {
|
||||
return Ok(None);
|
||||
};
|
||||
transaction.execute(
|
||||
"UPDATE config SET value=? WHERE keyname='configured_addr'",
|
||||
(&new_addr,),
|
||||
)?;
|
||||
Ok(Some(new_addr))
|
||||
}
|
||||
|
||||
/// Adds transport entry to the `transports` table with empty configuration.
|
||||
pub async fn add_pseudo_transport(context: &Context, addr: &str) -> Result<()> {
|
||||
context.sql
|
||||
|
||||
@@ -197,10 +197,6 @@ async fn test_delete_transport() -> Result<()> {
|
||||
.evtracker
|
||||
.get_matching(|e| matches!(e, EventType::TransportsModified))
|
||||
.await;
|
||||
assert_eq!(
|
||||
alice.get_config(Config::ConfiguredAddr).await?.as_deref(),
|
||||
Some("alice@otherprovider.com")
|
||||
);
|
||||
sync_and_check_recipients(alice, alice2, "alice@otherprovider.com").await;
|
||||
|
||||
check_addrs(
|
||||
@@ -226,50 +222,6 @@ async fn test_delete_transport() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tests that selecting sending transport by setting "configured_addr" does not
|
||||
/// send the sync message, is not synchronized between devices even if sync message is forced,
|
||||
/// and does not bump sending transport `add_timestamp`.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_no_configured_addr_synchronization() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
let alice = &tcm.alice().await;
|
||||
let alice2 = &tcm.alice().await;
|
||||
for a in [alice, alice2] {
|
||||
a.set_config_bool(Config::SyncMsgs, true).await?;
|
||||
a.set_config_bool(Config::BccSelf, true).await?;
|
||||
}
|
||||
|
||||
let addr = "alice@otherprovider.com";
|
||||
add_dummy_transport(alice, addr).await?;
|
||||
send_sync_transports(alice).await?;
|
||||
sync_and_check_recipients(alice, alice2, &format!("{addr} alice@example.org")).await;
|
||||
|
||||
// Selects `addr` on `alice` as the sending transport
|
||||
// and syncs the transport update to `alice2`,
|
||||
// whose own sending transport must stay unchanged.
|
||||
let old_timestamp = add_timestamp(alice2, addr).await;
|
||||
let alice2_primary = alice2.get_config(Config::ConfiguredAddr).await?;
|
||||
alice.set_config(Config::ConfiguredAddr, Some(addr)).await?;
|
||||
assert_eq!(add_timestamp(alice, addr).await, old_timestamp);
|
||||
|
||||
send_sync_transports(alice).await?;
|
||||
alice.send_sync_msg().await?.unwrap();
|
||||
let sync_msg = alice.pop_sent_msg().await;
|
||||
assert_eq!(sync_msg.recipients, format!("alice@example.org {addr}"));
|
||||
// The sync message comes from the new sending address,
|
||||
// which must not make `alice2` adopt it as its own sending address.
|
||||
assert!(sync_msg.payload.contains(&format!("From: <{addr}>")));
|
||||
alice2.recv_msg_trash(&sync_msg).await;
|
||||
|
||||
// add_timestamp must not change.
|
||||
assert_eq!(add_timestamp(alice2, addr).await, old_timestamp);
|
||||
assert_eq!(
|
||||
alice2.get_config(Config::ConfiguredAddr).await?,
|
||||
alice2_primary
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tests that `sync_transports()` requests an IO restart
|
||||
/// if and only if it modified anything.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
@@ -288,14 +240,6 @@ async fn test_sync_transports_requests_io_restart() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn add_timestamp(t: &TestContext, addr: &str) -> i64 {
|
||||
t.sql
|
||||
.query_get_value("SELECT add_timestamp FROM transports WHERE addr=?", (addr,))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Tests that removing the last transport keeps it.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_removing_last_transport() -> Result<()> {
|
||||
@@ -308,10 +252,6 @@ async fn test_removing_last_transport() -> Result<()> {
|
||||
};
|
||||
sync_transports(alice, &[], std::slice::from_ref(&removed)).await?;
|
||||
assert_eq!(alice.count_transports().await?, 1);
|
||||
assert_eq!(
|
||||
alice.get_config(Config::ConfiguredAddr).await?.as_deref(),
|
||||
Some("alice@otherprovider.com")
|
||||
);
|
||||
|
||||
let removed = RemovedTransportData {
|
||||
addr: "alice@otherprovider.com".to_string(),
|
||||
@@ -319,37 +259,6 @@ async fn test_removing_last_transport() -> Result<()> {
|
||||
};
|
||||
sync_transports(alice, &[], std::slice::from_ref(&removed)).await?;
|
||||
assert_eq!(alice.count_transports().await?, 1);
|
||||
assert_eq!(
|
||||
alice.get_config(Config::ConfiguredAddr).await?.as_deref(),
|
||||
Some("alice@otherprovider.com")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tests which transport is elected for sending.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_maybe_update_sending_transport() -> Result<()> {
|
||||
let t = &TestContext::new_alice().await;
|
||||
|
||||
add_dummy_transport(t, "alice@one.com").await?;
|
||||
assert_eq!(
|
||||
t.sql.transaction(maybe_update_sending_transport).await?,
|
||||
None
|
||||
);
|
||||
|
||||
t.sql
|
||||
.execute(
|
||||
"DELETE FROM transports WHERE addr=?",
|
||||
("alice@example.org",),
|
||||
)
|
||||
.await?;
|
||||
assert_eq!(
|
||||
t.sql
|
||||
.transaction(maybe_update_sending_transport)
|
||||
.await?
|
||||
.as_deref(),
|
||||
Some("alice@one.com")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user