mirror of
https://github.com/chatmail/core.git
synced 2026-07-15 15:33:07 +03:00
Compare commits
5 Commits
hpk/fix-re
...
iequidoo/q
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88ed20ea52 | ||
|
|
8b80ac146f | ||
|
|
d1f4e59d82 | ||
|
|
0a82d73eb5 | ||
|
|
c026910fa7 |
@@ -462,7 +462,10 @@ char* dc_get_blobdir (const dc_context_t* context);
|
||||
* - `gossip_period` = How often to gossip Autocrypt keys in chats with multiple recipients, in
|
||||
* seconds. 2 days by default.
|
||||
* This is not supposed to be changed by UIs and only used for testing.
|
||||
* - `is_chatmail` = 1 if the the server is a chatmail server, 0 otherwise.
|
||||
* - `is_chatmail` = (deprecated) 1 if the the server is a chatmail server, 0 otherwise.
|
||||
* This is deprecated, UIs should not behave differently
|
||||
* for chatmail relays and classical email servers.
|
||||
* Most usages in UIs can be replaced by `force_encryption`.
|
||||
* - `is_muted` = Whether a context is muted by the user.
|
||||
* Muted contexts should not sound, vibrate or show notifications.
|
||||
* In contrast to `dc_set_chat_mute_duration()`,
|
||||
|
||||
@@ -704,25 +704,3 @@ 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_alice_chat = 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()
|
||||
|
||||
bob_alice_chat.send_text("hi")
|
||||
snapshot = alice.wait_for_incoming_msg().get_snapshot()
|
||||
assert snapshot.text == "hi"
|
||||
|
||||
@@ -221,6 +221,30 @@ def test_account(acfactory) -> None:
|
||||
alice.stop_io()
|
||||
|
||||
|
||||
def test_mark_fresh_vs_self_mdn(acfactory) -> None:
|
||||
alice, bob = acfactory.get_online_accounts(2)
|
||||
bob.set_config("bcc_self", "1")
|
||||
|
||||
alice_contact_bob = alice.create_contact(bob)
|
||||
alice_chat = alice_contact_bob.create_chat()
|
||||
alice_chat.send_text("Hello!")
|
||||
|
||||
event = bob.wait_for_incoming_msg_event()
|
||||
chat_id = event.chat_id
|
||||
msg_id = event.msg_id
|
||||
|
||||
bob_chat = bob.get_chat_by_id(chat_id)
|
||||
message = bob.get_message_by_id(msg_id)
|
||||
bob_chat.accept()
|
||||
bob.mark_seen_messages([message])
|
||||
bob_chat.mark_fresh()
|
||||
assert bob_chat.get_fresh_message_count() == 1
|
||||
alice.wait_for_event(EventType.MSG_READ)
|
||||
alice_chat.send_text("You've read 'Hello!'")
|
||||
bob.wait_for_incoming_msg_event()
|
||||
assert bob_chat.get_fresh_message_count() == 2
|
||||
|
||||
|
||||
def test_chat(acfactory) -> None:
|
||||
alice, bob = acfactory.get_online_accounts(2)
|
||||
|
||||
|
||||
@@ -1374,6 +1374,18 @@ async fn test_markfresh_chat() -> Result<()> {
|
||||
assert_eq!(bob_chat_id.get_fresh_msg_cnt(bob).await?, 0);
|
||||
assert_eq!(bob.get_fresh_msgs().await?.len(), 0);
|
||||
|
||||
// Marking a message as seen results to sending an MDN to the contact and self.
|
||||
message::markseen_msgs(bob, vec![bob_msg2.id]).await?;
|
||||
assert_eq!(
|
||||
bob.sql
|
||||
.count(
|
||||
"SELECT COUNT(*) FROM smtp_mdns WHERE from_id=?",
|
||||
(bob_msg2.from_id,)
|
||||
)
|
||||
.await?,
|
||||
1
|
||||
);
|
||||
|
||||
// bob marks the chat as fresh again, fresh count is 1 again
|
||||
markfresh_chat(bob, bob_chat_id).await?;
|
||||
let bob_msg1 = Message::load_from_db(bob, bob_msg1.id).await?;
|
||||
|
||||
@@ -319,6 +319,12 @@ pub enum Config {
|
||||
/// True if account is configured.
|
||||
Configured,
|
||||
|
||||
/// Deprecated, we are trying to get rid of this global setting.
|
||||
/// It is possible to configure a profile with both chatmail relays
|
||||
/// and classical email servers.
|
||||
///
|
||||
/// Most usages in UIs can be replaced by `force_encryption`.
|
||||
///
|
||||
/// True if account is a chatmail account.
|
||||
IsChatmail,
|
||||
|
||||
|
||||
@@ -1026,9 +1026,7 @@ impl Contact {
|
||||
|| row_authname.is_empty());
|
||||
|
||||
row_id = id;
|
||||
let qr_with_fingerprint = !fingerprint.is_empty()
|
||||
&& origin == Origin::UnhandledSecurejoinQrScan;
|
||||
if (origin >= row_origin || qr_with_fingerprint) && addr != row_addr {
|
||||
if origin >= row_origin && addr != row_addr {
|
||||
update_addr = true;
|
||||
}
|
||||
if update_name || update_authname || update_addr || origin > row_origin {
|
||||
|
||||
@@ -566,6 +566,10 @@ impl Context {
|
||||
self.scheduler.maybe_network().await;
|
||||
}
|
||||
|
||||
/// Deprecated, we are trying to get rid of this global setting.
|
||||
/// It is possible to configure a profile with both chatmail relays
|
||||
/// and classical email servers.
|
||||
///
|
||||
/// Returns true if an account is on a chatmail server.
|
||||
pub async fn is_chatmail(&self) -> Result<bool> {
|
||||
self.get_config_bool(Config::IsChatmail).await
|
||||
|
||||
30
src/e2ee.rs
30
src/e2ee.rs
@@ -97,18 +97,6 @@ impl EncryptHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensures a private key exists for the configured user.
|
||||
///
|
||||
/// Normally the private key is generated when the first message is
|
||||
/// sent but in a few locations there are no such guarantees,
|
||||
/// e.g. when exporting keys, and calling this function ensures a
|
||||
/// private key will be present.
|
||||
// TODO, remove this once deltachat::key::Key no longer exists.
|
||||
pub async fn ensure_secret_key_exists(context: &Context) -> Result<()> {
|
||||
load_self_public_key(context).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -118,23 +106,7 @@ mod tests {
|
||||
use crate::message::Message;
|
||||
use crate::mimeparser::SystemMessage;
|
||||
use crate::receive_imf::receive_imf;
|
||||
use crate::test_utils::{TestContext, TestContextManager};
|
||||
|
||||
mod ensure_secret_key_exists {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_prexisting() {
|
||||
let t = TestContext::new_alice().await;
|
||||
assert!(ensure_secret_key_exists(&t).await.is_ok());
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_not_configured() {
|
||||
let t = TestContext::new().await;
|
||||
assert!(ensure_secret_key_exists(&t).await.is_err());
|
||||
}
|
||||
}
|
||||
use crate::test_utils::TestContextManager;
|
||||
|
||||
#[test]
|
||||
fn test_mailmime_parse() {
|
||||
|
||||
@@ -111,7 +111,7 @@ impl Session {
|
||||
}
|
||||
|
||||
// Returns true if IMAP server has `XCHATMAIL` capability.
|
||||
pub fn is_chatmail(&self) -> bool {
|
||||
pub(crate) fn is_chatmail(&self) -> bool {
|
||||
self.capabilities.is_chatmail
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ use crate::blob::BlobDirContents;
|
||||
use crate::chat::delete_and_reset_all_device_msgs;
|
||||
use crate::config::Config;
|
||||
use crate::context::Context;
|
||||
use crate::e2ee;
|
||||
use crate::events::EventType;
|
||||
use crate::key::{self, DcKey, SignedSecretKey};
|
||||
use crate::log::{LogExt, warn};
|
||||
@@ -170,7 +169,7 @@ async fn imex_inner(
|
||||
|
||||
if what == ImexMode::ExportBackup || what == ImexMode::ExportSelfKeys {
|
||||
// before we export anything, make sure the private key exists
|
||||
e2ee::ensure_secret_key_exists(context)
|
||||
key::ensure_secret_key_exists(context)
|
||||
.await
|
||||
.context("Cannot create private key or private key not available")?;
|
||||
|
||||
|
||||
@@ -38,15 +38,16 @@ use tokio::fs;
|
||||
use tokio::task::JoinHandle;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::EventType;
|
||||
use crate::chat::add_device_msg;
|
||||
use crate::context::Context;
|
||||
use crate::imex::BlobDirContents;
|
||||
use crate::key;
|
||||
use crate::log::warn;
|
||||
use crate::message::Message;
|
||||
use crate::qr::Qr;
|
||||
use crate::stock_str::backup_transfer_msg_body;
|
||||
use crate::tools::{TempPathGuard, create_id, time};
|
||||
use crate::{EventType, e2ee};
|
||||
|
||||
use super::{DBFILE_BACKUP_NAME, export_backup_stream, export_database, import_backup_stream};
|
||||
|
||||
@@ -112,7 +113,7 @@ impl BackupProvider {
|
||||
.context("Context dir not found")?;
|
||||
|
||||
// before we export, make sure the private key exists
|
||||
e2ee::ensure_secret_key_exists(context)
|
||||
key::ensure_secret_key_exists(context)
|
||||
.await
|
||||
.context("Cannot create private key or private key not available")?;
|
||||
|
||||
|
||||
27
src/key.rs
27
src/key.rs
@@ -320,6 +320,17 @@ pub(crate) async fn load_self_public_key(context: &Context) -> Result<SignedPubl
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensures a private key exists for the configured user.
|
||||
///
|
||||
/// Normally the private key is generated when the first message is
|
||||
/// sent but in a few locations there are no such guarantees,
|
||||
/// e.g. when exporting keys, and calling this function ensures a
|
||||
/// private key will be present.
|
||||
pub async fn ensure_secret_key_exists(context: &Context) -> Result<()> {
|
||||
load_self_public_key(context).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns our own public keyring.
|
||||
///
|
||||
/// No keys are generated and at most one key is returned.
|
||||
@@ -898,4 +909,20 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD
|
||||
"0102 0408 1020 4080 FF01\n0204 0810 2040 80FF 1314"
|
||||
);
|
||||
}
|
||||
|
||||
mod ensure_secret_key_exists {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_prexisting() {
|
||||
let t = TestContext::new_alice().await;
|
||||
assert!(ensure_secret_key_exists(&t).await.is_ok());
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_not_configured() {
|
||||
let t = TestContext::new().await;
|
||||
assert!(ensure_secret_key_exists(&t).await.is_err());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +271,9 @@ impl MimeFactory {
|
||||
|
||||
let public_key = SignedPublicKey::from_slice(&public_key_bytes)?;
|
||||
|
||||
recipients.extend(relay_addrs(&public_key, &addr));
|
||||
let relays =
|
||||
addresses_from_public_key(&public_key).unwrap_or_else(|| vec![addr.clone()]);
|
||||
recipients.extend(relays);
|
||||
to.push((authname, addr.clone()));
|
||||
|
||||
encryption_pubkeys = Some(vec![(addr, public_key)]);
|
||||
@@ -351,7 +353,7 @@ impl MimeFactory {
|
||||
};
|
||||
if add_timestamp >= remove_timestamp {
|
||||
let relays = if let Some(public_key) = public_key_opt {
|
||||
let addrs = relay_addrs(&public_key, &addr);
|
||||
let addrs = addresses_from_public_key(&public_key);
|
||||
keys.push((addr.clone(), public_key));
|
||||
addrs
|
||||
} else if id != ContactId::SELF && !should_encrypt_symmetrically(&msg, &chat) {
|
||||
@@ -359,10 +361,10 @@ impl MimeFactory {
|
||||
if is_encrypted {
|
||||
warn!(context, "Missing key for {addr}");
|
||||
}
|
||||
vec![addr.clone()]
|
||||
None
|
||||
} else {
|
||||
vec![addr.clone()]
|
||||
};
|
||||
None
|
||||
}.unwrap_or_else(|| vec![addr.clone()]);
|
||||
|
||||
if !recipients_contain_addr(&to, &addr) {
|
||||
if id != ContactId::SELF {
|
||||
@@ -391,7 +393,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 = relay_addrs(&public_key, &addr);
|
||||
let addrs = addresses_from_public_key(&public_key);
|
||||
keys.push((addr.clone(), public_key));
|
||||
addrs
|
||||
} else if id != ContactId::SELF && !should_encrypt_symmetrically(&msg, &chat) {
|
||||
@@ -399,10 +401,10 @@ impl MimeFactory {
|
||||
if is_encrypted {
|
||||
warn!(context, "Missing key for {addr}");
|
||||
}
|
||||
vec![addr.clone()]
|
||||
None
|
||||
} else {
|
||||
vec![addr.clone()]
|
||||
};
|
||||
None
|
||||
}.unwrap_or_else(|| vec![addr.clone()]);
|
||||
|
||||
// This is a "member removed" message,
|
||||
// we need to notify removed member
|
||||
@@ -616,9 +618,7 @@ impl MimeFactory {
|
||||
|
||||
fn should_skip_autocrypt(&self) -> bool {
|
||||
match &self.loaded {
|
||||
Loaded::Message { msg, .. } => {
|
||||
msg.param.get_bool(Param::SkipAutocrypt).unwrap_or_default()
|
||||
}
|
||||
Loaded::Message { .. } => false,
|
||||
Loaded::Mdn { .. } => true,
|
||||
}
|
||||
}
|
||||
@@ -2201,14 +2201,6 @@ async fn build_avatar_file(context: &Context, path: &str) -> Result<String> {
|
||||
Ok(encoded_body)
|
||||
}
|
||||
|
||||
fn relay_addrs(public_key: &SignedPublicKey, addr: &str) -> Vec<String> {
|
||||
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
|
||||
|
||||
@@ -64,7 +64,8 @@ pub enum Param {
|
||||
ForcePlaintext = b'u',
|
||||
|
||||
/// For Messages: do not include Autocrypt header.
|
||||
SkipAutocrypt = b'o',
|
||||
/// Deprecated on 2026-06-20
|
||||
DeprecatedSkipAutocrypt = b'o',
|
||||
|
||||
/// For Messages
|
||||
WantsMdn = b'r',
|
||||
|
||||
@@ -14,9 +14,9 @@ use crate::constants::{
|
||||
use crate::contact::mark_contact_id_as_verified;
|
||||
use crate::contact::{Contact, ContactId, Origin};
|
||||
use crate::context::Context;
|
||||
use crate::e2ee::ensure_secret_key_exists;
|
||||
use crate::events::EventType;
|
||||
use crate::headerdef::HeaderDef;
|
||||
use crate::key;
|
||||
use crate::key::{DcKey, Fingerprint, load_self_public_key, self_fingerprint};
|
||||
use crate::log::LogExt as _;
|
||||
use crate::log::warn;
|
||||
@@ -92,7 +92,7 @@ pub async fn get_securejoin_qr(context: &Context, chat: Option<ChatId>) -> Resul
|
||||
==== Step 1 in "Setup verified contact" protocol ====
|
||||
=======================================================*/
|
||||
|
||||
ensure_secret_key_exists(context).await.ok();
|
||||
key::ensure_secret_key_exists(context).await.ok();
|
||||
|
||||
let chat = match chat {
|
||||
Some(id) => {
|
||||
|
||||
91
src/smtp.rs
91
src/smtp.rs
@@ -492,7 +492,35 @@ async fn send_mdns(context: &Context, connection: &mut Smtp) -> Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let more_mdns = send_mdn(context, connection).await?;
|
||||
let more_mdns = send_mdn(context, async |rfc724_mid, body, recipients| {
|
||||
let recipients: Vec<_> = recipients
|
||||
.into_iter()
|
||||
.filter_map(|addr| {
|
||||
async_smtp::EmailAddress::new(addr.clone())
|
||||
.with_context(|| format!("Invalid recipient: {addr}"))
|
||||
.log_err(context)
|
||||
.ok()
|
||||
})
|
||||
.collect();
|
||||
|
||||
match smtp_send(context, &recipients, &body, connection, None).await {
|
||||
SendResult::Success => {
|
||||
if !recipients.is_empty() {
|
||||
info!(context, "Successfully sent MDN for {rfc724_mid}.");
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
SendResult::Retry => {
|
||||
info!(
|
||||
context,
|
||||
"Temporary SMTP failure while sending an MDN for {rfc724_mid}."
|
||||
);
|
||||
Ok(false)
|
||||
}
|
||||
SendResult::Failure(err) => Err(err),
|
||||
}
|
||||
})
|
||||
.await?;
|
||||
if !more_mdns {
|
||||
// No more MDNs to send or one of them failed.
|
||||
return Ok(());
|
||||
@@ -550,7 +578,7 @@ async fn send_mdn_rfc724_mid(
|
||||
context: &Context,
|
||||
rfc724_mid: &str,
|
||||
contact_id: ContactId,
|
||||
smtp: &mut Smtp,
|
||||
send_fn: impl AsyncFnOnce(&str, String, Vec<String>) -> Result<bool>,
|
||||
) -> Result<bool> {
|
||||
let contact = Contact::get_by_id(context, contact_id).await?;
|
||||
if contact.is_blocked() {
|
||||
@@ -590,48 +618,29 @@ async fn send_mdn_rfc724_mid(
|
||||
if context.get_config_bool(Config::BccSelf).await? {
|
||||
add_self_recipients(context, &mut recipients, encrypted).await?;
|
||||
}
|
||||
let recipients: Vec<_> = recipients
|
||||
.into_iter()
|
||||
.filter_map(|addr| {
|
||||
async_smtp::EmailAddress::new(addr.clone())
|
||||
.with_context(|| format!("Invalid recipient: {addr}"))
|
||||
.log_err(context)
|
||||
.ok()
|
||||
})
|
||||
.collect();
|
||||
|
||||
match smtp_send(context, &recipients, &body, smtp, None).await {
|
||||
SendResult::Success => {
|
||||
if !recipients.is_empty() {
|
||||
info!(context, "Successfully sent MDN for {rfc724_mid}.");
|
||||
}
|
||||
context
|
||||
.sql
|
||||
.transaction(|transaction| {
|
||||
let mut stmt =
|
||||
transaction.prepare("DELETE FROM smtp_mdns WHERE rfc724_mid = ?")?;
|
||||
stmt.execute((rfc724_mid,))?;
|
||||
for additional_rfc724_mid in additional_rfc724_mids {
|
||||
stmt.execute((additional_rfc724_mid,))?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.await?;
|
||||
Ok(true)
|
||||
}
|
||||
SendResult::Retry => {
|
||||
info!(
|
||||
context,
|
||||
"Temporary SMTP failure while sending an MDN for {rfc724_mid}."
|
||||
);
|
||||
Ok(false)
|
||||
}
|
||||
SendResult::Failure(err) => Err(err),
|
||||
message::insert_tombstone(context, &rendered_msg.rfc724_mid).await?;
|
||||
let sent = send_fn(rfc724_mid, body, recipients).await?;
|
||||
if sent {
|
||||
context
|
||||
.sql
|
||||
.transaction(|transaction| {
|
||||
let mut stmt = transaction.prepare("DELETE FROM smtp_mdns WHERE rfc724_mid = ?")?;
|
||||
stmt.execute((rfc724_mid,))?;
|
||||
for additional_rfc724_mid in additional_rfc724_mids {
|
||||
stmt.execute((additional_rfc724_mid,))?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
Ok(sent)
|
||||
}
|
||||
|
||||
/// Tries to send a single MDN. Returns true if more MDNs should be sent.
|
||||
async fn send_mdn(context: &Context, smtp: &mut Smtp) -> Result<bool> {
|
||||
pub(crate) async fn send_mdn(
|
||||
context: &Context,
|
||||
send_fn: impl AsyncFnOnce(&str, String, Vec<String>) -> Result<bool>,
|
||||
) -> Result<bool> {
|
||||
if !context.should_send_mdns().await? {
|
||||
context.sql.execute("DELETE FROM smtp_mdns", []).await?;
|
||||
return Ok(false);
|
||||
@@ -668,7 +677,7 @@ async fn send_mdn(context: &Context, smtp: &mut Smtp) -> Result<bool> {
|
||||
.await
|
||||
.context("Failed to update MDN retries count")?;
|
||||
|
||||
match send_mdn_rfc724_mid(context, &rfc724_mid, contact_id, smtp).await {
|
||||
match send_mdn_rfc724_mid(context, &rfc724_mid, contact_id, send_fn).await {
|
||||
Err(err) => {
|
||||
// If there is an error, for example there is no message corresponding to the msg_id in the
|
||||
// database, do not try to send this MDN again.
|
||||
|
||||
@@ -43,7 +43,7 @@ use crate::mimeparser::{MimeMessage, SystemMessage};
|
||||
use crate::pgp::SeipdVersion;
|
||||
use crate::receive_imf::{ReceivedMsg, receive_imf};
|
||||
use crate::securejoin::{get_securejoin_qr, join_securejoin};
|
||||
use crate::smtp::msg_has_pending_smtp_job;
|
||||
use crate::smtp::{self, msg_has_pending_smtp_job};
|
||||
use crate::stock_str::StockStrings;
|
||||
use crate::tools::time;
|
||||
|
||||
@@ -232,9 +232,7 @@ impl TestContextManager {
|
||||
|
||||
test_context.set_primary_self_addr(new_addr).await.unwrap();
|
||||
// ensure_secret_key_exists() is called during configure
|
||||
crate::e2ee::ensure_secret_key_exists(test_context)
|
||||
.await
|
||||
.unwrap();
|
||||
key::ensure_secret_key_exists(test_context).await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
test_context.get_primary_self_addr().await.unwrap(),
|
||||
@@ -1082,6 +1080,22 @@ ORDER BY id"
|
||||
res
|
||||
}
|
||||
|
||||
pub async fn get_sent_mdn(&self) -> SentMessage<'_> {
|
||||
let mut sent_mdn = None;
|
||||
smtp::send_mdn(self, async |_rfc724_mid, body, recipients| {
|
||||
sent_mdn = Some(SentMessage {
|
||||
payload: body,
|
||||
sender_msg_id: MsgId::new(u32::MAX),
|
||||
sender_context: &self.ctx,
|
||||
recipients: recipients.join(" "),
|
||||
});
|
||||
Ok(true)
|
||||
})
|
||||
.await
|
||||
.expect("smtp::send_mdn");
|
||||
sent_mdn.unwrap()
|
||||
}
|
||||
|
||||
pub async fn golden_test_chat(&self, chat_id: ChatId, filename: &str) {
|
||||
let filename = Path::new("test-data/golden/").join(filename);
|
||||
|
||||
|
||||
@@ -6,7 +6,9 @@ use crate::chat::{self, Chat, add_contact_to_chat, remove_contact_from_chat, sen
|
||||
use crate::config::Config;
|
||||
use crate::constants::Chattype;
|
||||
use crate::contact::{Contact, ContactId};
|
||||
use crate::key;
|
||||
use crate::key::self_fingerprint;
|
||||
use crate::message;
|
||||
use crate::message::{Message, Viewtype};
|
||||
use crate::mimefactory::MimeFactory;
|
||||
use crate::mimeparser::SystemMessage;
|
||||
@@ -18,7 +20,6 @@ use crate::test_utils::{
|
||||
E2EE_INFO_MSGS, TestContext, TestContextManager, get_chat_msg, mark_as_verified,
|
||||
};
|
||||
use crate::tools::SystemTime;
|
||||
use crate::{e2ee, message};
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_verified_oneonone_chat_not_broken_by_classical() {
|
||||
@@ -126,7 +127,7 @@ async fn test_create_verified_oneonone_chat() -> Result<()> {
|
||||
|
||||
let fiona_new = tcm.unconfigured().await;
|
||||
fiona_new.configure_addr("fiona@example.net").await;
|
||||
e2ee::ensure_secret_key_exists(&fiona_new).await?;
|
||||
key::ensure_secret_key_exists(&fiona_new).await?;
|
||||
|
||||
tcm.send_recv(&fiona_new, &alice, "I have a new device")
|
||||
.await;
|
||||
@@ -428,7 +429,7 @@ async fn test_verify_then_verify_again() -> Result<()> {
|
||||
drop(bob);
|
||||
let bob_new = tcm.unconfigured().await;
|
||||
bob_new.configure_addr("bob@example.net").await;
|
||||
e2ee::ensure_secret_key_exists(&bob_new).await?;
|
||||
key::ensure_secret_key_exists(&bob_new).await?;
|
||||
|
||||
tcm.execute_securejoin(&bob_new, &alice).await;
|
||||
assert_verified(&alice, &bob_new).await;
|
||||
|
||||
Reference in New Issue
Block a user