diff --git a/Cargo.lock b/Cargo.lock
index 0cdd387f..8fae87cf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -124,12 +124,6 @@ dependencies = [
"waker-fn",
]
-[[package]]
-name = "bumpalo"
-version = "3.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
-
[[package]]
name = "byteorder"
version = "1.3.4"
@@ -293,6 +287,37 @@ dependencies = [
"lazy_static",
]
+[[package]]
+name = "curl"
+version = "0.4.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9447ad28eee2a5cfb031c329d46bef77487244fff6a724b378885b8691a35f78"
+dependencies = [
+ "curl-sys",
+ "libc",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "socket2",
+ "winapi 0.3.8",
+]
+
+[[package]]
+name = "curl-sys"
+version = "0.4.33+curl-7.71.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e9818ea018327f79c811612f29b9834d2abddbe7db81460a2d5c7e12946b337"
+dependencies = [
+ "cc",
+ "libc",
+ "libnghttp2-sys",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+ "vcpkg",
+ "winapi 0.3.8",
+]
+
[[package]]
name = "data-encoding"
version = "2.2.1"
@@ -320,12 +345,6 @@ dependencies = [
"winapi 0.3.8",
]
-[[package]]
-name = "dtoa"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3"
-
[[package]]
name = "encoding"
version = "0.2.33"
@@ -613,25 +632,6 @@ dependencies = [
"wasi",
]
-[[package]]
-name = "h2"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79b7246d7e4b979c03fa093da39cfb3617a96bbeee6310af63991668d7e843ff"
-dependencies = [
- "bytes",
- "fnv",
- "futures-core",
- "futures-sink",
- "futures-util",
- "http",
- "indexmap",
- "log",
- "slab",
- "tokio",
- "tokio-util",
-]
-
[[package]]
name = "heck"
version = "0.3.1"
@@ -661,79 +661,6 @@ dependencies = [
"itoa",
]
-[[package]]
-name = "http-body"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
-dependencies = [
- "bytes",
- "http",
-]
-
-[[package]]
-name = "httparse"
-version = "1.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
-
-[[package]]
-name = "hyper"
-version = "0.13.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6e7655b9594024ad0ee439f3b5a7299369dc2a3f459b47c696f9ff676f9aa1f"
-dependencies = [
- "bytes",
- "futures-channel",
- "futures-core",
- "futures-util",
- "h2",
- "http",
- "http-body",
- "httparse",
- "itoa",
- "log",
- "pin-project",
- "socket2",
- "time",
- "tokio",
- "tower-service",
- "want",
-]
-
-[[package]]
-name = "hyper-tls"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3adcd308402b9553630734e9c36b77a7e48b3821251ca2493e8cd596763aafaa"
-dependencies = [
- "bytes",
- "hyper",
- "native-tls",
- "tokio",
- "tokio-tls",
-]
-
-[[package]]
-name = "idna"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
-dependencies = [
- "matches",
- "unicode-bidi",
- "unicode-normalization",
-]
-
-[[package]]
-name = "indexmap"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe"
-dependencies = [
- "autocfg",
-]
-
[[package]]
name = "inotify"
version = "0.7.1"
@@ -763,21 +690,39 @@ dependencies = [
"libc",
]
+[[package]]
+name = "isahc"
+version = "0.9.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b95d2708cacabb9e638a36e232ee3f2949c576b11150669835183af419dbaca"
+dependencies = [
+ "bytes",
+ "crossbeam-channel",
+ "crossbeam-utils",
+ "curl",
+ "curl-sys",
+ "encoding_rs",
+ "futures-channel",
+ "futures-io",
+ "futures-util",
+ "http",
+ "lazy_static",
+ "log",
+ "mime",
+ "serde",
+ "serde_json",
+ "slab",
+ "sluice",
+ "tracing",
+ "tracing-futures",
+]
+
[[package]]
name = "itoa"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
-[[package]]
-name = "js-sys"
-version = "0.3.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce10c23ad2ea25ceca0093bd3192229da4c5b3c0f2de499c1ecac0d98d452177"
-dependencies = [
- "wasm-bindgen",
-]
-
[[package]]
name = "kernel32-sys"
version = "0.2.2"
@@ -837,6 +782,16 @@ dependencies = [
"winapi 0.3.8",
]
+[[package]]
+name = "libnghttp2-sys"
+version = "0.1.4+1.41.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03624ec6df166e79e139a2310ca213283d6b3c30810c54844f307086d4488df1"
+dependencies = [
+ "cc",
+ "libc",
+]
+
[[package]]
name = "libsqlite3-sys"
version = "0.16.0"
@@ -847,6 +802,18 @@ dependencies = [
"vcpkg",
]
+[[package]]
+name = "libz-sys"
+version = "1.0.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
[[package]]
name = "linked-hash-map"
version = "0.5.3"
@@ -901,12 +868,6 @@ dependencies = [
"libc",
]
-[[package]]
-name = "matches"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
-
[[package]]
name = "maybe-uninit"
version = "2.0.0"
@@ -965,6 +926,7 @@ dependencies = [
"encoding",
"flate2",
"futures",
+ "isahc",
"libc",
"libloading",
"memmap",
@@ -972,7 +934,6 @@ dependencies = [
"nix",
"nom",
"notify",
- "reqwest",
"rusqlite",
"serde",
"serde_derive",
@@ -1017,16 +978,6 @@ version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
-[[package]]
-name = "mime_guess"
-version = "2.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212"
-dependencies = [
- "mime",
- "unicase",
-]
-
[[package]]
name = "miniz_oxide"
version = "0.4.0"
@@ -1298,12 +1249,6 @@ dependencies = [
"pkg-config",
]
-[[package]]
-name = "percent-encoding"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
-
[[package]]
name = "pin-project"
version = "0.4.20"
@@ -1324,12 +1269,6 @@ dependencies = [
"syn",
]
-[[package]]
-name = "pin-project-lite"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715"
-
[[package]]
name = "pin-utils"
version = "0.1.0"
@@ -1480,41 +1419,6 @@ dependencies = [
"winapi 0.3.8",
]
-[[package]]
-name = "reqwest"
-version = "0.10.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b82c9238b305f26f53443e3a4bc8528d64b8d0bee408ec949eb7bf5635ec680"
-dependencies = [
- "base64 0.12.3",
- "bytes",
- "encoding_rs",
- "futures-core",
- "futures-util",
- "http",
- "http-body",
- "hyper",
- "hyper-tls",
- "js-sys",
- "lazy_static",
- "log",
- "mime",
- "mime_guess",
- "native-tls",
- "percent-encoding",
- "pin-project-lite",
- "serde",
- "serde_json",
- "serde_urlencoded",
- "tokio",
- "tokio-tls",
- "url",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "web-sys",
- "winreg",
-]
-
[[package]]
name = "rmp"
version = "0.8.9"
@@ -1699,18 +1603,6 @@ dependencies = [
"serde",
]
-[[package]]
-name = "serde_urlencoded"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
-dependencies = [
- "dtoa",
- "itoa",
- "serde",
- "url",
-]
-
[[package]]
name = "signal-hook"
version = "0.1.15"
@@ -1737,6 +1629,18 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
+[[package]]
+name = "sluice"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed13b7cb46f13a15db2c4740f087a848acc8b31af89f95844d40137451f89b1"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-util",
+]
+
[[package]]
name = "smallvec"
version = "1.4.1"
@@ -1898,48 +1802,6 @@ dependencies = [
"winapi 0.3.8",
]
-[[package]]
-name = "tokio"
-version = "0.2.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d099fa27b9702bed751524694adbe393e18b36b204da91eb1cbbbbb4a5ee2d58"
-dependencies = [
- "bytes",
- "fnv",
- "futures-core",
- "iovec",
- "lazy_static",
- "memchr",
- "mio",
- "num_cpus",
- "pin-project-lite",
- "slab",
-]
-
-[[package]]
-name = "tokio-tls"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343"
-dependencies = [
- "native-tls",
- "tokio",
-]
-
-[[package]]
-name = "tokio-util"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
-dependencies = [
- "bytes",
- "futures-core",
- "futures-sink",
- "log",
- "pin-project-lite",
- "tokio",
-]
-
[[package]]
name = "toml"
version = "0.5.6"
@@ -1950,42 +1812,45 @@ dependencies = [
]
[[package]]
-name = "tower-service"
-version = "0.3.0"
+name = "tracing"
+version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"
-
-[[package]]
-name = "try-lock"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
-
-[[package]]
-name = "unicase"
-version = "2.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
+checksum = "f0aae59226cf195d8e74d4b34beae1859257efb4e5fed3f147d2dc2c7d372178"
dependencies = [
- "version_check",
+ "cfg-if",
+ "log",
+ "tracing-attributes",
+ "tracing-core",
]
[[package]]
-name = "unicode-bidi"
-version = "0.3.4"
+name = "tracing-attributes"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
+checksum = "f0693bf8d6f2bf22c690fc61a9d21ac69efdbb894a17ed596b9af0f01e64b84b"
dependencies = [
- "matches",
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
-name = "unicode-normalization"
-version = "0.1.12"
+name = "tracing-core"
+version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4"
+checksum = "d593f98af59ebc017c0648f0117525db358745a8894a8d684e185ba3f45954f9"
dependencies = [
- "smallvec",
+ "lazy_static",
+]
+
+[[package]]
+name = "tracing-futures"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c"
+dependencies = [
+ "pin-project",
+ "tracing",
]
[[package]]
@@ -2006,17 +1871,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
-[[package]]
-name = "url"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
-dependencies = [
- "idna",
- "matches",
- "percent-encoding",
-]
-
[[package]]
name = "uuid"
version = "0.8.1"
@@ -2062,100 +1916,12 @@ dependencies = [
"winapi-util",
]
-[[package]]
-name = "want"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
-dependencies = [
- "log",
- "try-lock",
-]
-
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.63"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c2dc4aa152834bc334f506c1a06b866416a8b6697d5c9f75b9a689c8486def0"
-dependencies = [
- "cfg-if",
- "serde",
- "serde_json",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.63"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ded84f06e0ed21499f6184df0e0cb3494727b0c5da89534e0fcc55c51d812101"
-dependencies = [
- "bumpalo",
- "lazy_static",
- "log",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-futures"
-version = "0.4.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64487204d863f109eb77e8462189d111f27cb5712cc9fdb3461297a76963a2f6"
-dependencies = [
- "cfg-if",
- "js-sys",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.63"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "838e423688dac18d73e31edce74ddfac468e37b1506ad163ffaf0a46f703ffe3"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.63"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.63"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9ba19973a58daf4db6f352eda73dc0e289493cd29fb2632eb172085b6521acd"
-
-[[package]]
-name = "web-sys"
-version = "0.3.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b72fe77fd39e4bd3eaa4412fd299a0be6b3dfe9d2597e2f1c20beb968f41d17"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
[[package]]
name = "wepoll-sys-stjepang"
version = "1.0.6"
@@ -2208,15 +1974,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-[[package]]
-name = "winreg"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
-dependencies = [
- "winapi 0.3.8",
-]
-
[[package]]
name = "ws2_32-sys"
version = "0.2.1"
diff --git a/melib/Cargo.toml b/melib/Cargo.toml
index 878d86b4..591e33e6 100644
--- a/melib/Cargo.toml
+++ b/melib/Cargo.toml
@@ -35,7 +35,7 @@ uuid = { version = "0.8.1", features = ["serde", "v4"] }
unicode-segmentation = { version = "1.2.1", optional = true }
libc = {version = "0.2.59", features = ["extra_traits",]}
-reqwest = { version ="0.10.0-alpha.2", optional=true, features = ["json", "blocking" ]}
+isahc = { version = "0.9.7", optional = true, default-features = false, features = ["http2", "json", "text-decoding"]}
serde_json = { version = "1.0", optional = true, features = ["raw_value",] }
smallvec = { version = "^1.4.0", features = ["serde", ] }
nix = "0.17.0"
@@ -52,13 +52,15 @@ flate2 = { version = "1.0.16", optional = true }
default = ["unicode_algorithms", "imap_backend", "maildir_backend", "mbox_backend", "vcard", "sqlite3", "smtp", "deflate_compression"]
debug-tracing = []
-unicode_algorithms = ["unicode-segmentation"]
+deflate_compression = ["flate2", ]
+http = ["isahc"]
+http-static = ["isahc", "isahc/static-curl"]
imap_backend = ["native-tls"]
+jmap_backend = ["http", "serde_json"]
maildir_backend = ["notify", "memmap"]
mbox_backend = ["notify", "memmap"]
notmuch_backend = []
-jmap_backend = ["reqwest", "serde_json" ]
-vcard = []
-sqlite3 = ["rusqlite", ]
smtp = ["native-tls", "base64"]
-deflate_compression = ["flate2", ]
+sqlite3 = ["rusqlite", ]
+unicode_algorithms = ["unicode-segmentation"]
+vcard = []
diff --git a/melib/src/backends.rs b/melib/src/backends.rs
index 90ec5d43..f97d67f0 100644
--- a/melib/src/backends.rs
+++ b/melib/src/backends.rs
@@ -47,8 +47,6 @@ pub mod maildir;
pub mod mbox;
#[cfg(feature = "imap_backend")]
pub use self::imap::ImapType;
-#[cfg(feature = "jmap_backend")]
-pub use self::jmap::JmapType;
#[cfg(feature = "imap_backend")]
pub use self::nntp::NntpType;
use crate::async_workers::*;
@@ -173,8 +171,8 @@ impl Backends {
b.register(
"jmap".to_string(),
Backend {
- create_fn: Box::new(|| Box::new(|f, i| JmapType::new(f, i))),
- validate_conf_fn: Box::new(JmapType::validate_config),
+ create_fn: Box::new(|| Box::new(|f, i| jmap::JmapType::new(f, i))),
+ validate_conf_fn: Box::new(jmap::JmapType::validate_config),
},
);
}
diff --git a/melib/src/backends/jmap.rs b/melib/src/backends/jmap.rs
index 61347729..c2b93061 100644
--- a/melib/src/backends/jmap.rs
+++ b/melib/src/backends/jmap.rs
@@ -19,12 +19,14 @@
* along with meli. If not, see .
*/
-use crate::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext};
+use crate::async_workers::{Async, WorkContext};
use crate::backends::*;
use crate::conf::AccountSettings;
use crate::email::*;
use crate::error::{MeliError, Result};
-use reqwest::blocking::Client;
+use futures::lock::Mutex as FutureMutex;
+use isahc::prelude::HttpClient;
+use isahc::ResponseExt;
use std::collections::{BTreeMap, HashMap};
use std::convert::TryFrom;
use std::str::FromStr;
@@ -181,10 +183,10 @@ pub struct Store {
#[derive(Debug)]
pub struct JmapType {
account_name: String,
- online: Arc)>>,
+ online: Arc)>>,
is_subscribed: Arc,
server_conf: JmapServerConf,
- connection: Arc,
+ connection: Arc>,
store: Arc>,
tag_index: Arc>>,
mailboxes: Arc>>,
@@ -193,7 +195,7 @@ pub struct JmapType {
impl MailBackend for JmapType {
fn capabilities(&self) -> MailBackendCapabilities {
const CAPABILITIES: MailBackendCapabilities = MailBackendCapabilities {
- is_async: false,
+ is_async: true,
is_remote: true,
supports_search: true,
extensions: None,
@@ -202,61 +204,67 @@ impl MailBackend for JmapType {
CAPABILITIES
}
- fn is_online(&self) -> Result<()> {
- if self.online.lock().unwrap().1.is_err()
- && Instant::now().duration_since(self.online.lock().unwrap().0)
- >= std::time::Duration::new(2, 0)
- {
- let _ = self.mailboxes();
- }
- self.online.lock().unwrap().1.clone()
+ fn is_online_async(&self) -> ResultFuture<()> {
+ let online = self.online.clone();
+ Ok(Box::pin(async move {
+ //match timeout(std::time::Duration::from_secs(3), connection.lock()).await {
+ let online_lck = online.lock().await;
+ if online_lck.1.is_err()
+ && Instant::now().duration_since(online_lck.0) >= std::time::Duration::new(2, 0)
+ {
+ //let _ = self.mailboxes();
+ }
+ online_lck.1.clone()
+ }))
}
- fn fetch(&mut self, mailbox_hash: MailboxHash) -> Result>>> {
- let mut w = AsyncBuilder::new();
+ fn fetch_async(
+ &mut self,
+ mailbox_hash: MailboxHash,
+ ) -> Result>> + Send + 'static>>> {
let mailboxes = self.mailboxes.clone();
let store = self.store.clone();
let tag_index = self.tag_index.clone();
let connection = self.connection.clone();
- let handle = {
- let tx = w.tx();
- let closure = move |_work_context| {
- tx.send(AsyncStatus::Payload(protocol::get(
- &connection,
- &store,
- &tag_index,
- &mailboxes.read().unwrap()[&mailbox_hash],
- )))
- .unwrap();
- tx.send(AsyncStatus::Finished).unwrap();
- };
- Box::new(closure)
- };
- Ok(w.build(handle))
+ Ok(Box::pin(async_stream::try_stream! {
+ let mut conn = connection.lock().await;
+ conn.connect().await?;
+ let res = protocol::fetch(
+ &conn,
+ &store,
+ &tag_index,
+ &mailboxes,
+ mailbox_hash,
+ ).await?;
+ yield res;
+ }))
}
- fn watch(
- &self,
- _sender: RefreshEventConsumer,
- _work_context: WorkContext,
- ) -> Result {
+ fn watch_async(&self, _sender: RefreshEventConsumer) -> ResultFuture<()> {
Err(MeliError::from("JMAP watch for updates is unimplemented"))
}
- fn mailboxes(&self) -> Result> {
- if self.mailboxes.read().unwrap().is_empty() {
- let mailboxes = debug!(protocol::get_mailboxes(&self.connection))?;
- *self.mailboxes.write().unwrap() = mailboxes;
- }
+ fn mailboxes_async(&self) -> ResultFuture> {
+ let mailboxes = self.mailboxes.clone();
+ let connection = self.connection.clone();
+ Ok(Box::pin(async move {
+ let mut conn = connection.lock().await;
+ conn.connect().await?;
+ if mailboxes.read().unwrap().is_empty() {
+ let new_mailboxes = debug!(protocol::get_mailboxes(&conn).await)?;
+ *mailboxes.write().unwrap() = new_mailboxes;
+ }
- Ok(self
- .mailboxes
- .read()
- .unwrap()
- .iter()
- .filter(|(_, f)| f.is_subscribed)
- .map(|(&h, f)| (h, BackendMailbox::clone(f) as Mailbox))
- .collect())
+ let ret = mailboxes
+ .read()
+ .unwrap()
+ .iter()
+ .filter(|(_, f)| f.is_subscribed)
+ .map(|(&h, f)| (h, BackendMailbox::clone(f) as Mailbox))
+ .collect();
+
+ Ok(ret)
+ }))
}
fn operation(&self, hash: EnvelopeHash) -> Result> {
@@ -289,7 +297,7 @@ impl MailBackend for JmapType {
q: crate::search::Query,
mailbox_hash: Option,
) -> ResultFuture> {
- let conn = self.connection.clone();
+ let connection = self.connection.clone();
let filter = if let Some(mailbox_hash) = mailbox_hash {
let mailbox_id = self.mailboxes.read().unwrap()[&mailbox_hash].id.clone();
@@ -304,44 +312,57 @@ impl MailBackend for JmapType {
Filter::::from(q)
};
- let email_call: EmailQuery = EmailQuery::new(
- Query::new()
- .account_id(conn.mail_account_id().to_string())
- .filter(Some(filter))
- .position(0),
- )
- .collapse_threads(false);
-
- let mut req = Request::new(conn.request_no.clone());
- req.add_call(&email_call);
-
- let res = conn
- .client
- .lock()
- .unwrap()
- .post(&conn.session.api_url)
- .basic_auth(
- &conn.server_conf.server_username,
- Some(&conn.server_conf.server_password),
+ Ok(Box::pin(async move {
+ let mut conn = connection.lock().await;
+ conn.connect().await?;
+ let email_call: EmailQuery = EmailQuery::new(
+ Query::new()
+ .account_id(conn.mail_account_id().to_string())
+ .filter(Some(filter))
+ .position(0),
)
- .json(&req)
- .send();
+ .collapse_threads(false);
- let res_text = res?.text()?;
- let mut v: MethodResponse = serde_json::from_str(&res_text).unwrap();
- *conn.online_status.lock().unwrap() = (std::time::Instant::now(), Ok(()));
- let m = QueryResponse::::try_from(v.method_responses.remove(0))?;
- let QueryResponse:: { ids, .. } = m;
- let ret = ids
- .into_iter()
- .map(|id| {
- use std::hash::Hasher;
- let mut h = std::collections::hash_map::DefaultHasher::new();
- h.write(id.as_bytes());
- h.finish()
- })
- .collect();
- Ok(Box::pin(async move { Ok(ret) }))
+ let mut req = Request::new(conn.request_no.clone());
+ req.add_call(&email_call);
+
+ let mut res = conn
+ .client
+ .post_async(&conn.session.api_url, serde_json::to_string(&req)?)
+ .await?;
+
+ let res_text = res.text_async().await?;
+ let mut v: MethodResponse = serde_json::from_str(&res_text).unwrap();
+ *conn.online_status.lock().await = (std::time::Instant::now(), Ok(()));
+ let m = QueryResponse::::try_from(v.method_responses.remove(0))?;
+ let QueryResponse:: { ids, .. } = m;
+ let ret = ids
+ .into_iter()
+ .map(|id| {
+ use std::hash::Hasher;
+ let mut h = std::collections::hash_map::DefaultHasher::new();
+ h.write(id.as_bytes());
+ h.finish()
+ })
+ .collect();
+ Ok(ret)
+ }))
+ }
+
+ fn fetch(&mut self, _mailbox_hash: MailboxHash) -> Result>>> {
+ Err(MeliError::new("Unimplemented."))
+ }
+
+ fn watch(
+ &self,
+ _sender: RefreshEventConsumer,
+ _work_context: WorkContext,
+ ) -> Result {
+ Err(MeliError::new("Unimplemented."))
+ }
+
+ fn mailboxes(&self) -> Result> {
+ Err(MeliError::new("Unimplemented."))
}
}
@@ -350,14 +371,17 @@ impl JmapType {
s: &AccountSettings,
is_subscribed: Box bool + Send + Sync>,
) -> Result> {
- let online = Arc::new(Mutex::new((
+ let online = Arc::new(FutureMutex::new((
std::time::Instant::now(),
Err(MeliError::new("Account is uninitialised.")),
)));
let server_conf = JmapServerConf::new(s)?;
Ok(Box::new(JmapType {
- connection: Arc::new(JmapConnection::new(&server_conf, online.clone())?),
+ connection: Arc::new(FutureMutex::new(JmapConnection::new(
+ &server_conf,
+ online.clone(),
+ )?)),
store: Arc::new(RwLock::new(Store::default())),
tag_index: Arc::new(RwLock::new(Default::default())),
mailboxes: Arc::new(RwLock::new(HashMap::default())),
diff --git a/melib/src/backends/jmap/connection.rs b/melib/src/backends/jmap/connection.rs
index b6a70514..f3e3ab38 100644
--- a/melib/src/backends/jmap/connection.rs
+++ b/melib/src/backends/jmap/connection.rs
@@ -20,13 +20,14 @@
*/
use super::*;
+use isahc::config::Configurable;
#[derive(Debug)]
pub struct JmapConnection {
pub session: JmapSession,
pub request_no: Arc>,
- pub client: Arc>,
- pub online_status: Arc)>>,
+ pub client: Arc,
+ pub online_status: Arc)>>,
pub server_conf: JmapServerConf,
pub account_id: Arc>,
pub method_call_states: Arc>>,
@@ -35,70 +36,21 @@ pub struct JmapConnection {
impl JmapConnection {
pub fn new(
server_conf: &JmapServerConf,
- online_status: Arc)>>,
+ online_status: Arc)>>,
) -> Result {
- use reqwest::header;
- let mut headers = header::HeaderMap::new();
- headers.insert(
- header::ACCEPT,
- header::HeaderValue::from_static("application/json"),
- );
- headers.insert(
- header::CONTENT_TYPE,
- header::HeaderValue::from_static("application/json"),
- );
- let client = reqwest::blocking::ClientBuilder::new()
- .danger_accept_invalid_certs(server_conf.danger_accept_invalid_certs)
- .default_headers(headers)
- .build()?;
- let mut jmap_session_resource_url = if server_conf.server_hostname.starts_with("https://") {
- server_conf.server_hostname.to_string()
- } else {
- format!("https://{}", &server_conf.server_hostname)
- };
- if server_conf.server_port != 443 {
- jmap_session_resource_url.push(':');
- jmap_session_resource_url.push_str(&server_conf.server_port.to_string());
- }
- jmap_session_resource_url.push_str("/.well-known/jmap");
-
- let req = client
- .get(&jmap_session_resource_url)
- .basic_auth(
+ let client = HttpClient::builder()
+ .timeout(std::time::Duration::from_secs(10))
+ .authentication(isahc::auth::Authentication::basic())
+ .credentials(isahc::auth::Credentials::new(
&server_conf.server_username,
- Some(&server_conf.server_password),
- )
- .send()?;
- let res_text = req.text()?;
-
- let session: JmapSession = serde_json::from_str(&res_text).map_err(|_| {
- let err = MeliError::new(format!("Could not connect to JMAP server endpoint for {}. Is your server hostname setting correct? (i.e. \"jmap.mailserver.org\") (Note: only session resource discovery via /.well-known/jmap is supported. DNS SRV records are not suppported.)\nReply from server: {}", &server_conf.server_hostname, &res_text));
- *online_status.lock().unwrap() = (Instant::now(), Err(err.clone()));
- err
- })?;
- if !session
- .capabilities
- .contains_key("urn:ietf:params:jmap:core")
- {
- let err = MeliError::new(format!("Server {} did not return JMAP Core capability (urn:ietf:params:jmap:core). Returned capabilities were: {}", &server_conf.server_hostname, session.capabilities.keys().map(String::as_str).collect::>().join(", ")));
- *online_status.lock().unwrap() = (Instant::now(), Err(err.clone()));
- return Err(err);
- }
- if !session
- .capabilities
- .contains_key("urn:ietf:params:jmap:mail")
- {
- let err = MeliError::new(format!("Server {} does not support JMAP Mail capability (urn:ietf:params:jmap:mail). Returned capabilities were: {}", &server_conf.server_hostname, session.capabilities.keys().map(String::as_str).collect::>().join(", ")));
- *online_status.lock().unwrap() = (Instant::now(), Err(err.clone()));
- return Err(err);
- }
-
- *online_status.lock().unwrap() = (Instant::now(), Ok(()));
+ &server_conf.server_password,
+ ))
+ .build()?;
let server_conf = server_conf.clone();
Ok(JmapConnection {
- session,
+ session: Default::default(),
request_no: Arc::new(Mutex::new(0)),
- client: Arc::new(Mutex::new(client)),
+ client: Arc::new(client),
online_status,
server_conf,
account_id: Arc::new(Mutex::new(String::new())),
@@ -106,6 +58,55 @@ impl JmapConnection {
})
}
+ pub async fn connect(&mut self) -> Result<()> {
+ if self.online_status.lock().await.1.is_ok() {
+ return Ok(());
+ }
+ let mut jmap_session_resource_url =
+ if self.server_conf.server_hostname.starts_with("https://") {
+ self.server_conf.server_hostname.to_string()
+ } else {
+ format!("https://{}", &self.server_conf.server_hostname)
+ };
+ if self.server_conf.server_port != 443 {
+ jmap_session_resource_url.push(':');
+ jmap_session_resource_url.push_str(&self.server_conf.server_port.to_string());
+ }
+ jmap_session_resource_url.push_str("/.well-known/jmap");
+
+ let mut req = self.client.get_async(&jmap_session_resource_url).await?;
+ let res_text = req.text_async().await?;
+
+ let session: JmapSession = match serde_json::from_str(&res_text) {
+ Err(err) => {
+ let err = MeliError::new(format!("Could not connect to JMAP server endpoint for {}. Is your server hostname setting correct? (i.e. \"jmap.mailserver.org\") (Note: only session resource discovery via /.well-known/jmap is supported. DNS SRV records are not suppported.)\nReply from server: {}", &self.server_conf.server_hostname, &res_text)).set_source(Some(Arc::new(err)));
+ *self.online_status.lock().await = (Instant::now(), Err(err.clone()));
+ return Err(err);
+ }
+ Ok(s) => s,
+ };
+ if !session
+ .capabilities
+ .contains_key("urn:ietf:params:jmap:core")
+ {
+ let err = MeliError::new(format!("Server {} did not return JMAP Core capability (urn:ietf:params:jmap:core). Returned capabilities were: {}", &self.server_conf.server_hostname, session.capabilities.keys().map(String::as_str).collect::>().join(", ")));
+ *self.online_status.lock().await = (Instant::now(), Err(err.clone()));
+ return Err(err);
+ }
+ if !session
+ .capabilities
+ .contains_key("urn:ietf:params:jmap:mail")
+ {
+ let err = MeliError::new(format!("Server {} does not support JMAP Mail capability (urn:ietf:params:jmap:mail). Returned capabilities were: {}", &self.server_conf.server_hostname, session.capabilities.keys().map(String::as_str).collect::>().join(", ")));
+ *self.online_status.lock().await = (Instant::now(), Err(err.clone()));
+ return Err(err);
+ }
+
+ *self.online_status.lock().await = (Instant::now(), Ok(()));
+ self.session = session;
+ Ok(())
+ }
+
pub fn mail_account_id(&self) -> &Id {
&self.session.primary_accounts["urn:ietf:params:jmap:mail"]
}
diff --git a/melib/src/backends/jmap/operations.rs b/melib/src/backends/jmap/operations.rs
index 4b093ba4..0605b484 100644
--- a/melib/src/backends/jmap/operations.rs
+++ b/melib/src/backends/jmap/operations.rs
@@ -20,72 +20,69 @@
*/
use super::*;
-use std::cell::Cell;
use std::sync::{Arc, RwLock};
/// `BackendOp` implementor for Imap
#[derive(Debug, Clone)]
pub struct JmapOp {
hash: EnvelopeHash,
- connection: Arc,
+ connection: Arc>,
store: Arc>,
- bytes: Option,
- flags: Cell