refactor: upgrade to Rust 2024

This commit is contained in:
link2xt
2025-06-28 17:07:59 +00:00
committed by l
parent 0ffd4d9f87
commit 5c3de759d3
94 changed files with 1083 additions and 711 deletions
+21 -12
View File
@@ -4,7 +4,7 @@ use std::collections::BTreeMap;
use std::future::Future;
use std::path::{Path, PathBuf};
use anyhow::{bail, ensure, Context as _, Result};
use anyhow::{Context as _, Result, bail, ensure};
use serde::{Deserialize, Serialize};
use tokio::fs;
use tokio::io::AsyncWriteExt;
@@ -14,7 +14,7 @@ use uuid::Uuid;
#[cfg(not(target_os = "ios"))]
use tokio::sync::oneshot;
#[cfg(not(target_os = "ios"))]
use tokio::time::{sleep, Duration};
use tokio::time::{Duration, sleep};
use crate::context::{Context, ContextBuilder};
use crate::events::{Event, EventEmitter, EventType, Events};
@@ -352,7 +352,10 @@ impl Accounts {
///
/// Returns a future that resolves when background fetch is done,
/// but does not capture `&self`.
pub fn background_fetch(&self, timeout: std::time::Duration) -> impl Future<Output = ()> {
pub fn background_fetch(
&self,
timeout: std::time::Duration,
) -> impl Future<Output = ()> + use<> {
let accounts: Vec<Context> = self.accounts.values().cloned().collect();
let events = self.events.clone();
Self::background_fetch_with_timeout(accounts, events, timeout)
@@ -456,7 +459,9 @@ impl Config {
Ok(())
});
if locked_rx.await.is_err() {
bail!("Delta Chat is already running. To use Delta Chat, you must first close the existing Delta Chat process, or restart your device. (accounts.lock file is already locked)");
bail!(
"Delta Chat is already running. To use Delta Chat, you must first close the existing Delta Chat process, or restart your device. (accounts.lock file is already locked)"
);
};
Ok(Some(lock_task))
}
@@ -500,11 +505,13 @@ impl Config {
/// protects from parallel calls resulting to a wrong file contents.
async fn sync(&mut self) -> Result<()> {
#[cfg(not(target_os = "ios"))]
ensure!(!self
.lock_task
.as_ref()
.context("Config is read-only")?
.is_finished());
ensure!(
!self
.lock_task
.as_ref()
.context("Config is read-only")?
.is_finished()
);
let tmp_path = self.file.with_extension("toml.tmp");
let mut file = fs::File::create(&tmp_path)
@@ -962,9 +969,11 @@ mod tests {
// Test that event emitter does not return `None` immediately.
let duration = std::time::Duration::from_millis(1);
assert!(tokio::time::timeout(duration, event_emitter.recv())
.await
.is_err());
assert!(
tokio::time::timeout(duration, event_emitter.recv())
.await
.is_err()
);
// When account manager is dropped, event emitter is exhausted.
drop(accounts);
+34 -26
View File
@@ -6,7 +6,7 @@ use std::collections::BTreeMap;
use std::fmt;
use std::str::FromStr;
use anyhow::{bail, Context as _, Error, Result};
use anyhow::{Context as _, Error, Result, bail};
use crate::key::{DcKey, SignedPublicKey};
@@ -217,7 +217,9 @@ mod tests {
let rendered = ah.to_string();
assert_eq!(rendered, fixed_header);
let ah = Aheader::from_str(&format!(" _foo; __FOO=BAR ;;; addr = a@b.example.org ;\r\n prefer-encrypt = mutual ; keydata = {RAWKEY}"))?;
let ah = Aheader::from_str(&format!(
" _foo; __FOO=BAR ;;; addr = a@b.example.org ;\r\n prefer-encrypt = mutual ; keydata = {RAWKEY}"
))?;
assert_eq!(ah.addr, "a@b.example.org");
assert_eq!(ah.prefer_encrypt, EncryptPreference::Mutual);
@@ -240,38 +242,44 @@ mod tests {
#[test]
fn test_display_aheader() {
assert!(format!(
"{}",
Aheader::new(
"test@example.com".to_string(),
SignedPublicKey::from_base64(RAWKEY).unwrap(),
EncryptPreference::Mutual
assert!(
format!(
"{}",
Aheader::new(
"test@example.com".to_string(),
SignedPublicKey::from_base64(RAWKEY).unwrap(),
EncryptPreference::Mutual
)
)
)
.contains("prefer-encrypt=mutual;"));
.contains("prefer-encrypt=mutual;")
);
// According to Autocrypt Level 1 specification,
// only "prefer-encrypt=mutual;" can be used.
// If the setting is nopreference, the whole attribute is omitted.
assert!(!format!(
"{}",
Aheader::new(
"test@example.com".to_string(),
SignedPublicKey::from_base64(RAWKEY).unwrap(),
EncryptPreference::NoPreference
assert!(
!format!(
"{}",
Aheader::new(
"test@example.com".to_string(),
SignedPublicKey::from_base64(RAWKEY).unwrap(),
EncryptPreference::NoPreference
)
)
)
.contains("prefer-encrypt"));
.contains("prefer-encrypt")
);
// Always lowercase the address in the header.
assert!(format!(
"{}",
Aheader::new(
"TeSt@eXaMpLe.cOm".to_string(),
SignedPublicKey::from_base64(RAWKEY).unwrap(),
EncryptPreference::Mutual
assert!(
format!(
"{}",
Aheader::new(
"TeSt@eXaMpLe.cOm".to_string(),
SignedPublicKey::from_base64(RAWKEY).unwrap(),
EncryptPreference::Mutual
)
)
)
.contains("test@example.com"));
.contains("test@example.com")
);
}
}
+7 -6
View File
@@ -548,12 +548,13 @@ Authentication-Results: dkim=";
let rcvd = bob.recv_msg(&sent).await;
// The message info should contain a warning:
assert!(rcvd
.id
.get_info(&bob)
.await
.unwrap()
.contains("DKIM Results: Passed=false"));
assert!(
rcvd.id
.get_info(&bob)
.await
.unwrap()
.contains("DKIM Results: Passed=false")
);
Ok(())
}
+4 -8
View File
@@ -6,11 +6,11 @@ use std::iter::FusedIterator;
use std::mem;
use std::path::{Path, PathBuf};
use anyhow::{ensure, format_err, Context as _, Result};
use anyhow::{Context as _, Result, ensure, format_err};
use base64::Engine as _;
use futures::StreamExt;
use image::codecs::jpeg::JpegEncoder;
use image::ImageReader;
use image::codecs::jpeg::JpegEncoder;
use image::{DynamicImage, GenericImage, GenericImageView, ImageFormat, Pixel, Rgba};
use num_traits::FromPrimitive;
use tokio::{fs, task};
@@ -20,7 +20,7 @@ use crate::config::Config;
use crate::constants::{self, MediaQuality};
use crate::context::Context;
use crate::events::EventType;
use crate::log::{error, info, warn, LogExt};
use crate::log::{LogExt, error, info, warn};
use crate::tools::sanitize_filename;
/// Represents a file in the blob directory.
@@ -205,11 +205,7 @@ impl<'a> BlobObject<'a> {
/// to be lowercase.
pub fn suffix(&self) -> Option<&str> {
let ext = self.name.rsplit('.').next();
if ext == Some(&self.name) {
None
} else {
ext
}
if ext == Some(&self.name) { None } else { ext }
}
/// Checks whether a name is a valid blob name.
+17 -14
View File
@@ -580,20 +580,23 @@ impl SendImageCheckMediaquality<'_> {
}
fn assert_extension(context: &TestContext, msg: Message, extension: &str) {
assert!(msg
.param
.get(Param::File)
.unwrap()
.ends_with(&format!(".{extension}")));
assert!(msg
.param
.get(Param::Filename)
.unwrap()
.ends_with(&format!(".{extension}")));
assert!(msg
.get_filename()
.unwrap()
.ends_with(&format!(".{extension}")));
assert!(
msg.param
.get(Param::File)
.unwrap()
.ends_with(&format!(".{extension}"))
);
assert!(
msg.param
.get(Param::Filename)
.unwrap()
.ends_with(&format!(".{extension}"))
);
assert!(
msg.get_filename()
.unwrap()
.ends_with(&format!(".{extension}"))
);
assert_eq!(
msg.get_file(context)
.unwrap()
+15 -12
View File
@@ -9,8 +9,8 @@ use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::time::Duration;
use anyhow::{anyhow, bail, ensure, Context as _, Result};
use deltachat_contact_tools::{sanitize_bidi_characters, sanitize_single_line, ContactAddress};
use anyhow::{Context as _, Result, anyhow, bail, ensure};
use deltachat_contact_tools::{ContactAddress, sanitize_bidi_characters, sanitize_single_line};
use deltachat_derive::{FromSql, ToSql};
use mail_builder::mime::MimePart;
use serde::{Deserialize, Serialize};
@@ -28,10 +28,10 @@ use crate::contact::{self, Contact, ContactId, Origin};
use crate::context::Context;
use crate::debug_logging::maybe_set_logging_xdc;
use crate::download::DownloadState;
use crate::ephemeral::{start_chat_ephemeral_timers, Timer as EphemeralTimer};
use crate::ephemeral::{Timer as EphemeralTimer, start_chat_ephemeral_timers};
use crate::events::EventType;
use crate::location;
use crate::log::{error, info, warn, LogExt};
use crate::log::{LogExt, error, info, warn};
use crate::message::{self, Message, MessageState, MsgId, Viewtype};
use crate::mimefactory::MimeFactory;
use crate::mimeparser::SystemMessage;
@@ -41,9 +41,9 @@ use crate::smtp::send_msg_to_smtp;
use crate::stock_str;
use crate::sync::{self, Sync::*, SyncData};
use crate::tools::{
buf_compress, create_id, create_outgoing_rfc724_mid, create_smeared_timestamp,
create_smeared_timestamps, get_abs_path, gm2local_offset, smeared_time, time,
truncate_msg_text, IsNoneOrEmpty, SystemTime,
IsNoneOrEmpty, SystemTime, buf_compress, create_id, create_outgoing_rfc724_mid,
create_smeared_timestamp, create_smeared_timestamps, get_abs_path, gm2local_offset,
smeared_time, time, truncate_msg_text,
};
use crate::webxdc::StatusUpdateSerial;
use crate::{chatlist_events, imap};
@@ -4085,7 +4085,10 @@ pub async fn remove_contact_from_chat(
res?;
set_group_explicitly_left(context, &chat.grpid).await?;
} else if let Err(e) = res {
warn!(context, "remove_contact_from_chat({chat_id}, {contact_id}): send_msg() failed: {e:#}.");
warn!(
context,
"remove_contact_from_chat({chat_id}, {contact_id}): send_msg() failed: {e:#}."
);
}
} else {
sync = Sync;
@@ -4918,10 +4921,10 @@ impl Context {
Contact::add_or_lookup(self, "", &addr, Origin::Hidden).await?;
match action {
SyncAction::Block => {
return contact::set_blocked(self, Nosync, contact_id, true).await
return contact::set_blocked(self, Nosync, contact_id, true).await;
}
SyncAction::Unblock => {
return contact::set_blocked(self, Nosync, contact_id, false).await
return contact::set_blocked(self, Nosync, contact_id, false).await;
}
_ => (),
}
@@ -4944,10 +4947,10 @@ impl Context {
return Ok(());
}
SyncAction::Block => {
return contact::set_blocked(self, Nosync, contact_id, true).await
return contact::set_blocked(self, Nosync, contact_id, true).await;
}
SyncAction::Unblock => {
return contact::set_blocked(self, Nosync, contact_id, false).await
return contact::set_blocked(self, Nosync, contact_id, false).await;
}
_ => (),
}
+97 -63
View File
@@ -3,10 +3,10 @@ use crate::chatlist::get_archived_cnt;
use crate::constants::{DC_GCL_ARCHIVED_ONLY, DC_GCL_NO_SPECIALS};
use crate::ephemeral::Timer;
use crate::headerdef::HeaderDef;
use crate::imex::{has_backup, imex, ImexMode};
use crate::message::{delete_msgs, MessengerMessage};
use crate::imex::{ImexMode, has_backup, imex};
use crate::message::{MessengerMessage, delete_msgs};
use crate::receive_imf::receive_imf;
use crate::test_utils::{sync, TestContext, TestContextManager, TimeShiftFalsePositiveNote};
use crate::test_utils::{TestContext, TestContextManager, TimeShiftFalsePositiveNote, sync};
use pretty_assertions::assert_eq;
use strum::IntoEnumIterator;
use tokio::fs;
@@ -961,9 +961,11 @@ async fn test_was_device_msg_ever_added() {
add_device_msg(&t, Some("another-label"), Some(&mut msg))
.await
.ok();
assert!(was_device_msg_ever_added(&t, "another-label")
.await
.unwrap());
assert!(
was_device_msg_ever_added(&t, "another-label")
.await
.unwrap()
);
assert!(!was_device_msg_ever_added(&t, "unused-label").await.unwrap());
@@ -1069,10 +1071,12 @@ async fn test_archive() {
assert_eq!(DC_GCL_NO_SPECIALS, 0x02);
// archive first chat
assert!(chat_id1
.set_visibility(&t, ChatVisibility::Archived)
.await
.is_ok());
assert!(
chat_id1
.set_visibility(&t, ChatVisibility::Archived)
.await
.is_ok()
);
assert!(
Chat::load_from_db(&t, chat_id1)
.await
@@ -1093,10 +1097,12 @@ async fn test_archive() {
assert_eq!(chatlist_len(&t, DC_GCL_ARCHIVED_ONLY).await, 1);
// archive second chat
assert!(chat_id2
.set_visibility(&t, ChatVisibility::Archived)
.await
.is_ok());
assert!(
chat_id2
.set_visibility(&t, ChatVisibility::Archived)
.await
.is_ok()
);
assert!(
Chat::load_from_db(&t, chat_id1)
.await
@@ -1117,18 +1123,24 @@ async fn test_archive() {
assert_eq!(chatlist_len(&t, DC_GCL_ARCHIVED_ONLY).await, 2);
// archive already archived first chat, unarchive second chat two times
assert!(chat_id1
.set_visibility(&t, ChatVisibility::Archived)
.await
.is_ok());
assert!(chat_id2
.set_visibility(&t, ChatVisibility::Normal)
.await
.is_ok());
assert!(chat_id2
.set_visibility(&t, ChatVisibility::Normal)
.await
.is_ok());
assert!(
chat_id1
.set_visibility(&t, ChatVisibility::Archived)
.await
.is_ok()
);
assert!(
chat_id2
.set_visibility(&t, ChatVisibility::Normal)
.await
.is_ok()
);
assert!(
chat_id2
.set_visibility(&t, ChatVisibility::Normal)
.await
.is_ok()
);
assert!(
Chat::load_from_db(&t, chat_id1)
.await
@@ -1368,10 +1380,12 @@ async fn test_pinned() {
assert_eq!(chatlist, vec![chat_id3, chat_id2, chat_id1]);
// pin
assert!(chat_id1
.set_visibility(&t, ChatVisibility::Pinned)
.await
.is_ok());
assert!(
chat_id1
.set_visibility(&t, ChatVisibility::Pinned)
.await
.is_ok()
);
assert_eq!(
Chat::load_from_db(&t, chat_id1)
.await
@@ -1385,10 +1399,12 @@ async fn test_pinned() {
assert_eq!(chatlist, vec![chat_id1, chat_id3, chat_id2]);
// unpin
assert!(chat_id1
.set_visibility(&t, ChatVisibility::Normal)
.await
.is_ok());
assert!(
chat_id1
.set_visibility(&t, ChatVisibility::Normal)
.await
.is_ok()
);
assert_eq!(
Chat::load_from_db(&t, chat_id1)
.await
@@ -1409,10 +1425,12 @@ async fn test_pinned_after_new_msgs() -> Result<()> {
let alice_chat_id = alice.create_chat(&bob).await.id;
let bob_chat_id = bob.create_chat(&alice).await.id;
assert!(alice_chat_id
.set_visibility(&alice, ChatVisibility::Pinned)
.await
.is_ok());
assert!(
alice_chat_id
.set_visibility(&alice, ChatVisibility::Pinned)
.await
.is_ok()
);
assert_eq!(
Chat::load_from_db(&alice, alice_chat_id)
.await?
@@ -1793,10 +1811,12 @@ async fn test_contact_request_fresh_messages() -> Result<()> {
let chats = Chatlist::try_load(&t, 0, None, None).await?;
assert_eq!(chats.len(), 1);
let chat_id = chats.get_chat_id(0).unwrap();
assert!(Chat::load_from_db(&t, chat_id)
.await
.unwrap()
.is_contact_request());
assert!(
Chat::load_from_db(&t, chat_id)
.await
.unwrap()
.is_contact_request()
);
assert_eq!(chat_id.get_msg_cnt(&t).await?, 1);
assert_eq!(chat_id.get_fresh_msg_cnt(&t).await?, 1);
let msgs = get_chat_msgs(&t, chat_id).await?;
@@ -2674,9 +2694,11 @@ async fn test_broadcast_multidev() -> Result<()> {
let a1_broadcast_chat = Chat::load_from_db(&alices[1], a1_broadcast_id).await?;
assert_eq!(a1_broadcast_chat.get_type(), Chattype::Broadcast);
assert_eq!(a1_broadcast_chat.get_name(), "Broadcast list 42");
assert!(get_chat_contacts(&alices[1], a1_broadcast_id)
.await?
.is_empty());
assert!(
get_chat_contacts(&alices[1], a1_broadcast_id)
.await?
.is_empty()
);
add_contact_to_chat(&alices[1], a1_broadcast_id, a1b_contact_id).await?;
set_chat_name(&alices[1], a1_broadcast_id, "Broadcast list 43").await?;
@@ -2686,9 +2708,11 @@ async fn test_broadcast_multidev() -> Result<()> {
let a0_broadcast_chat = Chat::load_from_db(&alices[0], a0_broadcast_id).await?;
assert_eq!(a0_broadcast_chat.get_type(), Chattype::Broadcast);
assert_eq!(a0_broadcast_chat.get_name(), "Broadcast list 42");
assert!(get_chat_contacts(&alices[0], a0_broadcast_id)
.await?
.is_empty());
assert!(
get_chat_contacts(&alices[0], a0_broadcast_id)
.await?
.is_empty()
);
Ok(())
}
@@ -3422,9 +3446,11 @@ async fn test_sync_broadcast() -> Result<()> {
remove_contact_from_chat(alice0, a0_broadcast_id, a0b_contact_id).await?;
sync(alice0, alice1).await;
assert!(get_chat_contacts(alice1, a1_broadcast_id).await?.is_empty());
assert!(get_past_chat_contacts(alice1, a1_broadcast_id)
.await?
.is_empty());
assert!(
get_past_chat_contacts(alice1, a1_broadcast_id)
.await?
.is_empty()
);
a0_broadcast_id.delete(alice0).await?;
sync(alice0, alice1).await;
@@ -4102,9 +4128,11 @@ async fn test_cannot_send_edit_request() -> Result<()> {
// Bob cannot edit Alice's message
let msg = bob.recv_msg(&sent1).await;
assert!(send_edit_request(bob, msg.id, "bar".to_string())
.await
.is_err());
assert!(
send_edit_request(bob, msg.id, "bar".to_string())
.await
.is_err()
);
// HTML messages cannot be edited
let mut msg = Message::new_text("plain text".to_string());
@@ -4122,18 +4150,22 @@ async fn test_cannot_send_edit_request() -> Result<()> {
let msg = alice.get_last_msg().await;
assert!(msg.is_info());
assert_eq!(msg.from_id, ContactId::SELF);
assert!(send_edit_request(alice, msg.id, "bar".to_string())
.await
.is_err());
assert!(
send_edit_request(alice, msg.id, "bar".to_string())
.await
.is_err()
);
// Videochat invitations cannot be edited
alice
.set_config(Config::WebrtcInstance, Some("https://foo.bar"))
.await?;
let msg_id = send_videochat_invitation(alice, chat_id).await?;
assert!(send_edit_request(alice, msg_id, "bar".to_string())
.await
.is_err());
assert!(
send_edit_request(alice, msg_id, "bar".to_string())
.await
.is_err()
);
// If not text was given initally, there is nothing to edit
// (this also avoids complexity in UI element changes; focus is typos and rewordings)
@@ -4200,9 +4232,11 @@ async fn test_send_delete_request_no_encryption() -> Result<()> {
// Alice sends a message, then tries to send a deletion request which fails.
let sent1 = alice.send_text(alice_chat.id, "wtf").await;
assert!(message::delete_msgs_ex(alice, &[sent1.sender_msg_id], true)
.await
.is_err());
assert!(
message::delete_msgs_ex(alice, &[sent1.sender_msg_id], true)
.await
.is_err()
);
sent1.load_from_db().await;
assert_eq!(alice_chat.id.get_msg_cnt(alice).await?, 1);
Ok(())
+16 -12
View File
@@ -1,9 +1,9 @@
//! # Chat list module.
use anyhow::{ensure, Context as _, Result};
use anyhow::{Context as _, Result, ensure};
use std::sync::LazyLock;
use crate::chat::{update_special_chat_names, Chat, ChatId, ChatVisibility};
use crate::chat::{Chat, ChatId, ChatVisibility, update_special_chat_names};
use crate::constants::{
Blocked, Chattype, DC_CHAT_ID_ALLDONE_HINT, DC_CHAT_ID_ARCHIVED_LINK, DC_GCL_ADD_ALLDONE_HINT,
DC_GCL_ARCHIVED_ONLY, DC_GCL_FOR_FORWARDING, DC_GCL_NO_SPECIALS,
@@ -483,8 +483,8 @@ mod tests {
use super::*;
use crate::chat::save_msgs;
use crate::chat::{
add_contact_to_chat, create_group_chat, get_chat_contacts, remove_contact_from_chat,
send_text_msg, ProtectionStatus,
ProtectionStatus, add_contact_to_chat, create_group_chat, get_chat_contacts,
remove_contact_from_chat, send_text_msg,
};
use crate::receive_imf::receive_imf;
use crate::stock_str::StockMessage;
@@ -580,19 +580,23 @@ mod tests {
let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 3);
assert!(!Chat::load_from_db(&t, chats.get_chat_id(0).unwrap())
.await
.unwrap()
.is_self_talk());
assert!(
!Chat::load_from_db(&t, chats.get_chat_id(0).unwrap())
.await
.unwrap()
.is_self_talk()
);
let chats = Chatlist::try_load(&t, DC_GCL_FOR_FORWARDING, None, None)
.await
.unwrap();
assert_eq!(chats.len(), 2); // device chat cannot be written and is skipped on forwarding
assert!(Chat::load_from_db(&t, chats.get_chat_id(0).unwrap())
.await
.unwrap()
.is_self_talk());
assert!(
Chat::load_from_db(&t, chats.get_chat_id(0).unwrap())
.await
.unwrap()
.is_self_talk()
);
remove_contact_from_chat(&t, chats.get_chat_id(1).unwrap(), ContactId::SELF)
.await
+7 -4
View File
@@ -4,7 +4,7 @@ use std::env;
use std::path::Path;
use std::str::FromStr;
use anyhow::{bail, ensure, Context as _, Result};
use anyhow::{Context as _, Result, bail, ensure};
use base64::Engine as _;
use deltachat_contact_tools::{addr_cmp, sanitize_single_line};
use serde::{Deserialize, Serialize};
@@ -17,10 +17,10 @@ use crate::configure::EnteredLoginParam;
use crate::constants;
use crate::context::Context;
use crate::events::EventType;
use crate::log::{info, LogExt};
use crate::log::{LogExt, info};
use crate::login_param::ConfiguredLoginParam;
use crate::mimefactory::RECOMMENDED_FILE_SIZE;
use crate::provider::{get_provider_by_id, Provider};
use crate::provider::{Provider, get_provider_by_id};
use crate::sync::{self, Sync::*, SyncData};
use crate::tools::get_abs_path;
@@ -813,7 +813,10 @@ impl Context {
bail!("Cannot change ConfiguredAddr");
}
if let Some(addr) = value {
info!(self, "Creating a pseudo configured account which will not be able to send or receive messages. Only meant for tests!");
info!(
self,
"Creating a pseudo configured account which will not be able to send or receive messages. Only meant for tests!"
);
ConfiguredLoginParam::from_json(&format!(
r#"{{"addr":"{addr}","imap":[],"imap_user":"","imap_password":"","smtp":[],"smtp_user":"","smtp_password":"","certificate_checks":"Automatic","oauth2":false}}"#
))?
+27 -20
View File
@@ -1,7 +1,7 @@
use num_traits::FromPrimitive;
use super::*;
use crate::test_utils::{sync, TestContext, TestContextManager};
use crate::test_utils::{TestContext, TestContextManager, sync};
#[test]
fn test_to_string() {
@@ -20,10 +20,11 @@ async fn test_set_config_addr() {
let t = TestContext::new().await;
// Test that uppercase address get lowercased.
assert!(t
.set_config(Config::Addr, Some("Foobar@eXample.oRg"))
.await
.is_ok());
assert!(
t.set_config(Config::Addr, Some("Foobar@eXample.oRg"))
.await
.is_ok()
);
assert_eq!(
t.get_config(Config::Addr).await.unwrap().unwrap(),
"foobar@example.org"
@@ -263,11 +264,13 @@ async fn test_sync() -> Result<()> {
self_chat_avatar_path,
alice0.get_blobdir().join(SAVED_MESSAGES_DEDUPLICATED_FILE)
);
assert!(alice1
.get_config(Config::Selfavatar)
.await?
.filter(|path| path.ends_with(".png"))
.is_some());
assert!(
alice1
.get_config(Config::Selfavatar)
.await?
.filter(|path| path.ends_with(".png"))
.is_some()
);
alice0.set_config(Config::Selfavatar, None).await?;
sync(&alice0, &alice1).await;
assert!(alice1.get_config(Config::Selfavatar).await?.is_none());
@@ -321,17 +324,21 @@ async fn test_no_sync_on_self_sent_msg() -> Result<()> {
.await?;
let sent_msg = alice0.send_text(a0b_chat_id, "hi").await;
alice1.recv_msg(&sent_msg).await;
assert!(alice1
.get_config(Config::Selfavatar)
.await?
.filter(|path| path.ends_with(".png"))
.is_some());
assert!(
alice1
.get_config(Config::Selfavatar)
.await?
.filter(|path| path.ends_with(".png"))
.is_some()
);
sync(alice1, alice0).await;
assert!(alice0
.get_config(Config::Selfavatar)
.await?
.filter(|path| path.ends_with(".jpg"))
.is_some());
assert!(
alice0
.get_config(Config::Selfavatar)
.await?
.filter(|path| path.ends_with(".jpg"))
.is_some()
);
Ok(())
}
+8 -6
View File
@@ -13,21 +13,21 @@ mod auto_mozilla;
mod auto_outlook;
pub(crate) mod server_params;
use anyhow::{bail, ensure, format_err, Context as _, Result};
use anyhow::{Context as _, Result, bail, ensure, format_err};
use auto_mozilla::moz_autoconfigure;
use auto_outlook::outlk_autodiscover;
use deltachat_contact_tools::{addr_normalize, EmailAddress};
use deltachat_contact_tools::{EmailAddress, addr_normalize};
use futures::FutureExt;
use futures_lite::FutureExt as _;
use percent_encoding::utf8_percent_encode;
use server_params::{expand_param_vector, ServerParams};
use server_params::{ServerParams, expand_param_vector};
use tokio::task;
use crate::config::{self, Config};
use crate::constants::NON_ALPHANUMERIC_WITHOUT_DOT;
use crate::context::Context;
use crate::imap::Imap;
use crate::log::{info, warn, LogExt};
use crate::log::{LogExt, info, warn};
pub use crate::login_param::EnteredLoginParam;
use crate::login_param::{
ConfiguredCertificateChecks, ConfiguredLoginParam, ConfiguredServerLoginParam,
@@ -39,8 +39,8 @@ use crate::provider::{Protocol, Provider, Socket, UsernamePattern};
use crate::smtp::Smtp;
use crate::sync::Sync::*;
use crate::tools::time;
use crate::{EventType, stock_str};
use crate::{chat, provider};
use crate::{stock_str, EventType};
use deltachat_contact_tools::addr_cmp;
macro_rules! progress {
@@ -215,7 +215,9 @@ impl Context {
/// (i.e. [EnteredLoginParam::addr]).
#[expect(clippy::unused_async)]
pub async fn delete_transport(&self, _addr: &str) -> Result<()> {
bail!("Adding and removing additional transports is not supported yet. Check back in a few months!")
bail!(
"Adding and removing additional transports is not supported yet. Check back in a few months!"
)
}
async fn inner_configure(&self, param: &EnteredLoginParam) -> Result<()> {
+8 -8
View File
@@ -6,19 +6,19 @@ use std::fmt;
use std::path::{Path, PathBuf};
use std::time::UNIX_EPOCH;
use anyhow::{bail, ensure, Context as _, Result};
use anyhow::{Context as _, Result, bail, ensure};
use async_channel::{self as channel, Receiver, Sender};
use base64::Engine as _;
pub use deltachat_contact_tools::may_be_valid_addr;
use deltachat_contact_tools::{
self as contact_tools, addr_normalize, sanitize_name, sanitize_name_and_addr, ContactAddress,
VcardContact,
self as contact_tools, ContactAddress, VcardContact, addr_normalize, sanitize_name,
sanitize_name_and_addr,
};
use deltachat_derive::{FromSql, ToSql};
use rusqlite::OptionalExtension;
use serde::{Deserialize, Serialize};
use tokio::task;
use tokio::time::{timeout, Duration};
use tokio::time::{Duration, timeout};
use crate::blob::BlobObject;
use crate::chat::{ChatId, ChatIdBlocked, ProtectionStatus};
@@ -28,15 +28,15 @@ use crate::constants::{Blocked, Chattype, DC_GCL_ADD_SELF};
use crate::context::Context;
use crate::events::EventType;
use crate::key::{
load_self_public_key, self_fingerprint, self_fingerprint_opt, DcKey, Fingerprint,
SignedPublicKey,
DcKey, Fingerprint, SignedPublicKey, load_self_public_key, self_fingerprint,
self_fingerprint_opt,
};
use crate::log::{info, warn, LogExt};
use crate::log::{LogExt, info, warn};
use crate::message::MessageState;
use crate::mimeparser::AvatarAction;
use crate::param::{Param, Params};
use crate::sync::{self, Sync::*};
use crate::tools::{duration_to_str, get_abs_path, time, SystemTime};
use crate::tools::{SystemTime, duration_to_str, get_abs_path, time};
use crate::{chat, chatlist_events, stock_str};
/// Time during which a contact is considered as seen recently.
+21 -13
View File
@@ -1,7 +1,7 @@
use deltachat_contact_tools::{addr_cmp, may_be_valid_addr};
use super::*;
use crate::chat::{get_chat_contacts, send_text_msg, Chat};
use crate::chat::{Chat, get_chat_contacts, send_text_msg};
use crate::chatlist::Chatlist;
use crate::receive_imf::receive_imf;
use crate::test_utils::{self, TestContext, TestContextManager, TimeShiftFalsePositiveNote};
@@ -677,20 +677,28 @@ async fn test_name_in_address() {
assert_eq!(contact.get_name(), "name1");
assert_eq!(contact.get_addr(), "dave@example.org");
assert!(Contact::create(&t, "", "<dskjfdslk@sadklj.dk")
.await
.is_err());
assert!(Contact::create(&t, "", "<dskjf>dslk@sadklj.dk>")
.await
.is_err());
assert!(
Contact::create(&t, "", "<dskjfdslk@sadklj.dk")
.await
.is_err()
);
assert!(
Contact::create(&t, "", "<dskjf>dslk@sadklj.dk>")
.await
.is_err()
);
assert!(Contact::create(&t, "", "dskjfdslksadklj.dk").await.is_err());
assert!(Contact::create(&t, "", "dskjfdslk@sadklj.dk>")
.await
.is_err());
assert!(
Contact::create(&t, "", "dskjfdslk@sadklj.dk>")
.await
.is_err()
);
assert!(Contact::create(&t, "", "dskjf dslk@d.e").await.is_err());
assert!(Contact::create(&t, "", "<dskjf dslk@sadklj.dk")
.await
.is_err());
assert!(
Contact::create(&t, "", "<dskjf dslk@sadklj.dk")
.await
.is_err()
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
+4 -4
View File
@@ -8,19 +8,19 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, OnceLock};
use std::time::Duration;
use anyhow::{bail, ensure, Context as _, Result};
use anyhow::{Context as _, Result, bail, ensure};
use async_channel::{self as channel, Receiver, Sender};
use pgp::types::PublicKeyTrait;
use ratelimit::Ratelimit;
use tokio::sync::{Mutex, Notify, RwLock};
use crate::chat::{get_chat_cnt, ChatId, ProtectionStatus};
use crate::chat::{ChatId, ProtectionStatus, get_chat_cnt};
use crate::chatlist_events;
use crate::config::Config;
use crate::constants::{
self, DC_BACKGROUND_FETCH_QUOTA_CHECK_RATELIMIT, DC_CHAT_ID_TRASH, DC_VERSION_STR,
};
use crate::contact::{import_vcard, mark_contact_id_as_verified, Contact, ContactId};
use crate::contact::{Contact, ContactId, import_vcard, mark_contact_id_as_verified};
use crate::debug_logging::DebugLogging;
use crate::download::DownloadState;
use crate::events::{Event, EventEmitter, EventType, Events};
@@ -33,7 +33,7 @@ use crate::param::{Param, Params};
use crate::peer_channels::Iroh;
use crate::push::PushSubscriber;
use crate::quota::QuotaInfo;
use crate::scheduler::{convert_folder_meaning, SchedulerState};
use crate::scheduler::{SchedulerState, convert_folder_meaning};
use crate::sql::Sql;
use crate::stock_str::StockStrings;
use crate::timesmearing::SmearedTimestamp;
+3 -3
View File
@@ -3,13 +3,13 @@ use strum::IntoEnumIterator;
use tempfile::tempdir;
use super::*;
use crate::chat::{get_chat_contacts, get_chat_msgs, send_msg, set_muted, Chat, MuteDuration};
use crate::chat::{Chat, MuteDuration, get_chat_contacts, get_chat_msgs, send_msg, set_muted};
use crate::chatlist::Chatlist;
use crate::constants::Chattype;
use crate::mimeparser::SystemMessage;
use crate::receive_imf::receive_imf;
use crate::test_utils::{get_chat_msg, TestContext};
use crate::tools::{create_outgoing_rfc724_mid, SystemTime};
use crate::test_utils::{TestContext, get_chat_msg};
use crate::tools::{SystemTime, create_outgoing_rfc724_mid};
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_wrong_db() -> Result<()> {
+7 -5
View File
@@ -6,11 +6,11 @@ use std::io::BufRead;
use std::sync::LazyLock;
use quick_xml::{
events::{BytesEnd, BytesStart, BytesText},
Reader,
events::{BytesEnd, BytesStart, BytesText},
};
use crate::simplify::{simplify_quote, SimplifiedText};
use crate::simplify::{SimplifiedText, simplify_quote};
struct Dehtml {
strbuilder: String,
@@ -481,8 +481,7 @@ mod tests {
#[test]
fn test_dehtml_html_encoded() {
let html =
"&lt;&gt;&quot;&apos;&amp; &auml;&Auml;&ouml;&Ouml;&uuml;&Uuml;&szlig; foo&AElig;&ccedil;&Ccedil; &diams;&lrm;&rlm;&zwnj;&noent;&zwj;";
let html = "&lt;&gt;&quot;&apos;&amp; &auml;&Auml;&ouml;&Ouml;&uuml;&Uuml;&szlig; foo&AElig;&ccedil;&Ccedil; &diams;&lrm;&rlm;&zwnj;&noent;&zwj;";
let plain = dehtml(html).unwrap().text;
@@ -540,6 +539,9 @@ mod tests {
fn test_spaces() {
let input = include_str!("../test-data/spaces.html");
let txt = dehtml(input).unwrap();
assert_eq!(txt.text, "Welcome back to Strolling!\n\nHey there,\n\nWelcome back! Use this link to securely sign in to your Strolling account:\n\nSign in to Strolling\n\nFor your security, the link will expire in 24 hours time.\n\nSee you soon!\n\nYou can also copy & paste this URL into your browser:\n\nhttps://strolling.rosano.ca/members/?token=XXX&action=signin&r=https%3A%2F%2Fstrolling.rosano.ca%2F\n\nIf you did not make this request, you can safely ignore this email.\n\nThis message was sent from [strolling.rosano.ca](https://strolling.rosano.ca/) to [alice@example.org](mailto:alice@example.org)");
assert_eq!(
txt.text,
"Welcome back to Strolling!\n\nHey there,\n\nWelcome back! Use this link to securely sign in to your Strolling account:\n\nSign in to Strolling\n\nFor your security, the link will expire in 24 hours time.\n\nSee you soon!\n\nYou can also copy & paste this URL into your browser:\n\nhttps://strolling.rosano.ca/members/?token=XXX&action=signin&r=https%3A%2F%2Fstrolling.rosano.ca%2F\n\nIf you did not make this request, you can safely ignore this email.\n\nThis message was sent from [strolling.rosano.ca](https://strolling.rosano.ca/) to [alice@example.org](mailto:alice@example.org)"
);
}
}
+18 -14
View File
@@ -3,7 +3,7 @@
use std::cmp::max;
use std::collections::BTreeMap;
use anyhow::{anyhow, bail, ensure, Result};
use anyhow::{Result, anyhow, bail, ensure};
use deltachat_derive::{FromSql, ToSql};
use serde::{Deserialize, Serialize};
@@ -14,7 +14,7 @@ use crate::log::info;
use crate::message::{Message, MsgId, Viewtype};
use crate::mimeparser::{MimeMessage, Part};
use crate::tools::time;
use crate::{chatlist_events, stock_str, EventType};
use crate::{EventType, chatlist_events, stock_str};
/// Download limits should not be used below `MIN_DOWNLOAD_LIMIT`.
///
@@ -83,7 +83,7 @@ impl MsgId {
let msg = Message::load_from_db(context, self).await?;
match msg.download_state() {
DownloadState::Done | DownloadState::Undecipherable => {
return Err(anyhow!("Nothing to download."))
return Err(anyhow!("Nothing to download."));
}
DownloadState::InProgress => return Err(anyhow!("Download already in progress.")),
DownloadState::Available | DownloadState::Failure => {
@@ -353,8 +353,7 @@ mod tests {
async fn test_partial_receive_imf() -> Result<()> {
let t = TestContext::new_alice().await;
let header =
"Received: (Postfix, from userid 1000); Mon, 4 Dec 2006 14:51:39 +0100 (CET)\n\
let header = "Received: (Postfix, from userid 1000); Mon, 4 Dec 2006 14:51:39 +0100 (CET)\n\
From: bob@example.com\n\
To: alice@example.org\n\
Subject: foo\n\
@@ -374,9 +373,10 @@ mod tests {
let msg = t.get_last_msg().await;
assert_eq!(msg.download_state(), DownloadState::Available);
assert_eq!(msg.get_subject(), "foo");
assert!(msg
.get_text()
.contains(&stock_str::partial_download_msg_body(&t, 100000).await));
assert!(
msg.get_text()
.contains(&stock_str::partial_download_msg_body(&t, 100000).await)
);
receive_imf_from_inbox(
&t,
@@ -472,9 +472,11 @@ mod tests {
)
.await?;
assert_eq!(get_chat_msgs(&bob, chat_id).await?.len(), 0);
assert!(Message::load_from_db_optional(&bob, msg.id)
.await?
.is_none());
assert!(
Message::load_from_db_optional(&bob, msg.id)
.await?
.is_none()
);
Ok(())
}
@@ -522,9 +524,11 @@ mod tests {
// (usually mdn are too small for not being downloaded directly)
receive_imf_from_inbox(&bob, "bar@example.org", raw, false, None).await?;
assert_eq!(get_chat_msgs(&bob, chat_id).await?.len(), 0);
assert!(Message::load_from_db_optional(&bob, msg.id)
.await?
.is_none());
assert!(
Message::load_from_db_optional(&bob, msg.id)
.await?
.is_none()
);
Ok(())
}
+1 -1
View File
@@ -9,7 +9,7 @@ use num_traits::FromPrimitive;
use crate::aheader::{Aheader, EncryptPreference};
use crate::config::Config;
use crate::context::Context;
use crate::key::{load_self_public_key, load_self_secret_key, SignedPublicKey};
use crate::key::{SignedPublicKey, load_self_public_key, load_self_secret_key};
use crate::pgp;
#[derive(Debug)]
+4 -4
View File
@@ -69,23 +69,23 @@ use std::num::ParseIntError;
use std::str::FromStr;
use std::time::{Duration, UNIX_EPOCH};
use anyhow::{ensure, Context as _, Result};
use anyhow::{Context as _, Result, ensure};
use async_channel::Receiver;
use serde::{Deserialize, Serialize};
use tokio::time::timeout;
use crate::chat::{send_msg, ChatId, ChatIdBlocked};
use crate::chat::{ChatId, ChatIdBlocked, send_msg};
use crate::constants::{DC_CHAT_ID_LAST_SPECIAL, DC_CHAT_ID_TRASH};
use crate::contact::ContactId;
use crate::context::Context;
use crate::download::MIN_DELETE_SERVER_AFTER;
use crate::events::EventType;
use crate::location;
use crate::log::{error, info, warn, LogExt};
use crate::log::{LogExt, error, info, warn};
use crate::message::{Message, MessageState, MsgId, Viewtype};
use crate::mimeparser::SystemMessage;
use crate::stock_str;
use crate::tools::{duration_to_str, time, SystemTime};
use crate::tools::{SystemTime, duration_to_str, time};
/// Ephemeral timer value.
#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)]
+18 -12
View File
@@ -1,7 +1,7 @@
use super::*;
use crate::chat::{
add_contact_to_chat, marknoticed_chat, remove_contact_from_chat, set_muted, ChatVisibility,
MuteDuration,
ChatVisibility, MuteDuration, add_contact_to_chat, marknoticed_chat, remove_contact_from_chat,
set_muted,
};
use crate::config::Config;
use crate::constants::DC_CHAT_ID_ARCHIVED_LINK;
@@ -12,7 +12,7 @@ use crate::receive_imf::receive_imf;
use crate::test_utils::{TestContext, TestContextManager};
use crate::timesmearing::MAX_SECONDS_TO_LEND_FROM_FUTURE;
use crate::{
chat::{self, create_group_chat, send_text_msg, Chat, ChatItem, ProtectionStatus},
chat::{self, Chat, ChatItem, ProtectionStatus, create_group_chat, send_text_msg},
tools::IsNoneOrEmpty,
};
@@ -649,9 +649,11 @@ async fn test_ephemeral_msg_offline() -> Result<()> {
.set_ephemeral_timer(&alice, Timer::Enabled { duration })
.await?;
let mut msg = Message::new_text("hi".to_string());
assert!(chat::send_msg_sync(&alice, chat.id, &mut msg)
.await
.is_err());
assert!(
chat::send_msg_sync(&alice, chat.id, &mut msg)
.await
.is_err()
);
let stmt = "SELECT COUNT(*) FROM smtp WHERE msg_id=?";
assert!(alice.sql.exists(stmt, (msg.id,)).await?);
let now = time();
@@ -729,9 +731,11 @@ async fn test_noticed_ephemeral_timer() -> Result<()> {
delete_expired_messages(bob, time()).await?;
assert!(Message::load_from_db_optional(bob, bob_received_message.id)
.await?
.is_none());
assert!(
Message::load_from_db_optional(bob, bob_received_message.id)
.await?
.is_none()
);
Ok(())
}
@@ -757,9 +761,11 @@ async fn test_archived_ephemeral_timer() -> Result<()> {
delete_expired_messages(bob, time()).await?;
assert!(Message::load_from_db_optional(bob, bob_received_message.id)
.await?
.is_none());
assert!(
Message::load_from_db_optional(bob, bob_received_message.id)
.await?
.is_none()
);
// Bob mutes the chat so it is not unarchived.
set_muted(bob, bob_received_message.chat_id, MuteDuration::Forever).await?;
+4 -4
View File
@@ -1,4 +1,4 @@
use crate::{chat::ChatId, contact::ContactId, context::Context, EventType};
use crate::{EventType, chat::ChatId, contact::ContactId, context::Context};
/// order or content of chatlist changes (chat ids, not the actual chatlist item)
pub(crate) fn emit_chatlist_changed(context: &Context) {
@@ -64,9 +64,10 @@ mod test_chatlist_events {
};
use crate::{
EventType,
chat::{
self, create_broadcast_list, create_group_chat, set_muted, ChatId, ChatVisibility,
MuteDuration, ProtectionStatus,
self, ChatId, ChatVisibility, MuteDuration, ProtectionStatus, create_broadcast_list,
create_group_chat, set_muted,
},
config::Config,
constants::*,
@@ -76,7 +77,6 @@ mod test_chatlist_events {
receive_imf::receive_imf,
securejoin::{get_securejoin_qr, join_securejoin},
test_utils::{TestContext, TestContextManager},
EventType,
};
use crate::tools::SystemTime;
+15 -16
View File
@@ -13,7 +13,7 @@ use std::{
time::{Duration, UNIX_EPOCH},
};
use anyhow::{bail, ensure, format_err, Context as _, Result};
use anyhow::{Context as _, Result, bail, ensure, format_err};
use async_channel::Receiver;
use async_imap::types::{Fetch, Flag, Name, NameAttribute, UnsolicitedResponse};
use deltachat_contact_tools::ContactAddress;
@@ -32,9 +32,9 @@ use crate::contact::{Contact, ContactId, Modifier, Origin};
use crate::context::Context;
use crate::events::EventType;
use crate::headerdef::{HeaderDef, HeaderDefMap};
use crate::log::{error, info, warn, LogExt};
use crate::log::{LogExt, error, info, warn};
use crate::login_param::{
prioritize_server_login_params, ConfiguredLoginParam, ConfiguredServerLoginParam,
ConfiguredLoginParam, ConfiguredServerLoginParam, prioritize_server_login_params,
};
use crate::message::{self, Message, MessageState, MessengerMessage, MsgId};
use crate::mimeparser;
@@ -43,7 +43,7 @@ use crate::net::session::SessionStream;
use crate::oauth2::get_oauth2_access_token;
use crate::push::encrypt_device_token;
use crate::receive_imf::{
from_field_to_contact_id, get_prefetch_parent_message, receive_imf_inner, ReceivedMsg,
ReceivedMsg, from_field_to_contact_id, get_prefetch_parent_message, receive_imf_inner,
};
use crate::scheduler::connectivity::ConnectivityStore;
use crate::stock_str;
@@ -56,7 +56,7 @@ pub mod scan_folders;
pub mod select_folder;
pub(crate) mod session;
use client::{determine_capabilities, Client};
use client::{Client, determine_capabilities};
use mailparse::SingleInfo;
use session::Session;
@@ -1123,7 +1123,8 @@ impl Session {
Err(err) => {
warn!(
context,
"store_seen_flags_on_imap: Failed to select {folder}, will retry later: {err:#}.");
"store_seen_flags_on_imap: Failed to select {folder}, will retry later: {err:#}."
);
continue;
}
Ok(folder_exists) => folder_exists,
@@ -1133,7 +1134,8 @@ impl Session {
} else if let Err(err) = self.add_flag_finalized_with_set(&uid_set, "\\Seen").await {
warn!(
context,
"Cannot mark messages {uid_set} in {folder} as seen, will retry later: {err:#}.");
"Cannot mark messages {uid_set} in {folder} as seen, will retry later: {err:#}."
);
continue;
} else {
info!(
@@ -1349,13 +1351,10 @@ impl Session {
// Try to find a requested UID in returned FETCH responses.
while fetch_response.is_none() {
let next_fetch_response =
if let Some(next_fetch_response) = fetch_responses.next().await {
next_fetch_response
} else {
// No more FETCH responses received from the server.
break;
};
let Some(next_fetch_response) = fetch_responses.next().await else {
// No more FETCH responses received from the server.
break;
};
let next_fetch_response =
next_fetch_response.context("Failed to process IMAP FETCH result")?;
@@ -1806,9 +1805,9 @@ impl Session {
/// In this case we may want to skip next IDLE and do a round
/// of fetching new messages and synchronizing seen flags.
fn drain_unsolicited_responses(&self, context: &Context) -> Result<bool> {
use UnsolicitedResponse::*;
use async_imap::imap_proto::Response;
use async_imap::imap_proto::ResponseCode;
use UnsolicitedResponse::*;
let folder = self.selected_folder.as_deref().unwrap_or_default();
let mut should_refetch = false;
@@ -2142,7 +2141,7 @@ fn get_folder_meaning_by_attrs(folder_attrs: &[NameAttribute]) -> FolderMeaning
NameAttribute::Junk => return FolderMeaning::Spam,
NameAttribute::Drafts => return FolderMeaning::Drafts,
NameAttribute::All | NameAttribute::Flagged => return FolderMeaning::Virtual,
NameAttribute::Extension(ref label) => {
NameAttribute::Extension(label) => {
match label.as_ref() {
"\\Spam" => return FolderMeaning::Spam,
"\\Important" => return FolderMeaning::Virtual,
+1 -1
View File
@@ -5,8 +5,8 @@ use async_channel::Receiver;
use async_imap::extensions::idle::IdleResponse;
use tokio::time::timeout;
use super::session::Session;
use super::Imap;
use super::session::Session;
use crate::context::Context;
use crate::log::{info, warn};
use crate::net::TIMEOUT;
+8 -2
View File
@@ -111,7 +111,9 @@ async fn check_target_folder_combination(
outgoing: bool,
setupmessage: bool,
) -> Result<()> {
println!("Testing: For folder {folder}, mvbox_move {mvbox_move}, chat_msg {chat_msg}, accepted {accepted_chat}, outgoing {outgoing}, setupmessage {setupmessage}");
println!(
"Testing: For folder {folder}, mvbox_move {mvbox_move}, chat_msg {chat_msg}, accepted {accepted_chat}, outgoing {outgoing}, setupmessage {setupmessage}"
);
let t = TestContext::new_alice().await;
t.ctx
@@ -166,7 +168,11 @@ async fn check_target_folder_combination(
} else {
Some(expected_destination)
};
assert_eq!(expected, actual.as_deref(), "For folder {folder}, mvbox_move {mvbox_move}, chat_msg {chat_msg}, accepted {accepted_chat}, outgoing {outgoing}, setupmessage {setupmessage}: expected {expected:?}, got {actual:?}");
assert_eq!(
expected,
actual.as_deref(),
"For folder {folder}, mvbox_move {mvbox_move}, chat_msg {chat_msg}, accepted {accepted_chat}, outgoing {outgoing}, setupmessage {setupmessage}: expected {expected:?}, got {actual:?}"
);
Ok(())
}
+2 -2
View File
@@ -4,8 +4,8 @@ use anyhow::{Context as _, Result};
use super::{get_folder_meaning_by_attrs, get_folder_meaning_by_name};
use crate::config::Config;
use crate::imap::{session::Session, Imap};
use crate::log::{info, LogExt};
use crate::imap::{Imap, session::Session};
use crate::log::{LogExt, info};
use crate::tools::{self, time_elapsed};
use crate::{context::Context, imap::FolderMeaning};
+8 -3
View File
@@ -11,7 +11,9 @@ type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Got a NO response when trying to select {0}, usually this means that it doesn't exist: {1}")]
#[error(
"Got a NO response when trying to select {0}, usually this means that it doesn't exist: {1}"
)]
NoFolder(String, String),
#[error("IMAP other error: {0}")]
@@ -139,7 +141,7 @@ impl ImapSession {
Error::NoFolder(..) => return Ok(false),
_ => {
return Err(err)
.with_context(|| format!("Failed to select folder {folder:?}"))?
.with_context(|| format!("Failed to select folder {folder:?}"))?;
}
},
}
@@ -210,7 +212,10 @@ impl ImapSession {
// If UIDNEXT changed, there are new emails.
self.new_mail |= new_uid_next != old_uid_next;
} else {
warn!(context, "Folder {folder} was just selected but we failed to determine UIDNEXT, assume that it has new mail.");
warn!(
context,
"Folder {folder} was just selected but we failed to determine UIDNEXT, assume that it has new mail."
);
self.new_mail = true;
}
}
+1 -1
View File
@@ -2,8 +2,8 @@ use std::collections::BTreeMap;
use std::ops::{Deref, DerefMut};
use anyhow::{Context as _, Result};
use async_imap::types::Mailbox;
use async_imap::Session as ImapSession;
use async_imap::types::Mailbox;
use futures::TryStreamExt;
use crate::imap::capabilities::Capabilities;
+15 -13
View File
@@ -4,7 +4,7 @@ use std::ffi::OsStr;
use std::path::{Path, PathBuf};
use std::pin::Pin;
use anyhow::{bail, ensure, format_err, Context as _, Result};
use anyhow::{Context as _, Result, bail, ensure, format_err};
use futures::TryStreamExt;
use futures_lite::FutureExt;
use pin_project::pin_project;
@@ -20,12 +20,12 @@ use crate::context::Context;
use crate::e2ee;
use crate::events::EventType;
use crate::key::{self, DcKey, DcSecretKey, SignedPublicKey, SignedSecretKey};
use crate::log::{error, info, warn, LogExt};
use crate::log::{LogExt, error, info, warn};
use crate::pgp;
use crate::qr::DCBACKUP_VERSION;
use crate::sql;
use crate::tools::{
create_folder, delete_file, get_filesuffix_lc, read_file, time, write_file, TempPathGuard,
TempPathGuard, create_folder, delete_file, get_filesuffix_lc, read_file, time, write_file,
};
mod key_transfer;
@@ -33,7 +33,7 @@ mod transfer;
use ::pgp::types::KeyDetails;
pub use key_transfer::{continue_key_transfer, initiate_key_transfer};
pub use transfer::{get_backup, BackupProvider};
pub use transfer::{BackupProvider, get_backup};
// Name of the database file in the backup.
const DBFILE_BACKUP_NAME: &str = "dc_database_backup.sqlite";
@@ -842,7 +842,7 @@ mod tests {
use super::*;
use crate::config::Config;
use crate::test_utils::{alice_keypair, TestContext};
use crate::test_utils::{TestContext, alice_keypair};
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_export_public_key_to_asc_file() {
@@ -982,14 +982,16 @@ mod tests {
let backup = has_backup(&context2, backup_dir.path()).await?;
// Import of unencrypted backup with incorrect "foobar" backup passphrase fails.
assert!(imex(
&context2,
ImexMode::ImportBackup,
backup.as_ref(),
Some("foobar".to_string())
)
.await
.is_err());
assert!(
imex(
&context2,
ImexMode::ImportBackup,
backup.as_ref(),
Some("foobar".to_string())
)
.await
.is_err()
);
assert!(
imex(&context2, ImexMode::ImportBackup, backup.as_ref(), None)
+5 -5
View File
@@ -1,9 +1,9 @@
//! # Key transfer via Autocrypt Setup Message.
use std::io::BufReader;
use rand::{thread_rng, Rng};
use rand::{Rng, thread_rng};
use anyhow::{bail, ensure, Result};
use anyhow::{Result, bail, ensure};
use crate::blob::BlobObject;
use crate::chat::{self, ChatId};
@@ -12,7 +12,7 @@ use crate::constants::{ASM_BODY, ASM_SUBJECT};
use crate::contact::ContactId;
use crate::context::Context;
use crate::imex::set_self_key;
use crate::key::{load_self_secret_key, DcKey};
use crate::key::{DcKey, load_self_secret_key};
use crate::message::{Message, MsgId, Viewtype};
use crate::mimeparser::SystemMessage;
use crate::param::Param;
@@ -141,7 +141,7 @@ fn create_setup_code(_context: &Context) -> String {
for i in 0..9 {
loop {
random_val = rng.gen();
random_val = rng.r#gen();
if random_val as usize <= 60000 {
break;
}
@@ -184,7 +184,7 @@ fn normalize_setup_code(s: &str) -> String {
mod tests {
use super::*;
use crate::pgp::{split_armored_data, HEADER_AUTOCRYPT, HEADER_SETUPCODE};
use crate::pgp::{HEADER_AUTOCRYPT, HEADER_SETUPCODE, split_armored_data};
use crate::receive_imf::receive_imf;
use crate::test_utils::{TestContext, TestContextManager};
use ::pgp::armor::BlockType;
+5 -5
View File
@@ -31,7 +31,7 @@ use std::pin::Pin;
use std::sync::Arc;
use std::task::Poll;
use anyhow::{bail, format_err, Context as _, Result};
use anyhow::{Context as _, Result, bail, format_err};
use futures_lite::FutureExt;
use iroh::{Endpoint, RelayMode};
use tokio::fs;
@@ -45,10 +45,10 @@ use crate::log::{info, warn};
use crate::message::Message;
use crate::qr::Qr;
use crate::stock_str::backup_transfer_msg_body;
use crate::tools::{create_id, time, TempPathGuard};
use crate::{e2ee, EventType};
use crate::tools::{TempPathGuard, create_id, time};
use crate::{EventType, e2ee};
use super::{export_backup_stream, export_database, import_backup_stream, DBFILE_BACKUP_NAME};
use super::{DBFILE_BACKUP_NAME, export_backup_stream, export_database, import_backup_stream};
/// ALPN protocol identifier for the backup transfer protocol.
const BACKUP_ALPN: &[u8] = b"/deltachat/backup";
@@ -382,7 +382,7 @@ pub async fn get_backup(context: &Context, qr: Qr) -> Result<()> {
mod tests {
use std::time::Duration;
use crate::chat::{get_chat_msgs, send_msg, ChatItem};
use crate::chat::{ChatItem, get_chat_msgs, send_msg};
use crate::message::Viewtype;
use crate::test_utils::TestContextManager;
+3 -3
View File
@@ -4,7 +4,7 @@ use std::collections::BTreeMap;
use std::fmt;
use std::io::Cursor;
use anyhow::{bail, ensure, Context as _, Result};
use anyhow::{Context as _, Result, bail, ensure};
use base64::Engine as _;
use deltachat_contact_tools::EmailAddress;
use pgp::composed::Deserializable;
@@ -15,7 +15,7 @@ use rand::thread_rng;
use tokio::runtime::Handle;
use crate::context::Context;
use crate::log::{info, LogExt};
use crate::log::{LogExt, info};
use crate::pgp::KeyPair;
use crate::tools::{self, time_elapsed};
@@ -526,7 +526,7 @@ mod tests {
use super::*;
use crate::config::Config;
use crate::test_utils::{alice_keypair, TestContext};
use crate::test_utils::{TestContext, alice_keypair};
static KEYPAIR: LazyLock<KeyPair> = LazyLock::new(alice_keypair);
+1 -1
View File
@@ -12,7 +12,7 @@
use std::time::Duration;
use anyhow::{ensure, Context as _, Result};
use anyhow::{Context as _, Result, ensure};
use async_channel::Receiver;
use quick_xml::events::{BytesEnd, BytesStart, BytesText};
use tokio::time::timeout;
+5 -9
View File
@@ -2,19 +2,19 @@
use std::fmt;
use anyhow::{bail, ensure, format_err, Context as _, Result};
use deltachat_contact_tools::{addr_cmp, addr_normalize, EmailAddress};
use anyhow::{Context as _, Result, bail, ensure, format_err};
use deltachat_contact_tools::{EmailAddress, addr_cmp, addr_normalize};
use num_traits::ToPrimitive as _;
use serde::{Deserialize, Serialize};
use crate::config::Config;
use crate::configure::server_params::{expand_param_vector, ServerParams};
use crate::configure::server_params::{ServerParams, expand_param_vector};
use crate::constants::{DC_LP_AUTH_FLAGS, DC_LP_AUTH_OAUTH2};
use crate::context::Context;
use crate::net::load_connection_timestamp;
pub use crate::net::proxy::ProxyConfig;
pub use crate::provider::Socket;
use crate::provider::{get_provider_by_id, Protocol, Provider, UsernamePattern};
use crate::provider::{Protocol, Provider, UsernamePattern, get_provider_by_id};
use crate::sql::Sql;
use crate::tools::ToOption;
@@ -330,11 +330,7 @@ impl fmt::Display for EnteredLoginParam {
}
fn unset_empty(s: &str) -> &str {
if s.is_empty() {
"unset"
} else {
s
}
if s.is_empty() { "unset" } else { s }
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
+6 -6
View File
@@ -5,29 +5,29 @@ use std::collections::HashSet;
use std::path::{Path, PathBuf};
use std::str;
use anyhow::{ensure, format_err, Context as _, Result};
use deltachat_contact_tools::{parse_vcard, VcardContact};
use anyhow::{Context as _, Result, ensure, format_err};
use deltachat_contact_tools::{VcardContact, parse_vcard};
use deltachat_derive::{FromSql, ToSql};
use serde::{Deserialize, Serialize};
use tokio::{fs, io};
use crate::blob::BlobObject;
use crate::chat::{send_msg, Chat, ChatId, ChatIdBlocked, ChatVisibility};
use crate::chat::{Chat, ChatId, ChatIdBlocked, ChatVisibility, send_msg};
use crate::chatlist_events;
use crate::config::Config;
use crate::constants::{
Blocked, Chattype, VideochatType, DC_CHAT_ID_TRASH, DC_MSG_ID_LAST_SPECIAL,
Blocked, Chattype, DC_CHAT_ID_TRASH, DC_MSG_ID_LAST_SPECIAL, VideochatType,
};
use crate::contact::{self, Contact, ContactId};
use crate::context::Context;
use crate::debug_logging::set_debug_logging_xdc;
use crate::download::DownloadState;
use crate::ephemeral::{start_ephemeral_timers_msgids, Timer as EphemeralTimer};
use crate::ephemeral::{Timer as EphemeralTimer, start_ephemeral_timers_msgids};
use crate::events::EventType;
use crate::imap::markseen_on_imap_table;
use crate::location::delete_poi_location;
use crate::log::{error, info, warn};
use crate::mimeparser::{parse_message_id, SystemMessage};
use crate::mimeparser::{SystemMessage, parse_message_id};
use crate::param::{Param, Params};
use crate::pgp::split_armored_data;
use crate::reaction::get_msg_reactions;
+6 -4
View File
@@ -1,7 +1,7 @@
use num_traits::FromPrimitive;
use super::*;
use crate::chat::{self, forward_msgs, marknoticed_chat, save_msgs, send_text_msg, ChatItem};
use crate::chat::{self, ChatItem, forward_msgs, marknoticed_chat, save_msgs, send_text_msg};
use crate::chatlist::Chatlist;
use crate::config::Config;
use crate::reaction::send_reaction;
@@ -734,9 +734,11 @@ async fn test_delete_msgs_offline() -> Result<()> {
.create_chat_with_contact("Bob", "bob@example.org")
.await;
let mut msg = Message::new_text("hi".to_string());
assert!(chat::send_msg_sync(&alice, chat.id, &mut msg)
.await
.is_err());
assert!(
chat::send_msg_sync(&alice, chat.id, &mut msg)
.await
.is_err()
);
let stmt = "SELECT COUNT(*) FROM smtp WHERE msg_id=?";
assert!(alice.sql.exists(stmt, (msg.id,)).await?);
delete_msgs(&alice, &[msg.id]).await?;
+11 -11
View File
@@ -4,12 +4,12 @@ use std::collections::{BTreeSet, HashSet};
use std::io::Cursor;
use std::path::Path;
use anyhow::{bail, Context as _, Result};
use anyhow::{Context as _, Result, bail};
use base64::Engine as _;
use chrono::TimeZone;
use deltachat_contact_tools::sanitize_bidi_characters;
use mail_builder::headers::address::{Address, EmailAddress};
use mail_builder::headers::HeaderType;
use mail_builder::headers::address::{Address, EmailAddress};
use mail_builder::mime::MimePart;
use tokio::fs;
@@ -28,14 +28,14 @@ use crate::key::{DcKey, SignedPublicKey};
use crate::location;
use crate::log::{info, warn};
use crate::message::{self, Message, MsgId, Viewtype};
use crate::mimeparser::{is_hidden, SystemMessage};
use crate::mimeparser::{SystemMessage, is_hidden};
use crate::param::Param;
use crate::peer_channels::create_iroh_header;
use crate::simplify::escape_message_footer_marks;
use crate::stock_str;
use crate::tools::{
create_outgoing_rfc724_mid, create_smeared_timestamp, remove_subject_prefix, time,
IsNoneOrEmpty,
IsNoneOrEmpty, create_outgoing_rfc724_mid, create_smeared_timestamp, remove_subject_prefix,
time,
};
use crate::webxdc::StatusUpdateSerial;
@@ -571,7 +571,7 @@ impl MimeFactory {
return chat.param.get(Param::ProfileImage).map(Into::into);
}
SystemMessage::GroupImageChanged => {
return msg.param.get(Param::Arg).map(Into::into)
return msg.param.get(Param::Arg).map(Into::into);
}
_ => {}
}
@@ -592,7 +592,7 @@ impl MimeFactory {
async fn subject_str(&self, context: &Context) -> Result<String> {
let subject = match &self.loaded {
Loaded::Message { ref chat, msg } => {
Loaded::Message { chat, msg } => {
let quoted_msg_subject = msg.quoted_message(context).await?.map(|m| m.subject);
if !msg.subject.is_empty() {
@@ -1100,9 +1100,9 @@ impl MimeFactory {
}
// Set the appropriate Content-Type for the inner message.
for (h, ref mut v) in &mut message.headers {
for (h, v) in &mut message.headers {
if h == "Content-Type" {
if let mail_builder::headers::HeaderType::ContentType(ref mut ct) = v {
if let mail_builder::headers::HeaderType::ContentType(ct) = v {
*ct = ct.clone().attribute("protected-headers", "v1");
}
}
@@ -1186,9 +1186,9 @@ impl MimeFactory {
message
} else {
for (h, ref mut v) in &mut message.headers {
for (h, v) in &mut message.headers {
if h == "Content-Type" {
if let mail_builder::headers::HeaderType::ContentType(ref mut ct) = v {
if let mail_builder::headers::HeaderType::ContentType(ct) = v {
*ct = ct.clone().attribute("protected-headers", "v1");
}
}
+29 -21
View File
@@ -1,12 +1,12 @@
use deltachat_contact_tools::ContactAddress;
use mail_builder::headers::Header;
use mailparse::{addrparse_header, MailHeaderMap};
use mailparse::{MailHeaderMap, addrparse_header};
use std::str;
use super::*;
use crate::chat::{
self, add_contact_to_chat, create_group_chat, remove_contact_from_chat, send_text_msg, ChatId,
ProtectionStatus,
self, ChatId, ProtectionStatus, add_contact_to_chat, create_group_chat,
remove_contact_from_chat, send_text_msg,
};
use crate::chatlist::Chatlist;
use crate::constants;
@@ -14,7 +14,7 @@ use crate::contact::Origin;
use crate::headerdef::HeaderDef;
use crate::mimeparser::MimeMessage;
use crate::receive_imf::receive_imf;
use crate::test_utils::{get_chat_msg, TestContext, TestContextManager};
use crate::test_utils::{TestContext, TestContextManager, get_chat_msg};
fn render_email_address(display_name: &str, addr: &str) -> String {
let mut output = Vec::<u8>::new();
@@ -32,9 +32,11 @@ fn test_render_email_address() {
let addr = "x@y.org";
assert!(!display_name.is_ascii());
assert!(!display_name
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == ' '));
assert!(
!display_name
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == ' ')
);
let s = render_email_address(display_name, addr);
@@ -49,9 +51,11 @@ fn test_render_email_address_noescape() {
let addr = "x@y.org";
assert!(display_name.is_ascii());
assert!(display_name
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == ' '));
assert!(
display_name
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == ' ')
);
let s = render_email_address(display_name, addr);
@@ -676,11 +680,13 @@ async fn test_selfavatar_unencrypted_signed() {
.unwrap()
.unwrap();
let alice_contact = Contact::get_by_id(&bob.ctx, alice_id).await.unwrap();
assert!(alice_contact
.get_profile_image(&bob.ctx)
.await
.unwrap()
.is_some());
assert!(
alice_contact
.get_profile_image(&bob.ctx)
.await
.unwrap()
.is_some()
);
// if another message is sent, that one must not contain the avatar
let mut msg = Message::new_text("this is the text!".to_string());
@@ -719,11 +725,13 @@ async fn test_selfavatar_unencrypted_signed() {
bob.recv_msg(&sent_msg).await;
let alice_contact = Contact::get_by_id(&bob.ctx, alice_id).await.unwrap();
assert!(alice_contact
.get_profile_image(&bob.ctx)
.await
.unwrap()
.is_some());
assert!(
alice_contact
.get_profile_image(&bob.ctx)
.await
.unwrap()
.is_some()
);
}
/// Test that removed member address does not go into the `To:` field.
@@ -757,7 +765,7 @@ async fn test_remove_member_bcc() -> Result<()> {
let to = addrparse_header(to)?;
for to_addr in to.iter() {
match to_addr {
mailparse::MailAddr::Single(ref info) => {
mailparse::MailAddr::Single(info) => {
// Addresses should be of existing members (Alice and Bob) and not Charlie.
assert_ne!(info.addr, charlie_addr);
}
+11 -8
View File
@@ -6,11 +6,11 @@ use std::path::Path;
use std::str;
use std::str::FromStr;
use anyhow::{bail, Context as _, Result};
use anyhow::{Context as _, Result, bail};
use deltachat_contact_tools::{addr_cmp, addr_normalize, sanitize_bidi_characters};
use deltachat_derive::{FromSql, ToSql};
use format_flowed::unformat_flowed;
use mailparse::{addrparse_header, DispositionType, MailHeader, MailHeaderMap, SingleInfo};
use mailparse::{DispositionType, MailHeader, MailHeaderMap, SingleInfo, addrparse_header};
use mime::Mime;
use crate::aheader::Aheader;
@@ -25,11 +25,11 @@ use crate::decrypt::{try_decrypt, validate_detached_signature};
use crate::dehtml::dehtml;
use crate::events::EventType;
use crate::headerdef::{HeaderDef, HeaderDefMap};
use crate::key::{self, load_self_secret_keyring, DcKey, Fingerprint, SignedPublicKey};
use crate::key::{self, DcKey, Fingerprint, SignedPublicKey, load_self_secret_keyring};
use crate::log::{error, info, warn};
use crate::message::{self, get_vcard_summary, set_msg_failed, Message, MsgId, Viewtype};
use crate::message::{self, Message, MsgId, Viewtype, get_vcard_summary, set_msg_failed};
use crate::param::{Param, Params};
use crate::simplify::{simplify, SimplifiedText};
use crate::simplify::{SimplifiedText, simplify};
use crate::sync::SyncItems;
use crate::tools::{
get_filemeta, parse_receive_headers, smeared_time, time, truncate_msg_text, validate_id,
@@ -1643,7 +1643,10 @@ impl MimeMessage {
if status_part.ctype.mimetype != "message/delivery-status"
&& status_part.ctype.mimetype != "message/global-delivery-status"
{
warn!(context, "Second part of Delivery Status Notification is not message/delivery-status or message/global-delivery-status, ignoring");
warn!(
context,
"Second part of Delivery Status Notification is not message/delivery-status or message/global-delivery-status, ignoring"
);
return Ok(None);
}
@@ -2222,13 +2225,13 @@ fn get_all_addresses_from_header(headers: &[MailHeader], header: &str) -> Vec<Si
if let Ok(addrs) = mailparse::addrparse_header(header) {
for addr in addrs.iter() {
match addr {
mailparse::MailAddr::Single(ref info) => {
mailparse::MailAddr::Single(info) => {
result.push(SingleInfo {
addr: addr_normalize(&info.addr).to_lowercase(),
display_name: info.display_name.clone(),
});
}
mailparse::MailAddr::Group(ref infos) => {
mailparse::MailAddr::Group(infos) => {
for info in &infos.addrs {
result.push(SingleInfo {
addr: addr_normalize(&info.addr).to_lowercase(),
+24 -13
View File
@@ -160,9 +160,11 @@ fn test_is_attachment() {
fn load_mail_with_attachment<'a>(t: &'a TestContext, raw: &'a [u8]) -> ParsedMail<'a> {
let mail = mailparse::parse_mail(raw).unwrap();
assert!(get_attachment_filename(t, &mail).unwrap().is_none());
assert!(get_attachment_filename(t, &mail.subparts[0])
.unwrap()
.is_none());
assert!(
get_attachment_filename(t, &mail.subparts[0])
.unwrap()
.is_none()
);
mail
}
@@ -321,9 +323,11 @@ async fn test_mailparse_0_16_0_panic() {
let raw = include_bytes!("../../test-data/message/mailparse-0.16.0-panic.eml");
// There should be an error, but no panic.
assert!(MimeMessage::from_bytes(&context.ctx, &raw[..], None)
.await
.is_err());
assert!(
MimeMessage::from_bytes(&context.ctx, &raw[..], None)
.await
.is_err()
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -422,9 +426,11 @@ async fn test_mimeparser_with_context() {
// make sure, headers that are only allowed in the encrypted part
// cannot be set from the outer part
assert!(mimeparser
.get_header(HeaderDef::SecureJoinFingerprint)
.is_none());
assert!(
mimeparser
.get_header(HeaderDef::SecureJoinFingerprint)
.is_none()
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -485,9 +491,11 @@ async fn test_mimeparser_with_videochat() {
.unwrap_or_default(),
"https://example.org/p2p/?roomname=6HiduoAn4xN"
);
assert!(mimeparser.parts[0]
.msg
.contains("https://example.org/p2p/?roomname=6HiduoAn4xN"));
assert!(
mimeparser.parts[0]
.msg
.contains("https://example.org/p2p/?roomname=6HiduoAn4xN")
);
assert_eq!(mimeparser.user_avatar, None);
assert_eq!(mimeparser.group_avatar, None);
}
@@ -1709,7 +1717,10 @@ async fn test_tlsrpt() -> Result<()> {
assert_eq!(msg.parts.len(), 1);
assert_eq!(msg.parts[0].typ, Viewtype::File);
assert_eq!(msg.parts[0].msg, "Report Domain: nine.testrun.org Submitter: google.com Report-ID: <2024.01.20T00.00.00Z+nine.testrun.org@google.com> – This is an aggregate TLS report from google.com");
assert_eq!(
msg.parts[0].msg,
"Report Domain: nine.testrun.org Submitter: google.com Report-ID: <2024.01.20T00.00.00Z+nine.testrun.org@google.com> – This is an aggregate TLS report from google.com"
);
Ok(())
}
+3 -3
View File
@@ -4,7 +4,7 @@ use std::net::SocketAddr;
use std::pin::Pin;
use std::time::Duration;
use anyhow::{format_err, Context as _, Result};
use anyhow::{Context as _, Result, format_err};
use tokio::net::TcpStream;
use tokio::task::JoinSet;
use tokio::time::timeout;
@@ -22,7 +22,7 @@ pub(crate) mod session;
pub(crate) mod tls;
use dns::lookup_host_with_cache;
pub use http::{read_url, read_url_blob, Response as HttpResponse};
pub use http::{Response as HttpResponse, read_url, read_url_blob};
use tls::wrap_tls;
/// Connection, write and read timeout.
@@ -128,7 +128,7 @@ pub(crate) async fn connect_tls_inner(
host: &str,
strict_tls: bool,
alpn: &[&str],
) -> Result<impl SessionStream> {
) -> Result<impl SessionStream + 'static> {
let tcp_stream = connect_tcp_inner(addr).await?;
let tls_stream = wrap_tls(strict_tls, host, alpn, tcp_stream).await?;
Ok(tls_stream)
+6 -4
View File
@@ -912,10 +912,12 @@ mod tests {
let ipv6_addr = IpAddr::V6(Ipv6Addr::new(0x2a01, 0x4f8, 0x241, 0x4ce8, 0, 0, 0, 2));
let now = time();
assert!(lookup_cache(alice, "nine.testrun.org", 587, "smtp", now)
.await
.unwrap()
.is_empty());
assert!(
lookup_cache(alice, "nine.testrun.org", 587, "smtp", now)
.await
.unwrap()
.is_empty()
);
update_cache(alice, "nine.testrun.org", "116.202.233.236", now)
.await
+1 -1
View File
@@ -1,6 +1,6 @@
//! # HTTP module.
use anyhow::{anyhow, bail, Context as _, Result};
use anyhow::{Context as _, Result, anyhow, bail};
use bytes::Bytes;
use http_body_util::BodyExt;
use hyper_util::rt::TokioIo;
+8 -5
View File
@@ -5,14 +5,14 @@
use std::fmt;
use std::pin::Pin;
use anyhow::{bail, format_err, Context as _, Result};
use anyhow::{Context as _, Result, bail, format_err};
use base64::Engine;
use bytes::{BufMut, BytesMut};
use fast_socks5::client::Socks5Stream;
use fast_socks5::util::target_addr::ToTargetAddr;
use fast_socks5::AuthenticationMethod;
use fast_socks5::Socks5Command;
use percent_encoding::{percent_encode, utf8_percent_encode, NON_ALPHANUMERIC};
use fast_socks5::client::Socks5Stream;
use fast_socks5::util::target_addr::ToTargetAddr;
use percent_encoding::{NON_ALPHANUMERIC, percent_encode, utf8_percent_encode};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
use tokio_io_timeout::TimeoutStream;
@@ -624,7 +624,10 @@ mod tests {
#[test]
fn test_http_connect_request() {
assert_eq!(http_connect_request("example.org", 143, Some(("aladdin", "opensesame"))), "CONNECT example.org:143 HTTP/1.1\r\nHost: example.org:143\r\nProxy-Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l\r\n\r\n");
assert_eq!(
http_connect_request("example.org", 143, Some(("aladdin", "opensesame"))),
"CONNECT example.org:143 HTTP/1.1\r\nHost: example.org:143\r\nProxy-Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l\r\n\r\n"
);
assert_eq!(
http_connect_request("example.net", 587, None),
"CONNECT example.net:587 HTTP/1.1\r\nHost: example.net:587\r\n\r\n"
+5 -5
View File
@@ -5,12 +5,12 @@ use anyhow::Result;
use crate::net::session::SessionStream;
pub async fn wrap_tls(
pub async fn wrap_tls<'a>(
strict_tls: bool,
hostname: &str,
alpn: &[&str],
stream: impl SessionStream + 'static,
) -> Result<impl SessionStream> {
) -> Result<impl SessionStream + 'a> {
if strict_tls {
let tls_stream = wrap_rustls(hostname, alpn, stream).await?;
let boxed_stream: Box<dyn SessionStream> = Box::new(tls_stream);
@@ -30,11 +30,11 @@ pub async fn wrap_tls(
}
}
pub async fn wrap_rustls(
pub async fn wrap_rustls<'a>(
hostname: &str,
alpn: &[&str],
stream: impl SessionStream,
) -> Result<impl SessionStream> {
stream: impl SessionStream + 'a,
) -> Result<impl SessionStream + 'a> {
let mut root_cert_store = rustls::RootCertStore::empty();
root_cert_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
+4 -2
View File
@@ -3,7 +3,7 @@
use std::collections::HashMap;
use anyhow::{Context as _, Result};
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
use percent_encoding::{NON_ALPHANUMERIC, utf8_percent_encode};
use serde::Deserialize;
use crate::context::Context;
@@ -20,7 +20,9 @@ const OAUTH2_GMAIL: Oauth2 = Oauth2 {
get_code: "https://accounts.google.com/o/oauth2/auth?client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&response_type=code&scope=https%3A%2F%2Fmail.google.com%2F%20email&access_type=offline",
init_token: "https://accounts.google.com/o/oauth2/token?client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&code=$CODE&grant_type=authorization_code",
refresh_token: "https://accounts.google.com/o/oauth2/token?client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&refresh_token=$REFRESH_TOKEN&grant_type=refresh_token",
get_userinfo: Some("https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=$ACCESS_TOKEN"),
get_userinfo: Some(
"https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=$ACCESS_TOKEN",
),
};
const OAUTH2_YANDEX: Oauth2 = Oauth2 {
+1 -1
View File
@@ -4,7 +4,7 @@ use std::path::PathBuf;
use std::str;
use anyhow::ensure;
use anyhow::{bail, Error, Result};
use anyhow::{Error, Result, bail};
use num_traits::FromPrimitive;
use serde::{Deserialize, Serialize};
+24 -20
View File
@@ -23,26 +23,26 @@
//! (scoped per WebXDC app instance/message-id). The other peers can then join the gossip with `joinRealtimeChannel().setListener()`
//! and `joinRealtimeChannel().send()` just like the other peers.
use anyhow::{anyhow, bail, Context as _, Result};
use anyhow::{Context as _, Result, anyhow, bail};
use data_encoding::BASE32_NOPAD;
use futures_lite::StreamExt;
use iroh::{Endpoint, NodeAddr, NodeId, PublicKey, RelayMode, RelayUrl, SecretKey};
use iroh_gossip::net::{Event, Gossip, GossipEvent, JoinOptions, GOSSIP_ALPN};
use iroh_gossip::net::{Event, GOSSIP_ALPN, Gossip, GossipEvent, JoinOptions};
use iroh_gossip::proto::TopicId;
use parking_lot::Mutex;
use std::collections::{BTreeSet, HashMap};
use std::env;
use tokio::sync::{oneshot, RwLock};
use tokio::sync::{RwLock, oneshot};
use tokio::task::JoinHandle;
use url::Url;
use crate::EventType;
use crate::chat::send_msg;
use crate::config::Config;
use crate::context::Context;
use crate::log::{info, warn};
use crate::message::{Message, MsgId, Viewtype};
use crate::mimeparser::SystemMessage;
use crate::EventType;
/// The length of an ed25519 `PublicKey`, in bytes.
const PUBLIC_KEY_LENGTH: usize = 32;
@@ -554,10 +554,10 @@ async fn subscribe_loop(
mod tests {
use super::*;
use crate::{
EventType,
chat::send_msg,
message::{Message, Viewtype},
test_utils::TestContextManager,
EventType,
};
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -733,10 +733,12 @@ mod tests {
let alice = &mut tcm.alice().await;
let bob = &mut tcm.bob().await;
assert!(alice
.get_config_bool(Config::WebxdcRealtimeEnabled)
.await
.unwrap());
assert!(
alice
.get_config_bool(Config::WebxdcRealtimeEnabled)
.await
.unwrap()
);
// Alice sends webxdc to bob
let alice_chat = alice.create_chat(bob).await;
let mut instance = Message::new(Viewtype::File);
@@ -901,17 +903,19 @@ mod tests {
.await
.unwrap()
.unwrap();
assert!(alice
.iroh
.read()
.await
.as_ref()
.unwrap()
.iroh_channels
.read()
.await
.get(&topic)
.is_none());
assert!(
alice
.iroh
.read()
.await
.as_ref()
.unwrap()
.iroh_channels
.read()
.await
.get(&topic)
.is_none()
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
+10 -6
View File
@@ -465,17 +465,21 @@ mod tests {
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_encrypt_signed() {
assert!(!ctext_signed().await.is_empty());
assert!(ctext_signed()
.await
.starts_with("-----BEGIN PGP MESSAGE-----"));
assert!(
ctext_signed()
.await
.starts_with("-----BEGIN PGP MESSAGE-----")
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_encrypt_unsigned() {
assert!(!ctext_unsigned().await.is_empty());
assert!(ctext_unsigned()
.await
.starts_with("-----BEGIN PGP MESSAGE-----"));
assert!(
ctext_unsigned()
.await
.starts_with("-----BEGIN PGP MESSAGE-----")
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
+11 -7
View File
@@ -5,7 +5,7 @@ pub(crate) mod data;
use anyhow::Result;
use deltachat_contact_tools::EmailAddress;
use hickory_resolver::name_server::TokioConnectionProvider;
use hickory_resolver::{config, Resolver, TokioResolver};
use hickory_resolver::{Resolver, TokioResolver, config};
use serde::{Deserialize, Serialize};
use crate::config::Config;
@@ -356,17 +356,21 @@ mod tests {
let t = TestContext::new().await;
assert!(get_provider_info(&t, "", false).await.is_none());
assert!(get_provider_info(&t, "google.com", false).await.unwrap().id == "gmail");
assert!(get_provider_info(&t, "example@google.com", false)
.await
.is_none());
assert!(
get_provider_info(&t, "example@google.com", false)
.await
.is_none()
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_get_provider_info_by_addr() -> Result<()> {
let t = TestContext::new().await;
assert!(get_provider_info_by_addr(&t, "google.com", false)
.await
.is_err());
assert!(
get_provider_info_by_addr(&t, "google.com", false)
.await
.is_err()
);
assert!(
get_provider_info_by_addr(&t, "example@google.com", false)
.await?
+220 -45
View File
@@ -102,8 +102,20 @@ static P_AOL: Provider = Provider {
after_login_hint: "",
overview_page: "https://providers.delta.chat/aol",
server: &[
Server { protocol: Imap, socket: Ssl, hostname: "imap.aol.com", port: 993, username_pattern: Email },
Server { protocol: Smtp, socket: Ssl, hostname: "smtp.aol.com", port: 465, username_pattern: Email },
Server {
protocol: Imap,
socket: Ssl,
hostname: "imap.aol.com",
port: 993,
username_pattern: Email,
},
Server {
protocol: Smtp,
socket: Ssl,
hostname: "smtp.aol.com",
port: 465,
username_pattern: Email,
},
],
opt: ProviderOptions::new(),
config_defaults: None,
@@ -423,8 +435,20 @@ static P_EXAMPLE_COM: Provider = Provider {
after_login_hint: "This provider doesn't really exist, so you can't use it :/ If you need an email provider for Delta Chat, take a look at providers.delta.chat!",
overview_page: "https://providers.delta.chat/example-com",
server: &[
Server { protocol: Imap, socket: Ssl, hostname: "imap.example.com", port: 1337, username_pattern: Emaillocalpart },
Server { protocol: Smtp, socket: Starttls, hostname: "smtp.example.com", port: 1337, username_pattern: Email },
Server {
protocol: Imap,
socket: Ssl,
hostname: "imap.example.com",
port: 1337,
username_pattern: Emaillocalpart,
},
Server {
protocol: Smtp,
socket: Starttls,
hostname: "smtp.example.com",
port: 1337,
username_pattern: Email,
},
],
opt: ProviderOptions::new(),
config_defaults: None,
@@ -435,8 +459,7 @@ static P_EXAMPLE_COM: Provider = Provider {
static P_FASTMAIL: Provider = Provider {
id: "fastmail",
status: Status::Preparation,
before_login_hint:
"You must create an app-specific password for Delta Chat before you can log in.",
before_login_hint: "You must create an app-specific password for Delta Chat before you can log in.",
after_login_hint: "",
overview_page: "https://providers.delta.chat/fastmail",
server: &[
@@ -467,8 +490,7 @@ static P_FIREMAIL_DE: Provider = Provider {
before_login_hint: "Firemail erlaubt nur bei bezahlten Accounts den vollen Zugriff auf das E-Mail-Protokoll. Wenn Sie nicht für Firemail bezahlen, verwenden Sie bitte einen anderen E-Mail-Anbieter.",
after_login_hint: "Leider schränkt Firemail die maximale Gruppengröße ein. Je nach Bezahlmodell sind nur 5 bis 30 Gruppenmitglieder erlaubt.",
overview_page: "https://providers.delta.chat/firemail-de",
server: &[
],
server: &[],
opt: ProviderOptions::new(),
config_defaults: None,
oauth2_authorizer: None,
@@ -508,10 +530,34 @@ static P_FREENET_DE: Provider = Provider {
after_login_hint: "",
overview_page: "https://providers.delta.chat/freenet-de",
server: &[
Server { protocol: Imap, socket: Ssl, hostname: "mx.freenet.de", port: 993, username_pattern: Email },
Server { protocol: Imap, socket: Starttls, hostname: "mx.freenet.de", port: 143, username_pattern: Email },
Server { protocol: Smtp, socket: Ssl, hostname: "mx.freenet.de", port: 465, username_pattern: Email },
Server { protocol: Smtp, socket: Starttls, hostname: "mx.freenet.de", port: 587, username_pattern: Email },
Server {
protocol: Imap,
socket: Ssl,
hostname: "mx.freenet.de",
port: 993,
username_pattern: Email,
},
Server {
protocol: Imap,
socket: Starttls,
hostname: "mx.freenet.de",
port: 143,
username_pattern: Email,
},
Server {
protocol: Smtp,
socket: Ssl,
hostname: "mx.freenet.de",
port: 465,
username_pattern: Email,
},
Server {
protocol: Smtp,
socket: Starttls,
hostname: "mx.freenet.de",
port: 587,
username_pattern: Email,
},
],
opt: ProviderOptions::new(),
config_defaults: None,
@@ -526,8 +572,20 @@ static P_GMAIL: Provider = Provider {
after_login_hint: "",
overview_page: "https://providers.delta.chat/gmail",
server: &[
Server { protocol: Imap, socket: Ssl, hostname: "imap.gmail.com", port: 993, username_pattern: Email },
Server { protocol: Smtp, socket: Ssl, hostname: "smtp.gmail.com", port: 465, username_pattern: Email },
Server {
protocol: Imap,
socket: Ssl,
hostname: "imap.gmail.com",
port: 993,
username_pattern: Email,
},
Server {
protocol: Smtp,
socket: Ssl,
hostname: "smtp.gmail.com",
port: 465,
username_pattern: Email,
},
],
opt: ProviderOptions {
delete_to_trash: true,
@@ -608,8 +666,7 @@ static P_HEY_COM: Provider = Provider {
before_login_hint: "hey.com does not offer the standard IMAP e-mail protocol, so you cannot log in with Delta Chat to hey.com.",
after_login_hint: "",
overview_page: "https://providers.delta.chat/hey-com",
server: &[
],
server: &[],
opt: ProviderOptions::new(),
config_defaults: None,
oauth2_authorizer: None,
@@ -733,8 +790,7 @@ static P_MAIL_COM: Provider = Provider {
before_login_hint: "To log in with Delta Chat, you first need to activate POP3/IMAP in your mail.com settings. Note that this is a mail.com Premium feature only.",
after_login_hint: "",
overview_page: "https://providers.delta.chat/mail-com",
server: &[
],
server: &[],
opt: ProviderOptions::new(),
config_defaults: None,
oauth2_authorizer: None,
@@ -776,8 +832,20 @@ static P_MAIL_RU: Provider = Provider {
after_login_hint: "",
overview_page: "https://providers.delta.chat/mail-ru",
server: &[
Server { protocol: Imap, socket: Ssl, hostname: "imap.mail.ru", port: 993, username_pattern: Email },
Server { protocol: Smtp, socket: Ssl, hostname: "smtp.mail.ru", port: 465, username_pattern: Email },
Server {
protocol: Imap,
socket: Ssl,
hostname: "imap.mail.ru",
port: 993,
username_pattern: Email,
},
Server {
protocol: Smtp,
socket: Ssl,
hostname: "smtp.mail.ru",
port: 465,
username_pattern: Email,
},
],
opt: ProviderOptions::new(),
config_defaults: None,
@@ -932,8 +1000,20 @@ static P_MEHL_STORE: Provider = Provider {
after_login_hint: "This account provides 3GB storage for eMails and the possibility to access a NEXTCLOUD-instance by using the email-credits!",
overview_page: "https://providers.delta.chat/mehl-store",
server: &[
Server { protocol: Imap, socket: Ssl, hostname: "mail.ende.in.net", port: 993, username_pattern: Email },
Server { protocol: Smtp, socket: Starttls, hostname: "mail.ende.in.net", port: 587, username_pattern: Email },
Server {
protocol: Imap,
socket: Ssl,
hostname: "mail.ende.in.net",
port: 993,
username_pattern: Email,
},
Server {
protocol: Smtp,
socket: Starttls,
hostname: "mail.ende.in.net",
port: 587,
username_pattern: Email,
},
],
opt: ProviderOptions::new(),
config_defaults: None,
@@ -1244,8 +1324,7 @@ static P_PROTONMAIL: Provider = Provider {
before_login_hint: "Protonmail does not offer the standard IMAP e-mail protocol, so you cannot log in with Delta Chat to Protonmail.",
after_login_hint: "To use Delta Chat with Protonmail, the IMAP bridge must be running in the background. If you have connectivity issues, double check whether it works as expected.",
overview_page: "https://providers.delta.chat/protonmail",
server: &[
],
server: &[],
opt: ProviderOptions::new(),
config_defaults: None,
oauth2_authorizer: None,
@@ -1287,8 +1366,20 @@ static P_QQ: Provider = Provider {
after_login_hint: "",
overview_page: "https://providers.delta.chat/qq",
server: &[
Server { protocol: Imap, socket: Ssl, hostname: "imap.qq.com", port: 993, username_pattern: Emaillocalpart },
Server { protocol: Smtp, socket: Ssl, hostname: "smtp.qq.com", port: 465, username_pattern: Email },
Server {
protocol: Imap,
socket: Ssl,
hostname: "imap.qq.com",
port: 993,
username_pattern: Emaillocalpart,
},
Server {
protocol: Smtp,
socket: Ssl,
hostname: "smtp.qq.com",
port: 465,
username_pattern: Email,
},
],
opt: ProviderOptions::new(),
config_defaults: None,
@@ -1303,9 +1394,27 @@ static P_RAMBLER_RU: Provider = Provider {
after_login_hint: "",
overview_page: "https://providers.delta.chat/rambler-ru",
server: &[
Server { protocol: Imap, socket: Ssl, hostname: "imap.rambler.ru", port: 993, username_pattern: Email },
Server { protocol: Smtp, socket: Ssl, hostname: "smtp.rambler.ru", port: 465, username_pattern: Email },
Server { protocol: Imap, socket: Starttls, hostname: "imap.rambler.ru", port: 143, username_pattern: Email },
Server {
protocol: Imap,
socket: Ssl,
hostname: "imap.rambler.ru",
port: 993,
username_pattern: Email,
},
Server {
protocol: Smtp,
socket: Ssl,
hostname: "smtp.rambler.ru",
port: 465,
username_pattern: Email,
},
Server {
protocol: Imap,
socket: Starttls,
hostname: "imap.rambler.ru",
port: 143,
username_pattern: Email,
},
],
opt: ProviderOptions::new(),
config_defaults: None,
@@ -1461,8 +1570,20 @@ static P_T_ONLINE: Provider = Provider {
after_login_hint: "",
overview_page: "https://providers.delta.chat/t-online",
server: &[
Server { protocol: Imap, socket: Ssl, hostname: "secureimap.t-online.de", port: 993, username_pattern: Email },
Server { protocol: Smtp, socket: Ssl, hostname: "securesmtp.t-online.de", port: 465, username_pattern: Email },
Server {
protocol: Imap,
socket: Ssl,
hostname: "secureimap.t-online.de",
port: 993,
username_pattern: Email,
},
Server {
protocol: Smtp,
socket: Ssl,
hostname: "securesmtp.t-online.de",
port: 465,
username_pattern: Email,
},
],
opt: ProviderOptions::new(),
config_defaults: None,
@@ -1559,8 +1680,7 @@ static P_TUTANOTA: Provider = Provider {
before_login_hint: "Tutanota does not offer the standard IMAP e-mail protocol, so you cannot log in with Delta Chat to Tutanota.",
after_login_hint: "",
overview_page: "https://providers.delta.chat/tutanota",
server: &[
],
server: &[],
opt: ProviderOptions::new(),
config_defaults: None,
oauth2_authorizer: None,
@@ -1671,8 +1791,20 @@ static P_VK_COM: Provider = Provider {
after_login_hint: "",
overview_page: "https://providers.delta.chat/vk-com",
server: &[
Server { protocol: Imap, socket: Ssl, hostname: "imap.mail.ru", port: 993, username_pattern: Email },
Server { protocol: Smtp, socket: Ssl, hostname: "smtp.mail.ru", port: 465, username_pattern: Email },
Server {
protocol: Imap,
socket: Ssl,
hostname: "imap.mail.ru",
port: 993,
username_pattern: Email,
},
Server {
protocol: Smtp,
socket: Ssl,
hostname: "smtp.mail.ru",
port: 465,
username_pattern: Email,
},
],
opt: ProviderOptions::new(),
config_defaults: None,
@@ -1715,9 +1847,27 @@ static P_WEB_DE: Provider = Provider {
after_login_hint: "Note: if you have your web.de spam settings too strict, you won't receive contact requests from new people. If you want to receive contact requests, you should disable the \"3-Wege-Spamschutz\" in the web.de settings. Read how: https://hilfe.web.de/email/spam-und-viren/spamschutz-einstellungen.html",
overview_page: "https://providers.delta.chat/web-de",
server: &[
Server { protocol: Imap, socket: Ssl, hostname: "imap.web.de", port: 993, username_pattern: Emaillocalpart },
Server { protocol: Imap, socket: Starttls, hostname: "imap.web.de", port: 143, username_pattern: Emaillocalpart },
Server { protocol: Smtp, socket: Starttls, hostname: "smtp.web.de", port: 587, username_pattern: Emaillocalpart },
Server {
protocol: Imap,
socket: Ssl,
hostname: "imap.web.de",
port: 993,
username_pattern: Emaillocalpart,
},
Server {
protocol: Imap,
socket: Starttls,
hostname: "imap.web.de",
port: 143,
username_pattern: Emaillocalpart,
},
Server {
protocol: Smtp,
socket: Starttls,
hostname: "smtp.web.de",
port: 587,
username_pattern: Emaillocalpart,
},
],
opt: ProviderOptions::new(),
config_defaults: None,
@@ -1760,8 +1910,20 @@ static P_YAHOO: Provider = Provider {
after_login_hint: "",
overview_page: "https://providers.delta.chat/yahoo",
server: &[
Server { protocol: Imap, socket: Ssl, hostname: "imap.mail.yahoo.com", port: 993, username_pattern: Email },
Server { protocol: Smtp, socket: Ssl, hostname: "smtp.mail.yahoo.com", port: 465, username_pattern: Email },
Server {
protocol: Imap,
socket: Ssl,
hostname: "imap.mail.yahoo.com",
port: 993,
username_pattern: Email,
},
Server {
protocol: Smtp,
socket: Ssl,
hostname: "smtp.mail.yahoo.com",
port: 465,
username_pattern: Email,
},
],
opt: ProviderOptions::new(),
config_defaults: None,
@@ -1804,13 +1966,26 @@ static P_YGGMAIL: Provider = Provider {
after_login_hint: "Make sure, the Yggmail companion app runs whenever you want to use this account. Note, that you usually cannot write from @yggmail addresses to normal e-mail-addresses (as @gmx.net). However, you can create another account in the normal e-mail-network for this purpose.",
overview_page: "https://providers.delta.chat/yggmail",
server: &[
Server { protocol: Imap, socket: Plain, hostname: "localhost", port: 1143, username_pattern: Email },
Server { protocol: Smtp, socket: Plain, hostname: "localhost", port: 1025, username_pattern: Email },
Server {
protocol: Imap,
socket: Plain,
hostname: "localhost",
port: 1143,
username_pattern: Email,
},
Server {
protocol: Smtp,
socket: Plain,
hostname: "localhost",
port: 1025,
username_pattern: Email,
},
],
opt: ProviderOptions::new(),
config_defaults: Some(&[
ConfigDefault { key: Config::MvboxMove, value: "0" },
]),
config_defaults: Some(&[ConfigDefault {
key: Config::MvboxMove,
value: "0",
}]),
oauth2_authorizer: None,
};
+1 -1
View File
@@ -6,8 +6,8 @@
//! It provides [`PushSubscriber`] type
//! which holds push notification token for the device,
//! shared by all accounts.
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::sync::atomic::Ordering;
use anyhow::{Context as _, Result};
use base64::Engine as _;
+6 -6
View File
@@ -4,10 +4,10 @@ mod dclogin_scheme;
use std::collections::BTreeMap;
use std::sync::LazyLock;
use anyhow::{anyhow, bail, ensure, Context as _, Result};
use anyhow::{Context as _, Result, anyhow, bail, ensure};
pub use dclogin_scheme::LoginOptions;
use deltachat_contact_tools::{addr_normalize, may_be_valid_addr, ContactAddress};
use percent_encoding::{percent_decode_str, percent_encode, NON_ALPHANUMERIC};
use deltachat_contact_tools::{ContactAddress, addr_normalize, may_be_valid_addr};
use percent_encoding::{NON_ALPHANUMERIC, percent_decode_str, percent_encode};
use serde::Deserialize;
pub(crate) use self::dclogin_scheme::configure_from_login_qr;
@@ -18,7 +18,7 @@ use crate::events::EventType;
use crate::key::Fingerprint;
use crate::message::Message;
use crate::net::http::post_empty;
use crate::net::proxy::{ProxyConfig, DEFAULT_SOCKS_PORT};
use crate::net::proxy::{DEFAULT_SOCKS_PORT, ProxyConfig};
use crate::token;
use crate::tools::validate_id;
@@ -367,8 +367,8 @@ pub async fn check_qr(context: &Context, qr: &str) -> Result<Qr> {
pub fn format_backup(qr: &Qr) -> Result<String> {
match qr {
Qr::Backup2 {
ref node_addr,
ref auth_token,
node_addr,
auth_token,
} => {
let node_addr = serde_json::to_string(node_addr)?;
Ok(format!(
+3 -3
View File
@@ -1,11 +1,11 @@
use std::collections::HashMap;
use anyhow::{bail, Context as _, Result};
use anyhow::{Context as _, Result, bail};
use deltachat_contact_tools::may_be_valid_addr;
use num_traits::cast::ToPrimitive;
use super::{Qr, DCLOGIN_SCHEME};
use super::{DCLOGIN_SCHEME, Qr};
use crate::config::Config;
use crate::context::Context;
use crate::login_param::EnteredCertificateChecks;
@@ -263,7 +263,7 @@ pub(crate) async fn configure_from_login_qr(
mod test {
use anyhow::bail;
use super::{decode_login, LoginOptions};
use super::{LoginOptions, decode_login};
use crate::{login_param::EnteredCertificateChecks, provider::Socket, qr::Qr};
macro_rules! login_options_just_pw {
+1 -1
View File
@@ -1,5 +1,5 @@
use super::*;
use crate::chat::{create_group_chat, ProtectionStatus};
use crate::chat::{ProtectionStatus, create_group_chat};
use crate::config::Config;
use crate::securejoin::get_securejoin_qr;
use crate::test_utils::{TestContext, TestContextManager};
+2 -2
View File
@@ -3,7 +3,7 @@
use std::collections::BTreeMap;
use std::time::Duration;
use anyhow::{anyhow, Context as _, Result};
use anyhow::{Context as _, Result, anyhow};
use async_imap::types::{Quota, QuotaResource};
use crate::chat::add_device_msg_with_importance;
@@ -14,7 +14,7 @@ use crate::imap::session::Session as ImapSession;
use crate::log::warn;
use crate::message::Message;
use crate::tools::{self, time_elapsed};
use crate::{stock_str, EventType};
use crate::{EventType, stock_str};
/// warn about a nearly full mailbox after this usage percentage is reached.
/// quota icon is "yellow".
+3 -3
View File
@@ -21,13 +21,13 @@ use std::fmt;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use crate::chat::{send_msg, Chat, ChatId};
use crate::chat::{Chat, ChatId, send_msg};
use crate::chatlist_events;
use crate::contact::ContactId;
use crate::context::Context;
use crate::events::EventType;
use crate::log::info;
use crate::message::{rfc724_mid_exists, Message, MsgId};
use crate::message::{Message, MsgId, rfc724_mid_exists};
use crate::param::Param;
/// A single reaction consisting of multiple emoji sequences.
@@ -404,7 +404,7 @@ mod tests {
use crate::config::Config;
use crate::contact::{Contact, Origin};
use crate::download::DownloadState;
use crate::message::{delete_msgs, MessageState};
use crate::message::{MessageState, delete_msgs};
use crate::receive_imf::{receive_imf, receive_imf_from_inbox};
use crate::sql::housekeeping;
use crate::test_utils::TestContext;
+13 -10
View File
@@ -7,7 +7,7 @@ use std::sync::LazyLock;
use anyhow::{Context as _, Result};
use data_encoding::BASE32_NOPAD;
use deltachat_contact_tools::{
addr_cmp, addr_normalize, may_be_valid_addr, sanitize_single_line, ContactAddress,
ContactAddress, addr_cmp, addr_normalize, may_be_valid_addr, sanitize_single_line,
};
use iroh_gossip::proto::TopicId;
use mailparse::SingleInfo;
@@ -16,26 +16,26 @@ use regex::Regex;
use crate::chat::{self, Chat, ChatId, ChatIdBlocked, ProtectionStatus};
use crate::config::Config;
use crate::constants::{Blocked, Chattype, ShowEmails, DC_CHAT_ID_TRASH, EDITED_PREFIX};
use crate::contact::{mark_contact_id_as_verified, Contact, ContactId, Origin};
use crate::constants::{Blocked, Chattype, DC_CHAT_ID_TRASH, EDITED_PREFIX, ShowEmails};
use crate::contact::{Contact, ContactId, Origin, mark_contact_id_as_verified};
use crate::context::Context;
use crate::debug_logging::maybe_set_logging_xdc_inner;
use crate::download::DownloadState;
use crate::ephemeral::{stock_ephemeral_timer_changed, Timer as EphemeralTimer};
use crate::ephemeral::{Timer as EphemeralTimer, stock_ephemeral_timer_changed};
use crate::events::EventType;
use crate::headerdef::{HeaderDef, HeaderDefMap};
use crate::imap::{markseen_on_imap_table, GENERATED_PREFIX};
use crate::imap::{GENERATED_PREFIX, markseen_on_imap_table};
use crate::key::self_fingerprint_opt;
use crate::key::{DcKey, Fingerprint, SignedPublicKey};
use crate::log::LogExt;
use crate::log::{info, warn};
use crate::message::{
self, rfc724_mid_exists, Message, MessageState, MessengerMessage, MsgId, Viewtype,
self, Message, MessageState, MessengerMessage, MsgId, Viewtype, rfc724_mid_exists,
};
use crate::mimeparser::{parse_message_ids, AvatarAction, MimeMessage, SystemMessage};
use crate::mimeparser::{AvatarAction, MimeMessage, SystemMessage, parse_message_ids};
use crate::param::{Param, Params};
use crate::peer_channels::{add_gossip_peer_from_header, insert_topic_stub};
use crate::reaction::{set_msg_reaction, Reaction};
use crate::reaction::{Reaction, set_msg_reaction};
use crate::rusqlite::OptionalExtension;
use crate::securejoin::{self, handle_securejoin_handshake, observe_securejoin_on_other_device};
use crate::simplify;
@@ -244,7 +244,7 @@ async fn get_to_and_past_contact_ids(
// but want to assign the message to 1:1 chat.
let chat_id = match chat_assignment {
ChatAssignment::Trash => None,
ChatAssignment::GroupChat { ref grpid } => {
ChatAssignment::GroupChat { grpid } => {
if let Some((chat_id, _protected, _blocked)) =
chat::get_chat_id_by_grpid(context, grpid).await?
{
@@ -1729,7 +1729,10 @@ async fn add_parts(
let is_from_in_chat =
!chat_contacts.contains(&ContactId::SELF) || chat_contacts.contains(&from_id);
info!(context, "Received new ephemeral timer value {ephemeral_timer:?} for chat {chat_id}, checking if it should be applied.");
info!(
context,
"Received new ephemeral timer value {ephemeral_timer:?} for chat {chat_id}, checking if it should be applied."
);
if !is_from_in_chat {
warn!(
context,
+38 -28
View File
@@ -5,20 +5,19 @@ use tokio::fs;
use super::*;
use crate::chat::{
add_contact_to_chat, add_to_chat_contacts_table, create_group_chat, get_chat_contacts,
get_chat_msgs, is_contact_in_chat, remove_contact_from_chat, send_text_msg, ChatItem,
ChatVisibility,
ChatItem, ChatVisibility, add_contact_to_chat, add_to_chat_contacts_table, create_group_chat,
get_chat_contacts, get_chat_msgs, is_contact_in_chat, remove_contact_from_chat, send_text_msg,
};
use crate::chatlist::Chatlist;
use crate::constants::DC_GCL_FOR_FORWARDING;
use crate::contact;
use crate::download::MIN_DOWNLOAD_LIMIT;
use crate::imap::prefetch_should_download;
use crate::imex::{imex, ImexMode};
use crate::imex::{ImexMode, imex};
use crate::securejoin::get_securejoin_qr;
use crate::test_utils::mark_as_verified;
use crate::test_utils::{get_chat_msg, TestContext, TestContextManager};
use crate::tools::{time, SystemTime};
use crate::test_utils::{TestContext, TestContextManager, get_chat_msg};
use crate::tools::{SystemTime, time};
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_outgoing() -> Result<()> {
@@ -358,10 +357,12 @@ async fn test_no_from() {
assert!(chats.is_empty());
// Check that the message was added to the db:
assert!(message::rfc724_mid_exists(context, "3924@example.com")
.await
.unwrap()
.is_some());
assert!(
message::rfc724_mid_exists(context, "3924@example.com")
.await
.unwrap()
.is_some()
);
}
/// If there is no Message-Id header, we generate a random id.
@@ -390,14 +391,15 @@ async fn test_no_message_id_header() {
.unwrap();
assert!(received.is_none());
assert!(!t
.sql
.exists(
"SELECT COUNT(*) FROM msgs WHERE chat_id=?;",
(DC_CHAT_ID_TRASH,),
)
.await
.unwrap());
assert!(
!t.sql
.exists(
"SELECT COUNT(*) FROM msgs WHERE chat_id=?;",
(DC_CHAT_ID_TRASH,),
)
.await
.unwrap()
);
let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap();
// Check that the message is not shown to the user:
@@ -827,7 +829,10 @@ async fn load_imf_email(context: &Context, imf_raw: &[u8]) -> Message {
async fn test_html_only_mail() {
let t = TestContext::new_alice().await;
let msg = load_imf_email(&t, include_bytes!("../../test-data/message/wrong-html.eml")).await;
assert_eq!(msg.text, "Guten Abend,\n\nLots of text\n\ntext with Umlaut ä...\n\nMfG\n\n--------------------------------------\n\n[Camping ](https://example.com/)\n\nsomeaddress\n\nsometown");
assert_eq!(
msg.text,
"Guten Abend,\n\nLots of text\n\ntext with Umlaut ä...\n\nMfG\n\n--------------------------------------\n\n[Camping ](https://example.com/)\n\nsomeaddress\n\nsometown"
);
}
static GH_MAILINGLIST: &[u8] =
@@ -843,8 +848,7 @@ static GH_MAILINGLIST: &[u8] =
\n\
hello\n";
static GH_MAILINGLIST2: &str =
"Received: (Postfix, from userid 1000); Mon, 4 Dec 2006 14:51:39 +0100 (CET)\n\
static GH_MAILINGLIST2: &str = "Received: (Postfix, from userid 1000); Mon, 4 Dec 2006 14:51:39 +0100 (CET)\n\
From: Github <notifications@github.com>\n\
To: deltachat/deltachat-core-rust <deltachat-core-rust@noreply.github.com>\n\
Subject: [deltachat/deltachat-core-rust] PR run failed\n\
@@ -2693,7 +2697,10 @@ async fn test_gmx_forwarded_msg() -> Result<()> {
let msg = t.get_last_msg().await;
assert!(msg.has_html());
assert_eq!(msg.id.get_html(&t).await?.unwrap().replace("\r\n", "\n"), "<html><head></head><body><div style=\"font-family: Verdana;font-size: 12.0px;\"><div>&nbsp;</div>\n\n<div>&nbsp;\n<div>&nbsp;\n<div data-darkreader-inline-border-left=\"\" name=\"quote\" style=\"margin: 10px 5px 5px 10px; padding: 10px 0px 10px 10px; border-left: 2px solid rgb(195, 217, 229); overflow-wrap: break-word; --darkreader-inline-border-left:#274759;\">\n<div style=\"margin:0 0 10px 0;\"><b>Gesendet:</b>&nbsp;Donnerstag, 12. August 2021 um 15:52 Uhr<br/>\n<b>Von:</b>&nbsp;&quot;Claire&quot; &lt;claire@example.org&gt;<br/>\n<b>An:</b>&nbsp;alice@example.org<br/>\n<b>Betreff:</b>&nbsp;subject</div>\n\n<div name=\"quoted-content\">bodytext</div>\n</div>\n</div>\n</div></div></body></html>\n\n");
assert_eq!(
msg.id.get_html(&t).await?.unwrap().replace("\r\n", "\n"),
"<html><head></head><body><div style=\"font-family: Verdana;font-size: 12.0px;\"><div>&nbsp;</div>\n\n<div>&nbsp;\n<div>&nbsp;\n<div data-darkreader-inline-border-left=\"\" name=\"quote\" style=\"margin: 10px 5px 5px 10px; padding: 10px 0px 10px 10px; border-left: 2px solid rgb(195, 217, 229); overflow-wrap: break-word; --darkreader-inline-border-left:#274759;\">\n<div style=\"margin:0 0 10px 0;\"><b>Gesendet:</b>&nbsp;Donnerstag, 12. August 2021 um 15:52 Uhr<br/>\n<b>Von:</b>&nbsp;&quot;Claire&quot; &lt;claire@example.org&gt;<br/>\n<b>An:</b>&nbsp;alice@example.org<br/>\n<b>Betreff:</b>&nbsp;subject</div>\n\n<div name=\"quoted-content\">bodytext</div>\n</div>\n</div>\n</div></div></body></html>\n\n"
);
Ok(())
}
@@ -3233,9 +3240,11 @@ async fn test_outgoing_undecryptable() -> Result<()> {
.unwrap();
let dev_msg = alice.get_last_msg_in(dev_chat_id).await;
assert!(dev_msg.error().is_none());
assert!(dev_msg
.text
.contains(&stock_str::cant_decrypt_outgoing_msgs(alice).await));
assert!(
dev_msg
.text
.contains(&stock_str::cant_decrypt_outgoing_msgs(alice).await)
);
let raw = include_bytes!("../../test-data/message/thunderbird_encrypted_signed.eml");
receive_imf(alice, raw, false).await?;
@@ -3462,9 +3471,10 @@ async fn test_big_forwarded_with_big_attachment() -> Result<()> {
let msg = Message::load_from_db(t, rcvd.msg_ids[1]).await?;
assert_eq!(msg.get_viewtype(), Viewtype::Text);
assert!(msg
.get_text()
.starts_with("this text with 42 chars is just repeated."));
assert!(
msg.get_text()
.starts_with("this text with 42 chars is just repeated.")
);
assert!(msg.get_text().ends_with("[...]"));
assert!(!msg.has_html());
+6 -6
View File
@@ -3,12 +3,12 @@ use std::iter::{self, once};
use std::num::NonZeroUsize;
use std::sync::atomic::Ordering;
use anyhow::{bail, Context as _, Error, Result};
use anyhow::{Context as _, Error, Result, bail};
use async_channel::{self as channel, Receiver, Sender};
use futures::future::try_join_all;
use futures_lite::FutureExt;
use rand::Rng;
use tokio::sync::{oneshot, RwLock, RwLockWriteGuard};
use tokio::sync::{RwLock, RwLockWriteGuard, oneshot};
use tokio::task;
use tokio_util::sync::CancellationToken;
use tokio_util::task::TaskTracker;
@@ -17,14 +17,14 @@ use self::connectivity::ConnectivityStore;
use crate::config::{self, Config};
use crate::contact::{ContactId, RecentlySeenLoop};
use crate::context::Context;
use crate::download::{download_msg, DownloadState};
use crate::download::{DownloadState, download_msg};
use crate::ephemeral::{self, delete_expired_imap_messages};
use crate::events::EventType;
use crate::imap::{session::Session, FolderMeaning, Imap};
use crate::imap::{FolderMeaning, Imap, session::Session};
use crate::location;
use crate::log::{error, info, warn, LogExt};
use crate::log::{LogExt, error, info, warn};
use crate::message::MsgId;
use crate::smtp::{send_smtp_messages, Smtp};
use crate::smtp::{Smtp, send_smtp_messages};
use crate::sql;
use crate::tools::{self, duration_to_str, maybe_add_time_based_warnings, time, time_elapsed};
+5 -3
View File
@@ -3,11 +3,11 @@ use std::cmp::min;
use std::{iter::once, ops::Deref, sync::Arc};
use anyhow::Result;
use humansize::{format_size, BINARY};
use humansize::{BINARY, format_size};
use tokio::sync::Mutex;
use crate::events::EventType;
use crate::imap::{scan_folders::get_watched_folder_configs, FolderMeaning};
use crate::imap::{FolderMeaning, scan_folders::get_watched_folder_configs};
use crate::log::info;
use crate::quota::{QUOTA_ERROR_THRESHOLD_PERCENTAGE, QUOTA_WARN_THRESHOLD_PERCENTAGE};
use crate::stock_str;
@@ -509,7 +509,9 @@ impl Context {
"green"
};
let div_width_percent = min(100, percent);
ret += &format!("<div class=\"bar\"><div class=\"progress {color}\" style=\"width: {div_width_percent}%\">{percent}%</div></div>");
ret += &format!(
"<div class=\"bar\"><div class=\"progress {color}\" style=\"width: {div_width_percent}%\">{percent}%</div></div>"
);
ret += "</li>";
}
+4 -4
View File
@@ -1,10 +1,10 @@
//! Implementation of [SecureJoin protocols](https://securejoin.delta.chat/).
use anyhow::{ensure, Context as _, Error, Result};
use anyhow::{Context as _, Error, Result, ensure};
use deltachat_contact_tools::ContactAddress;
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
use percent_encoding::{NON_ALPHANUMERIC, utf8_percent_encode};
use crate::chat::{self, get_chat_id_by_grpid, Chat, ChatId, ChatIdBlocked, ProtectionStatus};
use crate::chat::{self, Chat, ChatId, ChatIdBlocked, ProtectionStatus, get_chat_id_by_grpid};
use crate::chatlist_events;
use crate::config::Config;
use crate::constants::{Blocked, Chattype, NON_ALPHANUMERIC_WITHOUT_DOT};
@@ -14,7 +14,7 @@ use crate::context::Context;
use crate::e2ee::ensure_secret_key_exists;
use crate::events::EventType;
use crate::headerdef::HeaderDef;
use crate::key::{load_self_public_key, DcKey, Fingerprint};
use crate::key::{DcKey, Fingerprint, load_self_public_key};
use crate::log::{error, info, warn};
use crate::message::{Message, Viewtype};
use crate::mimeparser::{MimeMessage, SystemMessage};
+5 -9
View File
@@ -2,9 +2,9 @@
use anyhow::{Context as _, Result};
use super::qrinvite::QrInvite;
use super::HandshakeMessage;
use crate::chat::{self, is_contact_in_chat, ChatId, ProtectionStatus};
use super::qrinvite::QrInvite;
use crate::chat::{self, ChatId, ProtectionStatus, is_contact_in_chat};
use crate::constants::{Blocked, Chattype};
use crate::contact::Origin;
use crate::context::Context;
@@ -14,7 +14,7 @@ use crate::log::info;
use crate::message::{Message, Viewtype};
use crate::mimeparser::{MimeMessage, SystemMessage};
use crate::param::Param;
use crate::securejoin::{encrypted_and_signed, verify_sender_by_fingerprint, ContactId};
use crate::securejoin::{ContactId, encrypted_and_signed, verify_sender_by_fingerprint};
use crate::stock_str;
use crate::sync::Sync::*;
use crate::tools::{create_smeared_timestamp, time};
@@ -285,7 +285,7 @@ pub(crate) async fn send_handshake_message(
// Previous Delta Chat core also sent `Secure-Join-Group` header
// in `vg-request` messages,
// but it was not used on the receiver.
if let QrInvite::Group { ref grpid, .. } = invite {
if let QrInvite::Group { grpid, .. } = invite {
msg.param.set(Param::Arg4, grpid);
}
}
@@ -346,11 +346,7 @@ async fn joining_chat_id(
) -> Result<ChatId> {
match invite {
QrInvite::Contact { .. } => Ok(alice_chat_id),
QrInvite::Group {
ref grpid,
ref name,
..
} => {
QrInvite::Group { grpid, name, .. } => {
let group_chat_id = match chat::get_chat_id_by_grpid(context, grpid).await? {
Some((chat_id, _protected, _blocked)) => {
chat_id.unblock_ex(context, Nosync).await?;
+1 -1
View File
@@ -4,7 +4,7 @@
//! with it rather hard, so here we have a wrapper type that specifically deals with Secure-Join
//! QR-codes so that the Secure-Join code can have more guarantees when dealing with this.
use anyhow::{bail, Error, Result};
use anyhow::{Error, Result, bail};
use crate::contact::ContactId;
use crate::key::Fingerprint;
+8 -7
View File
@@ -1,14 +1,14 @@
use deltachat_contact_tools::EmailAddress;
use super::*;
use crate::chat::{remove_contact_from_chat, CantSendReason};
use crate::chat::{CantSendReason, remove_contact_from_chat};
use crate::chatlist::Chatlist;
use crate::constants::Chattype;
use crate::key::self_fingerprint;
use crate::receive_imf::receive_imf;
use crate::stock_str::{self, chat_protection_enabled};
use crate::test_utils::{
get_chat_msg, TestContext, TestContextManager, TimeShiftFalsePositiveNote,
TestContext, TestContextManager, TimeShiftFalsePositiveNote, get_chat_msg,
};
use crate::tools::SystemTime;
use std::time::Duration;
@@ -405,11 +405,12 @@ async fn test_setup_contact_concurrent_calls() -> Result<()> {
assert!(!alice_id.is_special());
assert_eq!(chat.typ, Chattype::Single);
assert_ne!(claire_id, alice_id);
assert!(bob
.pop_sent_msg()
.await
.payload()
.contains("alice@example.org"));
assert!(
bob.pop_sent_msg()
.await
.payload()
.contains("alice@example.org")
);
Ok(())
}
+6 -5
View File
@@ -165,11 +165,12 @@ pub(crate) fn simplify(mut input: String, is_chat_message: bool) -> SimplifiedTe
/// a message is forwarded or not.
fn skip_forward_header<'a>(lines: &'a [&str]) -> (&'a [&'a str], bool) {
match lines {
["---------- Forwarded message ----------", first_line, "", rest @ ..]
if first_line.starts_with("From: ") =>
{
(rest, true)
}
[
"---------- Forwarded message ----------",
first_line,
"",
rest @ ..,
] if first_line.starts_with("From: ") => (rest, true),
_ => (lines, false),
}
}
+6 -3
View File
@@ -3,12 +3,12 @@
mod connect;
pub mod send;
use anyhow::{bail, format_err, Context as _, Error, Result};
use anyhow::{Context as _, Error, Result, bail, format_err};
use async_smtp::response::{Category, Code, Detail};
use async_smtp::{EmailAddress, SmtpTransport};
use tokio::task;
use crate::chat::{add_info_msg_with_cmd, ChatId};
use crate::chat::{ChatId, add_info_msg_with_cmd};
use crate::config::Config;
use crate::contact::{Contact, ContactId};
use crate::context::Context;
@@ -231,7 +231,10 @@ pub(crate) async fn smtp_send(
};
if maybe_transient {
info!(context, "Permanent error that is likely to actually be transient, postponing retry for later.");
info!(
context,
"Permanent error that is likely to actually be transient, postponing retry for later."
);
SendResult::Retry
} else {
info!(context, "Permanent error, message sending failed.");
+1 -1
View File
@@ -2,7 +2,7 @@
use std::net::SocketAddr;
use anyhow::{bail, Context as _, Result};
use anyhow::{Context as _, Result, bail};
use async_smtp::{SmtpClient, SmtpTransport};
use tokio::io::{AsyncBufRead, AsyncWrite, BufStream};
+4 -4
View File
@@ -3,8 +3,8 @@
use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf};
use anyhow::{bail, Context as _, Result};
use rusqlite::{config::DbConfig, types::ValueRef, Connection, OpenFlags, Row};
use anyhow::{Context as _, Result, bail};
use rusqlite::{Connection, OpenFlags, Row, config::DbConfig, types::ValueRef};
use tokio::sync::RwLock;
use crate::blob::BlobObject;
@@ -16,14 +16,14 @@ use crate::debug_logging::set_debug_logging_xdc;
use crate::ephemeral::start_ephemeral_timers;
use crate::imex::BLOBS_BACKUP_NAME;
use crate::location::delete_orphaned_poi_locations;
use crate::log::{error, info, warn, LogExt};
use crate::log::{LogExt, error, info, warn};
use crate::message::{Message, MsgId};
use crate::net::dns::prune_dns_cache;
use crate::net::http::http_cache_cleanup;
use crate::net::prune_connection_history;
use crate::param::{Param, Params};
use crate::stock_str;
use crate::tools::{delete_file, time, SystemTime};
use crate::tools::{SystemTime, delete_file, time};
/// Extension to [`rusqlite::ToSql`] trait
/// which also includes [`Send`] and [`Sync`].
+22 -7
View File
@@ -4,9 +4,9 @@ use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::time::Instant;
use anyhow::{ensure, Context as _, Result};
use deltachat_contact_tools::addr_cmp;
use anyhow::{Context as _, Result, ensure};
use deltachat_contact_tools::EmailAddress;
use deltachat_contact_tools::addr_cmp;
use pgp::composed::SignedPublicKey;
use rusqlite::OptionalExtension;
@@ -1521,7 +1521,10 @@ fn migrate_key_contacts(
context,
"Created key-contacts identified by autocrypt key: {autocrypt_key_contacts:?}"
);
info!(context, "Created key-contacts with 'reset' peerstate identified by autocrypt key: {autocrypt_key_contacts_with_reset_peerstate:?}");
info!(
context,
"Created key-contacts with 'reset' peerstate identified by autocrypt key: {autocrypt_key_contacts_with_reset_peerstate:?}"
);
info!(
context,
"Created key-contacts identified by verified key: {verified_key_contacts:?}"
@@ -1538,7 +1541,10 @@ fn migrate_key_contacts(
match verified_key_contacts.get(&verifier_original_contact) {
Some(v) => *v,
None => {
warn!(context, "Couldn't find key-contact for {verifier_original_contact} who verified {new_contact}");
warn!(
context,
"Couldn't find key-contact for {verifier_original_contact} who verified {new_contact}"
);
continue;
}
}
@@ -1630,7 +1636,10 @@ fn migrate_key_contacts(
.context("Step 26")?;
let mut keep_address_contacts = |reason: &str| {
info!(context, "Chat {chat_id} will be an unencrypted chat with contacts identified by email address: {reason}");
info!(
context,
"Chat {chat_id} will be an unencrypted chat with contacts identified by email address: {reason}"
);
for m in &old_members {
orphaned_contacts.remove(m);
}
@@ -1645,7 +1654,10 @@ fn migrate_key_contacts(
// and the effect will be the same.
100 => {
let Some(old_member) = old_members.first() else {
info!(context, "1:1 chat {chat_id} doesn't contain contact, probably it's self or device chat");
info!(
context,
"1:1 chat {chat_id} doesn't contain contact, probably it's self or device chat"
);
continue;
};
@@ -1778,7 +1790,10 @@ fn migrate_key_contacts(
update_member_stmt.execute((new_member, old_member, chat_id))?;
}
} else {
info!(context, "Old member {old_member} in chat {chat_id} can't be upgraded to key-contact, removing them");
info!(
context,
"Old member {old_member} in chat {chat_id} can't be upgraded to key-contact, removing them"
);
transaction
.execute(
"DELETE FROM chats_contacts WHERE contact_id=? AND chat_id=?",
+1 -1
View File
@@ -1,5 +1,5 @@
use super::*;
use crate::{test_utils::TestContext, EventType};
use crate::{EventType, test_utils::TestContext};
#[test]
fn test_maybe_add_file() {
+2 -2
View File
@@ -3,8 +3,8 @@
use std::collections::HashMap;
use std::sync::Arc;
use anyhow::{bail, Result};
use humansize::{format_size, BINARY};
use anyhow::{Result, bail};
use humansize::{BINARY, format_size};
use strum::EnumProperty as EnumPropertyTrait;
use strum_macros::EnumProperty;
use tokio::sync::RwLock;
+12 -10
View File
@@ -28,16 +28,18 @@ async fn test_set_stock_translation() {
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_set_stock_translation_wrong_replacements() {
let t = TestContext::new().await;
assert!(t
.ctx
.set_stock_translation(StockMessage::NoMessages, "xyz %1$s ".to_string())
.await
.is_err());
assert!(t
.ctx
.set_stock_translation(StockMessage::NoMessages, "xyz %2$s ".to_string())
.await
.is_err());
assert!(
t.ctx
.set_stock_translation(StockMessage::NoMessages, "xyz %1$s ".to_string())
.await
.is_err()
);
assert!(
t.ctx
.set_stock_translation(StockMessage::NoMessages, "xyz %2$s ".to_string())
.await
.is_err()
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
+1 -1
View File
@@ -332,7 +332,7 @@ mod tests {
use anyhow::bail;
use super::*;
use crate::chat::{remove_contact_from_chat, Chat, ProtectionStatus};
use crate::chat::{Chat, ProtectionStatus, remove_contact_from_chat};
use crate::chatlist::Chatlist;
use crate::contact::{Contact, Origin};
use crate::securejoin::get_securejoin_qr;
+17 -14
View File
@@ -15,26 +15,26 @@ use deltachat_contact_tools::{ContactAddress, EmailAddress};
use nu_ansi_term::Color;
use pretty_assertions::assert_eq;
use rand::Rng;
use tempfile::{tempdir, TempDir};
use tempfile::{TempDir, tempdir};
use tokio::runtime::Handle;
use tokio::{fs, task};
use crate::chat::{
self, add_to_chat_contacts_table, create_group_chat, Chat, ChatId, ChatIdBlocked,
MessageListOptions, ProtectionStatus,
self, Chat, ChatId, ChatIdBlocked, MessageListOptions, ProtectionStatus,
add_to_chat_contacts_table, create_group_chat,
};
use crate::chatlist::Chatlist;
use crate::config::Config;
use crate::constants::{Blocked, Chattype};
use crate::constants::{DC_CHAT_ID_TRASH, DC_GCL_NO_SPECIALS};
use crate::contact::{
import_vcard, make_vcard, mark_contact_id_as_verified, Contact, ContactId, Modifier, Origin,
Contact, ContactId, Modifier, Origin, import_vcard, make_vcard, mark_contact_id_as_verified,
};
use crate::context::Context;
use crate::events::{Event, EventEmitter, EventType, Events};
use crate::key::{self, self_fingerprint, DcKey, DcSecretKey};
use crate::key::{self, DcKey, DcSecretKey, self_fingerprint};
use crate::log::warn;
use crate::message::{update_msg_state, Message, MessageState, MsgId, Viewtype};
use crate::message::{Message, MessageState, MsgId, Viewtype, update_msg_state};
use crate::mimeparser::{MimeMessage, SystemMessage};
use crate::pgp::KeyPair;
use crate::receive_imf::receive_imf;
@@ -143,7 +143,8 @@ impl TestContextManager {
) -> Message {
let received_msg = self.send_recv(from, to, msg).await;
assert_eq!(
received_msg.chat_blocked, Blocked::Request,
received_msg.chat_blocked,
Blocked::Request,
"`send_recv_accept()` is meant to be used for chat requests. Use `send_recv()` if the chat is already accepted."
);
received_msg.chat_id.accept(to).await.unwrap();
@@ -418,7 +419,7 @@ impl TestContext {
async fn new_internal(name: Option<String>, log_sink: Option<LogSink>) -> Self {
let dir = tempdir().unwrap();
let dbfile = dir.path().join("db.sqlite");
let id = rand::thread_rng().gen();
let id = rand::thread_rng().r#gen();
if let Some(name) = name {
let mut context_names = CONTEXT_NAMES.write().unwrap();
context_names.insert(id, name);
@@ -866,11 +867,13 @@ impl TestContext {
pub async fn assert_no_chat(&self, id: ChatId) {
assert!(Chat::load_from_db(self, id).await.is_err());
assert!(!self
.sql
.exists("SELECT COUNT(*) FROM chats WHERE id=?", (id,))
.await
.unwrap());
assert!(
!self
.sql
.exists("SELECT COUNT(*) FROM chats WHERE id=?", (id,))
.await
.unwrap()
);
}
/// Sends out the text message.
@@ -1311,7 +1314,7 @@ impl EventTracker {
/// Consumes events looking for an [`EventType::Info`] with substring matching.
pub async fn get_info_contains(&self, s: &str) -> EventType {
self.get_matching(|evt| match evt {
EventType::Info(ref msg) => msg.contains(s),
EventType::Info(msg) => msg.contains(s),
_ => false,
})
.await
+3 -3
View File
@@ -5,11 +5,11 @@ use std::time::Duration;
use anyhow::Result;
use tempfile::tempdir;
use crate::EventType;
use crate::accounts::Accounts;
use crate::config::Config;
use crate::imex::{get_backup, has_backup, imex, BackupProvider, ImexMode};
use crate::test_utils::{sync, EventTracker, TestContext, TestContextManager};
use crate::EventType;
use crate::imex::{BackupProvider, ImexMode, get_backup, has_backup, imex};
use crate::test_utils::{EventTracker, TestContext, TestContextManager, sync};
async fn wait_for_item_changed(context: &TestContext) {
context
+1 -1
View File
@@ -14,9 +14,9 @@ use crate::contact::{Contact, ContactId};
use crate::message::Message;
use crate::receive_imf::receive_imf;
use crate::securejoin::get_securejoin_qr;
use crate::test_utils::mark_as_verified;
use crate::test_utils::TestContext;
use crate::test_utils::TestContextManager;
use crate::test_utils::mark_as_verified;
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_change_primary_self_addr() -> Result<()> {
+3 -3
View File
@@ -3,19 +3,19 @@ use pretty_assertions::assert_eq;
use crate::chat::resend_msgs;
use crate::chat::{
self, add_contact_to_chat, remove_contact_from_chat, send_msg, Chat, ProtectionStatus,
self, Chat, ProtectionStatus, add_contact_to_chat, remove_contact_from_chat, send_msg,
};
use crate::config::Config;
use crate::constants::Chattype;
use crate::contact::{Contact, ContactId};
use crate::key::{load_self_public_key, DcKey};
use crate::key::{DcKey, load_self_public_key};
use crate::message::{Message, Viewtype};
use crate::mimefactory::MimeFactory;
use crate::mimeparser::SystemMessage;
use crate::receive_imf::receive_imf;
use crate::securejoin::{get_securejoin_qr, join_securejoin};
use crate::stock_str;
use crate::test_utils::{get_chat_msg, mark_as_verified, TestContext, TestContextManager};
use crate::test_utils::{TestContext, TestContextManager, get_chat_msg, mark_as_verified};
use crate::tools::SystemTime;
use crate::{e2ee, message};
+1 -1
View File
@@ -82,7 +82,7 @@ mod tests {
use super::*;
use crate::test_utils::TestContext;
use crate::tools::{
create_smeared_timestamp, create_smeared_timestamps, smeared_time, time, SystemTime,
SystemTime, create_smeared_timestamp, create_smeared_timestamps, smeared_time, time,
};
#[test]
+4 -8
View File
@@ -20,18 +20,18 @@ pub use std::time::SystemTime as Time;
#[cfg(not(test))]
pub use std::time::SystemTime;
use anyhow::{bail, ensure, Context as _, Result};
use anyhow::{Context as _, Result, bail, ensure};
use base64::Engine as _;
use chrono::{Local, NaiveDateTime, NaiveTime, TimeZone};
use deltachat_contact_tools::EmailAddress;
#[cfg(test)]
pub use deltachat_time::SystemTimeTools as SystemTime;
use futures::TryStreamExt;
use mailparse::MailHeaderMap;
use mailparse::dateparse;
use mailparse::headers::Headers;
use mailparse::MailHeaderMap;
use num_traits::PrimInt;
use rand::{thread_rng, Rng};
use rand::{Rng, thread_rng};
use tokio::{fs, io};
use url::Url;
use uuid::Uuid;
@@ -609,11 +609,7 @@ pub(crate) trait ToOption<T> {
}
impl<'a> ToOption<&'a str> for &'a String {
fn to_option(self) -> Option<&'a str> {
if self.is_empty() {
None
} else {
Some(self)
}
if self.is_empty() { None } else { Some(self) }
}
}
impl ToOption<String> for u16 {
+28 -21
View File
@@ -10,20 +10,17 @@ use crate::{receive_imf::receive_imf, test_utils::TestContext};
fn test_parse_receive_headers() {
// Test `parse_receive_headers()` with some more-or-less random emails from the test-data
let raw = include_bytes!("../../test-data/message/mail_with_cc.txt");
let expected =
"Hop: From: localhost; By: hq5.merlinux.eu; Date: Sat, 14 Sep 2019 17:00:22 +0000\n\
let expected = "Hop: From: localhost; By: hq5.merlinux.eu; Date: Sat, 14 Sep 2019 17:00:22 +0000\n\
Hop: From: hq5.merlinux.eu; By: hq5.merlinux.eu; Date: Sat, 14 Sep 2019 17:00:25 +0000";
check_parse_receive_headers(raw, expected);
let raw = include_bytes!("../../test-data/message/wrong-html.eml");
let expected =
"Hop: From: oxbsltgw18.schlund.de; By: mrelayeu.kundenserver.de; Date: Thu, 6 Aug 2020 16:40:31 +0000\n\
let expected = "Hop: From: oxbsltgw18.schlund.de; By: mrelayeu.kundenserver.de; Date: Thu, 6 Aug 2020 16:40:31 +0000\n\
Hop: From: mout.kundenserver.de; By: dd37930.kasserver.com; Date: Thu, 6 Aug 2020 16:40:32 +0000";
check_parse_receive_headers(raw, expected);
let raw = include_bytes!("../../test-data/message/posteo_ndn.eml");
let expected =
"Hop: By: mout01.posteo.de; Date: Tue, 9 Jun 2020 18:44:22 +0000\n\
let expected = "Hop: By: mout01.posteo.de; Date: Tue, 9 Jun 2020 18:44:22 +0000\n\
Hop: From: mout01.posteo.de; By: mx04.posteo.de; Date: Tue, 9 Jun 2020 18:44:22 +0000\n\
Hop: From: mx04.posteo.de; By: mailin06.posteo.de; Date: Tue, 9 Jun 2020 18:44:23 +0000\n\
Hop: From: mailin06.posteo.de; By: proxy02.posteo.de; Date: Tue, 9 Jun 2020 18:44:23 +0000\n\
@@ -273,9 +270,11 @@ async fn test_file_handling() {
};
}
assert!(delete_file(context, Path::new("$BLOBDIR/lkqwjelqkwlje"))
.await
.is_err());
assert!(
delete_file(context, Path::new("$BLOBDIR/lkqwjelqkwlje"))
.await
.is_err()
);
assert!(
write_file(context, Path::new("$BLOBDIR/foobar"), b"content")
.await
@@ -298,21 +297,29 @@ async fn test_file_handling() {
assert!(file_exist!(context, &abs_path));
assert!(delete_file(context, Path::new("$BLOBDIR/foobar"))
.await
.is_ok());
assert!(create_folder(context, Path::new("$BLOBDIR/foobar-folder"))
.await
.is_ok());
assert!(
delete_file(context, Path::new("$BLOBDIR/foobar"))
.await
.is_ok()
);
assert!(
create_folder(context, Path::new("$BLOBDIR/foobar-folder"))
.await
.is_ok()
);
assert!(file_exist!(context, "$BLOBDIR/foobar-folder"));
assert!(delete_file(context, Path::new("$BLOBDIR/foobar-folder"))
.await
.is_err());
assert!(
delete_file(context, Path::new("$BLOBDIR/foobar-folder"))
.await
.is_err()
);
let fn0 = "$BLOBDIR/data.data";
assert!(write_file(context, Path::new(fn0), b"content")
.await
.is_ok());
assert!(
write_file(context, Path::new(fn0), b"content")
.await
.is_ok()
);
assert!(delete_file(context, Path::new(fn0)).await.is_ok());
assert!(!file_exist!(context, &fn0));
+7 -3
View File
@@ -22,7 +22,7 @@ use std::cmp::max;
use std::collections::HashMap;
use std::path::Path;
use anyhow::{anyhow, bail, ensure, format_err, Context as _, Result};
use anyhow::{Context as _, Result, anyhow, bail, ensure, format_err};
use async_zip::tokio::read::seek::ZipFileReader as SeekZipFileReader;
use deltachat_contact_tools::sanitize_bidi_characters;
@@ -518,7 +518,9 @@ impl Context {
})?;
let viewtype = instance.viewtype;
if viewtype != Viewtype::Webxdc {
bail!("send_webxdc_status_update: message {instance_msg_id} is not a webxdc message, but a {viewtype} message.");
bail!(
"send_webxdc_status_update: message {instance_msg_id} is not a webxdc message, but a {viewtype} message."
);
}
if instance.param.get_int(Param::WebxdcIntegration).is_some() {
@@ -683,7 +685,9 @@ impl Context {
.await?
.with_context(|| format!("Chat type for chat {chat_id} not found"))?;
if chat_type != Chattype::Mailinglist {
bail!("receive_status_update: status sender {from_id} is not a member of chat {chat_id}")
bail!(
"receive_status_update: status sender {from_id} is not a member of chat {chat_id}"
)
}
}
+2 -2
View File
@@ -1,12 +1,12 @@
use std::path::Path;
use crate::chat::{send_msg, ChatId};
use crate::chat::{ChatId, send_msg};
use crate::config::Config;
use crate::contact::ContactId;
use crate::context::Context;
use crate::message::{Message, MsgId, Viewtype};
use crate::param::Param;
use crate::webxdc::{maps_integration, StatusUpdateItem, StatusUpdateSerial};
use crate::webxdc::{StatusUpdateItem, StatusUpdateSerial, maps_integration};
use anyhow::Result;
impl Context {
+3 -3
View File
@@ -33,7 +33,7 @@
//! ```
use crate::{chat, location};
use std::collections::{hash_map, HashMap};
use std::collections::{HashMap, hash_map};
use crate::context::Context;
use crate::message::{Message, MsgId};
@@ -169,13 +169,13 @@ pub(crate) async fn intercept_get_updates(
#[cfg(test)]
mod tests {
use crate::chat::{create_group_chat, ChatId, ProtectionStatus};
use crate::chat::{ChatId, ProtectionStatus, create_group_chat};
use crate::chatlist::Chatlist;
use crate::contact::Contact;
use crate::message::Message;
use crate::test_utils::TestContext;
use crate::webxdc::StatusUpdateSerial;
use crate::{location, EventType};
use crate::{EventType, location};
use anyhow::Result;
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
+56 -43
View File
@@ -5,8 +5,8 @@ use serde_json::json;
use super::*;
use crate::chat::{
add_contact_to_chat, create_broadcast_list, create_group_chat, forward_msgs,
remove_contact_from_chat, resend_msgs, send_msg, send_text_msg, ChatId, ProtectionStatus,
ChatId, ProtectionStatus, add_contact_to_chat, create_broadcast_list, create_group_chat,
forward_msgs, remove_contact_from_chat, resend_msgs, send_msg, send_text_msg,
};
use crate::chatlist::Chatlist;
use crate::config::Config;
@@ -296,14 +296,17 @@ async fn test_webxdc_contact_request() -> Result<()> {
let bob_instance = bob.get_last_msg().await;
let bob_chat = Chat::load_from_db(&bob, bob_instance.chat_id).await?;
assert!(bob_chat.is_contact_request());
assert!(bob_instance
.get_webxdc_blob(&bob, "index.html")
.await
.is_ok());
assert!(bob
.send_webxdc_status_update(bob_instance.id, r#"{"payload":42}"#)
.await
.is_err());
assert!(
bob_instance
.get_webxdc_blob(&bob, "index.html")
.await
.is_ok()
);
assert!(
bob.send_webxdc_status_update(bob_instance.id, r#"{"payload":42}"#)
.await
.is_err()
);
assert_eq!(
bob.get_webxdc_status_updates(bob_instance.id, StatusUpdateSerial(0))
.await?,
@@ -312,10 +315,11 @@ async fn test_webxdc_contact_request() -> Result<()> {
// Once the contact request is accepted, Bob can send updates
bob_chat.id.accept(&bob).await?;
assert!(bob
.send_webxdc_status_update(bob_instance.id, r#"{"payload":42}"#)
.await
.is_ok());
assert!(
bob.send_webxdc_status_update(bob_instance.id, r#"{"payload":42}"#)
.await
.is_ok()
);
assert_eq!(
bob.get_webxdc_status_updates(bob_instance.id, StatusUpdateSerial(0))
.await?,
@@ -548,15 +552,17 @@ async fn test_create_status_update_record() -> Result<()> {
.await?;
assert_eq!(update_id1_duplicate, None);
assert!(t
.send_webxdc_status_update(instance.id, "\n\n\n")
.await
.is_err());
assert!(
t.send_webxdc_status_update(instance.id, "\n\n\n")
.await
.is_err()
);
assert!(t
.send_webxdc_status_update(instance.id, "bad json")
.await
.is_err());
assert!(
t.send_webxdc_status_update(instance.id, "bad json")
.await
.is_err()
);
assert_eq!(
t.get_webxdc_status_updates(instance.id, StatusUpdateSerial(0))
@@ -631,12 +637,13 @@ async fn test_receive_status_update() -> Result<()> {
let instance = send_webxdc_instance(&t, chat_id).await?;
let now = tools::time();
assert!(t
.receive_status_update(ContactId::SELF, &instance, now, true, r#"foo: bar"#)
.await
.is_err()); // no json
assert!(t
.receive_status_update(
assert!(
t.receive_status_update(ContactId::SELF, &instance, now, true, r#"foo: bar"#)
.await
.is_err()
); // no json
assert!(
t.receive_status_update(
ContactId::SELF,
&instance,
now,
@@ -644,9 +651,10 @@ async fn test_receive_status_update() -> Result<()> {
r#"{"updada":[{"payload":{"foo":"bar"}}]}"#
)
.await
.is_err()); // "updates" object missing
assert!(t
.receive_status_update(
.is_err()
); // "updates" object missing
assert!(
t.receive_status_update(
ContactId::SELF,
&instance,
now,
@@ -654,9 +662,10 @@ async fn test_receive_status_update() -> Result<()> {
r#"{"updates":[{"foo":"bar"}]}"#
)
.await
.is_err()); // "payload" field missing
assert!(t
.receive_status_update(
.is_err()
); // "payload" field missing
assert!(
t.receive_status_update(
ContactId::SELF,
&instance,
now,
@@ -664,7 +673,8 @@ async fn test_receive_status_update() -> Result<()> {
r#"{"updates":{"payload":{"foo":"bar"}}}"#
)
.await
.is_err()); // not an array
.is_err()
); // not an array
t.receive_status_update(
ContactId::SELF,
@@ -1101,10 +1111,11 @@ async fn test_send_webxdc_status_update_to_non_webxdc() -> Result<()> {
let t = TestContext::new_alice().await;
let chat_id = create_group_chat(&t, ProtectionStatus::Unprotected, "foo").await?;
let msg_id = send_text_msg(&t, chat_id, "ho!".to_string()).await?;
assert!(t
.send_webxdc_status_update(msg_id, r#"{"foo":"bar"}"#)
.await
.is_err());
assert!(
t.send_webxdc_status_update(msg_id, r#"{"foo":"bar"}"#)
.await
.is_err()
);
Ok(())
}
@@ -1118,10 +1129,12 @@ async fn test_get_webxdc_blob() -> Result<()> {
assert_eq!(buf.len(), 188);
assert!(String::from_utf8_lossy(&buf).contains("document.write"));
assert!(instance
.get_webxdc_blob(&t, "not-existent.html")
.await
.is_err());
assert!(
instance
.get_webxdc_blob(&t, "not-existent.html")
.await
.is_err()
);
Ok(())
}