Compare commits

..

1 Commits

Author SHA1 Message Date
Alexander Krotov
90255bda68 Do not interrupt inbox when a moved message is detected
Interrupting inbox task causes fetch on the inbox. There is nothing to
fetch on the inbox when a message was just moved to movebox, possibly
by another device.
2020-06-16 00:17:38 +03:00
16 changed files with 134 additions and 494 deletions

View File

@@ -1,27 +1,5 @@
# Changelog
## 1.36.0
- parse ndn (network delivery notification) reports
and report faild messages as such #1552 #1622 #1630
- read image orientation from exif before recoding #1619
- improve logging #1593 #1598
- improve python and bot bindings #1583 #1609
- improve imap logout #1595
- fix sorting #1600 #1604
- fix qr code generation #1631
- update rustcrypto releases #1603
- refactorings #1617
## 1.35.0
- enable strict-tls from a new provider-db setting #1587

211
Cargo.lock generated
View File

@@ -11,9 +11,9 @@ dependencies = [
[[package]]
name = "adler32"
version = "1.1.0"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d"
checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
[[package]]
name = "aead"
@@ -187,7 +187,7 @@ checksum = "2a397614997df8e3a8b81ff8d882c0fdc100568d3162fadbd1b1410f95c40277"
dependencies = [
"async-native-tls",
"async-std",
"base64 0.12.2",
"base64 0.12.1",
"byte-pool",
"chrono",
"futures 0.3.5",
@@ -215,17 +215,17 @@ dependencies = [
[[package]]
name = "async-smtp"
version = "0.3.2"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9720181a7d56bf3b4d0cfdcb6353df975125996bdd2958b4e639c8317fcaa68"
checksum = "81598a96675097ba5df18eec536a0c1d669244aeb4170f2dfa5ef12e1b2ee4b1"
dependencies = [
"async-native-tls",
"async-std",
"async-trait",
"base64 0.12.2",
"base64 0.12.1",
"bufstream",
"fast_chemail",
"hostname 0.1.5",
"hostname",
"log",
"nom 5.1.2",
"pin-project",
@@ -261,18 +261,6 @@ dependencies = [
"wasm-bindgen-futures",
]
[[package]]
name = "async-std-resolver"
version = "0.19.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d113439234775ae3e43d4e7589c5cc64fa3565996ae82dfe26b4ed78c02165be"
dependencies = [
"async-std",
"async-trait",
"futures 0.3.5",
"trust-dns-resolver",
]
[[package]]
name = "async-task"
version = "3.0.0"
@@ -315,14 +303,13 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]]
name = "backtrace"
version = "0.3.49"
version = "0.3.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05100821de9e028f12ae3d189176b41ee198341eb8f369956407fea2f5cc666c"
checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130"
dependencies = [
"addr2line",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
@@ -350,9 +337,9 @@ checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
[[package]]
name = "base64"
version = "0.12.2"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e223af0dc48c96d4f8342ec01a4974f139df863896b316681efd36742f22cc67"
checksum = "53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42"
[[package]]
name = "bit-set"
@@ -646,7 +633,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca761767cf3fa9068cc893ec8c247a22d0fd0535848e65640c0548bd1f8bbb36"
dependencies = [
"aes-gcm",
"base64 0.12.2",
"base64 0.12.1",
"hkdf",
"hmac",
"percent-encoding",
@@ -814,7 +801,7 @@ dependencies = [
[[package]]
name = "deltachat"
version = "1.36.0"
version = "1.35.0"
dependencies = [
"ansi_term 0.12.1",
"anyhow",
@@ -822,10 +809,9 @@ dependencies = [
"async-native-tls",
"async-smtp",
"async-std",
"async-std-resolver",
"async-trait",
"backtrace",
"base64 0.12.2",
"base64 0.12.1",
"bitflags",
"byteorder",
"charset",
@@ -886,7 +872,7 @@ dependencies = [
[[package]]
name = "deltachat_ffi"
version = "1.36.0"
version = "1.35.0"
dependencies = [
"anyhow",
"async-std",
@@ -1107,18 +1093,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca"
[[package]]
name = "enum-as-inner"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc4bfcfacb61d231109d1d55202c1f33263319668b168843e02ad4652725ec9c"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "env_logger"
version = "0.7.1"
@@ -1415,9 +1389,9 @@ dependencies = [
[[package]]
name = "hermit-abi"
version = "0.1.14"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
dependencies = [
"libc",
]
@@ -1458,17 +1432,6 @@ dependencies = [
"winutil",
]
[[package]]
name = "hostname"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
dependencies = [
"libc",
"match_cfg",
"winapi",
]
[[package]]
name = "http-client"
version = "3.0.0"
@@ -1606,6 +1569,15 @@ dependencies = [
"byteorder",
]
[[package]]
name = "inflate"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"
dependencies = [
"adler32",
]
[[package]]
name = "iovec"
version = "0.1.4"
@@ -1615,18 +1587,6 @@ dependencies = [
"libc",
]
[[package]]
name = "ipconfig"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7"
dependencies = [
"socket2",
"widestring",
"winapi",
"winreg",
]
[[package]]
name = "itertools"
version = "0.8.2"
@@ -1803,12 +1763,6 @@ dependencies = [
"quoted_printable",
]
[[package]]
name = "match_cfg"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
[[package]]
name = "matches"
version = "0.1.8"
@@ -2024,9 +1978,9 @@ dependencies = [
[[package]]
name = "object"
version = "0.20.0"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2"
[[package]]
name = "once_cell"
@@ -2140,7 +2094,7 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59698ea79df9bf77104aefd39cc3ec990cb9693fb59c3b0a70ddf2646fdffb4b"
dependencies = [
"base64 0.12.2",
"base64 0.12.1",
"once_cell",
"regex",
]
@@ -2158,7 +2112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d3fd4e0b2b7a8195b22e196a947c9ceb0d0f722d060e38e0641f48f56e195b"
dependencies = [
"aes 0.4.0",
"base64 0.12.2",
"base64 0.12.1",
"bitfield",
"block-modes",
"block-padding 0.2.0",
@@ -2201,18 +2155,18 @@ dependencies = [
[[package]]
name = "pin-project"
version = "0.4.22"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12e3a6cdbfe94a5e4572812a0201f8c0ed98c1c452c7b8563ce2276988ef9c17"
checksum = "e75373ff9037d112bb19bc61333a06a159eaeb217660dcfbea7d88e1db823919"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "0.4.22"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a0ffd45cf79d88737d7cc85bfd5d2894bee1139b356e616fe85dc389c61aaf7"
checksum = "10b4b44893d3c370407a1d6a5cfde7c41ae0478e31c516c85f67eb3adc51be6d"
dependencies = [
"proc-macro2",
"quote",
@@ -2251,14 +2205,14 @@ checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
[[package]]
name = "png"
version = "0.16.5"
version = "0.16.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ccdd66f6fe4b2433b07e4728e9a013e43233120427046e93ceb709c3a439bf"
checksum = "12faa637ed9ae3d3c881332e54b5ae2dba81cda9fc4bbce0faa1ba53abcead50"
dependencies = [
"bitflags",
"crc32fast",
"deflate",
"miniz_oxide",
"inflate",
]
[[package]]
@@ -2307,9 +2261,9 @@ checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4"
[[package]]
name = "proc-macro-nested"
version = "0.1.6"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
checksum = "0afe1bd463b9e9ed51d0e0f0b50b6b146aec855c56fd182bb242388710a9b6de"
[[package]]
name = "proc-macro2"
@@ -2525,9 +2479,9 @@ checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
dependencies = [
"winapi",
]
@@ -2553,16 +2507,6 @@ dependencies = [
"syn",
]
[[package]]
name = "resolv-conf"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11834e137f3b14e309437a8276714eed3a80d1ef894869e510f2c0c0b98b9f4a"
dependencies = [
"hostname 0.3.1",
"quick-error",
]
[[package]]
name = "ripemd160"
version = "0.9.0"
@@ -2777,18 +2721,18 @@ checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0"
[[package]]
name = "serde"
version = "1.0.112"
version = "1.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "736aac72d1eafe8e5962d1d1c3d99b0df526015ba40915cb3c49d042e92ec243"
checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.112"
version = "1.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf0343ce212ac0d3d6afd9391ac8e9c9efe06b533c8d33f660f6390cc4093f57"
checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250"
dependencies = [
"proc-macro2",
"quote",
@@ -2914,9 +2858,9 @@ checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4"
[[package]]
name = "smol"
version = "0.1.12"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afcf8beb4aa23cc616e3351e49585153b462637c8fec929163b54d88e522b3b0"
checksum = "845f5e7db6b614a8f4f59e565c3035f0fab2f71c9537ff0119eddb60d866cae3"
dependencies = [
"async-task",
"crossbeam-deque",
@@ -3154,18 +3098,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.20"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08"
checksum = "b13f926965ad00595dd129fa12823b04bbf866e9085ab0a5f2b05b850fbfc344"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.20"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793"
checksum = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479"
dependencies = [
"proc-macro2",
"quote",
@@ -3249,44 +3193,6 @@ dependencies = [
"serde",
]
[[package]]
name = "trust-dns-proto"
version = "0.19.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdd7061ba6f4d4d9721afedffbfd403f20f39a4301fee1b70d6fcd09cca69f28"
dependencies = [
"async-trait",
"backtrace",
"enum-as-inner",
"futures 0.3.5",
"idna",
"lazy_static",
"log",
"rand 0.7.3",
"smallvec",
"thiserror",
"url",
]
[[package]]
name = "trust-dns-resolver"
version = "0.19.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f23cdfdc3d8300b3c50c9e84302d3bd6d860fb9529af84ace6cf9665f181b77"
dependencies = [
"backtrace",
"cfg-if",
"futures 0.3.5",
"ipconfig",
"lazy_static",
"log",
"lru-cache",
"resolv-conf",
"smallvec",
"thiserror",
"trust-dns-proto",
]
[[package]]
name = "try_from"
version = "0.3.2"
@@ -3539,12 +3445,6 @@ dependencies = [
"cc",
]
[[package]]
name = "widestring"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a763e303c0e0f23b0da40888724762e802a8ffefbc22de4127ef42493c2ea68c"
[[package]]
name = "winapi"
version = "0.3.8"
@@ -3576,15 +3476,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "winreg"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
dependencies = [
"winapi",
]
[[package]]
name = "winutil"
version = "0.1.1"

View File

@@ -1,12 +1,12 @@
[package]
name = "deltachat"
version = "1.36.0"
version = "1.35.0"
authors = ["Delta Chat Developers (ML) <delta@codespeak.net>"]
edition = "2018"
license = "MPL-2.0"
[profile.release]
lto = true
# lto = true
[dependencies]
deltachat_derive = { path = "./deltachat_derive" }
@@ -59,7 +59,6 @@ thiserror = "1.0.14"
anyhow = "1.0.28"
async-trait = "0.1.31"
url = "2.1.1"
async-std-resolver = "0.19.5"
pretty_env_logger = { version = "0.4.0", optional = true }
log = {version = "0.4.8", optional = true }

View File

@@ -1,6 +1,6 @@
[package]
name = "deltachat_ffi"
version = "1.36.0"
version = "1.35.0"
description = "Deltachat FFI"
authors = ["Delta Chat Developers (ML) <delta@codespeak.net>"]
edition = "2018"

View File

@@ -307,9 +307,9 @@ char* dc_get_blobdir (const dc_context_t* context);
* DC_MEDIA_QUALITY_WORSE (1)
* allow worse images/videos/voice quality to gain smaller sizes,
* suitable for providers or areas known to have a bad connection.
* The library uses the `media_quality` setting to use different defaults
* for recoding images sent with type DC_MSG_IMAGE.
* If needed, recoding other file types is up to the UI.
* In contrast to other options, the implementation of this option is currently up to the UIs;
* this may change in future, however,
* having the option in the core allows provider-specific-defaults already today.
*
* If you want to retrieve a value, use dc_get_config().
*
@@ -528,20 +528,9 @@ int dc_is_io_running(const dc_context_t* context);
void dc_stop_io(dc_context_t* context);
/**
* This function should be called when there is a hint
* that the network is available again,
* eg. as a response to system event reporting network availability.
* The library will try to send pending messages out immediately.
*
* Moreover, to have a reliable state
* when the app comes to foreground with network available,
* it may be reasonable to call the function also at that moment.
*
* It is okay to call the function unconditionally when there is
* network available, however, calling the function
* _without_ having network may interfere with the backoff algorithm
* and will led to let the jobs fail faster, with fewer retries
* and may avoid messages being sent out.
* This function can be called whenever there is a hint
* that the network is available again.
* The library will try to send pending messages out.
*
* @memberof dc_context_t
* @param context The context as created by dc_context_new().
@@ -765,15 +754,6 @@ uint32_t dc_prepare_msg (dc_context_t* context, uint32_t ch
* dc_msg_unref(msg);
* ~~~
*
* If you send images with the DC_MSG_IMAGE type,
* they will be recoded to a reasonable size before sending, if possible
* (cmp the dc_set_config()-option `media_quality`).
* If that fails, is not possible, or the image is already small enough, the image is sent as original.
* If you want images to be always sent as the original file, use the DC_MSG_FILE type.
*
* Videos and other file types are currently not recoded by the library,
* with dc_prepare_msg(), however, you can do that from the UI.
*
* @memberof dc_context_t
* @param context The context object as returned from dc_context_new().
* @param chat_id Chat ID to send the message to.
@@ -2802,9 +2782,6 @@ int dc_msg_get_viewtype (const dc_msg_t* msg);
* If a sent message changes to this state, you'll receive the event #DC_EVENT_MSG_DELIVERED.
* - DC_STATE_OUT_MDN_RCVD (28) - Outgoing message read by the recipient (two checkmarks; this requires goodwill on the receiver's side)
* If a sent message changes to this state, you'll receive the event #DC_EVENT_MSG_READ.
* Also messages already read by some recipients
* may get into the state DC_STATE_OUT_FAILED at a later point,
* eg. when in a group, delivery fails for some recipients.
*
* If you just want to check if a message is sent or not, please use dc_msg_is_sent() which regards all states accordingly.
*
@@ -4140,9 +4117,8 @@ void dc_event_unref(dc_event_t* event);
/**
* A single message could not be sent.
* State changed from DC_STATE_OUT_PENDING, DC_STATE_OUT_DELIVERED or DC_STATE_OUT_MDN_RCVD
* to DC_STATE_OUT_FAILED, see dc_msg_get_state().
* A single message could not be sent. State changed from DC_STATE_OUT_PENDING or DC_STATE_OUT_DELIVERED to
* DC_STATE_OUT_FAILED, see dc_msg_get_state().
*
* @param data1 (int) chat_id
* @param data2 (int) msg_id

View File

@@ -285,7 +285,7 @@ pub unsafe extern "C" fn dc_start_io(context: *mut dc_context_t) {
}
let ctx = &*context;
block_on(ctx.start_io())
block_on({ ctx.start_io() })
}
#[no_mangle]
@@ -295,7 +295,7 @@ pub unsafe extern "C" fn dc_is_io_running(context: *mut dc_context_t) -> libc::c
}
let ctx = &*context;
block_on(ctx.is_io_running()) as libc::c_int
block_on({ ctx.is_io_running() }) as libc::c_int
}
#[no_mangle]
@@ -1829,11 +1829,7 @@ pub unsafe extern "C" fn dc_send_locations_to_chat(
}
let ctx = &*context;
block_on(location::send_locations_to_chat(
&ctx,
ChatId::new(chat_id),
seconds as i64,
));
block_on({ location::send_locations_to_chat(&ctx, ChatId::new(chat_id), seconds as i64) });
}
#[no_mangle]

View File

@@ -187,9 +187,7 @@ class DirectImap:
""" (blocking) wait for next idle message from server. """
assert self._idling
self.account.log("imap-direct: calling idle_check")
res = self.conn.idle_check(timeout=30)
if len(res) == 0:
raise TimeoutError
res = self.conn.idle_check()
if terminate:
self.idle_done()
return res

View File

@@ -850,7 +850,6 @@ class TestOnlineAccount:
lp.sec("mark messages as seen on ac2, wait for changes on ac1")
ac2.direct_imap.idle_start()
ac1.direct_imap.idle_start()
ac2.mark_seen_messages([msg2, msg4])
ac2.direct_imap.idle_check(terminate=True)
lp.step("1")
@@ -859,8 +858,6 @@ class TestOnlineAccount:
assert ev.data1 > const.DC_CHAT_ID_LAST_SPECIAL
assert ev.data2 > const.DC_MSG_ID_LAST_SPECIAL
lp.step("2")
ac1.direct_imap.idle_wait_for_seen() # Check that ac1 marks the read receipt as read
assert msg1.is_out_mdn_received()
assert msg3.is_out_mdn_received()

View File

@@ -227,19 +227,6 @@ pub async fn dc_receive_imf(
context
.do_heuristics_moves(server_folder.as_ref(), insert_msg_id)
.await;
if !mime_parser.mdn_reports.is_empty() && mime_parser.has_chat_version() {
// This is a Delta Chat MDN. Mark as read.
job::add(
context,
job::Job::new(
Action::MarkseenMsgOnImap,
insert_msg_id.to_u32(),
Params::new(),
0,
),
)
.await;
}
}
}
@@ -345,7 +332,7 @@ async fn add_parts(
return Ok(());
}
let mut is_dc_message = if mime_parser.has_chat_version() {
let mut msgrmsg = if mime_parser.has_chat_version() {
MessengerMessage::Yes
} else if is_reply_to_messenger_message(context, mime_parser).await {
MessengerMessage::Reply
@@ -357,7 +344,7 @@ async fn add_parts(
let show_emails =
ShowEmails::from_i32(context.get_config_int(Config::ShowEmails).await).unwrap_or_default();
if mime_parser.is_system_message != SystemMessage::AutocryptSetupMessage
&& is_dc_message == MessengerMessage::No
&& msgrmsg == MessengerMessage::No
{
// this message is a classic email not a chat-message nor a reply to one
match show_emails {
@@ -386,7 +373,7 @@ async fn add_parts(
// handshake may mark contacts as verified and must be processed before chats are created
if mime_parser.get(HeaderDef::SecureJoin).is_some() {
is_dc_message = MessengerMessage::Yes; // avoid discarding by show_emails setting
msgrmsg = MessengerMessage::Yes; // avoid discarding by show_emails setting
*chat_id = ChatId::new(0);
allow_creation = true;
match handle_securejoin_handshake(context, mime_parser, from_id).await {
@@ -519,7 +506,7 @@ async fn add_parts(
if Blocked::Not != chat_id_blocked
&& state == MessageState::InFresh
&& !incoming_origin.is_known()
&& is_dc_message == MessengerMessage::No
&& msgrmsg == MessengerMessage::No
&& show_emails != ShowEmails::All
{
state = MessageState::InNoticed;
@@ -534,7 +521,7 @@ async fn add_parts(
// handshake may mark contacts as verified and must be processed before chats are created
if mime_parser.get(HeaderDef::SecureJoin).is_some() {
is_dc_message = MessengerMessage::Yes; // avoid discarding by show_emails setting
msgrmsg = MessengerMessage::Yes; // avoid discarding by show_emails setting
*chat_id = ChatId::new(0);
allow_creation = true;
match observe_securejoin_on_other_device(context, mime_parser, to_id).await {
@@ -573,7 +560,7 @@ async fn add_parts(
}
}
if chat_id.is_unset() && allow_creation {
let create_blocked = if MessengerMessage::No != is_dc_message
let create_blocked = if MessengerMessage::No != msgrmsg
&& !Contact::is_blocked_load(context, to_id).await
{
Blocked::Not
@@ -710,7 +697,7 @@ async fn add_parts(
rcvd_timestamp,
part.typ,
state,
is_dc_message,
msgrmsg,
part.msg,
// txt_raw might contain invalid utf8
txt_raw,
@@ -2347,18 +2334,6 @@ mod tests {
);
}
#[async_std::test]
async fn test_parse_ndn_tiscali() {
test_parse_ndn(
"alice@tiscali.it",
"shenauithz@testrun.org",
"Mr.un2NYERi1RM.lbQ5F9q-QyJ@tiscali.it",
include_bytes!("../test-data/message/tiscali_ndn.eml"),
"",
)
.await;
}
#[async_std::test]
async fn test_parse_ndn_testrun() {
test_parse_ndn(

View File

@@ -811,6 +811,7 @@ impl Imap {
Ok(_) => Some(server_uid),
Err(err) => {
warn!(context, "dc_receive_imf error: {}", err);
read_errors += 1;
None
}
}
@@ -1401,10 +1402,7 @@ async fn precheck_imf(
if old_server_folder != server_folder || old_server_uid != server_uid {
update_server_uid(context, rfc724_mid, server_folder, server_uid).await;
context
.interrupt_inbox(InterruptInfo::new(false, Some(msg_id)))
.await;
info!(context, "Updating server_uid and interrupting")
info!(context, "Updating server_uid")
}
Ok(true)
} else {
@@ -1457,8 +1455,7 @@ pub(crate) async fn prefetch_should_download(
let is_reply_to_chat_message = prefetch_is_reply_to_chat_message(context, &headers).await;
let maybe_ndn = if let Some(from) = headers.get_header_value(HeaderDef::From_) {
let from = from.to_ascii_lowercase();
from.contains("mailer-daemon") || from.contains("mail-daemon")
from.to_ascii_lowercase().contains("mailer-daemon")
} else {
false
};

View File

@@ -530,7 +530,7 @@ pub async fn save(
accuracy,
..
} = location;
let (loc_id, ts) = context
context
.sql
.with_conn(move |mut conn| {
let mut stmt_test = conn
@@ -569,11 +569,9 @@ pub async fn save(
)?;
}
}
Ok((newest_location_id, newest_timestamp))
Ok(())
})
.await?;
newest_timestamp = ts;
newest_location_id = loc_id;
}
Ok(newest_location_id)

View File

@@ -257,8 +257,7 @@ impl MimeMessage {
self.parts[0].msg = "".to_string();
// swap new with old
self.parts.push(filepart); // push to the end
let _ = self.parts.swap_remove(0); // drops first element, replacing it with the last one in O(1)
std::mem::replace(&mut self.parts[0], filepart);
}
}
}
@@ -571,13 +570,13 @@ impl MimeMessage {
any_part_added = true;
}
// Some providers, e.g. Tiscali, forget to set the report-type. So, if it's None, assume that it might be delivery-status
Some("delivery-status") | None => {
Some("delivery-status") => {
if let Some(report) = self.process_delivery_status(context, mail)? {
self.failure_report = Some(report);
}
// Add all parts (we need another part, preferrably text/plain, to show as an error message)
// Add all parts (in fact, AddSinglePartIfKnown() later check if
// the parts are really supported)
for cur_data in mail.subparts.iter() {
if self.parse_mime_recursive(context, cur_data).await? {
any_part_added = true;
@@ -589,6 +588,7 @@ impl MimeMessage {
any_part_added = self.parse_mime_recursive(context, first).await?;
}
}
None => {}
}
}
}
@@ -904,13 +904,16 @@ impl MimeMessage {
/// If you improve heuristics here you might also have to change prefetch_should_download() in imap/mod.rs.
/// Also you should add a test in dc_receive_imf.rs (there already are lots of test_parse_ndn_* tests).
async fn heuristically_parse_ndn(&mut self, context: &Context) -> Option<()> {
let maybe_ndn = if let Some(from) = self.get(HeaderDef::From_) {
let from = from.to_ascii_lowercase();
from.contains("mailer-daemon") || from.contains("mail-daemon")
} else {
false
};
if maybe_ndn && self.failure_report.is_none() {
if self
.get(HeaderDef::Subject)?
.to_ascii_lowercase()
.contains("fail")
&& self
.get(HeaderDef::From_)?
.to_ascii_lowercase()
.contains("mailer-daemon")
&& self.failure_report.is_none()
{
lazy_static! {
static ref RE: regex::Regex = regex::Regex::new(r"Message-ID:(.*)").unwrap();
}

View File

@@ -1,9 +1,7 @@
//! OAuth 2 module
use regex::Regex;
use std::collections::HashMap;
use async_std_resolver::{config, resolver};
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
use serde::Deserialize;
@@ -17,7 +15,6 @@ const OAUTH2_GMAIL: Oauth2 = Oauth2 {
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"),
mx_pattern: Some(r"^aspmx\.l\.google\.com\.$"),
};
const OAUTH2_YANDEX: Oauth2 = Oauth2 {
@@ -27,11 +24,8 @@ const OAUTH2_YANDEX: Oauth2 = Oauth2 {
init_token: "https://oauth.yandex.com/token?grant_type=authorization_code&code=$CODE&client_id=$CLIENT_ID&client_secret=58b8c6e94cf44fbe952da8511955dacf",
refresh_token: "https://oauth.yandex.com/token?grant_type=refresh_token&refresh_token=$REFRESH_TOKEN&client_id=$CLIENT_ID&client_secret=58b8c6e94cf44fbe952da8511955dacf",
get_userinfo: None,
mx_pattern: None,
};
const OAUTH2_PROVIDERS: [Oauth2; 1] = [OAUTH2_GMAIL];
#[derive(Debug, Clone, PartialEq, Eq)]
struct Oauth2 {
client_id: &'static str,
@@ -39,7 +33,6 @@ struct Oauth2 {
init_token: &'static str,
refresh_token: &'static str,
get_userinfo: Option<&'static str>,
mx_pattern: Option<&'static str>,
}
/// OAuth 2 Access Token Response
@@ -60,7 +53,7 @@ pub async fn dc_get_oauth2_url(
addr: impl AsRef<str>,
redirect_uri: impl AsRef<str>,
) -> Option<String> {
if let Some(oauth2) = Oauth2::from_address(addr).await {
if let Some(oauth2) = Oauth2::from_address(addr) {
if context
.sql
.set_raw_config(
@@ -88,7 +81,7 @@ pub async fn dc_get_oauth2_access_token(
code: impl AsRef<str>,
regenerate: bool,
) -> Option<String> {
if let Some(oauth2) = Oauth2::from_address(addr).await {
if let Some(oauth2) = Oauth2::from_address(addr) {
let lock = context.oauth2_mutex.lock().await;
// read generated token
@@ -246,7 +239,7 @@ pub async fn dc_get_oauth2_addr(
addr: impl AsRef<str>,
code: impl AsRef<str>,
) -> Option<String> {
let oauth2 = Oauth2::from_address(addr.as_ref()).await?;
let oauth2 = Oauth2::from_address(addr.as_ref())?;
oauth2.get_userinfo?;
if let Some(access_token) =
@@ -270,62 +263,23 @@ pub async fn dc_get_oauth2_addr(
}
impl Oauth2 {
async fn from_address(addr: impl AsRef<str>) -> Option<Self> {
fn from_address(addr: impl AsRef<str>) -> Option<Self> {
let addr_normalized = normalize_addr(addr.as_ref());
if let Some(domain) = addr_normalized
.find('@')
.map(|index| addr_normalized.split_at(index + 1).1)
{
if let Some(provider) = Oauth2::lookup_whitelist(domain) {
Some(provider)
} else {
Oauth2::lookup_mx(domain).await
match domain {
"gmail.com" | "googlemail.com" => Some(OAUTH2_GMAIL),
"yandex.com" | "yandex.by" | "yandex.kz" | "yandex.ru" | "yandex.ua" | "ya.ru"
| "narod.ru" => Some(OAUTH2_YANDEX),
_ => None,
}
} else {
None
}
}
fn lookup_whitelist(domain: impl AsRef<str>) -> Option<Self> {
let domain = domain.as_ref();
match domain {
"gmail.com" | "googlemail.com" => Some(OAUTH2_GMAIL),
"yandex.com" | "yandex.by" | "yandex.kz" | "yandex.ru" | "yandex.ua" | "ya.ru"
| "narod.ru" => Some(OAUTH2_YANDEX),
_ => None,
}
}
async fn lookup_mx(domain: impl AsRef<str>) -> Option<Self> {
if let Ok(resolver) = resolver(
config::ResolverConfig::default(),
config::ResolverOpts::default(),
)
.await
{
for provider in OAUTH2_PROVIDERS.iter() {
if let Some(pattern) = provider.mx_pattern {
let re = Regex::new(pattern).unwrap();
let mut fqdn: String = String::from(domain.as_ref());
if !fqdn.ends_with('.') {
fqdn.push_str(".");
}
if let Ok(res) = resolver.mx_lookup(fqdn).await {
for rr in res.iter() {
if re.is_match(&rr.exchange().to_lowercase().to_utf8()) {
return Some(provider.clone());
}
}
}
}
}
}
None
}
async fn get_addr(&self, context: &Context, access_token: impl AsRef<str>) -> Option<String> {
let userinfo_url = self.get_userinfo.unwrap_or_else(|| "");
let userinfo_url = replace_in_uri(&userinfo_url, "$ACCESS_TOKEN", access_token);
@@ -408,34 +362,20 @@ mod tests {
);
}
#[async_std::test]
async fn test_oauth_from_address() {
#[test]
fn test_oauth_from_address() {
assert_eq!(Oauth2::from_address("hello@gmail.com"), Some(OAUTH2_GMAIL));
assert_eq!(
Oauth2::from_address("hello@gmail.com").await,
Oauth2::from_address("hello@googlemail.com"),
Some(OAUTH2_GMAIL)
);
assert_eq!(
Oauth2::from_address("hello@googlemail.com").await,
Some(OAUTH2_GMAIL)
);
assert_eq!(
Oauth2::from_address("hello@yandex.com").await,
Some(OAUTH2_YANDEX)
);
assert_eq!(
Oauth2::from_address("hello@yandex.ru").await,
Oauth2::from_address("hello@yandex.com"),
Some(OAUTH2_YANDEX)
);
assert_eq!(Oauth2::from_address("hello@yandex.ru"), Some(OAUTH2_YANDEX));
assert_eq!(Oauth2::from_address("hello@web.de").await, None);
}
#[async_std::test]
async fn test_oauth_from_mx() {
assert_eq!(
Oauth2::from_address("hello@google.com").await,
Some(OAUTH2_GMAIL)
);
assert_eq!(Oauth2::from_address("hello@web.de"), None);
}
#[async_std::test]

View File

@@ -272,14 +272,6 @@ pub async fn pk_encrypt(
.await
}
/// Decrypts the message with keys from the private key keyring.
///
/// Receiver private keys are provided in
/// `private_keys_for_decryption`.
///
/// If `ret_signature_fingerprints` is not `None`, stores fingerprints
/// of all keys from the `public_keys_for_validation` keyring that
/// have valid signatures there.
#[allow(clippy::implicit_hasher)]
pub async fn pk_decrypt(
ctext: Vec<u8>,
@@ -298,41 +290,36 @@ pub async fn pk_decrypt(
})
.await?;
if let Some(msg) = msgs.into_iter().next() {
// get_content() will decompress the message if needed,
// but this avoids decompressing it again to check signatures
let msg = msg.decompress()?;
ensure!(!msgs.is_empty(), "No valid messages found");
let content = match msg.get_content()? {
Some(content) => content,
None => bail!("The decrypted message is empty"),
};
let content = match msgs[0].get_content()? {
Some(content) => content,
None => bail!("Decrypted message is empty"),
};
if let Some(ret_signature_fingerprints) = ret_signature_fingerprints {
if !public_keys_for_validation.is_empty() {
let fingerprints = async_std::task::spawn_blocking(move || {
let pkeys = public_keys_for_validation.keys();
if let Some(ret_signature_fingerprints) = ret_signature_fingerprints {
if !public_keys_for_validation.is_empty() {
let fingerprints = async_std::task::spawn_blocking(move || {
let dec_msg = &msgs[0];
let mut fingerprints: Vec<Fingerprint> = Vec::new();
if let signed_msg @ pgp::composed::Message::Signed { .. } = msg {
for pkey in pkeys {
if signed_msg.verify(&pkey.primary_key).is_ok() {
let fp = DcKey::fingerprint(pkey);
fingerprints.push(fp);
}
}
let pkeys = public_keys_for_validation.keys();
let mut fingerprints: Vec<Fingerprint> = Vec::new();
for pkey in pkeys {
if dec_msg.verify(&pkey.primary_key).is_ok() {
let fp = DcKey::fingerprint(pkey);
fingerprints.push(fp);
}
fingerprints
})
.await;
}
fingerprints
})
.await;
ret_signature_fingerprints.extend(fingerprints);
}
ret_signature_fingerprints.extend(fingerprints);
}
Ok(content)
} else {
bail!("No valid messages found");
}
Ok(content)
}
/// Symmetric encryption.

View File

@@ -114,7 +114,7 @@ pub async fn dc_get_securejoin_qr(context: &Context, group_chat_id: ChatId) -> O
Some(format!(
"OPENPGP4FPR:{}#a={}&g={}&x={}&i={}&s={}",
fingerprint.hex(),
fingerprint,
self_addr_urlencoded,
&group_name_urlencoded,
&chat.grpid,
@@ -129,11 +129,7 @@ pub async fn dc_get_securejoin_qr(context: &Context, group_chat_id: ChatId) -> O
// parameters used: a=n=i=s=
Some(format!(
"OPENPGP4FPR:{}#a={}&n={}&i={}&s={}",
fingerprint.hex(),
self_addr_urlencoded,
self_name_urlencoded,
&invitenumber,
&auth,
fingerprint, self_addr_urlencoded, self_name_urlencoded, &invitenumber, &auth,
))
};

View File

@@ -1,91 +0,0 @@
Return-Path: <>
Delivered-To: alice@tiscali.it
Received: from director-5.mail.tiscali.sys ([10.39.80.174])
by dovecot-08.mail.tiscali.sys with LMTP id SBRfEpGb517VAgAAd2fHbg
for <alice@tiscali.it>; Mon, 15 Jun 2020 16:02:25 +0000
Received: from cmgw-4.mail.tiscali.it ([10.39.80.174])
by director-5.mail.tiscali.sys with LMTP id MFUPL5Cb516tawAArQJVuQ
; Mon, 15 Jun 2020 16:02:25 +0000
Received: from michael.mail.tiscali.it ([213.205.33.246])
by cmgw-4.mail.tiscali.it with
id rTtS2200V5JdeUd01U2RlV; Mon, 15 Jun 2020 16:02:25 +0000
x-cnfs-analysis: v=2.3 cv=ZdPMyfdA c=1 sm=1 tr=0 cx=a_idp_d
a=AfTPebshMYb+aQOCLa9q3Q==:117 a=HpEJnUlJZJkA:10 a=jmdcTMp_Gj4A:10
a=r77TgQKjGQsHNAKrUKIA:9 a=b8iBRs35AAAA:8 a=NMdB-582e605uxHDr_AA:9
a=QEXdDO2ut3YA:10 a=MhhPCb74-dYA:10 a=HXlsH_Kov2KnitTn7A4A:9
a=BkuCPOF3BOzethIN9HQA:9 a=qG5HpJ6ZyD35YNEB:21 a=kvHihYffoorsyJbA:21
a=xD8EQi6zkreDqSNPYj5l:22
Date: Mon, 15 Jun 2020 16:02:25 +0000
From: Mail Delivery System <mail-daemon@smtp.tiscali.it>
To: alice@tiscali.it
Subject: Delivery status notification
MIME-Version: 1.0
Content-Type: multipart/report; boundary="------------I305M09060309060P_896715922369450"
This is a multi-part message in MIME format.
--------------I305M09060309060P_896715922369450
Content-Type: text/plain; charset=UTF-8;
Content-Transfer-Encoding: 8bit
This is an automatically generated Delivery Status Notification.
Delivery to the following recipients was aborted after 2 second(s):
* shenauithz@testrun.org
--------------I305M09060309060P_896715922369450
Content-Type: message/delivery-status; charset=UTF-8;
Content-Transfer-Encoding: 8bit
Reporting-MTA: dns; michael.mail.tiscali.it [213.205.33.13]
Received-From-MTA: dns; localhost [146.241.100.150]
Arrival-Date: Mon, 15 Jun 2020 16:02:23 +0000
Final-recipient: rfc822; shenauithz@testrun.org
Action: failed
Status: 5.1.1
Diagnostic-Code: smtp; 550 5.1.1 <shenauithz@testrun.org>: Recipient address rejected: User unknown in virtual mailbox table
Last-attempt-Date: Mon, 15 Jun 2020 16:02:25 +0000
--------------I305M09060309060P_896715922369450
Content-Type: text/rfc822-headers; Content-Transfer-Encoding: 8bit
Content-Disposition: attachment
x-auth-user: alice@tiscali.it
Chat-Disposition-Notification-To: alice@tiscali.it
Chat-User-Avatar: avatar.jpg
Subject: =?utf-8?q?Message_from_=F0=9F=8F=9E=EF=B8=8F_Mefiscali?=
MIME-Version: 1.0
Date: Mon, 15 Jun 2020 16:02:22 +0000
X-Mailer: Delta Chat Core 1.35.0/Android 1.9.5
Chat-Version: 1.0
Autocrypt: addr=alice@tiscali.it; prefer-encrypt=mutual;
keydata=xjMEXtFRUBYJKwYBBAHaRw8BAQdA5sqHJqkWlveCgsNd0rtwtZrT1mmo1gwaGC5+WheYk5
nNHTxhbmRyZWFzLmxhdHRtYW5uQHRpc2NhbGkuaXQ+wosEEBYIADMCGQEFAl7RUXoCGwMECwkIBwYV
CAkKCwIDFgIBFiEEJUsbRIjZEaRNAs1p1Z5M1vshkrAACgkQ1Z5M1vshkrAAaAEA4wssXeU2IXnowv
iu3zmcNzDgE4HdmW4RFyqJC6bgxXQA/3aTfE/PhQgZvi6RrKMvP4zygXpD9y+3ydIZP88Bp8kIzjgE
XtFRUBIKKwYBBAGXVQEFAQEHQKaAwlP0j9m0aYsCtO+qD9+foH0kiTN5BWDe5YcZrckVAwEIB8J4BB
gWCAAgBQJe0VF6AhsMFiEEJUsbRIjZEaRNAs1p1Z5M1vshkrAACgkQ1Z5M1vshkrA1JgEAkscCQlps
h3ZxlLqBlbf2+85f4S4aGQfFPtIYEkKKhYEBAJbQulNNp9UarvhfyBiIdvkBVDcCnJZwzbORqp8RM0 gC
Message-ID: <Mr.un2NYERi1RM.lbQ5F9q-QyJ@tiscali.it>
To: <shenauithz@testrun.org>
From: =?utf-8?b?8J+Pnu+4jyBNZWZpc2NhbGk=?= <alice@tiscali.it>
Content-Type: multipart/mixed; boundary="5uAmYQux1HZxxriijTjjKSp4DMoJwq"
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tiscali.it; s=smtp;
t=1592236943; bh=C3taz+zuSre1ko5Q5CzGPmbyrgegKYBClx/3Dv7t/Xw=;
h=Subject:Date:To:From;
b=LrcfLfrQoemOkHTQsqR8MExqNlx5KPYNFWhwlBWylvVc5GlmlhzqM6SAVKd0NVsKE
gVRlBId5FvnlwoJ2WZnXaw/+3lWKilMTuzzQ1oFGvLnZ1XUaUEfuliIv+9NI79dJWX
+S3jsSgzJMJc9+fO6s9bJsX1EHQ2a8GXNbwDtLXs=
--------------I305M09060309060P_896715922369450--