mirror of
https://github.com/chatmail/core.git
synced 2026-10-18 02:43:02 +03:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e32437d5a4 | ||
|
|
6a8f29f126 | ||
|
|
62d56947ee | ||
|
|
960a7f82ef | ||
|
|
25be8ccd05 | ||
|
|
da6c68629d | ||
|
|
b63baf939e |
@@ -2,12 +2,16 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
- new config option for "manual encryption mode"
|
||||
|
||||
### Changes
|
||||
|
||||
### API-Changes
|
||||
|
||||
### Fixes
|
||||
- fix detection of "All mail", "Trash", "Junk" etc folders. #3760
|
||||
- fetch messages sequentially to fix reactions on partially downloaded messages #3688
|
||||
|
||||
|
||||
## 1.101.0
|
||||
|
||||
@@ -332,6 +332,7 @@ char* dc_get_blobdir (const dc_context_t* context);
|
||||
* To save traffic, however, the avatar is attached only as needed
|
||||
* and also recoded to a reasonable size.
|
||||
* - `e2ee_enabled` = 0=no end-to-end-encryption, 1=prefer end-to-end-encryption (default)
|
||||
* - `manual_encryption_mode` = 0=autocrypt mode (default), 1=choose encryption mode manually per chat
|
||||
* - `mdns_enabled` = 0=do not send or request read receipts,
|
||||
* 1=send and request read receipts (default)
|
||||
* - `bcc_self` = 0=do not send a copy of outgoing messages to self (default),
|
||||
|
||||
@@ -1146,12 +1146,12 @@ impl CommandApi {
|
||||
Ok(contacts)
|
||||
}
|
||||
|
||||
async fn delete_contact(&self, account_id: u32, contact_id: u32) -> Result<bool> {
|
||||
async fn delete_contact(&self, account_id: u32, contact_id: u32) -> Result<()> {
|
||||
let ctx = self.get_context(account_id).await?;
|
||||
let contact_id = ContactId::new(contact_id);
|
||||
|
||||
Contact::delete(&ctx, contact_id).await?;
|
||||
Ok(true)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn change_contact_name(
|
||||
|
||||
@@ -730,8 +730,8 @@ export class RawClient {
|
||||
}
|
||||
|
||||
|
||||
public deleteContact(accountId: T.U32, contactId: T.U32): Promise<boolean> {
|
||||
return (this._transport.request('delete_contact', [accountId, contactId] as RPC.Params)) as Promise<boolean>;
|
||||
public deleteContact(accountId: T.U32, contactId: T.U32): Promise<null> {
|
||||
return (this._transport.request('delete_contact', [accountId, contactId] as RPC.Params)) as Promise<null>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -195,4 +195,4 @@ export type MessageNotificationInfo={"id":U32;"chatId":U32;"accountId":U32;"imag
|
||||
export type MessageSearchResult={"id":U32;"authorProfileImage":(string|null);"authorName":string;"authorColor":string;"chatName":(string|null);"message":string;"timestamp":I64;};
|
||||
export type F64=number;
|
||||
export type Location={"locationId":U32;"isIndependent":boolean;"latitude":F64;"longitude":F64;"accuracy":F64;"timestamp":I64;"contactId":U32;"msgId":U32;"chatId":U32;"marker":(string|null);};
|
||||
export type __AllTyps=[string,boolean,Record<string,string>,U32,U32,null,(U32)[],U32,null,(U32|null),(Account)[],null,null,U32,null,U32,null,U32,Account,U32,U64,U32,string,(ProviderInfo|null),U32,boolean,U32,Record<string,string>,U32,string,(string|null),null,U32,Record<string,(string|null)>,null,U32,string,null,U32,string,Qr,U32,string,(string|null),U32,(string)[],Record<string,(string|null)>,Record<U32,string>,null,U32,null,U32,null,U32,string,(string|null),null,U32,string,(string|null),null,U32,(U32)[],U32,U32,Usize,U32,boolean,I64,Usize,U32,string,U32,U32,string,null,U32,(U32|null),(string|null),(U32|null),(ChatListEntry)[],U32,(ChatListEntry)[],Record<U32,ChatListItemFetchResult>,U32,U32,FullChat,U32,U32,BasicChat,U32,U32,null,U32,U32,null,U32,U32,null,U32,U32,string,U32,(U32|null),[string,string],U32,string,U32,U32,U32,null,U32,U32,U32,null,U32,U32,U32,null,U32,U32,(U32)[],U32,string,boolean,U32,U32,U32,U32,U32,string,null,U32,U32,(string|null),null,U32,U32,ChatVisibility,null,U32,U32,U32,null,U32,U32,U32,U32,string,string,U32,U32,U32,null,U32,U32,(U32|null),U32,U32,MuteDuration,null,U32,U32,boolean,U32,(U32)[],null,U32,U32,U32,(U32)[],U32,U32,U32,(MessageListItem)[],U32,U32,Message,U32,U32,(string|null),U32,(U32)[],Record<U32,Message>,U32,U32,MessageNotificationInfo,U32,(U32)[],null,U32,U32,string,U32,U32,null,U32,string,(U32|null),(U32)[],U32,(U32)[],Record<U32,MessageSearchResult>,U32,U32,Contact,U32,string,(string|null),U32,U32,U32,U32,U32,U32,null,U32,U32,null,U32,(Contact)[],U32,U32,(string|null),(U32)[],U32,U32,(string|null),(Contact)[],U32,(U32)[],Record<U32,Contact>,U32,U32,boolean,U32,U32,string,null,U32,U32,string,U32,string,(U32|null),U32,(U32|null),Viewtype,(Viewtype|null),(Viewtype|null),(U32)[],U32,U32,Viewtype,(Viewtype|null),(Viewtype|null),[(U32|null),(U32|null)],U32,string,(string|null),null,U32,string,(string|null),null,null,U32,U32,U32,string,U32,(U32|null),(U32|null),I64,I64,(Location)[],U32,U32,string,string,null,U32,U32,U32,string,U32,U32,WebxdcMessageInfo,U32,(U32)[],U32,null,U32,U32,string,U32,U32,U32,(string)[],U32,U32,U32,null,U32,U32,(Message|null),U32,U32,U32,U32,string,U32,U32,string,null,U32,Record<string,(string)[]>,U32,U32,string,U32,U32,U32,(string|null),(string|null),([F64,F64]|null),(U32|null),[U32,Message],U32,U32,(string|null),(string|null),(U32|null),null];
|
||||
export type __AllTyps=[string,boolean,Record<string,string>,U32,U32,null,(U32)[],U32,null,(U32|null),(Account)[],null,null,U32,null,U32,null,U32,Account,U32,U64,U32,string,(ProviderInfo|null),U32,boolean,U32,Record<string,string>,U32,string,(string|null),null,U32,Record<string,(string|null)>,null,U32,string,null,U32,string,Qr,U32,string,(string|null),U32,(string)[],Record<string,(string|null)>,Record<U32,string>,null,U32,null,U32,null,U32,string,(string|null),null,U32,string,(string|null),null,U32,(U32)[],U32,U32,Usize,U32,boolean,I64,Usize,U32,string,U32,U32,string,null,U32,(U32|null),(string|null),(U32|null),(ChatListEntry)[],U32,(ChatListEntry)[],Record<U32,ChatListItemFetchResult>,U32,U32,FullChat,U32,U32,BasicChat,U32,U32,null,U32,U32,null,U32,U32,null,U32,U32,string,U32,(U32|null),[string,string],U32,string,U32,U32,U32,null,U32,U32,U32,null,U32,U32,U32,null,U32,U32,(U32)[],U32,string,boolean,U32,U32,U32,U32,U32,string,null,U32,U32,(string|null),null,U32,U32,ChatVisibility,null,U32,U32,U32,null,U32,U32,U32,U32,string,string,U32,U32,U32,null,U32,U32,(U32|null),U32,U32,MuteDuration,null,U32,U32,boolean,U32,(U32)[],null,U32,U32,U32,(U32)[],U32,U32,U32,(MessageListItem)[],U32,U32,Message,U32,U32,(string|null),U32,(U32)[],Record<U32,Message>,U32,U32,MessageNotificationInfo,U32,(U32)[],null,U32,U32,string,U32,U32,null,U32,string,(U32|null),(U32)[],U32,(U32)[],Record<U32,MessageSearchResult>,U32,U32,Contact,U32,string,(string|null),U32,U32,U32,U32,U32,U32,null,U32,U32,null,U32,(Contact)[],U32,U32,(string|null),(U32)[],U32,U32,(string|null),(Contact)[],U32,(U32)[],Record<U32,Contact>,U32,U32,null,U32,U32,string,null,U32,U32,string,U32,string,(U32|null),U32,(U32|null),Viewtype,(Viewtype|null),(Viewtype|null),(U32)[],U32,U32,Viewtype,(Viewtype|null),(Viewtype|null),[(U32|null),(U32|null)],U32,string,(string|null),null,U32,string,(string|null),null,null,U32,U32,U32,string,U32,(U32|null),(U32|null),I64,I64,(Location)[],U32,U32,string,string,null,U32,U32,U32,string,U32,U32,WebxdcMessageInfo,U32,(U32)[],U32,null,U32,U32,string,U32,U32,U32,(string)[],U32,U32,U32,null,U32,U32,(Message|null),U32,U32,U32,U32,string,U32,U32,string,null,U32,Record<string,(string)[]>,U32,U32,string,U32,U32,U32,(string|null),(string|null),([F64,F64]|null),(U32|null),[U32,Message],U32,U32,(string|null),(string|null),(U32|null),null];
|
||||
|
||||
@@ -43,12 +43,14 @@ export class BaseDeltaChat<
|
||||
const method = request.method;
|
||||
if (method === "event") {
|
||||
const event = request.params! as DCWireEvent<Event>;
|
||||
//@ts-ignore
|
||||
this.emit(event.event.type, event.contextId, event.event as any);
|
||||
this.emit("ALL", event.contextId, event.event as any);
|
||||
|
||||
if (this.contextEmitters[event.contextId]) {
|
||||
this.contextEmitters[event.contextId].emit(
|
||||
event.event.type,
|
||||
//@ts-ignore
|
||||
event.event as any
|
||||
);
|
||||
this.contextEmitters[event.contextId].emit("ALL", event.event);
|
||||
|
||||
+1
-1
@@ -616,7 +616,7 @@ describe('Offline Tests with unconfigured account', function () {
|
||||
const id = context.createContact('someuser', 'someuser@site.com')
|
||||
const contact = context.getContact(id)
|
||||
strictEqual(contact.getId(), id, 'contact id matches')
|
||||
strictEqual(context.deleteContact(id), true, 'delete call succesful')
|
||||
context.deleteContact(id)
|
||||
strictEqual(context.getContact(id), null, 'contact is gone')
|
||||
})
|
||||
|
||||
|
||||
+2
-2
@@ -681,7 +681,7 @@ Authentication-Results: box.hispanilandia.net; spf=pass smtp.mailfrom=adbenitez@
|
||||
.await;
|
||||
|
||||
sent.payload
|
||||
.insert_str(0, "Authentication-Results: example.org; dkim=fail");
|
||||
.insert_str(0, "Authentication-Results: example.org; dkim=fail\n");
|
||||
|
||||
let received = alice.recv_msg(&sent).await;
|
||||
|
||||
@@ -717,7 +717,7 @@ Authentication-Results: box.hispanilandia.net; spf=pass smtp.mailfrom=adbenitez@
|
||||
loop {
|
||||
if let Some(mut sent) = bob2.pop_sent_msg_opt(Duration::ZERO).await {
|
||||
sent.payload
|
||||
.insert_str(0, "Authentication-Results: example.org; dkim=fail");
|
||||
.insert_str(0, "Authentication-Results: example.org; dkim=fail\n");
|
||||
alice.recv_msg(&sent).await;
|
||||
} else if let Some(sent) = alice.pop_sent_msg_opt(Duration::ZERO).await {
|
||||
bob2.recv_msg(&sent).await;
|
||||
|
||||
@@ -61,6 +61,9 @@ pub enum Config {
|
||||
#[strum(props(default = "1"))]
|
||||
E2eeEnabled,
|
||||
|
||||
#[strum(props(default = "0"))]
|
||||
ManualEncryptionMode,
|
||||
|
||||
#[strum(props(default = "1"))]
|
||||
MdnsEnabled,
|
||||
|
||||
|
||||
@@ -543,6 +543,7 @@ impl Context {
|
||||
.await?
|
||||
.unwrap_or_else(|| "unknown".to_string());
|
||||
let e2ee_enabled = self.get_config_int(Config::E2eeEnabled).await?;
|
||||
let manual_encryption_mode = self.get_config_int(Config::ManualEncryptionMode).await?;
|
||||
let mdns_enabled = self.get_config_int(Config::MdnsEnabled).await?;
|
||||
let bcc_self = self.get_config_int(Config::BccSelf).await?;
|
||||
let send_sync_msgs = self.get_config_int(Config::SendSyncMsgs).await?;
|
||||
@@ -650,6 +651,7 @@ impl Context {
|
||||
res.insert("configured_mvbox_folder", configured_mvbox_folder);
|
||||
res.insert("mdns_enabled", mdns_enabled.to_string());
|
||||
res.insert("e2ee_enabled", e2ee_enabled.to_string());
|
||||
res.insert("manual_encryption_mode", manual_encryption_mode.to_string());
|
||||
res.insert(
|
||||
"key_gen_type",
|
||||
self.get_config_int(Config::KeyGenType).await?.to_string(),
|
||||
|
||||
+34
-40
@@ -780,8 +780,7 @@ impl Imap {
|
||||
let show_emails = ShowEmails::from_i32(context.get_config_int(Config::ShowEmails).await?)
|
||||
.unwrap_or_default();
|
||||
let download_limit = context.download_limit().await?;
|
||||
let mut uids_fetch_fully = Vec::with_capacity(msgs.len());
|
||||
let mut uids_fetch_partially = Vec::with_capacity(msgs.len());
|
||||
let mut uids_fetch = Vec::<(_, bool /* partially? */)>::with_capacity(msgs.len() + 1);
|
||||
let mut uid_message_ids = BTreeMap::new();
|
||||
let mut largest_uid_skipped = None;
|
||||
|
||||
@@ -840,14 +839,11 @@ impl Imap {
|
||||
.await?
|
||||
{
|
||||
match download_limit {
|
||||
Some(download_limit) => {
|
||||
if fetch_response.size.unwrap_or_default() > download_limit {
|
||||
uids_fetch_partially.push(uid);
|
||||
} else {
|
||||
uids_fetch_fully.push(uid)
|
||||
}
|
||||
}
|
||||
None => uids_fetch_fully.push(uid),
|
||||
Some(download_limit) => uids_fetch.push((
|
||||
uid,
|
||||
fetch_response.size.unwrap_or_default() > download_limit,
|
||||
)),
|
||||
None => uids_fetch.push((uid, false)),
|
||||
}
|
||||
uid_message_ids.insert(uid, message_id);
|
||||
} else {
|
||||
@@ -855,33 +851,37 @@ impl Imap {
|
||||
}
|
||||
}
|
||||
|
||||
if !uids_fetch_fully.is_empty() || !uids_fetch_partially.is_empty() {
|
||||
if !uids_fetch.is_empty() {
|
||||
self.connectivity.set_working(context).await;
|
||||
}
|
||||
|
||||
// Actually download messages.
|
||||
let (largest_uid_fully_fetched, mut received_msgs) = self
|
||||
.fetch_many_msgs(
|
||||
context,
|
||||
folder,
|
||||
uids_fetch_fully,
|
||||
&uid_message_ids,
|
||||
false,
|
||||
fetch_existing_msgs,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let (largest_uid_partially_fetched, received_msgs_2) = self
|
||||
.fetch_many_msgs(
|
||||
context,
|
||||
folder,
|
||||
uids_fetch_partially,
|
||||
&uid_message_ids,
|
||||
true,
|
||||
fetch_existing_msgs,
|
||||
)
|
||||
.await?;
|
||||
received_msgs.extend(received_msgs_2);
|
||||
let mut largest_uid_fetched: u32 = 0;
|
||||
let mut received_msgs = Vec::with_capacity(uids_fetch.len());
|
||||
let mut uids_fetch_in_batch = Vec::with_capacity(max(uids_fetch.len(), 1));
|
||||
let mut fetch_partially = false;
|
||||
uids_fetch.push((0, !uids_fetch.last().unwrap_or(&(0, false)).1));
|
||||
for (uid, fp) in uids_fetch {
|
||||
if fp != fetch_partially {
|
||||
let (largest_uid_fetched_in_batch, received_msgs_in_batch) = self
|
||||
.fetch_many_msgs(
|
||||
context,
|
||||
folder,
|
||||
uids_fetch_in_batch.split_off(0),
|
||||
&uid_message_ids,
|
||||
fetch_partially,
|
||||
fetch_existing_msgs,
|
||||
)
|
||||
.await?;
|
||||
received_msgs.extend(received_msgs_in_batch);
|
||||
largest_uid_fetched = max(
|
||||
largest_uid_fetched,
|
||||
largest_uid_fetched_in_batch.unwrap_or(0),
|
||||
);
|
||||
fetch_partially = fp;
|
||||
}
|
||||
uids_fetch_in_batch.push(uid);
|
||||
}
|
||||
|
||||
// determine which uid_next to use to update to
|
||||
// receive_imf() returns an `Err` value only on recoverable errors, otherwise it just logs an error.
|
||||
@@ -889,13 +889,7 @@ impl Imap {
|
||||
|
||||
// So: Update the uid_next to the largest uid that did NOT recoverably fail. Not perfect because if there was
|
||||
// another message afterwards that succeeded, we will not retry. The upside is that we will not retry an infinite amount of times.
|
||||
let largest_uid_without_errors = max(
|
||||
max(
|
||||
largest_uid_fully_fetched.unwrap_or(0),
|
||||
largest_uid_partially_fetched.unwrap_or(0),
|
||||
),
|
||||
largest_uid_skipped.unwrap_or(0),
|
||||
);
|
||||
let largest_uid_without_errors = max(largest_uid_fetched, largest_uid_skipped.unwrap_or(0));
|
||||
let new_uid_next = largest_uid_without_errors + 1;
|
||||
|
||||
if new_uid_next > old_uid_next {
|
||||
|
||||
Reference in New Issue
Block a user