Merge remote-tracking branch 'origin/master' into feat/async-jobs

This commit is contained in:
dignifiedquire
2020-03-26 16:52:07 +01:00
10 changed files with 248 additions and 18 deletions

View File

@@ -412,9 +412,11 @@ async fn exec_step(
}
16 => {
progress!(ctx, 900);
let create_mvbox = ctx.get_config_bool(Config::MvboxWatch).await
|| ctx.get_config_bool(Config::MvboxMove).await;
if let Err(err) = imap.ensure_configured_folders(ctx, create_mvbox).await {
if let Err(err) = imap.configure_folders(ctx, create_mvbox).await {
bail!("configuring folders failed: {:?}", err);
}

View File

@@ -214,6 +214,9 @@ pub const DC_BOB_SUCCESS: i32 = 1;
// max. width/height of an avatar
pub const AVATAR_SIZE: u32 = 192;
// this value can be increased if the folder configuration is changed and must be redone on next program start
pub const DC_FOLDERS_CONFIGURED_VERSION: i32 = 3;
#[derive(
Debug,
Display,

View File

@@ -402,7 +402,11 @@ async fn add_parts(
let (new_chat_id, new_chat_id_blocked) = create_or_lookup_group(
context,
&mut mime_parser,
allow_creation,
if test_normal_chat_id.is_unset() {
allow_creation
} else {
true
},
create_blocked,
from_id,
to_ids,
@@ -1715,8 +1719,9 @@ fn dc_create_incoming_rfc724_mid(
#[cfg(test)]
mod tests {
use super::*;
use crate::chatlist::Chatlist;
use crate::message::Message;
use crate::test_utils::dummy_context;
use crate::test_utils::{dummy_context, TestContext};
#[test]
fn test_hex_hash() {
@@ -1811,4 +1816,179 @@ mod tests {
assert!(is_msgrmsg_rfc724_mid(&t.ctx, &msg.rfc724_mid).await);
assert!(!is_msgrmsg_rfc724_mid(&t.ctx, "nonexistant@message.id").await);
}
async fn configured_offline_context() -> TestContext {
let t = dummy_context().await;
t.ctx
.set_config(Config::Addr, Some("alice@example.org"))
.await
.unwrap();
t.ctx
.set_config(Config::ConfiguredAddr, Some("alice@example.org"))
.await
.unwrap();
t.ctx
.set_config(Config::Configured, Some("1"))
.await
.unwrap();
t
}
static MSGRMSG: &[u8] = b"From: Bob <bob@example.org>\n\
To: alice@example.org\n\
Chat-Version: 1.0\n\
Subject: Chat: hello\n\
Message-ID: <Mr.1111@example.org>\n\
Date: Sun, 22 Mar 2020 22:37:55 +0000\n\
\n\
hello\n";
static ONETOONE_NOREPLY_MAIL: &[u8] = b"From: Bob <bob@example.org>\n\
To: alice@example.org\n\
Subject: Chat: hello\n\
Message-ID: <2222@example.org>\n\
Date: Sun, 22 Mar 2020 22:37:56 +0000\n\
\n\
hello\n";
static GRP_MAIL: &[u8] = b"From: bob@example.org\n\
To: alice@example.org, claire@example.org\n\
Subject: group with Alice, Bob and Claire\n\
Message-ID: <3333@example.org>\n\
Date: Sun, 22 Mar 2020 22:37:57 +0000\n\
\n\
hello\n";
#[async_std::test]
async fn test_adhoc_group_show_chats_only() {
let t = configured_offline_context().await;
assert_eq!(t.ctx.get_config_int(Config::ShowEmails).await, 0);
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 0);
dc_receive_imf(&t.ctx, MSGRMSG, "INBOX", 1, false)
.await
.unwrap();
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 1);
dc_receive_imf(&t.ctx, ONETOONE_NOREPLY_MAIL, "INBOX", 1, false)
.await
.unwrap();
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 1);
dc_receive_imf(&t.ctx, GRP_MAIL, "INBOX", 1, false)
.await
.unwrap();
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 1);
}
#[async_std::test]
async fn test_adhoc_group_show_accepted_contact_unknown() {
let t = configured_offline_context().await;
t.ctx
.set_config(Config::ShowEmails, Some("1"))
.await
.unwrap();
dc_receive_imf(&t.ctx, GRP_MAIL, "INBOX", 1, false)
.await
.unwrap();
// adhoc-group with unknown contacts with show_emails=accepted is ignored for unknown contacts
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 0);
}
#[async_std::test]
async fn test_adhoc_group_show_accepted_contact_known() {
let t = configured_offline_context().await;
t.ctx
.set_config(Config::ShowEmails, Some("1"))
.await
.unwrap();
Contact::create(&t.ctx, "Bob", "bob@example.org")
.await
.unwrap();
dc_receive_imf(&t.ctx, GRP_MAIL, "INBOX", 1, false)
.await
.unwrap();
// adhoc-group with known contacts with show_emails=accepted is still ignored for known contacts
// (and existent chat is required)
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 0);
}
#[async_std::test]
async fn test_adhoc_group_show_accepted_contact_accepted() {
let t = configured_offline_context().await;
t.ctx
.set_config(Config::ShowEmails, Some("1"))
.await
.unwrap();
// accept Bob by accepting a delta-message from Bob
dc_receive_imf(&t.ctx, MSGRMSG, "INBOX", 1, false)
.await
.unwrap();
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 1);
assert!(chats.get_chat_id(0).is_deaddrop());
let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap())
.await
.unwrap();
assert!(!chat_id.is_special());
let chat = chat::Chat::load_from_db(&t.ctx, chat_id).await.unwrap();
assert_eq!(chat.typ, Chattype::Single);
assert_eq!(chat.name, "Bob");
assert_eq!(chat::get_chat_contacts(&t.ctx, chat_id).await.len(), 1);
assert_eq!(chat::get_chat_msgs(&t.ctx, chat_id, 0, None).await.len(), 1);
// receive a non-delta-message from Bob, shows up because of the show_emails setting
dc_receive_imf(&t.ctx, ONETOONE_NOREPLY_MAIL, "INBOX", 2, false)
.await
.unwrap();
assert_eq!(chat::get_chat_msgs(&t.ctx, chat_id, 0, None).await.len(), 2);
// let Bob create an adhoc-group by a non-delta-message, shows up because of the show_emails setting
dc_receive_imf(&t.ctx, GRP_MAIL, "INBOX", 3, false)
.await
.unwrap();
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 2);
let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap())
.await
.unwrap();
let chat = chat::Chat::load_from_db(&t.ctx, chat_id).await.unwrap();
assert_eq!(chat.typ, Chattype::Group);
assert_eq!(chat.name, "group with Alice, Bob and Claire");
assert_eq!(chat::get_chat_contacts(&t.ctx, chat_id).await.len(), 3);
}
#[async_std::test]
async fn test_adhoc_group_show_all() {
let t = configured_offline_context().await;
t.ctx
.set_config(Config::ShowEmails, Some("2"))
.await
.unwrap();
dc_receive_imf(&t.ctx, GRP_MAIL, "INBOX", 1, false)
.await
.unwrap();
// adhoc-group with unknown contacts with show_emails=all will show up in the deaddrop
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 1);
assert!(chats.get_chat_id(0).is_deaddrop());
let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap())
.await
.unwrap();
let chat = chat::Chat::load_from_db(&t.ctx, chat_id).await.unwrap();
assert_eq!(chat.typ, Chattype::Group);
assert_eq!(chat.name, "group with Alice, Bob and Claire");
assert_eq!(chat::get_chat_contacts(&t.ctx, chat_id).await.len(), 3);
}
}

