Compare commits

...

31 Commits

Author SHA1 Message Date
link2xt
6a3902d90d chore(release): prepare for 1.140.2 2024-06-07 22:22:27 +00:00
Simon Laux
d412887bf4 refactor(@deltachat/stdio-rpc-server): use old school require instead of the experimental json import (#5628)
to get rid of warning. Should also make it possible to use nodejs versions older than 20.11.
2024-06-07 21:34:12 +00:00
Simon Laux
9c2526bbdd fix(@deltachat/stdio-rpc-server): make local non-symlinked installation possible by using absolute paths for local dev version (#5679)
this fixes the local non-symlinked (copied) instalation with `npm i
--install-links=true` possible

I probably need this for flatpak building.
2024-06-07 21:32:57 +00:00
iequidoo
889b947792 api(jsonrpc): Add set_draft_vcard(.., msg_id, contacts)
Add a function setting a vCard containing the given contacts to the message draft. This should
simplify sending contacts as vCards for apps.
2024-06-06 16:14:47 -03:00
iequidoo
0a0e7156e0 fix: Revert member addition if the corresponding message couldn't be sent (#5508) 2024-06-06 11:53:53 -03:00
iequidoo
24a06d175e fix: Remove group member locally even if send_msg() fails (#5508)
Otherwise it's impossible to remove a member with missing key from a protected group. In the worst
case a removed member will be added back due to the group membership consistency algo.
2024-06-06 11:53:53 -03:00
iequidoo
980bab3040 test: Don't leave protected group if some member's key is missing (#5508)
The "I left the group" message can't be sent to a protected group if some member's key is missing,
in this case we should remain in the group. The problem should be fixed first, then the user may
retry to leave the group.
2024-06-06 11:53:53 -03:00
dependabot[bot]
b6dceb4271 chore(cargo): bump backtrace from 0.3.71 to 0.3.72
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.71 to 0.3.72.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.71...0.3.72)

---
updated-dependencies:
- dependency-name: backtrace
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-06 00:14:10 +00:00
iequidoo
87a57cd63b fix: Allow fetch_existing_msgs for bots (#4976)
There was a comment in `fetch_existing_msgs()`: "Bots don't want those messages". If a bot doesn't
want this setting, why enable it? It's disabled by default anyway.
2024-06-05 21:11:50 -03:00
iequidoo
25b8a482bc test: Set fetch_existing_msgs for bots (#4976)
A bot process is run asynchronously, so some messages can arrive before the bot is fully
initialised.
2024-06-05 18:27:20 -03:00
dependabot[bot]
d7dd563df4 chore(cargo): bump schemars from 0.8.19 to 0.8.21
Bumps [schemars](https://github.com/GREsau/schemars) from 0.8.19 to 0.8.21.
- [Release notes](https://github.com/GREsau/schemars/releases)
- [Changelog](https://github.com/GREsau/schemars/blob/master/CHANGELOG.md)
- [Commits](https://github.com/GREsau/schemars/compare/v0.8.19...v0.8.21)

---
updated-dependencies:
- dependency-name: schemars
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 19:42:09 +00:00
link2xt
6d720b793d chore(release): prepare for 1.140.1 2024-06-05 19:07:26 +00:00
dependabot[bot]
6cc3e0a19a chore(cargo): bump libc from 0.2.153 to 0.2.155
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.153 to 0.2.155.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.153...0.2.155)

---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 18:40:19 +00:00
link2xt
380116d107 fix: do not miss new messages while expunging the folder
This should fix flaky `test_verified_group_vs_delete_server_after`.
2024-06-05 18:15:23 +00:00
link2xt
216b295f52 docs(imap): document why CLOSE is faster than EXPUNGE 2024-06-05 18:15:23 +00:00
link2xt
388980ed6c refactor: remove unused select_folder::Error variants 2024-06-05 18:15:23 +00:00
dependabot[bot]
2a2983ace0 chore(cargo): bump serde_json from 1.0.116 to 1.0.117
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.116 to 1.0.117.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.116...v1.0.117)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 15:03:39 -03:00
dependabot[bot]
a7f56e164e chore(cargo): bump num-traits from 0.2.18 to 0.2.19
Bumps [num-traits](https://github.com/rust-num/num-traits) from 0.2.18 to 0.2.19.
- [Changelog](https://github.com/rust-num/num-traits/blob/master/RELEASES.md)
- [Commits](https://github.com/rust-num/num-traits/compare/num-traits-0.2.18...num-traits-0.2.19)

---
updated-dependencies:
- dependency-name: num-traits
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 17:01:23 +00:00
dependabot[bot]
db4183596c chore(cargo): bump tokio-util from 0.7.10 to 0.7.11
Bumps [tokio-util](https://github.com/tokio-rs/tokio) from 0.7.10 to 0.7.11.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-util-0.7.10...tokio-util-0.7.11)

---
updated-dependencies:
- dependency-name: tokio-util
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 17:00:30 +00:00
dependabot[bot]
2b06e672de chore(cargo): bump serde from 1.0.200 to 1.0.203
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.200 to 1.0.203.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.200...v1.0.203)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 15:18:44 +00:00
link2xt
e596664753 fix: log messages with info! instead of println! 2024-06-05 13:16:21 +00:00
link2xt
79d1c96db4 refactor: improve SMTP logs and errors 2024-06-05 13:16:21 +00:00
dependabot[bot]
cc7c235556 chore(cargo): bump tokio from 1.37.0 to 1.38.0
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.37.0 to 1.38.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.37.0...tokio-1.38.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 11:24:10 +00:00
dependabot[bot]
56960882ce chore(cargo): bump async-channel from 2.2.1 to 2.3.1
Bumps [async-channel](https://github.com/smol-rs/async-channel) from 2.2.1 to 2.3.1.
- [Release notes](https://github.com/smol-rs/async-channel/releases)
- [Changelog](https://github.com/smol-rs/async-channel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smol-rs/async-channel/compare/v2.2.1...v2.3.1)

---
updated-dependencies:
- dependency-name: async-channel
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 11:23:48 +00:00
dependabot[bot]
b11c2c6cc5 chore(cargo): bump thiserror from 1.0.59 to 1.0.61
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.59 to 1.0.61.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.59...1.0.61)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 11:22:17 +00:00
dependabot[bot]
12e0a1962d chore(cargo): bump parking_lot from 0.12.2 to 0.12.3
Bumps [parking_lot](https://github.com/Amanieu/parking_lot) from 0.12.2 to 0.12.3.
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/0.12.2...0.12.3)

---
updated-dependencies:
- dependency-name: parking_lot
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 11:21:52 +00:00
dependabot[bot]
f379bea669 chore(cargo): bump toml from 0.8.12 to 0.8.13
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.12 to 0.8.13.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.12...toml-v0.8.13)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 11:21:23 +00:00
dependabot[bot]
bf674151cc chore(cargo): bump syn from 2.0.60 to 2.0.66
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.60 to 2.0.66.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.60...2.0.66)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 11:19:52 +00:00
dependabot[bot]
c11cb5fb3e chore(cargo): bump anyhow from 1.0.82 to 1.0.86
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.82 to 1.0.86.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.82...1.0.86)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 11:18:15 +00:00
link2xt
941208cc64 test(deltachat-rpc-client): reenable log_cli
It was accidentally disabled in f4dfc79808
2024-06-05 09:55:44 +00:00
iequidoo
9f3cbdc873 fix: Set Config::IsChatmail in configure()
`IsChatmail` is set also by `inbox_fetch_idle()`, but it isn't called during `configure()`. Setting
`IsChatmail` from `inbox_fetch_idle()` is necessary to handle client/server upgrades, but
`IsChatmail` also should be available for the app after configuring an account, e.g. DC Android
needs it to know whether to ask the user to disable battery optimisations.
2024-06-04 17:41:38 -03:00
34 changed files with 435 additions and 233 deletions

View File

@@ -1,5 +1,55 @@
# Changelog
## [1.140.2] - 2024-06-07
### API-Changes
- jsonrpc: Add set_draft_vcard(.., msg_id, contacts).
### Fixes
- Allow fetch_existing_msgs for bots ([#4976](https://github.com/deltachat/deltachat-core-rust/pull/4976)).
- Remove group member locally even if send_msg() fails ([#5508](https://github.com/deltachat/deltachat-core-rust/pull/5508)).
- Revert member addition if the corresponding message couldn't be sent ([#5508](https://github.com/deltachat/deltachat-core-rust/pull/5508)).
- @deltachat/stdio-rpc-server: Make local non-symlinked installation possible by using absolute paths for local dev version ([#5679](https://github.com/deltachat/deltachat-core-rust/pull/5679)).
### Miscellaneous Tasks
- cargo: Bump schemars from 0.8.19 to 0.8.21.
- cargo: Bump backtrace from 0.3.71 to 0.3.72.
### Refactor
- @deltachat/stdio-rpc-server: Use old school require instead of the experimental json import ([#5628](https://github.com/deltachat/deltachat-core-rust/pull/5628)).
### Tests
- Set fetch_existing_msgs for bots ([#4976](https://github.com/deltachat/deltachat-core-rust/pull/4976)).
- Don't leave protected group if some member's key is missing ([#5508](https://github.com/deltachat/deltachat-core-rust/pull/5508)).
## [1.140.1] - 2024-06-05
### Fixes
- Retry sending MDNs on temporary error.
- Set Config::IsChatmail in configure().
- Do not miss new messages while expunging the folder.
- Log messages with `info!` instead of `println!`.
### Documentation
- imap: Document why CLOSE is faster than EXPUNGE.
### Refactor
- imap: Make select_folder() accept non-optional folder.
- Improve SMTP logs and errors.
- Remove unused `select_folder::Error` variants.
### Tests
- deltachat-rpc-client: reenable `log_cli`.
## [1.140.0] - 2024-06-04
### Features / Changes
@@ -4371,3 +4421,5 @@ https://github.com/deltachat/deltachat-core-rust/pulls?q=is%3Apr+is%3Aclosed
[1.139.5]: https://github.com/deltachat/deltachat-core-rust/compare/v1.139.4...v1.139.5
[1.139.6]: https://github.com/deltachat/deltachat-core-rust/compare/v1.139.5...v1.139.6
[1.140.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.139.6...v1.140.0
[1.140.1]: https://github.com/deltachat/deltachat-core-rust/compare/v1.140.0...v1.140.1
[1.140.2]: https://github.com/deltachat/deltachat-core-rust/compare/v1.140.1...v1.140.2

204
Cargo.lock generated
View File

@@ -17,9 +17,9 @@ dependencies = [
[[package]]
name = "addr2line"
version = "0.21.0"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
dependencies = [
"gimli",
]
@@ -174,9 +174,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.82"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
dependencies = [
"backtrace",
]
@@ -251,7 +251,7 @@ checksum = "7378575ff571966e99a744addeff0bff98b8ada0dedf1956d59e634db95eaac1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
"synstructure 0.13.1",
]
@@ -274,7 +274,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -302,12 +302,11 @@ dependencies = [
[[package]]
name = "async-channel"
version = "2.2.1"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "136d4d23bcc79e27423727b36823d86233aad06dfea531837b038394d11e9928"
checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
dependencies = [
"concurrent-queue",
"event-listener 5.2.0",
"event-listener-strategy",
"futures-core",
"pin-project-lite",
@@ -332,7 +331,7 @@ version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98892ebee4c05fc66757e600a7466f0d9bfcde338f645d64add323789f26cb36"
dependencies = [
"async-channel 2.2.1",
"async-channel 2.3.1",
"base64 0.21.7",
"bytes",
"chrono",
@@ -394,7 +393,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -499,9 +498,9 @@ dependencies = [
[[package]]
name = "backtrace"
version = "0.3.71"
version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11"
dependencies = [
"addr2line",
"cc",
@@ -780,9 +779,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.90"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f"
[[package]]
name = "cfb-mode"
@@ -933,9 +932,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "concurrent-queue"
version = "2.4.0"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363"
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
dependencies = [
"crossbeam-utils",
]
@@ -1213,7 +1212,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -1324,12 +1323,12 @@ dependencies = [
[[package]]
name = "deltachat"
version = "1.140.0"
version = "1.140.2"
dependencies = [
"ansi_term",
"anyhow",
"async-broadcast",
"async-channel 2.2.1",
"async-channel 2.3.1",
"async-imap",
"async-native-tls",
"async-smtp",
@@ -1418,10 +1417,10 @@ dependencies = [
[[package]]
name = "deltachat-jsonrpc"
version = "1.140.0"
version = "1.140.2"
dependencies = [
"anyhow",
"async-channel 2.2.1",
"async-channel 2.3.1",
"axum",
"base64 0.22.1",
"deltachat",
@@ -1443,7 +1442,7 @@ dependencies = [
[[package]]
name = "deltachat-repl"
version = "1.140.0"
version = "1.140.2"
dependencies = [
"ansi_term",
"anyhow",
@@ -1458,7 +1457,7 @@ dependencies = [
[[package]]
name = "deltachat-rpc-server"
version = "1.140.0"
version = "1.140.2"
dependencies = [
"anyhow",
"deltachat",
@@ -1482,12 +1481,12 @@ name = "deltachat_derive"
version = "2.0.0"
dependencies = [
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
name = "deltachat_ffi"
version = "1.140.0"
version = "1.140.2"
dependencies = [
"anyhow",
"deltachat",
@@ -1575,7 +1574,7 @@ checksum = "5fe87ce4529967e0ba1dcf8450bab64d97dfd5010a6256187ffe2e43e6f0e049"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -1649,7 +1648,7 @@ checksum = "2bba3e9872d7c58ce7ef0fcf1844fcc3e23ef2a58377b50df35dd98e42a5726e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
"unicode-xid",
]
@@ -1739,7 +1738,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -2079,7 +2078,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -2092,7 +2091,7 @@ dependencies = [
"num-traits",
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -2112,7 +2111,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -2214,9 +2213,9 @@ dependencies = [
[[package]]
name = "event-listener-strategy"
version = "0.5.0"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291"
checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1"
dependencies = [
"event-listener 5.2.0",
"pin-project-lite",
@@ -2501,7 +2500,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -2603,9 +2602,9 @@ dependencies = [
[[package]]
name = "gimli"
version = "0.28.1"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
[[package]]
name = "glob"
@@ -3555,9 +3554,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.153"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libm"
@@ -3981,7 +3980,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -4006,9 +4005,9 @@ dependencies = [
[[package]]
name = "num-traits"
version = "0.2.18"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
"libm",
@@ -4042,14 +4041,14 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
name = "object"
version = "0.32.2"
version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e"
dependencies = [
"memchr",
]
@@ -4113,7 +4112,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -4245,9 +4244,9 @@ checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae"
[[package]]
name = "parking_lot"
version = "0.12.2"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core",
@@ -4346,7 +4345,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -4433,7 +4432,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -4566,7 +4565,7 @@ dependencies = [
"proc-macro2",
"quote",
"regex",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -4744,9 +4743,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.81"
version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
dependencies = [
"unicode-ident",
]
@@ -4771,7 +4770,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -5387,9 +5386,9 @@ checksum = "efe2374f2385cdd8755a446f80b2a646de603c9d8539ca38734879b5c71e378b"
[[package]]
name = "rustc-demangle"
version = "0.1.23"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustc-hash"
@@ -5585,9 +5584,9 @@ dependencies = [
[[package]]
name = "schemars"
version = "0.8.19"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc6e7ed6919cb46507fb01ff1654309219f62b4d603822501b0b80d42f6f21ef"
checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92"
dependencies = [
"dyn-clone",
"schemars_derive",
@@ -5597,14 +5596,14 @@ dependencies = [
[[package]]
name = "schemars_derive"
version = "0.8.19"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "185f2b7aa7e02d418e453790dde16890256bbd2bcd04b7dc5348811052b53f49"
checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e"
dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -5691,9 +5690,9 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.200"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f"
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [
"serde_derive",
]
@@ -5718,13 +5717,13 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.200"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb"
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -5735,14 +5734,14 @@ checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
name = "serde_json"
version = "1.0.116"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
dependencies = [
"itoa",
"ryu",
@@ -5761,9 +5760,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
version = "0.6.5"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
dependencies = [
"serde",
]
@@ -6093,7 +6092,7 @@ dependencies = [
"proc-macro2",
"quote",
"struct_iterable_internal",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -6121,7 +6120,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -6183,9 +6182,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.60"
version = "2.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
dependencies = [
"proc-macro2",
"quote",
@@ -6224,7 +6223,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -6334,22 +6333,22 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.59"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.59"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -6431,9 +6430,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.37.0"
version = "1.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
dependencies = [
"backtrace",
"bytes",
@@ -6460,13 +6459,13 @@ dependencies = [
[[package]]
name = "tokio-macros"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -6583,35 +6582,34 @@ dependencies = [
[[package]]
name = "tokio-util"
version = "0.7.10"
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
"tracing",
]
[[package]]
name = "toml"
version = "0.8.12"
version = "0.8.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit 0.22.9",
"toml_edit 0.22.13",
]
[[package]]
name = "toml_datetime"
version = "0.6.5"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
dependencies = [
"serde",
]
@@ -6629,9 +6627,9 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.22.9"
version = "0.22.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4"
checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c"
dependencies = [
"indexmap",
"serde",
@@ -6688,7 +6686,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -7023,7 +7021,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
"wasm-bindgen-shared",
]
@@ -7057,7 +7055,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -7240,7 +7238,7 @@ checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -7251,7 +7249,7 @@ checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -7657,7 +7655,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]
@@ -7677,7 +7675,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"syn 2.0.66",
]
[[package]]

View File

@@ -1,6 +1,6 @@
[package]
name = "deltachat"
version = "1.140.0"
version = "1.140.2"
edition = "2021"
license = "MPL-2.0"
rust-version = "1.77"
@@ -40,7 +40,7 @@ ratelimit = { path = "./deltachat-ratelimit" }
anyhow = { workspace = true }
async-broadcast = "0.7.0"
async-channel = "2.2.1"
async-channel = "2.3.1"
async-imap = { version = "0.9.7", default-features = false, features = ["runtime-tokio"] }
async-native-tls = { version = "0.5", default-features = false, features = ["runtime-tokio"] }
async-smtp = { version = "0.9", default-features = false, features = ["runtime-tokio"] }
@@ -95,11 +95,11 @@ strum_macros = "0.26"
tagger = "4.3.4"
textwrap = "0.16.1"
thiserror = "1"
tokio = { version = "1.37.0", features = ["fs", "rt-multi-thread", "macros"] }
tokio = { version = "1.38.0", features = ["fs", "rt-multi-thread", "macros"] }
tokio-io-timeout = "1.2.0"
tokio-stream = { version = "0.1.15", features = ["fs"] }
tokio-tar = { version = "0.3" } # TODO: integrate tokio into async-tar
tokio-util = "0.7.9"
tokio-util = "0.7.11"
toml = "0.8"
url = "2"
uuid = { version = "1", features = ["serde", "v4"] }
@@ -113,7 +113,7 @@ log = "0.4"
proptest = { version = "1", default-features = false, features = ["std"] }
tempfile = "3"
testdir = "0.9.0"
tokio = { version = "1.37.0", features = ["parking_lot", "rt-multi-thread", "macros"] }
tokio = { version = "1.38.0", features = ["parking_lot", "rt-multi-thread", "macros"] }
pretty_assertions = "1.3.0"
[workspace]

View File

@@ -1,6 +1,6 @@
[package]
name = "deltachat_ffi"
version = "1.140.0"
version = "1.140.2"
description = "Deltachat FFI"
edition = "2018"
readme = "README.md"
@@ -20,7 +20,7 @@ libc = "0.2"
human-panic = { version = "2", default-features = false }
num-traits = "0.2"
serde_json = "1.0"
tokio = { version = "1.37.0", features = ["rt-multi-thread"] }
tokio = { version = "1.38.0", features = ["rt-multi-thread"] }
anyhow = "1"
thiserror = "1"
rand = "0.8"

View File

@@ -1,6 +1,6 @@
[package]
name = "deltachat-jsonrpc"
version = "1.140.0"
version = "1.140.2"
description = "DeltaChat JSON-RPC API"
edition = "2021"
default-run = "deltachat-jsonrpc-server"
@@ -17,16 +17,16 @@ anyhow = "1"
deltachat = { path = ".." }
deltachat-contact-tools = { path = "../deltachat-contact-tools" }
num-traits = "0.2"
schemars = "0.8.19"
schemars = "0.8.21"
serde = { version = "1.0", features = ["derive"] }
tempfile = "3.10.1"
log = "0.4"
async-channel = { version = "2.2.1" }
async-channel = { version = "2.3.1" }
futures = { version = "0.3.30" }
serde_json = "1"
yerpc = { version = "0.5.2", features = ["anyhow_expose", "openrpc"] }
typescript-type-def = { version = "0.5.8", features = ["json_value"] }
tokio = { version = "1.37.0" }
tokio = { version = "1.38.0" }
sanitize-filename = "0.5"
walkdir = "2.5.0"
base64 = "0.22"
@@ -36,7 +36,7 @@ axum = { version = "0.7", optional = true, features = ["ws"] }
env_logger = { version = "0.11.3", optional = true }
[dev-dependencies]
tokio = { version = "1.37.0", features = ["full", "rt-multi-thread"] }
tokio = { version = "1.38.0", features = ["full", "rt-multi-thread"] }
[features]

View File

@@ -1476,6 +1476,20 @@ impl CommandApi {
deltachat::contact::make_vcard(&ctx, &contacts).await
}
/// Sets vCard containing the given contacts to the message draft.
async fn set_draft_vcard(
&self,
account_id: u32,
msg_id: u32,
contacts: Vec<u32>,
) -> Result<()> {
let ctx = self.get_context(account_id).await?;
let contacts: Vec<_> = contacts.iter().map(|&c| ContactId::new(c)).collect();
let mut msg = Message::load_from_db(&ctx, MsgId::new(msg_id)).await?;
msg.make_vcard(&ctx, &contacts).await?;
msg.get_chat_id().set_draft(&ctx, Some(&mut msg)).await
}
// ---------------------------------------------
// chat
// ---------------------------------------------

View File

@@ -58,5 +58,5 @@
},
"type": "module",
"types": "dist/deltachat.d.ts",
"version": "1.140.0"
"version": "1.140.2"
}

View File

@@ -1,6 +1,6 @@
[package]
name = "deltachat-repl"
version = "1.140.0"
version = "1.140.2"
license = "MPL-2.0"
edition = "2021"
repository = "https://github.com/deltachat/deltachat-core-rust"
@@ -13,7 +13,7 @@ dirs = "5"
log = "0.4.21"
rusqlite = "0.31"
rustyline = "14"
tokio = { version = "1.37.0", features = ["fs", "rt-multi-thread", "macros"] }
tokio = { version = "1.38.0", features = ["fs", "rt-multi-thread", "macros"] }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
[features]

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "deltachat-rpc-client"
version = "1.140.0"
version = "1.140.2"
description = "Python client for Delta Chat core JSON-RPC interface"
classifiers = [
"Development Status :: 5 - Production/Stable",

View File

@@ -28,5 +28,5 @@ commands =
[pytest]
timeout = 300
#log_cli = true
log_cli = true
log_level = debug

View File

@@ -1,6 +1,6 @@
[package]
name = "deltachat-rpc-server"
version = "1.140.0"
version = "1.140.2"
description = "DeltaChat JSON-RPC server"
edition = "2021"
readme = "README.md"
@@ -18,8 +18,8 @@ futures-lite = "2.3.0"
log = "0.4"
serde_json = "1"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.37.0", features = ["io-std"] }
tokio-util = "0.7.9"
tokio = { version = "1.38.0", features = ["io-std"] }
tokio-util = "0.7.11"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
yerpc = { version = "0.5.2", features = ["anyhow_expose", "openrpc"] }

View File

@@ -7,7 +7,7 @@ This simplifies cross-compilation and even reduces binary size (no CFFI layer an
## Usage
> The **minimum** nodejs version for this package is `20.11`
> The **minimum** nodejs version for this package is `16`
```
npm i @deltachat/stdio-rpc-server @deltachat/jsonrpc-client

View File

@@ -11,9 +11,6 @@ import {
NPM_NOT_FOUND_UNSUPPORTED_PLATFORM_ERROR,
} from "./src/errors.js";
// Because this is not compiled by typescript, esm needs this stuff (` with { type: "json" };`,
// nodejs still complains about it being experimental, but deno also uses it, so treefit bets taht it will become standard)
import package_json from "./package.json" with { type: "json" };
import { createRequire } from "node:module";
function findRPCServerInNodeModules() {
@@ -25,7 +22,12 @@ function findRPCServerInNodeModules() {
return resolve(package_name);
} catch (error) {
console.debug("findRpcServerInNodeModules", error);
if (Object.keys(package_json.optionalDependencies).includes(package_name)) {
const require = createRequire(import.meta.url);
if (
Object.keys(require("./package.json").optionalDependencies).includes(
package_name
)
) {
throw new Error(NPM_NOT_FOUND_SUPPORTED_PLATFORM_ERROR(package_name));
} else {
throw new Error(NPM_NOT_FOUND_UNSUPPORTED_PLATFORM_ERROR());

View File

@@ -15,5 +15,5 @@
},
"type": "module",
"types": "index.d.ts",
"version": "1.140.0"
"version": "1.140.2"
}

View File

@@ -55,9 +55,10 @@ for (const { folder_name, package_name } of platform_package_names) {
}
if (is_local) {
package_json.peerDependencies["@deltachat/jsonrpc-client"] = 'file:../../deltachat-jsonrpc/typescript'
package_json.peerDependencies["@deltachat/jsonrpc-client"] =
`file:${join(expected_cwd, "/../../deltachat-jsonrpc/typescript")}`;
} else {
package_json.peerDependencies["@deltachat/jsonrpc-client"] = "*"
package_json.peerDependencies["@deltachat/jsonrpc-client"] = "*";
}
await fs.writeFile("./package.json", JSON.stringify(package_json, null, 4));

View File

@@ -55,5 +55,5 @@
"test:mocha": "mocha node/test/test.mjs --growl --reporter=spec --bail --exit"
},
"types": "node/dist/index.d.ts",
"version": "1.140.0"
"version": "1.140.2"
}

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "deltachat"
version = "1.140.0"
version = "1.140.2"
description = "Python bindings for the Delta Chat Core library using CFFI against the Rust-implemented libdeltachat"
readme = "README.rst"
requires-python = ">=3.7"

View File

@@ -551,6 +551,9 @@ class ACFactory:
fn = module.__file__
bot_cfg = self.get_next_liveconfig()
# The bot process is run asynchronously, so some messages can arrive before the bot is fully
# initialised.
bot_cfg["fetch_existing_msgs"] = "1"
bot_ac = self.prepare_account_from_liveconfig(bot_cfg)
# Forget ac as it will be opened by the bot subprocess

View File

@@ -1 +1 @@
2024-06-04
2024-06-07

View File

@@ -3760,7 +3760,10 @@ pub(crate) async fn add_contact_to_chat_ex(
msg.param.set_cmd(SystemMessage::MemberAddedToGroup);
msg.param.set(Param::Arg, contact_addr);
msg.param.set_int(Param::Arg2, from_handshake.into());
msg.id = send_msg(context, chat_id, &mut msg).await?;
if let Err(e) = send_msg(context, chat_id, &mut msg).await {
remove_from_chat_contacts_table(context, chat_id, contact_id).await?;
return Err(e);
}
sync = Nosync;
}
context.emit_event(EventType::ChatModified(chat_id));
@@ -3916,8 +3919,7 @@ pub async fn remove_contact_from_chat(
if let Some(contact) = Contact::get_by_id_optional(context, contact_id).await? {
if chat.typ == Chattype::Group && chat.is_promoted() {
msg.viewtype = Viewtype::Text;
if contact.id == ContactId::SELF {
set_group_explicitly_left(context, &chat.grpid).await?;
if contact_id == ContactId::SELF {
msg.text = stock_str::msg_group_left_local(context, ContactId::SELF).await;
} else {
msg.text = stock_str::msg_del_member_local(
@@ -3929,17 +3931,24 @@ pub async fn remove_contact_from_chat(
}
msg.param.set_cmd(SystemMessage::MemberRemovedFromGroup);
msg.param.set(Param::Arg, contact.get_addr().to_lowercase());
msg.id = send_msg(context, chat_id, &mut msg).await?;
let res = send_msg(context, chat_id, &mut msg).await;
if contact_id == ContactId::SELF {
res?;
set_group_explicitly_left(context, &chat.grpid).await?;
} else if let Err(e) = res {
warn!(context, "remove_contact_from_chat({chat_id}, {contact_id}): send_msg() failed: {e:#}.");
}
} else {
sync = Sync;
}
}
// we remove the member from the chat after constructing the
// to-be-send message. If between send_msg() and here the
// process dies the user will have to re-do the action. It's
// better than the other way round: you removed
// someone from DB but no peer or device gets to know about it and
// group membership is thus different on different devices.
// process dies, the user will be able to redo the action. It's better than the other
// way round: you removed someone from DB but no peer or device gets to know about it
// and group membership is thus different on different devices. But if send_msg()
// failed, we still remove the member locally, otherwise it would be impossible to
// remove a member with missing key from a protected group.
// Note also that sending a message needs all recipients
// in order to correctly determine encryption so if we
// removed it first, it would complicate the
@@ -5023,6 +5032,7 @@ mod tests {
// Bob leaves the chat.
remove_contact_from_chat(&bob, bob_chat_id, ContactId::SELF).await?;
bob.pop_sent_msg().await;
// Bob receives a msg about Alice adding Claire to the group.
bob.recv_msg(&alice_sent_add_msg).await;
@@ -5075,6 +5085,7 @@ mod tests {
let sent_msg = alice.pop_sent_msg().await;
bob.recv_msg(&sent_msg).await;
remove_contact_from_chat(&bob, bob_chat_id, bob_fiona_contact_id).await?;
bob.pop_sent_msg().await;
// This doesn't add Fiona back because Bob just removed them.
let sent_msg = alice.send_text(alice_chat_id, "Welcome, Fiona!").await;

View File

@@ -459,6 +459,7 @@ async fn configure(ctx: &Context, param: &mut LoginParam) -> Result<()> {
progress!(ctx, 900);
if imap_session.is_chatmail() {
ctx.set_config(Config::IsChatmail, Some("1")).await?;
ctx.set_config(Config::SentboxWatch, None).await?;
ctx.set_config(Config::MvboxMove, Some("0")).await?;
ctx.set_config(Config::OnlyFetchMvbox, None).await?;

View File

@@ -184,7 +184,7 @@ impl Session {
bail!("Attempt to fetch UID 0");
}
self.select_folder(context, folder).await?;
self.select_with_uidvalidity(context, folder).await?;
// we are connected, and the folder is selected
info!(context, "Downloading message {}/{} fully...", folder, uid);

View File

@@ -313,7 +313,7 @@ impl Imap {
if !ratelimit_duration.is_zero() {
warn!(
context,
"IMAP got rate limited, waiting for {} until can connect",
"IMAP got rate limited, waiting for {} until can connect.",
duration_to_str(ratelimit_duration),
);
let interrupted = async {
@@ -543,15 +543,16 @@ impl Imap {
return Ok(false);
}
let new_emails = session
session
.select_with_uidvalidity(context, folder)
.await
.with_context(|| format!("Failed to select folder {folder:?}"))?;
if !new_emails && !fetch_existing_msgs {
if !session.new_mail && !fetch_existing_msgs {
info!(context, "No new emails in folder {folder:?}.");
return Ok(false);
}
session.new_mail = false;
let uid_validity = get_uidvalidity(context, folder).await?;
let old_uid_next = get_uid_next(context, folder).await?;
@@ -765,10 +766,6 @@ impl Imap {
context: &Context,
session: &mut Session,
) -> Result<()> {
if context.get_config_bool(Config::Bot).await? {
return Ok(()); // Bots don't want those messages
}
add_all_recipients_as_contacts(context, session, Config::ConfiguredSentboxFolder)
.await
.context("failed to get recipients from the sentbox")?;
@@ -838,7 +835,7 @@ impl Session {
// Collect pairs of UID and Message-ID.
let mut msgs = BTreeMap::new();
self.select_folder(context, folder).await?;
self.select_with_uidvalidity(context, folder).await?;
let mut list = self
.uid_fetch("1:*", RFC724MID_UID)
@@ -1039,7 +1036,7 @@ impl Session {
// MOVE/DELETE operations. This does not result in multiple SELECT commands
// being sent because `select_folder()` does nothing if the folder is already
// selected.
self.select_folder(context, folder).await?;
self.select_with_uidvalidity(context, folder).await?;
// Empty target folder name means messages should be deleted.
if target.is_empty() {
@@ -1087,7 +1084,7 @@ impl Session {
.await?;
for (folder, rowid_set, uid_set) in UidGrouper::from(rows) {
self.select_folder(context, &folder)
self.select_with_uidvalidity(context, &folder)
.await
.context("failed to select folder")?;
@@ -1131,7 +1128,7 @@ impl Session {
return Ok(());
}
self.select_folder(context, folder)
self.select_with_uidvalidity(context, folder)
.await
.context("failed to select folder")?;

View File

@@ -29,9 +29,13 @@ impl Session {
) -> Result<Self> {
use futures::future::FutureExt;
self.select_folder(context, folder).await?;
self.select_with_uidvalidity(context, folder).await?;
if self.server_sent_unsolicited_exists(context)? {
self.new_mail = true;
}
if self.new_mail {
return Ok(self);
}
@@ -92,6 +96,9 @@ impl Session {
session.as_mut().set_read_timeout(Some(IMAP_TIMEOUT));
self.inner = session;
// Fetch mail once we exit IDLE.
self.new_mail = true;
Ok(self)
}
}

View File

@@ -10,12 +10,6 @@ type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("IMAP Connection Lost or no connection established")]
ConnectionLost,
#[error("IMAP Folder name invalid: {0}")]
BadFolderName(String),
#[error("Got a NO response when trying to select {0}, usually this means that it doesn't exist: {1}")]
NoFolder(String, String),
@@ -33,7 +27,8 @@ impl ImapSession {
/// Issues a CLOSE command if selected folder needs expunge,
/// i.e. if Delta Chat marked a message there as deleted previously.
///
/// CLOSE is considerably faster than an EXPUNGE, see
/// CLOSE is considerably faster than an EXPUNGE
/// because no EXPUNGE responses are sent, see
/// <https://tools.ietf.org/html/rfc3501#section-6.4.2>
pub(super) async fn maybe_close_folder(&mut self, context: &Context) -> anyhow::Result<()> {
if let Some(folder) = &self.selected_folder {
@@ -44,6 +39,7 @@ impl ImapSession {
info!(context, "close/expunge succeeded");
self.selected_folder = None;
self.selected_folder_needs_expunge = false;
self.new_mail = false;
}
}
Ok(())
@@ -52,11 +48,7 @@ impl ImapSession {
/// Selects a folder, possibly updating uid_validity and, if needed,
/// expunging the folder to remove delete-marked messages.
/// Returns whether a new folder was selected.
pub(crate) async fn select_folder(
&mut self,
context: &Context,
folder: &str,
) -> Result<NewlySelected> {
async fn select_folder(&mut self, context: &Context, folder: &str) -> Result<NewlySelected> {
// if there is a new folder and the new folder is equal to the selected one, there's nothing to do.
// if there is _no_ new folder, we continue as we might want to expunge below.
if let Some(selected_folder) = &self.selected_folder {
@@ -85,10 +77,6 @@ impl ImapSession {
self.selected_mailbox = Some(mailbox);
Ok(NewlySelected::Yes)
}
Err(async_imap::error::Error::ConnectionLost) => Err(Error::ConnectionLost),
Err(async_imap::error::Error::Validate(_)) => {
Err(Error::BadFolderName(folder.to_string()))
}
Err(async_imap::error::Error::No(response)) => {
Err(Error::NoFolder(folder.to_string(), response))
}
@@ -128,13 +116,14 @@ impl ImapSession {
/// When selecting a folder for the first time, sets the uid_next to the current
/// mailbox.uid_next so that no old emails are fetched.
///
/// Returns Result<new_emails> (i.e. whether new emails arrived),
/// if in doubt, returns new_emails=true so emails are fetched.
/// Updates `self.new_mail` if folder was previously unselected
/// and new mails are detected after selecting,
/// i.e. UIDNEXT advanced while the folder was closed.
pub(crate) async fn select_with_uidvalidity(
&mut self,
context: &Context,
folder: &str,
) -> Result<bool> {
) -> Result<()> {
let newly_selected = self
.select_or_create_folder(context, folder)
.await
@@ -191,28 +180,26 @@ impl ImapSession {
mailbox.uid_next = new_uid_next;
if new_uid_validity == old_uid_validity {
let new_emails = if newly_selected == NewlySelected::No {
// The folder was not newly selected i.e. no SELECT command was run. This means that mailbox.uid_next
// was not updated and may contain an incorrect value. So, just return true so that
// the caller tries to fetch new messages (we could of course run a SELECT command now, but trying to fetch
// new messages is only one command, just as a SELECT command)
true
} else if let Some(new_uid_next) = new_uid_next {
if new_uid_next < old_uid_next {
warn!(
context,
"The server illegally decreased the uid_next of folder {folder:?} from {old_uid_next} to {new_uid_next} without changing validity ({new_uid_validity}), resyncing UIDs...",
);
set_uid_next(context, folder, new_uid_next).await?;
context.schedule_resync().await?;
}
new_uid_next != old_uid_next // If UIDNEXT changed, there are new emails
} else {
// We have no UIDNEXT and if in doubt, return true.
true
};
if newly_selected == NewlySelected::Yes {
if let Some(new_uid_next) = new_uid_next {
if new_uid_next < old_uid_next {
warn!(
context,
"The server illegally decreased the uid_next of folder {folder:?} from {old_uid_next} to {new_uid_next} without changing validity ({new_uid_validity}), resyncing UIDs...",
);
set_uid_next(context, folder, new_uid_next).await?;
context.schedule_resync().await?;
}
return Ok(new_emails);
// If UIDNEXT changed, there are new emails.
self.new_mail |= new_uid_next != old_uid_next;
} else {
warn!(context, "Folder {folder} was just selected but we failed to determine UIDNEXT, assume that it has new mail.");
self.new_mail = true;
}
}
return Ok(());
}
// UIDVALIDITY is modified, reset highest seen MODSEQ.
@@ -223,6 +210,7 @@ impl ImapSession {
let new_uid_next = new_uid_next.unwrap_or_default();
set_uid_next(context, folder, new_uid_next).await?;
set_uidvalidity(context, folder, new_uid_validity).await?;
self.new_mail = true;
// Collect garbage entries in `imap` table.
context
@@ -245,7 +233,7 @@ impl ImapSession {
old_uid_next,
old_uid_validity,
);
Ok(false)
Ok(())
}
}

View File

@@ -40,6 +40,11 @@ pub(crate) struct Session {
pub selected_mailbox: Option<Mailbox>,
pub selected_folder_needs_expunge: bool,
/// True if currently selected folder has new messages.
///
/// Should be false if no folder is currently selected.
pub new_mail: bool,
}
impl Deref for Session {
@@ -67,6 +72,7 @@ impl Session {
selected_folder: None,
selected_mailbox: None,
selected_folder_needs_expunge: false,
new_mail: false,
}
}

View File

@@ -16,7 +16,7 @@ use crate::config::Config;
use crate::constants::{
Blocked, Chattype, VideochatType, DC_CHAT_ID_TRASH, DC_DESIRED_TEXT_LEN, DC_MSG_ID_LAST_SPECIAL,
};
use crate::contact::{Contact, ContactId};
use crate::contact::{self, Contact, ContactId};
use crate::context::Context;
use crate::debug_logging::set_debug_logging_xdc;
use crate::download::DownloadState;
@@ -1081,6 +1081,18 @@ impl Message {
Ok(())
}
/// Makes message a vCard-containing message using the specified contacts.
pub async fn make_vcard(&mut self, context: &Context, contacts: &[ContactId]) -> Result<()> {
ensure!(
matches!(self.viewtype, Viewtype::File | Viewtype::Vcard),
"Wrong viewtype for vCard: {}",
self.viewtype,
);
let vcard = contact::make_vcard(context, contacts).await?;
self.set_file_from_bytes(context, "vcard.vcf", vcard.as_bytes(), None)
.await
}
/// Set different sender name for a message.
/// This overrides the name set by the `set_config()`-option `displayname`.
pub fn set_override_sender_name(&mut self, name: Option<String>) {

View File

@@ -10,10 +10,11 @@ use crate::chat::{
};
use crate::chatlist::Chatlist;
use crate::constants::{DC_GCL_FOR_FORWARDING, DC_GCL_NO_SPECIALS};
use crate::contact;
use crate::download::MIN_DOWNLOAD_LIMIT;
use crate::imap::prefetch_should_download;
use crate::imex::{imex, ImexMode};
use crate::test_utils::{get_chat_msg, TestContext, TestContextManager};
use crate::test_utils::{get_chat_msg, mark_as_verified, TestContext, TestContextManager};
use crate::tools::SystemTime;
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -3923,6 +3924,7 @@ async fn test_dont_readd_with_normal_msg() -> Result<()> {
bob_chat_id.accept(&bob).await?;
remove_contact_from_chat(&bob, bob_chat_id, ContactId::SELF).await?;
bob.pop_sent_msg().await;
assert_eq!(get_chat_contacts(&bob, bob_chat_id).await?.len(), 1);
SystemTime::shift(Duration::from_secs(3600));
@@ -4085,6 +4087,7 @@ async fn test_mua_can_readd() -> Result<()> {
// And leaves it.
remove_contact_from_chat(&alice, alice_chat.id, ContactId::SELF).await?;
alice.pop_sent_msg().await;
assert!(!is_contact_in_chat(&alice, alice_chat.id, ContactId::SELF).await?);
// Bob uses a classical MUA to answer, adding Alice back.
@@ -4159,6 +4162,7 @@ async fn test_recreate_member_list_on_missing_add_of_self() -> Result<()> {
// But if Bob just left, they mustn't recreate the member list even after missing a message.
bob_chat_id.accept(&bob).await?;
remove_contact_from_chat(&bob, bob_chat_id, ContactId::SELF).await?;
bob.pop_sent_msg().await;
send_text_msg(&alice, alice_chat_id, "3rd message".to_string()).await?;
alice.pop_sent_msg().await;
send_text_msg(&alice, alice_chat_id, "4th message".to_string()).await?;
@@ -4464,6 +4468,79 @@ Chat-Group-Member-Added: charlie@example.com",
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_leave_protected_group_missing_member_key() -> Result<()> {
let mut tcm = TestContextManager::new();
let alice = &tcm.alice().await;
let bob = &tcm.bob().await;
mark_as_verified(alice, bob).await;
let alice_bob_id = alice.add_or_lookup_contact(bob).await.id;
let group_id = create_group_chat(alice, ProtectionStatus::Protected, "Group").await?;
add_contact_to_chat(alice, group_id, alice_bob_id).await?;
alice.send_text(group_id, "Hello!").await;
alice
.sql
.execute(
"UPDATE acpeerstates SET addr=? WHERE addr=?",
("b@b", "bob@example.net"),
)
.await?;
assert!(remove_contact_from_chat(alice, group_id, ContactId::SELF)
.await
.is_err());
assert!(is_contact_in_chat(alice, group_id, ContactId::SELF).await?);
alice
.sql
.execute(
"UPDATE acpeerstates SET addr=? WHERE addr=?",
("bob@example.net", "b@b"),
)
.await?;
remove_contact_from_chat(alice, group_id, ContactId::SELF).await?;
alice.pop_sent_msg().await;
assert!(!is_contact_in_chat(alice, group_id, ContactId::SELF).await?);
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_protected_group_add_remove_member_missing_key() -> Result<()> {
let mut tcm = TestContextManager::new();
let alice = &tcm.alice().await;
let bob = &tcm.bob().await;
let bob_addr = bob.get_config(Config::Addr).await?.unwrap();
mark_as_verified(alice, bob).await;
let group_id = create_group_chat(alice, ProtectionStatus::Protected, "Group").await?;
let alice_bob_id = alice.add_or_lookup_contact(bob).await.id;
add_contact_to_chat(alice, group_id, alice_bob_id).await?;
alice.send_text(group_id, "Hello!").await;
alice
.sql
.execute("DELETE FROM acpeerstates WHERE addr=?", (&bob_addr,))
.await?;
let fiona = &tcm.fiona().await;
mark_as_verified(alice, fiona).await;
let alice_fiona_id = alice.add_or_lookup_contact(fiona).await.id;
assert!(add_contact_to_chat(alice, group_id, alice_fiona_id)
.await
.is_err());
assert!(!is_contact_in_chat(alice, group_id, alice_fiona_id).await?);
// Now the chat has a message "You added member fiona@example.net. [INFO] !!" (with error) that
// may be confusing, but if the error is displayed in UIs, it's more or less ok. This is not a
// normal scenario anyway.
remove_contact_from_chat(alice, group_id, alice_bob_id).await?;
assert!(!is_contact_in_chat(alice, group_id, alice_bob_id).await?);
let msg = alice.get_last_msg_in(group_id).await;
assert!(msg.is_info());
assert_eq!(
msg.get_text(),
stock_str::msg_del_member_local(alice, &bob_addr, ContactId::SELF,).await
);
assert!(msg.error().is_some());
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_forged_from() -> Result<()> {
let mut tcm = TestContextManager::new();
@@ -4621,6 +4698,39 @@ async fn test_receive_vcard() -> Result<()> {
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_make_n_send_vcard() -> Result<()> {
let mut tcm = TestContextManager::new();
let alice = &tcm.alice().await;
let bob = &tcm.bob().await;
let vcard = "BEGIN:VCARD\n\
VERSION:4.0\n\
FN:Claire\n\
EMAIL;TYPE=work:claire@example.org\n\
END:VCARD";
let contact_ids = contact::import_vcard(alice, vcard).await?;
assert_eq!(contact_ids.len(), 1);
let mut msg = Message::new(Viewtype::File);
msg.make_vcard(alice, &contact_ids).await?;
let alice_bob_chat = alice.create_chat(bob).await;
let sent = alice.send_msg(alice_bob_chat.id, &mut msg).await;
let rcvd = bob.recv_msg(&sent).await;
let sent = Message::load_from_db(alice, sent.sender_msg_id).await?;
assert_eq!(sent.viewtype, Viewtype::Vcard);
assert_eq!(rcvd.viewtype, Viewtype::Vcard);
let vcard = tokio::fs::read(rcvd.get_file(bob).unwrap()).await?;
let vcard = std::str::from_utf8(&vcard)?;
let parsed = deltachat_contact_tools::parse_vcard(vcard);
assert_eq!(parsed.len(), 1);
assert_eq!(&parsed[0].addr, "claire@example.org");
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_group_no_recipients() -> Result<()> {
let t = &TestContext::new_alice().await;

View File

@@ -749,7 +749,7 @@ async fn smtp_loop(
) {
use futures::future::FutureExt;
info!(ctx, "starting smtp loop");
info!(ctx, "Starting SMTP loop.");
let SmtpConnectionHandlers {
mut connection,
stop_receiver,
@@ -760,14 +760,14 @@ async fn smtp_loop(
let fut = async move {
let ctx = ctx1;
if let Err(()) = started.send(()) {
warn!(&ctx, "smtp loop, missing started receiver");
warn!(&ctx, "SMTP loop, missing started receiver.");
return;
}
let mut timeout = None;
loop {
if let Err(err) = send_smtp_messages(&ctx, &mut connection).await {
warn!(ctx, "send_smtp_messages failed: {:#}", err);
warn!(ctx, "send_smtp_messages failed: {:#}.", err);
timeout = Some(timeout.unwrap_or(30));
} else {
timeout = None;
@@ -784,7 +784,7 @@ async fn smtp_loop(
}
// Fake Idle
info!(ctx, "smtp fake idle - started");
info!(ctx, "SMTP fake idle started.");
match &connection.last_send_error {
None => connection.connectivity.set_idle(&ctx).await,
Some(err) => connection.connectivity.set_err(&ctx, err).await,
@@ -798,7 +798,7 @@ async fn smtp_loop(
let now = tools::Time::now();
info!(
ctx,
"smtp has messages to retry, planning to retry {} seconds later", t,
"SMTP has messages to retry, planning to retry {t} seconds later."
);
let duration = std::time::Duration::from_secs(t);
tokio::time::timeout(duration, async {
@@ -812,18 +812,18 @@ async fn smtp_loop(
slept.saturating_add(rand::thread_rng().gen_range((slept / 2)..=slept)),
));
} else {
info!(ctx, "smtp has no messages to retry, waiting for interrupt");
info!(ctx, "SMTP has no messages to retry, waiting for interrupt.");
idle_interrupt_receiver.recv().await.unwrap_or_default();
};
info!(ctx, "smtp fake idle - interrupted")
info!(ctx, "SMTP fake idle interrupted.")
}
};
stop_receiver
.recv()
.map(|_| {
info!(ctx, "shutting down smtp loop");
info!(ctx, "Shutting down SMTP loop.");
})
.race(fut)
.await;

View File

@@ -1403,6 +1403,7 @@ First thread."#;
let alice_bob_contact_id = Contact::create(&alice, "Bob", "bob@example.net").await?;
remove_contact_from_chat(&alice, alice_chat_id, alice_bob_contact_id).await?;
alice.pop_sent_msg().await;
// The message from Bob is delivered late, Bob is already removed.
let msg = alice.recv_msg(&sent).await;

View File

@@ -87,7 +87,7 @@ impl Smtp {
/// Connect using configured parameters.
pub async fn connect_configured(&mut self, context: &Context) -> Result<()> {
if self.has_maybe_stale_connection() {
info!(context, "Closing stale connection");
info!(context, "Closing stale connection.");
self.disconnect();
}
@@ -364,8 +364,7 @@ pub(crate) async fn smtp_send(
msg_id: MsgId,
) -> SendResult {
if std::env::var(crate::DCC_MIME_DEBUG).is_ok() {
info!(context, "smtp-sending out mime message:");
println!("{message}");
info!(context, "SMTP-sending out mime message:\n{message}");
}
smtp.connectivity.set_working(context).await;
@@ -385,7 +384,7 @@ pub(crate) async fn smtp_send(
let status = match send_result {
Err(crate::smtp::send::Error::SmtpSend(err)) => {
// Remote error, retry later.
info!(context, "SMTP failed to send: {:?}", &err);
info!(context, "SMTP failed to send: {:?}.", &err);
let res = match err {
async_smtp::error::Error::Permanent(ref response) => {
@@ -412,10 +411,10 @@ pub(crate) async fn smtp_send(
};
if maybe_transient {
info!(context, "Permanent error that is likely to actually be transient, postponing retry for later");
info!(context, "Permanent error that is likely to actually be transient, postponing retry for later.");
SendResult::Retry
} else {
info!(context, "Permanent error, message sending failed");
info!(context, "Permanent error, message sending failed.");
// If we do not retry, add an info message to the chat.
// Yandex error "554 5.7.1 [2] Message rejected under suspicion of SPAM; https://ya.cc/..."
// should definitely go here, because user has to open the link to
@@ -436,20 +435,19 @@ pub(crate) async fn smtp_send(
// Any extended smtp status codes like x.1.1, x.1.2 or x.1.3 that we
// receive as a transient error are misconfigurations of the smtp server.
// See <https://tools.ietf.org/html/rfc3463#section-3.2>
info!(context, "Received extended status code {} for a transient error. This looks like a misconfigured SMTP server, let's fail immediately", first_word);
info!(context, "Received extended status code {first_word} for a transient error. This looks like a misconfigured SMTP server, let's fail immediately.");
SendResult::Failure(format_err!("Permanent SMTP error: {}", err))
} else {
info!(
context,
"Transient error with status code {}, postponing retry for later",
first_word
"Transient error with status code {first_word}, postponing retry for later."
);
SendResult::Retry
}
} else {
info!(
context,
"Transient error without status code, postponing retry for later"
"Transient error without status code, postponing retry for later."
);
SendResult::Retry
}
@@ -457,14 +455,14 @@ pub(crate) async fn smtp_send(
_ => {
info!(
context,
"Message sending failed without error returned by the server, retry later"
"Message sending failed without error returned by the server, retry later."
);
SendResult::Retry
}
};
// this clears last_success info
info!(context, "Failed to send message over SMTP, disconnecting");
info!(context, "Failed to send message over SMTP, disconnecting.");
smtp.disconnect();
res
@@ -472,19 +470,19 @@ pub(crate) async fn smtp_send(
Err(crate::smtp::send::Error::Envelope(err)) => {
// Local error, job is invalid, do not retry.
smtp.disconnect();
warn!(context, "SMTP job is invalid: {}", err);
warn!(context, "SMTP job is invalid: {err:#}.");
SendResult::Failure(err)
}
Err(crate::smtp::send::Error::NoTransport) => {
// Should never happen.
// It does not even make sense to disconnect here.
error!(context, "SMTP job failed because SMTP has no transport");
error!(context, "SMTP job failed because SMTP has no transport.");
SendResult::Failure(format_err!("SMTP has not transport"))
}
Err(crate::smtp::send::Error::Other(err)) => {
// Local error, job is invalid, do not retry.
smtp.disconnect();
warn!(context, "unable to load job: {}", err);
warn!(context, "Unable to load SMTP job: {err:#}.");
SendResult::Failure(err)
}
Ok(()) => SendResult::Success,
@@ -558,12 +556,12 @@ pub(crate) async fn send_msg_to_smtp(
.sql
.execute("DELETE FROM smtp WHERE id=?", (rowid,))
.await
.context("failed to remove message with exceeded retry limit from smtp table")?;
.context("Failed to remove message with exceeded retry limit from smtp table")?;
return Ok(());
}
info!(
context,
"Try number {retries} to send message {msg_id} (entry {rowid}) over SMTP"
"Try number {retries} to send message {msg_id} (entry {rowid}) over SMTP."
);
let recipients_list = recipients
@@ -572,7 +570,7 @@ pub(crate) async fn send_msg_to_smtp(
|addr| match async_smtp::EmailAddress::new(addr.to_string()) {
Ok(addr) => Some(addr),
Err(err) => {
warn!(context, "invalid recipient: {} {:?}", addr, err);
warn!(context, "Invalid recipient: {} {:?}.", addr, err);
None
}
},
@@ -650,7 +648,7 @@ pub(crate) async fn send_msg_to_smtp(
async fn send_mdns(context: &Context, connection: &mut Smtp) -> Result<()> {
loop {
if !context.ratelimit.read().await.can_send() {
info!(context, "Ratelimiter does not allow sending MDNs now");
info!(context, "Ratelimiter does not allow sending MDNs now.");
return Ok(());
}
@@ -697,7 +695,7 @@ pub(crate) async fn send_smtp_messages(context: &Context, connection: &mut Smtp)
for rowid in rowids {
send_msg_to_smtp(context, connection, rowid)
.await
.context("failed to send message")?;
.context("Failed to send message")?;
}
// although by slow sending, ratelimit may have been expired meanwhile,
@@ -706,7 +704,7 @@ pub(crate) async fn send_smtp_messages(context: &Context, connection: &mut Smtp)
if !ratelimited {
send_mdns(context, connection)
.await
.context("failed to send MDNs")?;
.context("Failed to send MDNs")?;
}
Ok(())
}
@@ -762,7 +760,7 @@ async fn send_mdn_msg_id(
match smtp_send(context, &recipients, &body, smtp, msg_id).await {
SendResult::Success => {
info!(context, "Successfully sent MDN for {}", msg_id);
info!(context, "Successfully sent MDN for {msg_id}.");
context
.sql
.execute("DELETE FROM smtp_mdns WHERE msg_id = ?", (msg_id,))
@@ -782,7 +780,7 @@ async fn send_mdn_msg_id(
SendResult::Retry => {
info!(
context,
"Temporary SMTP failure while sending an MDN for {}", msg_id
"Temporary SMTP failure while sending an MDN for {msg_id}."
);
Ok(false)
}
@@ -798,7 +796,7 @@ async fn send_mdn(context: &Context, smtp: &mut Smtp) -> Result<bool> {
context.sql.execute("DELETE FROM smtp_mdns", []).await?;
return Ok(false);
}
info!(context, "Sending MDNs");
info!(context, "Sending MDNs.");
context
.sql
@@ -828,7 +826,7 @@ async fn send_mdn(context: &Context, smtp: &mut Smtp) -> Result<bool> {
(msg_id,),
)
.await
.context("failed to update MDN retries count")?;
.context("Failed to update MDN retries count")?;
match send_mdn_msg_id(context, msg_id, contact_id, smtp).await {
Err(err) => {

View File

@@ -2588,6 +2588,7 @@ sth_for_the = "future""#
);
remove_contact_from_chat(&alice, chat_id, contact_bob).await?;
alice.pop_sent_msg().await;
let status =
helper_send_receive_status_update(&bob, &alice, &bob_instance, &instance).await?;

View File

@@ -2,7 +2,7 @@ Group#Chat#10: Group chat [3 member(s)]
--------------------------------------------------------------------------------
Msg#10: (Contact#Contact#11): I created a group [FRESH]
Msg#11: (Contact#Contact#11): Member Fiona (fiona@example.net) added by alice@example.org. [FRESH][INFO]
Msg#12: Me (Contact#Contact#Self): You removed member Fiona (fiona@example.net). [INFO] o
Msg#12: Me (Contact#Contact#Self): You removed member Fiona (fiona@example.net). [INFO]
Msg#13: (Contact#Contact#11): Welcome, Fiona! [FRESH]
Msg#14: info (Contact#Contact#Info): Member Fiona (fiona@example.net) added. [NOTICED][INFO]
Msg#15: (Contact#Contact#11): Welcome back, Fiona! [FRESH]

View File

@@ -1,7 +1,7 @@
Group#Chat#10: Group chat [4 member(s)]
--------------------------------------------------------------------------------
Msg#10: (Contact#Contact#10): Hi! I created a group. [FRESH]
Msg#11: Me (Contact#Contact#Self): You left the group. [INFO] o
Msg#11: Me (Contact#Contact#Self): You left the group. [INFO]
Msg#12: (Contact#Contact#10): Member claire@example.net added by alice@example.org. [FRESH][INFO]
Msg#13: info (Contact#Contact#Info): Member Me (bob@example.net) added. [NOTICED][INFO]
Msg#14: (Contact#Contact#10): What a silence! [FRESH]