Compare commits

...
Author SHA1 Message Date
missytake e32437d5a4 changelog update 2022-11-20 22:42:03 +01:00
missytake 6a8f29f126 ran npm run build in deltachat-jsonrpc/typescript 2022-11-20 22:37:30 +01:00
missytake 62d56947ee introduce config option to enable manual encryption mode 2022-11-20 21:42:35 +01:00
Hocuri 960a7f82ef Small test fix (#3764)
Doesn't make a difference at this point, since the test is ignored
anyway.
2022-11-19 12:03:05 +01:00
iequidoo 25be8ccd05 fetch_new_messages(): fetch messages sequentially (#3688)
If we fetch messages out of order, then f.e. reactions don't work because if we process a reaction not yet having the corresponding message processed, the reaction is thrown away.
2022-11-17 15:51:59 -03:00
link2xt da6c68629d jsonrpc: do not return a result from deleteContact()
It was always true anyway.
2022-11-17 18:36:38 +00:00
link2xt b63baf939e Ignore two typescript errors
`as any` is not enough anymore.
2022-11-16 14:06:17 +00:00
11 changed files with 54 additions and 48 deletions
+4
View File
@@ -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
+1
View File
@@ -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),
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+3
View File
@@ -61,6 +61,9 @@ pub enum Config {
#[strum(props(default = "1"))]
E2eeEnabled,
#[strum(props(default = "0"))]
ManualEncryptionMode,
#[strum(props(default = "1"))]
MdnsEnabled,
+2
View File
@@ -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
View File
@@ -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 {