View File

@@ -187,7 +187,6 @@ struct ImapConfig {
/// True if the server has MOVE capability as defined in
/// https://tools.ietf.org/html/rfc6851
pub can_move: bool,
pub imap_delimiter: char,
}
impl Default for ImapConfig {
@@ -205,7 +204,6 @@ impl Default for ImapConfig {
selected_folder_needs_expunge: false,
can_idle: false,
can_move: false,
imap_delimiter: '.',
}
}
}
@@ -1111,17 +1109,17 @@ impl Imap {
.sql
.get_raw_config_int(context, "folders_configured")
.await;
if folders_configured.unwrap_or_default() >= 3 {
info!(context, "IMAP-folders already configured");
// the "3" here we increase if we have future updates to
// to folder configuration
if folders_configured.unwrap_or_default() >= DC_FOLDERS_CONFIGURED_VERSION {
return Ok(());
}
self.configure_folders(context, create_mvbox).await
}
pub async fn configure_folders(&mut self, context: &Context, create_mvbox: bool) -> Result<()> {
if !self.is_connected() {
return Err(Error::NoConnection);
}
info!(context, "Configuring IMAP-folders.");
if let Some(ref mut session) = &mut self.session {
let mut folders = match session.list(Some(""), Some("*")).await {
@@ -1133,7 +1131,17 @@ impl Imap {
let mut sentbox_folder = None;
let mut mvbox_folder = None;
let delimiter = self.config.imap_delimiter;
let mut delimiter = ".".to_string();
if let Some(folder) = folders.next().await {
let folder = folder.map_err(|err| Error::Other(err.to_string()))?;
if let Some(d) = folder.delimiter() {
if !d.is_empty() {
delimiter = d.to_string();
}
}
}
info!(context, "Using \"{}\" as folder-delimiter.", delimiter);
let fallback_folder = format!("INBOX{}DeltaChat", delimiter);
while let Some(folder) = folders.next().await {
@@ -1221,9 +1229,14 @@ impl Imap {
}
context
.sql
.set_raw_config_int(context, "folders_configured", 3)
.set_raw_config_int(context, "folders_configured", DC_FOLDERS_CONFIGURED_VERSION)
.await?;
}
context
.sql
.set_raw_config_int(context, "folders_configured", 3)
.await?;
info!(context, "FINISHED configuring IMAP-folders.");
Ok(())
}

View File

@@ -408,7 +408,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
self.from_addr.clone(),
);
let mut to = Vec::with_capacity(self.recipients.len());
let mut to = Vec::new();
for (name, addr) in self.recipients.iter() {
if name.is_empty() {
to.push(Address::new_mailbox(addr.clone()));
@@ -420,6 +420,10 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
}
}
if to.is_empty() {
to.push(from.clone());
}
if !self.references.is_empty() {
unprotected_headers.push(Header::new("References".into(), self.references.clone()));
}