Compare commits

..

569 Commits

Author SHA1 Message Date
link2xt
3b1529ef81 chore(release): prepare for 1.133.2 2024-01-24 01:57:45 +00:00
link2xt
15187c0adb fix: downgrade OpenSSL from 3.2.0 to 3.1.4 2024-01-24 01:48:23 +00:00
Sebastian Klähn
c5f31c3d03 fix: No new chats for MDNs with alias (#5196) (#5199)
close #5196
2024-01-22 16:51:37 +01:00
link2xt
2c17e78347 chore(release): prepare for 1.133.1 2024-01-21 04:18:13 +00:00
Sebastian Klähn
4ee646ce0b feat(api): Add is_bot to cffi and jsonrpc (#5197)
@adbenitez wants this feature on Deltalab to display a bot tag. 
Other UIs might also want to adopt this feature :)

---------
Co-authored-by: link2xt <link2xt@testrun.org>
2024-01-20 15:00:10 +00:00
B. Petersen
1f7b4a74fa add missing 'unencrypted message' defines
in #5161, it was forgotten to adapt deltachat.h;
moreover, this PR tweaks some other minor things
2024-01-20 15:00:23 +01:00
Sebastian Klähn
4bc90701cc feat: Add system message when provider does not allow unencrypted messages (#5161) (#5195)
close #5161

![Screenshot from 2024-01-19
19-56-09](https://github.com/deltachat/deltachat-core-rust/assets/39526136/27ecdd9b-1739-410b-bb26-80d5bdbbc39a)

---------

Co-authored-by: bjoern <r10s@b44t.com>
2024-01-20 11:47:23 +00:00
dependabot[bot]
490deb9347 chore(deps): bump h2 from 0.3.17 to 0.3.24 in /fuzz
Bumps [h2](https://github.com/hyperium/h2) from 0.3.17 to 0.3.24.
- [Release notes](https://github.com/hyperium/h2/releases)
- [Changelog](https://github.com/hyperium/h2/blob/v0.3.24/CHANGELOG.md)
- [Commits](https://github.com/hyperium/h2/compare/v0.3.17...v0.3.24)

---
updated-dependencies:
- dependency-name: h2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-19 23:58:52 +00:00
Sebastian Klähn
28d9484a13 fix(node): run tests with native ESM modules instead of esm (#5194)
close #5156

---------

Co-authored-by: Septias <scoreplayer2000@gmail.comclear>
2024-01-19 18:09:19 +01:00
link2xt
e67e684ee0 test: wait for joiner success in test_verified_group_[member_added]_recovery
If we wait for inviter success,
vg-member-added message may be still in flight
and reach ac2 after device resetup.

Making ac2 wait for joining the group ensures that old
device receives vg-member-added message
and new device will not receive it and fail to decrypt.

Other instances of wait_for_securejoin_inviter_success()
in the same tests are also replaced for reliability.
2024-01-18 17:00:21 +00:00
link2xt
6cfe3e6a97 chore(deps): update h2 0.4.0 -> 0.4.2 2024-01-18 13:40:38 +00:00
Sebastian Klähn
99ac524905 chore(deps): update h2 from 0.3.22 -> 0.3.24 2024-01-18 14:21:58 +01:00
link2xt
2faf7fdb78 fix: BCC-to-self even if server deletion is set to "at once" 2024-01-18 10:20:01 +00:00
link2xt
6a8ea8a083 fix: set message download state to Failure on IMAP errors
Previously the message was removed from `download` table,
but message bubble was stuck in InProgress state.

Now download state is updated by the caller,
so it cannot be accidentally skipped.
2024-01-18 10:18:57 +00:00
link2xt
e0e56cd831 chore: update quoted_printable to 0.5
And update mailparse to 0.14.1 so there is no duplicate dependency.
2024-01-18 09:35:05 +00:00
missytake
bbc6febb72 test: no timeout in SetupPlugin 2024-01-17 14:20:29 +01:00
missytake
7f7f42d721 test: Ensure that member is added before yielding chat 2024-01-17 14:20:29 +01:00
iequidoo
589236c27b fix: chat::send_msg: Remove encryption-related params from already sent message
This allows to send existing messages (incoming and outgoing) taken from encrypted chats, to
unencrypted ones. `Param::ForcePlaintext` is removed as well -- if a message can be sent encrypted
this time, nothing bad with this.
2024-01-17 14:20:29 +01:00
iequidoo
c16c5e0802 test: Bring test_forward_encrypted_to_unencrypted into line with current API
Currently `Chat.send_msg()` modifies the source message and returns another message object
equivalent to the source one. That's how it works in the core and thus in Python bindings too.
2024-01-17 14:20:29 +01:00
missytake
36cab40ac1 test: add get_protected_chat to testplugin.py 2024-01-17 14:20:29 +01:00
missytake
4186d78305 test: add python test for message forwarding from encrypted to unencrypted chat 2024-01-17 14:20:29 +01:00
iequidoo
06cccb77f8 feat: Use Quoted-Printable for the text part (#3986)
This is needed to protect from ESPs (such as gmx.at) doing their own Quoted-Printable encoding and
thus breaking messages and signatures. It's unlikely that the reader uses a MUA not supporting
Quoted-Printable encoding. And RFC 2646 "4.6" also recommends it for encrypted messages.
2024-01-16 23:46:24 -03:00
link2xt
1895f4c556 chore(release): prepare for 1.133.0 2024-01-15 22:55:26 +00:00
link2xt
849a873e61 feat: only try to configure non-strict TLS checks if explicitly set
Trying non-strict TLS checks is not necessary
for most servers with proper TLS setup,
but doubles the time needed to fail configuration
when the server is not responding, e.g.
when all connection attempts time out.

There is also a risk of accidentally
configuring non-strict TLS checks in a rare case
that strict TLS check configuration spuriously failed,
e.g. on a bad network.

If the server has a known broken TLS setup,
it can still be added to the provider database
or configured with non-strict TLS check manually.
User can also configure another email provider,
such as chatmail servers, instead of using the server
with invalid TLS hostname.

This change does not affect exising setups.
2024-01-15 22:54:31 +00:00
link2xt
b5c0372c99 docs: restore "Constants" page in Doxygen >=1.9.8
deltachat.h uses `@defgroup` commands to create topics
for groups of constants. Prior to Doxygen 1.9.8
defining a group created a "module"
and all constants were visible from the modules.html page.
In Doxygen 1.9.8 "modules" were renamed into "topics"
as C++20 modules have taken their place,
so Delta Chat documentation does not have modules
in Doxygen sense anymore.

The change is to replace "modules.html" with "topics.html"
in the DoxygenLayout.xml.

See <https://www.doxygen.nl/manual/grouping.html> for
Doxygen documentation about groups and their relation to topics.
2024-01-14 12:17:54 +00:00
link2xt
1ba9b69849 chore: npm run build:core:constants 2024-01-13 22:51:24 +00:00
holger krekel
6345a4f5b3 fix link for securejoin 2024-01-13 12:50:16 +01:00
Sebastian Klähn
382fc75b1e Add more docs (#5174)
Add some docs to smtp functions
2024-01-12 11:14:05 +01:00
Sebastian Klähn
92fc9ea971 feat: Encrypt MDNs #5168 (#5175)
This PR stops MDNs from being forced to be sent unencrypted. 
If no encryption is possible (by `should_encrypt`), the fix #5152 still
applies.

close #5168
2024-01-12 10:54:54 +01:00
Sebastian Klähn
de7ac2a240 fix: emit events more reliable when starting and stopping io #5097 (#5101)
Send `EventType::ConnectivityChanged` when using the context methods
`start_io` and `stop_io`.

close #5097

---------

Co-authored-by: Septias <scoreplayer2000@gmail.comclear>
2024-01-12 09:45:34 +01:00
link2xt
7b0e5adaee chore(deps): update rustyline from 12 to 13 2024-01-12 02:45:53 +00:00
iequidoo
406b59501b chore: deltachat-jsonrpc/src/api/types/events.rs: Apply rustfmt 2024-01-11 21:53:26 -03:00
iequidoo
d5da2bed75 feat: Add ConfigSynced event
Add an event for a case if a multi-device synced config value changed. Maybe the app needs to
refresh smth on such an event. For uniformity it is emitted on the source device too. The value is
omitted, otherwise it would be logged which might not be good for privacy.
2024-01-11 21:53:26 -03:00
iequidoo
924d5b9377 feat: Sync contact creation/rename across devices (#5163)
Use `chat::SyncAction::Rename` for that. Anyway 1:1-s can't be renamed and a separate sync action
would only complicate the code.
2024-01-10 16:46:54 -03:00
iequidoo
bb47299ee4 fix: contact::set_blocked(): Don't fail on sync errors, just log them
Multi-device synchronisation is not critical and should not fail the local operation, in other
places sync errors are already ignored.
2024-01-10 16:46:54 -03:00
link2xt
20065d3daa docs: add a NOTE comment about KeyId backward verification race 2024-01-09 21:46:37 +00:00
link2xt
ccb267beab refactor: rename notify_peer_verified() into set_peer_verified()
It was named notify_peer_verified()
because it added info message,
but this is no longer true since
https://github.com/deltachat/deltachat-core-rust/pull/4998
(commit c6ea4e389a)
is merged.
2024-01-09 21:46:37 +00:00
link2xt
32bcb59601 refactor: do not emit ChatModified event in notify_peer_verified()
The chat is not modified at least since
c6ea4e389a
(PR https://github.com/deltachat/deltachat-core-rust/pull/4998),
even the info message is not posted there.
2024-01-09 21:46:37 +00:00
link2xt
c708c44f0a feat: mark 1:1 chat as verified for Bob early
Mark 1:1 chat as verified as soon as Alice is forward-verified
so Bob can already start sending Chat-Verified headers.
This way Alice and Bob can scan each other's QR codes
and even if all Secure-Join headers are dropped from the network,
still get forward verifications via QR-code scans
and backward verifications via Chat-Verified messages in 1:1 chat.
2024-01-09 21:46:37 +00:00
link2xt
9415a71f9d refactor: rename fingerprint_equals_sender to verify_sender_by_fingerprint 2024-01-09 21:46:37 +00:00
link2xt
1fd42f2c53 test: test recovery from lost vc-contact-confirm 2024-01-09 21:46:37 +00:00
link2xt
1e52502ab3 refactor: send Secure-Join-Fingerprint only in *-request-with-auth 2024-01-09 21:46:37 +00:00
link2xt
a144d7e4f3 test: test that changing default private key breaks backward verification 2024-01-09 21:46:37 +00:00
link2xt
e855b79f9c feat: add backward_verified_key_id column to acpeerstates 2024-01-09 21:46:37 +00:00
link2xt
2f8a8f9f50 ci: update to Rust 1.75.0 and fix clippy 2024-01-08 20:01:40 +00:00
link2xt
b9a58bf625 docs: add a link to autoconfig RFC draft
This will hopefully replace deleted Mozilla documentation page
in the future.
2024-01-07 22:55:16 +00:00
iequidoo
c8075e53d2 fix: Reset message error when scheduling resending (#5119)
Before, while a message is in OutPending state after resending is requested, the user still sees the
red marker with error and it is confusing, so the user don't know the sending state of the message.
2024-01-07 15:02:31 -03:00
iequidoo
ff54cf24a1 fix: message::update_msg_state(): Reset error if message is delivered (#5119) 2024-01-05 20:43:55 -03:00
link2xt
af0833e821 ci: downgrade chai from 4.4.0 to 4.3.10
4.4.0 fails with a syntax error in CI currently.
2024-01-05 23:36:57 +00:00
link2xt
da11542322 fix: do not remove contents from Schleuder ML messages
Before this fix actual contents of the message
reposted by Schleuder is considered a mailing list footer and removed,
not visible even in the "Show Full Message..." view.

With this change there will be two message bubbles,
one for header and one for the contents,
but it is still better than losing the contents completely.

Attempting to parse header part is out of scope for this change.
2024-01-05 15:42:56 +00:00
link2xt
3bcdd1770a test: test that read receipts don't degrade encryption
This is broken since 44227d7b86
mimeparser only recognizes read receipts
by the Content-Type being "multipart/report".
If multipart/report is hidden inside multipart/mixed
and the message is not encrypted,
it degrades encryption.
2024-01-05 15:34:48 +00:00
link2xt
4dc596e646 fix(mimefactory): do not wrap MDNs into multipart/mixed part 2024-01-05 15:34:48 +00:00
link2xt
2e69210825 refactor: use wait_for_incoming_msg_event() more 2024-01-05 15:34:48 +00:00
iequidoo
625887d249 fix: Split SMTP jobs already in chat::create_send_msg_jobs() (#5115)
a27e84ad89 "fix: Delete received outgoing messages from SMTP queue"
can break sending messages sent as several SMTP messages because they have a lot of recipients:
`pub(crate) const DEFAULT_MAX_SMTP_RCPT_TO: usize = 50;`

We should not cancel sending if it is such a message and we received BCC-self because it does not
mean the other part was sent successfully. For this, split such messages into separate jobs in the
`smtp` table so that only a job containing BCC-self is canceled from `receive_imf_inner()`. Although
this doesn't solve the initial problem with timed-out SMTP requests for such messages completely,
this enables fine-grained SMTP retries so we don't need to resend all SMTP messages if only some of
them failed to be sent.
2024-01-05 01:53:41 -03:00
link2xt
b7c34b7794 chore: remove minor version from serde_json spec 2024-01-04 16:06:33 +00:00
link2xt
941cf38a3e chore(deps): cargo update 2024-01-04 16:03:28 +00:00
dependabot[bot]
7f61896ec8 Merge pull request #5136 from deltachat/dependabot/cargo/futures-0.3.30 2024-01-03 17:19:18 +00:00
dependabot[bot]
b14b49cbf0 Merge pull request #5146 from deltachat/dependabot/cargo/anyhow-1.0.79 2024-01-03 17:17:21 +00:00
dependabot[bot]
6de3510a5d Merge pull request #5131 from deltachat/dependabot/cargo/reqwest-0.11.23 2024-01-03 04:53:00 +00:00
dependabot[bot]
dea519095c chore(cargo): bump futures from 0.3.29 to 0.3.30
Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.29 to 0.3.30.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.29...0.3.30)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-03 04:48:48 +00:00
dependabot[bot]
3f8ca0cee9 Merge pull request #5133 from deltachat/dependabot/cargo/tempfile-3.9.0 2024-01-03 04:47:42 +00:00
dependabot[bot]
1b998da57a chore(cargo): bump anyhow from 1.0.75 to 1.0.79
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.75 to 1.0.79.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.75...1.0.79)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-03 04:46:17 +00:00
dependabot[bot]
772747d42d Merge pull request #5135 from deltachat/dependabot/cargo/syn-2.0.43 2024-01-03 04:43:06 +00:00
dependabot[bot]
3998258afb Merge pull request #5141 from deltachat/dependabot/cargo/quote-1.0.34 2024-01-03 04:40:31 +00:00
dependabot[bot]
4e86de98c4 chore(cargo): bump quote from 1.0.33 to 1.0.34
Bumps [quote](https://github.com/dtolnay/quote) from 1.0.33 to 1.0.34.
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.33...1.0.34)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-01 21:33:28 +00:00
dependabot[bot]
2a497989e9 chore(cargo): bump syn from 2.0.41 to 2.0.43
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.41 to 2.0.43.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.41...2.0.43)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-01 21:32:04 +00:00
dependabot[bot]
361b19e455 chore(cargo): bump tempfile from 3.8.1 to 3.9.0
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.8.1 to 3.9.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.8.1...v3.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-01 21:31:38 +00:00
dependabot[bot]
c036b26ae5 chore(cargo): bump reqwest from 0.11.22 to 0.11.23
Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.22 to 0.11.23.
- [Release notes](https://github.com/seanmonstar/reqwest/releases)
- [Changelog](https://github.com/seanmonstar/reqwest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/seanmonstar/reqwest/compare/v0.11.22...v0.11.23)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-01 21:31:13 +00:00
link2xt
dcf6ffef12 fix(imap): fail fast on LIST errors
async-imap returns infinite stream of errors
in case of EOF or timeout on the input stream,
so attempting to skip and log errors results in busy loop
similar to this:

   2023-12-22T13:07:35.751Z core/event WARNING "" 2 "/__w/deltachat-core-rust/deltachat-core-rust/src/imap/scan_folders.rs:112: list_folders() can't get folder: io: timed out: timed out"
   2023-12-22T13:07:35.751Z core/event WARNING "" 2 "/__w/deltachat-core-rust/deltachat-core-rust/src/imap/scan_folders.rs:112: list_folders() can't get folder: io: timed out: timed out"
   2023-12-22T13:07:35.751Z core/event WARNING "" 2 "/__w/deltachat-core-rust/deltachat-core-rust/src/imap/scan_folders.rs:112: list_folders() can't get folder: io: timed out: timed out"
   2023-12-22T13:07:35.751Z core/event WARNING "" 2 "/__w/deltachat-core-rust/deltachat-core-rust/src/imap/scan_folders.rs:112: list_folders() can't get folder: io: timed out: timed out"
   2023-12-22T13:07:35.752Z core/event WARNING "" 2 "/__w/deltachat-core-rust/deltachat-core-rust/src/imap/scan_folders.rs:112: list_folders() can't get folder: io: timed out: timed out"
   2023-12-22T13:07:35.752Z core/event WARNING "" 2 "/__w/deltachat-core-rust/deltachat-core-rust/src/imap/scan_folders.rs:112: list_folders() can't get folder: io: timed out: timed out"
   2023-12-22T13:07:35.752Z core/event WARNING "" 2 "/__w/deltachat-core-rust/deltachat-core-rust/src/imap/scan_folders.rs:112: list_folders() can't get folder: io: timed out: timed out"
   2023-12-22T13:07:35.752Z core/event WARNING "" 2 "/__w/deltachat-core-rust/deltachat-core-rust/src/imap/scan_folders.rs:112: list_folders() can't get folder: io: timed out: timed out"
   2023-12-22T13:07:35.753Z core/event WARNING "" 2 "/__w/deltachat-core-rust/deltachat-core-rust/src/imap/scan_folders.rs:112: list_folders() can't get folder: io: timed out: timed out"
   2023-12-22T13:07:35.754Z core/event WARNING "" 2 "/__w/deltachat-core-rust/deltachat-core-rust/src/imap/scan_folders.rs:112: list_folders() can't get folder: io: timed out: timed out"
   2023-12-22T13:07:35.754Z core/event WARNING "" 2 "/__w/deltachat-core-rust/deltachat-core-rust/src/imap/scan_folders.rs:112: list_folders() can't get folder: io: timed out: timed out"

To avoid busy loop, fail fast on first error
and bubble it up instead of trying to recover.
2023-12-28 15:20:15 +00:00
iequidoo
865ede39fe fix: Properly escape target in receive_imf_inner()
The bug was made in 44227d7b86. Sql::execute() with placeholders must
be used to escape strings, one never should escape them manually as strings themselves can contain
escape symbols. Thanks to @link2xt for noticing.
2023-12-22 17:42:25 -03:00
iequidoo
a27e84ad89 fix: Delete received outgoing messages from SMTP queue (#5115)
Some SMTP servers are running slow before-queue filters, most commonly Postfix with `rspamd` filter
which is implemented as a [before-queue Milter](https://www.postfix.org/MILTER_README.html). Some of
`rspamd` plugin filters are slow on large mails.

We previously had problems with timing out during waiting for SMTP response:
https://github.com/deltachat/deltachat-core-rust/issues/1383. This is largely fixed by
https://github.com/async-email/async-smtp/pull/29 and currently we have 60-second timeout just for
reading a response but apparently it is not sufficient -- maybe connection gets killed by NAT while
we are waiting for response or `rspamd` takes more than 60 seconds for large messages.

As a result a message is resent multiple times and eventually fails with "too many retries" while
multiple BCC-self messages are received.

We should remove the message from the SMTP queue as soon as we receive it via IMAP as it is clear
the message was sent even if we did not manage to get actual SMTP server response.
2023-12-21 16:57:23 -03:00
iequidoo
b83bd26325 refactor: Don't pass seen=true to add_parts() when replacing existing message
First of all, it's just downloaded and hasn't been seen yet by the user. Also this changes nothing
as `msgs.state` isn't changed when replacing a message anyway.
2023-12-21 16:14:52 -03:00
iequidoo
44227d7b86 fix: Put Message-ID into hidden headers and take it from there on receiver (#4798)
Put a copy of Message-ID into hidden headers and prefer it over the one in the IMF header section
that servers mess up with.

This also reverts "Set X-Microsoft-Original-Message-ID on outgoing emails for amazonaws (#3077)".
2023-12-21 16:14:52 -03:00
iequidoo
6bcf022523 refactor: receive_imf_inner: Rename replace_partial_download to replace_msg_id
It's more consistent with `replace_chat_id` and the same as the corresponding parameter name of
`add_parts()`.
2023-12-21 16:14:52 -03:00
link2xt
ccec26ffa7 fix(imap): limit the rate of LOGIN attempts rather than connection attempts
As ratelimit was introduced to avoid reconnecting immediately after disconnecting
in case of bugs in IMAP protocol handling,
connection attempts should only be counted when IMAP is actually used,
i.e. when the first command (LOGIN) is sent.
2023-12-21 08:07:34 +00:00
link2xt
83e159e42f refactor: better log at the start of imex_inner() 2023-12-18 21:03:09 +00:00
link2xt
cbabd4219e refactor: improve error message when non-verified contact is added to protected chat 2023-12-18 21:03:09 +00:00
link2xt
548afe3153 refactor: derive Debug, PartialEq and Eq for VerifiedEncryption 2023-12-18 21:03:09 +00:00
link2xt
35c5f42b35 refactor: use let-else in *-request-with-auth handler 2023-12-18 21:03:09 +00:00
link2xt
b9ff8b1d6c refactor: flatten peerstate::maybe_do_aeap_transition 2023-12-18 21:03:09 +00:00
link2xt
bb6a20dc11 test: test joining non-protected group 2023-12-18 21:03:09 +00:00
link2xt
e97955f5a0 refactor: flatten handle_auth_require() with let..else 2023-12-18 21:03:09 +00:00
iequidoo
35bd56ffea fix: Securejoin: Mark 1:1s as protected regardless of the Config::VerifiedOneOnOneChats
As per the comment in `receive_imf.rs`, `chat.protected` must be maintained regardless of the
`Config::VerifiedOneOnOneChats`. The only thing that mustn't be done if `VerifiedOneOnOneChats` is
unset (i.e. for non-supporting UIs) is marking chats as "protection broken" because this needs
showing the corresponding dialog to a user.
2023-12-18 16:32:09 -03:00
link2xt
78affb766e fix: do not ignore peerstate.save_to_db() errors 2023-12-18 11:57:16 +00:00
link2xt
9b1704e3b2 feat(deltachat-repl): enable INFO logging by default and add timestamps 2023-12-17 15:10:19 +00:00
link2xt
55cdbdc085 refactor(sql): recreate keypairs table
Removed unused `addr` and `created` field.
`is_default` boolean flag is moved into `config` row
pointing to the current default key.
2023-12-17 14:13:54 +00:00
link2xt
58620988d7 refactor(sql): recreate config table with UNIQUE constraint 2023-12-17 14:13:54 +00:00
link2xt
467f313091 chore: cargo update 2023-12-17 13:31:20 +00:00
dependabot[bot]
091578573a chore(cargo): bump zerocopy from 0.7.29 to 0.7.31
Bumps [zerocopy](https://github.com/google/zerocopy) from 0.7.29 to 0.7.31.
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/compare/v0.7.29...v0.7.31)

---
updated-dependencies:
- dependency-name: zerocopy
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-15 16:17:23 -03:00
iequidoo
62c1237024 refactor: Move calc_{protection_msg_,}sort_timestamp() to impl ChatId 2023-12-13 20:29:47 -03:00
iequidoo
8d41d02397 fix: calc_sort_timestamp: Skip messages that mustn't affect sorting of a new message (#5088)
Drafts mustn't affect sorting of any other messages, they aren't even displayed in the chat
window. Also hidden messages mustn't affect sorting of usual messages. But let hidden messages sort
together with protection messages because hidden messages also can be or not be verified, so let's
preserve this information -- even it's not useful currently, it can be useful in the future
versions.
2023-12-13 20:29:47 -03:00
iequidoo
fce3f80654 fix: Always pass the correct sort timestamp to ChatId::set_protection() (#5088)
Before in some places it was correctly calculated by passing the "sent" timestamp to
`calc_sort_timestamp()`, but in other places just the system time was used. In some complex
scenarios like #5088 (restoration of a backup made before a contact verification) it led to wrong
sort timestamps of protection messages and also messages following by them.

But to reduce number of args passed to functions needing to calculate the sort timestamp, add
message timestamps to `struct MimeMessage` which is anyway passed everywhere.
2023-12-13 20:29:47 -03:00
link2xt
2a0a51bea0 chore: remove n0-computer from deny.toml 2023-12-12 19:57:24 +00:00
link2xt
91d94d5920 build: use released version of iroh 0.4.2 2023-12-12 14:56:38 +00:00
link2xt
c59f21230d chore(release): prepare for 1.132.1 2023-12-12 02:58:29 +00:00
link2xt
828cc1fbd1 fix(connectivity): return false from all_work_done() immediately after connecting
We do not want all_work_done() to return true immediately
after calling start_io(), but only when connection goes idle.

"Connected" state is set immediately after connecting to the server,
but it does not mean there is nothing to do.

This change make all_work_done() return false
from the Connected state and introduces a new Idle
connectivity state that is only set before connection
actually goes idle. For idle state all_work_done() returns true.

From the user point of view both old Connected state
and new Idle state look the same.
2023-12-12 02:19:51 +00:00
link2xt
57f4958fc6 test(deltachat-rpc-client): test Account.{import,export}_self_keys 2023-12-11 06:43:10 +00:00
link2xt
3aeb57b4df api(deltachat-jsonrpc-client): add Account.{import,export}_self_keys 2023-12-11 06:43:10 +00:00
link2xt
1b85614db9 fix: renew IDLE timeout on keepalives and reduce it to 5 minutes
This change depends on async-imap update that resets the timeout
every time an `* OK Still here` is received.

Reducing timeout allows to detect lost connections
not later than 6 minutes
because Delta Chat will attempt to finish IDLE with DONE
after 5 minutes without keepalives
and will either get TCP RST directly
or, worst case, wait another minute for TCP socket read timeout.
2023-12-11 06:32:13 +00:00
link2xt
57ecf49eb1 chore: fix typo ("Bot" instead of "Bob") 2023-12-11 04:08:45 +00:00
iequidoo
f279b0d1e5 feat: Sync user actions for ad-hoc groups across devices (#5065)
Ad-hoc groups don't have grpid-s that can be used to identify them across devices and thus wasn't
synced until now.

The same problem already exists for assigning messages to ad-hoc groups and this assignment is done
by `get_parent_message()` and `lookup_chat_by_reply()`. Let's reuse this logic for the
synchronisation, it works well enough and this way we have less surprises than if we try to
implement grpids for ad-hoc groups. I.e. add an `Msgids` variant to `chat::SyncId` analogous to the
"References" header in messages and put two following Message-IDs to a sync message:
- The latest message A having `DownloadState::Done` and the state to be one of `InFresh, InNoticed,
  InSeen, OutDelivered, OutMdnRcvd`.
- The message that A references in `In-Reply-To`.

This way the logic is almost the same to what we have in `Chat::prepare_msg_raw()` (the difference
is that we don't use the oldest Message-ID) and it's easier to reuse the existing code.

NOTE: If a chat has only an OutPending message f.e., the synchronisation wouldn't work, but trying
to work in such a corner case has no significant value and isn't worth complicating the code.
2023-12-09 01:41:07 -03:00
iequidoo
32071297e6 feat: Add "From:" to protected headers for signed-only messages 2023-12-09 00:57:35 -03:00
link2xt
1d98c38ff3 ci: update to Rust 1.74.1 2023-12-08 23:52:36 +00:00
link2xt
c09e0e2b65 refactor: move AEAP and peerstate save from mimeparser to receive_imf()
Ideally mimeparser should be functional
and have no side effects such as modifying a peerstate in the database.
2023-12-08 23:32:03 +00:00
link2xt
0c8f967391 test: refine test_encrypted_no_autocrypt()
- Use TestContextManager
- Actually run receive_imf rather than only mimeparser on "received" messages
- Check that received message parts actually have a padlock
2023-12-08 23:32:03 +00:00
link2xt
aca34379e0 fix: add padlock to empty part if the whole message is empty
parse_mime_recursive() skips empty text parts,
so there may be no parts as the result of parsing.
In this case an empty part is added.
However, because it is added with parts.push()
rather than add_single_part(),
it is added without a padlock even if the message is encrypted.
`do_add_single_part()` adds padlock (GuaranteeE2EE param)
and should be used to add parts instead.
2023-12-07 03:38:20 +00:00
link2xt
1edd7045be chore(release): prepare for 1.132.0 2023-12-06 17:52:46 +00:00
B. Petersen
c784c499c2 fix: do not check lock_task on iOS before syncing
`lock_task` is anyways always `None` on iOS
to avoid lock files held open and cause 0xdead10cc crashes.
2023-12-06 18:17:49 +01:00
link2xt
36c751bcc3 chore: cargo update 2023-12-06 17:02:22 +00:00
link2xt
8a14a84bec test: check that ac2 gets a verified chat in test_securejoin_after_contact_resetup 2023-12-06 16:44:18 +00:00
link2xt
b00703cec2 fix: protect groups even if some members are not verified 2023-12-06 16:44:18 +00:00
link2xt
05e783564f refactor: log if the group is created as protected or not 2023-12-06 16:44:18 +00:00
link2xt
330fb02486 test: add test_securejoin_after_contact_resetup test
This test reproduces a bug preventing joining the group with a QR code
if the group already has a contact with inconsistent key state,
which means both Autocrypt and verified key exist,
but don't match.
This can happen when an invite QR code created by this contact
is scanned as scanning an invite code creates unprotected group
with the inviter for info messages.
If securejoin process never finishes because the inviter is offline,
group remains in this unprotected state with added inviter.

Normally the group becomes verified when a "Member added" (vg-member-added)
message is received in the chat.
However, current code checks that all members
of the chat are verified
(have a green checkmark, use verified key in 1:1 chat)
before marking the group as verified and fails otherwise.
2023-12-06 16:44:18 +00:00
link2xt
1447ab8dac refactor: clean up the logs and reduce noise
- Remove "Detected Autocrypt-mime message" logs printed for every incoming Autocrypt message.
- Print only a single line at the beginning of receive_imf with both the Message-ID and seen flag.
- Print Securejoin step only once, inside handle_securejoin_handshake or observe_securejoin_on_other_device.
- Do not log "Not creating ad-hoc group" every time ad-hoc group is not created, log when it is created instead.
- Log ID of the chat where Autocrypt-Gossip for all members is received.
- Do not print "Secure-join requested." for {vg,vc}-request, we already log the step.
- Remove ">>>>>>>>>>>>>>>>>>>>>>>>>" noise from securejoin logs.
2023-12-06 01:56:35 +00:00
link2xt
d574ee4edb chore: update zerocopy from 0.7.28 to 0.7.29
0.7.28 is yanked.
2023-12-05 19:25:27 +00:00
link2xt
814fe953a9 chore(cargo): update filetime 2023-12-05 16:45:24 +00:00
link2xt
280f13b8cf fix: do not lock accounts.toml on iOS
This results in 0xdead10cc crashes on suspend.
iOS itself ensures that multiple instances of Delta Chat are not running.
2023-12-04 21:51:17 +00:00
link2xt
a96b44a482 fix: do not mark recipients as verified if there is no Chat-Verified header 2023-12-04 15:34:09 +00:00
link2xt
4286d248e9 feat: increase TCP timeouts from 30 to 60 seconds
GitHub Action tests sometimes fail with TCP connection
timeouts, especially for macOS.
2023-12-04 12:50:07 +00:00
dependabot[bot]
116537019b chore(deps): bump self_cell from 1.0.1 to 1.0.2 in /fuzz
Bumps [self_cell](https://github.com/Voultapher/self_cell) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/Voultapher/self_cell/releases)
- [Commits](https://github.com/Voultapher/self_cell/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: self_cell
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-03 16:05:27 -03:00
iequidoo
8b37b8c1fd fix: Don't sort message creating a protected group over a protection message (#4963)
Otherwise it looks like the message creating a protected group is not verified. For this, use
`sent_timestamp` of the received message as an upper limit of the sort timestamp (`msgs.timestamp`)
of the protection message. As the protection message is added to the chat earlier, this way its
timestamp is always less or eq than the received message's timestamp.
2023-12-03 15:10:54 -03:00
iequidoo
63b4339ca0 test: Message order in a just created protected group on the second device (#4963)
Test that on the second device of a protected group creator the first message is
`SystemMessage::ChatProtectionEnabled` and the second one is the message populating the group.
2023-12-03 15:10:54 -03:00
link2xt
fdd239f61f fix: narrow the scope of verification exception to 1:1 chats
Allowing outgoing unencrypted messages in groups with 2 members
breaks the test
`python/tests/test_0_complex_or_slow.py::test_verified_group_vs_delete_server_after`
2023-12-03 15:46:56 +00:00
link2xt
5ca5d95c5e refactor: call has_verified_encryption() in a single place
This centralizes all Securejoin/verification checks and updates in one
place right before add_parts() even before we assign the message to
the chat, so we can decouple chat logic from verification logic.
2023-12-03 15:46:56 +00:00
link2xt
3fcad50924 refactor: move to_ids.is_empty() check into mark_recepients_as_verified() 2023-12-03 15:46:56 +00:00
link2xt
8e40540d24 refactor: add debug assertion where we expect a 1:1 chat 2023-12-03 15:46:56 +00:00
link2xt
04d22bb84d refactor: remove chattype argument from has_verified_encryption() 2023-12-03 15:46:56 +00:00
link2xt
5415f1bfa1 docs: has_verified_encryption() does not check that all members are verified 2023-12-03 15:46:56 +00:00
link2xt
ff3bf4791a chore: update dependencies 2023-12-03 00:43:21 +00:00
dependabot[bot]
eebea216cb chore(cargo): bump testdir from 0.8.1 to 0.9.0
Bumps [testdir](https://github.com/flub/testdir) from 0.8.1 to 0.9.0.
- [Changelog](https://github.com/flub/testdir/blob/main/CHANGELOG.md)
- [Commits](https://github.com/flub/testdir/compare/v0.8.1...v0.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-02 15:50:51 +00:00
link2xt
fbcd7f46b8 chore(release): prepare for 1.131.9 2023-12-02 01:18:34 +00:00
iequidoo
846278b18e feat: chat::rename_ex: Don't send sync message if usual message is sent
It's not necessary and in other places like add_contact_to_chat_ex() sync messages are also sent
only if there are no system messages sent like MemberAddedToGroup.
2023-12-01 21:41:58 -03:00
iequidoo
2f2b1e18bf test: Split test_sync_alter_chat() into smaller tests 2023-12-01 21:41:58 -03:00
iequidoo
073c250fa4 refactor: Add test_utils::sync()
Add a function that pops a sync message from one Alice's device and receives it on another.
2023-12-01 21:41:58 -03:00
iequidoo
1f336f89a6 feat: Sync Config::Displayname across devices (#4893)
We already synchronise status/footer when we see a self-sent message with a Chat-Version
header. Would be nice to do the same for display name.

But let's do it the same way as for `Config::{MdnsEnabled,ShowEmails}`. Otherwise, if we sync the
display name using the "From" header, smth like `Param::StatusTimestamp` is needed then to reject
outdated display names. Also this timestamp needs to be updated when `Config::Displayname` is set
locally. Also this wouldn't work if system time isn't synchronised on devices. Also using multiple
approaches to sync different config values would lead to more code and bugs while having almost no
value -- using "From" only saves some bytes and allows to sync some things w/o the synchronisation
itself to be enabled. But the latter also can be a downside -- if it's usual synchonisation, you can
(potentially) disable it and share the same email account across people in some organisation
allowing them to have different display names. With using "From" for synchronisation such a
capability definitely requires a new config option.
2023-12-01 21:41:58 -03:00
iequidoo
a47fec7f6c feat: Sync Config::{MdnsEnabled,ShowEmails} across devices (#4954)
Motivation: Syncing these options will improve UX in very most cases and should be done. Other
candidates are less clear or are advanced options, we can reconsider that at some point later.

Approach:
- Sync options one-by-one when the corresponding option is set (even if to the same value).
- Don't sync when an option is reset to a default as defaults may differ across client versions.
- Check on both sides that the option should be synced so that if there are different client
  versions, the synchronisation of the option is either done or not done in both directions.
  Moreover, receivers of a config value need to check if a key can be synced because some settings
  (e.g. Avatar path) could otherwise lead to exfiltration of files from a receiver's device if we
  assume an attacker to have control of a device in a multi-device setting or if multiple users are
  sharing an account.
- Don't sync `SyncMsgs` itself.
2023-12-01 21:41:58 -03:00
iequidoo
084434d3b4 feat: receive_imf_inner: Add missing initialisation of ReceivedMsg::from_is_signed 2023-12-01 21:41:58 -03:00
iequidoo
ebfbc11973 feat: Don't affect MimeMessage with "From" and secured headers from encrypted unsigned messages
If a message is encrypted, but unsigned:
- Don't set `MimeMessage::from_is_signed`.
- Remove "secure-join-fingerprint" and "chat-verified" headers from `MimeMessage`.
- Minor: Preserve "Subject" from the unencrypted top level if there's no "Subject" in the encrypted
  part, this message is displayed w/o a padlock anyway.

Apparently it didn't lead to any vulnerabilities because there are checks for
`MimeMessage::signatures.is_empty()` in all necessary places, but still the code looked dangerous,
especially because `from_is_singed` var name didn't correspond to its actual value (it was rather
`from_is_encrypted_maybe_signed`).
2023-12-01 19:06:11 -03:00
link2xt
9cc9579b2d feat: remove receiver limit on .xdc size
If we have downloaded the file anyway,
might as well allow to open it.
2023-12-01 15:53:38 +00:00
link2xt
7beccd9dbc refactor: better error context in send_webxdc_status_update_struct() 2023-12-01 15:19:23 +00:00
link2xt
0e195bc7a2 fix: lock the database when INSERTing a webxdc update
`query_row_optional` does not hold the write lock
and may fail with "database is locked" error
or cause the other task such as SMTP loop to fail.
2023-12-01 15:19:23 +00:00
link2xt
f89efd5fce test: test inserting lots of webxdc updates
Currently this leads to
DEBUG    root:rpc.py:136 account_id=1 got an event {'kind': 'Warning', 'msg': 'src/scheduler.rs:711: send_smtp_messages failed: failed to send message: failed to update retries count: database is locked: Error code 5: The database file is locked'}
and
FAILED tests/test_webxdc.py::test_webxdc_insert_lots_of_updates - deltachat_rpc_client.rpc.JsonRpcError: {'code': -1, 'message': 'database is locked\n\nCaused by:\n    Error code 5: The database file is locked'}
2023-12-01 15:19:23 +00:00
link2xt
48d278fca9 chore: update dependencies 2023-12-01 02:41:48 +00:00
link2xt
c84effdaa1 refactor: add more error context to send_webxdc_status_update()
This is a follow-up to b9fa05c3bb
2023-12-01 02:32:21 +00:00
link2xt
e9601ef138 test: make Result-returning tests produce a line number
Without this change
when the test returns a `Result`, `cargo test` does not show
the line number.

To make the tests as easy to debug as the panicking tests,
enable `backtrace` feature on `anyhow` and add debug information
to add source line numbers to backtraces.

Now running `RUST_BACKTRACE=1 cargo test` produces backtraces
with the line numbers. For example:

Error: near ",": syntax error in SELECT COUNT(,,*) FROM msgs_status_updates; at offset 13

Caused by:
    Error code 1: SQL error or missing database

Stack backtrace:
   0: <core::result::Result<T,F> as core::ops::try_trait::FromResidual<core::result::Result<core::convert::Infallible,E>>>::from_residual
             at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/core/src/result.rs:1962:27
   1: deltachat::sql::Sql::query_row::{{closure}}::{{closure}}
             at ./src/sql.rs:466:23
   2: deltachat::sql::Sql::call::{{closure}}::{{closure}}
             at ./src/sql.rs:379:55
   3: tokio::runtime::context::runtime_mt::exit_runtime
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/context/runtime_mt.rs:35:5
   4: tokio::runtime::scheduler::multi_thread::worker::block_in_place
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/scheduler/multi_thread/worker.rs:438:9
   5: tokio::runtime::scheduler::block_in_place::block_in_place
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/scheduler/block_in_place.rs:20:5
   6: tokio::task::blocking::block_in_place
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/task/blocking.rs:78:9
   7: deltachat::sql::Sql::call::{{closure}}
             at ./src/sql.rs:379:19
   8: deltachat::sql::Sql::query_row::{{closure}}
             at ./src/sql.rs:469:10
   9: deltachat::sql::Sql::count::{{closure}}
             at ./src/sql.rs:443:76
  10: deltachat::webxdc::tests::change_logging_webxdc::{{closure}}
             at ./src/webxdc.rs:2644:18
  11: <core::pin::Pin<P> as core::future::future::Future>::poll
             at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/core/src/future/future.rs:125:9
  12: tokio::runtime::park::CachedParkThread::block_on::{{closure}}
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/park.rs:282:63
  13: tokio::runtime::coop::with_budget
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/coop.rs:107:5
      tokio::runtime::coop::budget
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/coop.rs:73:5
      tokio::runtime::park::CachedParkThread::block_on
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/park.rs:282:31
  14: tokio::runtime::context::blocking::BlockingRegionGuard::block_on
             at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/context/blocking.rs:66:9
...

Line 10 of the backtrace contains the line number in the test (2644).
2023-11-30 22:27:38 +00:00
iequidoo
44c5cd5526 feat: Ratelimit IMAP connections (#4940)
Limit the number of IMAP connections to 1 per minute regardless of the reason of reconnection, but
allow one immediate retry. This is more reliable than ratelimiting only in error conditions because
ratelimiting can't be skipped by mistake. Anyway connections shouldn't be frequent in normal
operation mode.
2023-11-30 19:22:01 -03:00
link2xt
1c9662a8f2 refactor: rename min_verified into verified 2023-11-30 12:04:03 +00:00
link2xt
5d08b2ce33 refactor: remove unused PeerstateVerifiedStatus 2023-11-30 12:04:03 +00:00
link2xt
bb9d7d7ef3 feat: send Chat-Verified headers in 1:1 chats
Chat-Verified is going to be useful to upgrade one-way verification
to bidirectional verification.
2023-11-30 12:04:03 +00:00
link2xt
766bb5c8aa refactor: factor securejoin processing out of add_parts 2023-11-30 12:04:03 +00:00
link2xt
84144659cf refactor: remove {vc-contact-confirm,vg-member-added}-received steps 2023-11-30 12:04:03 +00:00
link2xt
1394137436 refactor: make min_verified a boolean
We either need a securejoin or autocrypt key,
there are no intermediate states.
2023-11-30 12:04:03 +00:00
link2xt
998614b923 api: make Contact.is_verified() return bool 2023-11-30 12:04:03 +00:00
B. Petersen
5b346397b8 api: deprecate CFFI APIs dc_send_reaction(), dc_get_msg_reactions(), dc_reactions_get_contacts(), dc_reactions_get_by_contact_id(), dc_reactions_unref and dc_reactions_t
this is now done with jsonrpc via
`dc_jsonrpc_request()` or `dc_jsonrpc_blocking_call()`
using the methods `send_reaction` and `get_message_reactions`
2023-11-29 11:29:29 +01:00
B. Petersen
1f99269002 api: remove dc_get_http_response(), dc_http_response_get_mimetype(), dc_http_response_get_encoding(), dc_http_response_get_blob(), dc_http_response_get_size(), dc_http_response_unref() and dc_http_response_t from cffi
this is now done with jsonrpc via
`dc_jsonrpc_request()` or `dc_jsonrpc_blocking_call()`
using the method `get_http_response`
2023-11-29 11:29:29 +01:00
iequidoo
160cbe8125 fix: Use keyring with all private keys when decrypting a message (#5046)
Before a keyring with the only default key was used, i.e. the key used for signing and encrypting to
self.
2023-11-29 02:20:19 -03:00
link2xt
b9fa05c3bb refactor: improve logging of send_webxdc_status_update errors
send_webxdc_status_update JSON-RPC call
and corresponding Rust call sometimes fail in CI with
---
database is locked

Caused by:
    Error code 5: The database file is locked
---

Adding more context to send_webxdc_status_update() errors
to better localize the error origin.
2023-11-28 22:48:55 +00:00
link2xt
4287a4d3ad refactor: factor out insert_tombstone 2023-11-28 21:57:41 +00:00
link2xt
37d2aafb26 fix: return correct MsgId for malformed message tombstone
.execute() returns the number of affected rows,
in this case it is always 1 and MsgId(1) is returned
instead of the actual tombstone row ID.
2023-11-28 21:57:41 +00:00
link2xt
4332170691 ci: add exception for RUSTSEC-2023-0071 to cargo-deny config
See
<https://rustsec.org/advisories/RUSTSEC-2023-0071>
and discussion at
<https://github.com/RustCrypto/RSA/issues/19>
for details.
2023-11-28 16:26:11 +00:00
link2xt
9a7c0f4737 chore: update OpenSSL 2023-11-28 15:05:34 +00:00
link2xt
9e7e172a7b build: switch from fork of iroh to iroh 0.4.2 pre-release 2023-11-28 02:59:42 +00:00
link2xt
71fbaf572a chore(release): prepare for 1.131.8 2023-11-28 00:01:17 +00:00
link2xt
2ab29e5bfa fix: allow IMAP servers not returning UIDNEXT on SELECT and STATUS 2023-11-27 23:50:43 +00:00
link2xt
85f8f910b9 chore: update wasm-bindgen from 0.2.88 to 0.2.89
0.2.88 is yanked: https://github.com/rustwasm/wasm-bindgen/issues/3685
2023-11-27 21:41:23 +00:00
link2xt
b779d08d7f test: check that receive_status_update has forward compatibility
This ensures old version of Delta Chat will be fine with a new "uid" field.
2023-11-27 13:49:41 +00:00
link2xt
3b5634f14b fix: do not emit events about webxdc update events logged into debug log webxdc 2023-11-27 13:49:41 +00:00
link2xt
f91ba357cf feat(webxdc): add unique IDs to status updates sent outside
This allows for deduplication
if status updates are sent over multiple transports.
2023-11-27 13:49:41 +00:00
Hocuri
616faff96b fix: Use the correct securejoin strings used in the UI, remove old TODO (#5047) 2023-11-26 15:54:11 +01:00
link2xt
5e6869403e chore(release): prepare for 1.131.7 2023-11-24 18:26:25 +00:00
link2xt
7ff7d82959 Revert "fix: check UIDNEXT with a STATUS command before going IDLE"
This reverts commit 2e50abedaa.

STATUS is broken on mail.163.com.
It returns `STATUS "INBOX" ()` reply
when `STATUS "INBOX" (UIDNEXT)` is requested.
2023-11-24 18:19:02 +00:00
link2xt
9b751c1865 chore(release): prepare for 1.131.6 2023-11-21 21:05:29 +00:00
link2xt
d1d31096e0 fix: fail fast if IMAP FETCH cannot be parsed
Otherwise when connection is lost IMAP may get into infinite loop
trying to parse remaining bytes:
11-21 18:00:48.442 14858 12946 W DeltaChat: src/imap.rs:1457: Failed to process IMAP FETCH result: io: bytes remaining in stream.
11-21 18:00:48.442 14858 12946 W DeltaChat: src/imap.rs:1457: Failed to process IMAP FETCH result: io: bytes remaining in stream.
11-21 18:00:48.442 14858 12946 W DeltaChat: src/imap.rs:1457: Failed to process IMAP FETCH result: io: bytes remaining in stream.
11-21 18:00:48.442 14858 12946 W DeltaChat: src/imap.rs:1457: Failed to process IMAP FETCH result: io: bytes remaining in stream.
11-21 18:00:48.442 14858 12946 W DeltaChat: src/imap.rs:1457: Failed to process IMAP FETCH result: io: bytes remaining in stream.
11-21 18:00:48.442 14858 12946 W DeltaChat: src/imap.rs:1457: Failed to process IMAP FETCH result: io: bytes remaining in stream.

Returning an error bubbles it up to `fetch_idle()`
which will call `trigger_reconnect()` and drop the connection.
2023-11-21 20:59:16 +00:00
link2xt
30f8522626 docs: generate deltachat-rpc-client documentation
To preview the docs, run:
```
scripts/build-python-docs.sh
firefox dist/html/index.html
```

I have removed the Makefile because modern Sphinx Makefile is just a
wrapper for `sphinx-build -M`:
3596590317/sphinx/templates/quickstart/Makefile.new_t
and sphinx-quickstart even has an option `--no-makefile`.
`make.bat` makes even less sense.
In `scripts/build-python-docs.sh` I use `sphinx-build` directly
without `make` wrapper.
2023-11-20 19:56:22 +00:00
link2xt
d3c221e061 chore: update dependencies 2023-11-20 19:52:40 +00:00
link2xt
8a421224f8 chore(release): prepare for 1.131.5 2023-11-20 19:04:57 +00:00
link2xt
7dfce71ac9 fix: lowercase addr when it is set
Prevent users from creating new accounts with uppercase letters
in the address.
2023-11-20 16:46:59 +00:00
link2xt
35ba97f76a fix: lowercase the address in member added/removed messages 2023-11-20 16:46:59 +00:00
link2xt
41921eaf3d fix: compare verifier addr to peerstate addr with addr_cmp 2023-11-20 16:46:59 +00:00
link2xt
03221ea86c refactor: lowercase the address in addr_normalize() 2023-11-20 16:46:59 +00:00
link2xt
b50761e4d1 api: turn ContactAddress into an owned type
This allows to normalize the address on creation more,
e.g. lowercase it.
2023-11-20 16:46:59 +00:00
link2xt
40dea771cc ci: test with Rust 1.74 2023-11-19 21:41:28 +00:00
link2xt
e011f8f42f chore: fix Rust 1.74 clippy warning 2023-11-19 21:40:19 +00:00
link2xt
09d4b4354a feat: lowercase addresses in Autocrypt and Autocrypt-Gossip
Email addresses should generally be compared case-insensitively,
but there may be errors in comparison code.
To reduce the chance of problems, encode addresses
in Autocrypt and Autocrypt-Gossip in lowercase
to avoid propagating uppercase characters over the network
to other accounts potentially running buggy code.
2023-11-19 06:22:25 +00:00
link2xt
ab151654fb chore: remove unused import from python tests 2023-11-18 11:32:34 +01:00
link2xt
ea9556b1b9 test: port test_aeap_flow_verified to JSON-RPC 2023-11-18 11:32:34 +01:00
link2xt
3dc6fd5c10 api(deltachat-rpc-client): add Message.get_sender_contact() 2023-11-18 11:32:34 +01:00
link2xt
f39acbc037 test: port test_qr_new_group_unblocked() to JSON-RPC 2023-11-18 11:32:34 +01:00
link2xt
005f7ff07e test: port test_qr_join_chat_with_pending_bobstate_issue4894 to JSON-RPC 2023-11-18 11:32:34 +01:00
link2xt
144ca7c171 test: port test_qr_join_chat to JSON-RPC
Disabled `verified_one_on_one_chats` is not tested
as it is not interesting, other checks are moved.
2023-11-18 11:32:34 +01:00
link2xt
7012b99d73 test: remove test_qr_setup_contact from online python tests
There is an identical `test_qr_setup_contact` in deltachat-rpc-client
test suite which also checks that contact profiles get verified.
2023-11-18 11:32:34 +01:00
Hocuri
72bacd56f7 Update securejoin links 2023-11-18 11:30:59 +01:00
iequidoo
cc75038ccc docs: Contributing guidelines for error handling 2023-11-18 00:34:47 -03:00
link2xt
f4810125e3 fix: recognize Chat-Group-Member-Added of self case-insensitively
If configured address is `Bob@example.net`,
but the message arrives adding `bob@example.net`,
Bob's device should still recognize it as addition of self
and fully recreate the group.
2023-11-18 02:42:28 +00:00
link2xt
acf1faf151 refactor(deltachat-rpc-client): add helper functions to wait for securejoin 2023-11-17 13:32:20 +00:00
link2xt
255fbe94f7 fix: do not use square brackets error for unknown sender
If the sender of the message in protected group chat
is not a member of the chat, mark the sender name with `~`
as we do it in non-protected chats and set the error
instead of replacing the whole message with
"Unknown sender for this chat. See 'info' for more details."

To send a message to a protected group this way
the sender needs to know the group ID
and sign the message with the current verified key.
Usually this is just a late message
delivered shortly after the user has left
the group or was removed from it.

Replacing the message with a single error text part
as done before this change makes it impossible
to access anything other than text, such as attached images.
2023-11-17 10:26:38 +00:00
link2xt
b5d1eba28e docs: add missing 1.131.4 link to the changelog 2023-11-17 10:13:18 +00:00
iequidoo
1509978738 fix: chat::rename_ex(): Sync improved chat name to other devices
Other devices should get the same chat name as the currently used device, i.e. the name a user sees
after renaming the chat. This fix is minor because `improve_single_line_input()` logic isn't going
to change often, but still, and also it simplifies the code.
2023-11-17 03:55:50 -03:00
iequidoo
607b9e55a9 fix: Chat::sync_contacts(): Fetch contact addresses in a single query
In order to protect from races with contacts removal and (just in case) dangling contact ids in
`chats_contacts` table.
2023-11-17 03:55:50 -03:00
holger krekel
7c4c980409 for testrun.org subdomains we can allow 60 messages per minute (or lift the limit completely but maybe good to protect against wild-running bots or so) 2023-11-17 06:50:19 +00:00
B. Petersen
b8ad3ec1b1 chore(release): prepare for 1.131.4 2023-11-16 21:04:19 +01:00
link2xt
87dd33f66e fix: always add "Member added" as system message 2023-11-16 01:54:45 +00:00
link2xt
7d8d13759a docs: document DC_DOWNLOAD_UNDECIPHERABLE
This was introduced in https://github.com/deltachat/deltachat-core-rust/pull/4685
for internal use when looking up a chat based on In-Reply-To,
but actually affects the UIs as they should not display Download button
when the message is downloaded but cannot be decrypted.
2023-11-15 23:07:10 +00:00
link2xt
2b4f2a9171 chore(release): prepare for 1.131.3 2023-11-15 20:08:20 +00:00
link2xt
8e869de350 fix(sync): skip sync when chat name is set to the current one 2023-11-15 19:18:13 +00:00
link2xt
b0ef082b2a fix(sync): ignore unknown sync items to provide forward compatibility 2023-11-15 19:17:38 +00:00
link2xt
bf8e74198d chore: update dependencies 2023-11-15 18:40:15 +00:00
link2xt
e77805471c fix: reset gossiped timestamp on securejoin
If verified key for a contact is changed via securejoin,
gossip the keys in every group with this contact next time
we send a message there to let others learn new verified key
and let the contact who has resetup their device learn keys of others
in groups.
2023-11-15 17:27:37 +00:00
link2xt
45a8004b33 fix: update async-imap to 0.9.4 which does not ignore EOF on FETCH 2023-11-15 15:59:29 +01:00
Simon Laux
990f4dce9b return connectivity html even when IO is stopped.
The returned error is unexpected and no UI I tested with stoped IO really handled it besides maybe displaying a toast.
(desktop and iOS don't handle it, deltatouch shows a toast)

This should not be shown to the user, it is only shown to the user if the UI has a bug, so that bug should be clearly visible.
2023-11-15 13:58:12 +01:00
link2xt
0f36197c54 fix: substitute variables in STATUS error logs 2023-11-15 10:57:05 +00:00
link2xt
890a2bcc15 chore(release): prepare for v1.131.2 2023-11-14 10:13:35 +00:00
link2xt
224355e83a fix: add "setup changed" message for verified key before the message
Merge the code paths for verified and autocrypt key.
If both are changed, only one will be added.

Existing code path adds a message to all chats with the contact
rather than to 1:1 chat. If we later decide that
only 1:1 chat or only verified chats should be notified,
we can add a separate `verified_fingerprint_changed` flag.
2023-11-14 10:00:25 +00:00
link2xt
c6ea4e389a feat: do not post "... verified" messages on QR scan success
We still post "... not verified" on failure.
2023-11-14 09:59:19 +00:00
link2xt
678142b3fb fix: assign MDNs to the trash chat early
Otherwise we will try to create an ad-hoc group
and failing because there are only two contacts
and then unblock a 1:1 chat just to assign
the message to trash in the end.
2023-11-14 08:59:37 +00:00
link2xt
ae6f83cd21 test: add a test checking that read receipt does not unblock 1:1 chat
Hidden 1:1 chat is created for the "chat protected" message.
It should not appear simply because we received
a read receipt from the contact in a group.
2023-11-14 08:59:37 +00:00
link2xt
626b2be1fe api(deltachat-rpc-client): add Account.get_chat_by_contact() 2023-11-14 08:59:37 +00:00
iequidoo
ac5c789c75 feat: Never drop better message from apply_group_changes()
Looks like this doesn't fix anything currently, because a better message from
`apply_group_changes()` doesn't appear in a context with another better message, but why drop it if
it's possible to add it, moreover, messages about implicit member additions are never dropped while
looking less important.
2023-11-14 03:11:30 -03:00
iequidoo
ce2878f1e8 test: If a message implicitly adds a group member, both messages appear (#4987) 2023-11-14 03:11:30 -03:00
link2xt
d4162899b4 fix: ignore special chats when calculating similar chats
The second SQL statement calculating chat size
was already fixed in f656cb29be,
but more important statement calculating member list intersection
was overlooked.
As a result, trash chat with members added there due to former bugs
could still appear in similar chats.
2023-11-13 23:32:52 +00:00
link2xt
e900d50e38 fix: allow to securejoin groups with 1:1 contact request from inviter 2023-11-13 18:24:20 +00:00
link2xt
a438a4746a chore(release): prepare for 1.131.1 2023-11-13 16:14:04 +00:00
link2xt
cfb819506f fix: do not skip actual message parts when group_changes_msg is inserted 2023-11-13 14:18:32 +00:00
link2xt
b86b915f40 chore(release): prepare for 1.131.0 2023-11-13 09:35:57 +00:00
iequidoo
ad5a5ad3db feat: Multi-device broadcast lists (#4953) 2023-11-13 05:00:57 -03:00
iequidoo
74081d8a36 feat: Sync Chat::name across devices (#4953) 2023-11-13 05:00:57 -03:00
iequidoo
34a434f07c refactor: Move chat-related code from sync to chat module
- Reduce cross-module dependencies.
- Stop bloating the `sync` module while implementing synchronisation of more entities.
- Now there's the only `ChatId` :)
2023-11-13 05:00:57 -03:00
iequidoo
dc944d8ca7 test: Broadcast lists synchronisation (#4953) 2023-11-13 05:00:57 -03:00
iequidoo
b06a7e7197 fix: Context::execute_sync_items: Ignore all errors (#4817)
An error while executing an item mustn't prevent next items from being executed. There was a comment
that only critical errors like db write failures must be reported upstack, but in fact it's hard to
achieve in the current design, there are no error codes or so, so it's bug-prone. E.g.
`ChatAction::Block` and `Unblock` already reported all errors upstack. So, let's make error handling
the same as everywhere and just ignore any errors in the item execution loop. In the worst case we
just do more unsuccessful db writes f.e.
2023-11-13 05:00:57 -03:00
iequidoo
fa61d90115 fix: Ignore errors from generating sync messages
It's sufficient if the local state is updated successfully, no need to fail the whole
operation. Anyway delivery of sync messages and applying them on other devices are beyond of our
control. If an error occurs when generating a sync messages, probably a log message is sufficient,
no need to even show it to a user. As for the tests, anyway there are ones on synchronisation which
perform necessary checks. Particularly, some sync messages can't be generated if an account is
unconfigured. Adding the corresponding checks to the device synchronisation code (and maybe even
more checks in the future) would complicate the code unnecessarily. Even errors caused by bugs in
this code aren't a reason to fail a local operation.
2023-11-13 05:00:57 -03:00
iequidoo
7977c9ab44 feat: Sync creating broadcast lists across devices (#4953) 2023-11-13 05:00:57 -03:00
iequidoo
6273a7d54e refactor: Rename Chat::add_sync_item() to sync() 2023-11-13 05:00:57 -03:00
iequidoo
4d1a9c2aa1 feat: Sync chat contacts across devices (#4953)
Sync chat contacts across devices for broadcast lists and groups. This needs the corresponding chat
to exist on other devices which is not the case for unpromoted groups, so it fails for them now but
it's only a warning and will work once creation of unpromoted groups is synchronised too.
2023-11-13 05:00:57 -03:00
Hocuri
b26ded423b Fix #4982: Allow to send unverified securejoin messages to protected chats 2023-11-12 20:15:38 +01:00
Hocuri
e4b6eba5d7 Correct comment 2023-11-12 20:15:38 +01:00
Hocuri
bc225024a1 Add tests 2023-11-12 20:15:38 +01:00
Hocuri
e616ecf160 Fix CI 2023-11-12 20:15:38 +01:00
Hocuri
f93562c6bf Refactorings 2023-11-12 20:15:38 +01:00
Hocuri
ac39c3699b Make sure the resetup happy path works 2023-11-12 20:15:38 +01:00
link2xt
091bc1ab13 fix: encode chat name in the List-ID header
List-ID header is added for broadcast lists.
UTF-8 in email headers is allowed only if
all recipient MTAs support SMTPUTF8 extension,
which is not always the case even if our submission service
reports SMTPUTF8 support.
2023-11-12 19:56:09 +01:00
link2xt
fcbb66a788 chore: update dependencies 2023-11-12 13:35:13 +00:00
link2xt
ab2bc3bfb2 chore: update dependencies 2023-11-10 21:28:28 +00:00
link2xt
42dd6f9d08 chore(release): prepare for 1.130.0 2023-11-10 21:26:27 +00:00
Sebastian Klähn
465bcd46f8 test: test chatlist can load for obfuscated chats (#4979)
close #4598
2023-11-10 20:23:51 +00:00
iequidoo
cc88a6cb58 fix: smtp_loop(): Don't grow timeout if interrupted early (#4833)
Don't grow timeout if interrupted early and slept not enough. Also:
- Don't grow timeout too fast, but 1.5--2 times (randomly) per iteration.
- Don't interrupt if rate-limited.
- Reset timeout if rate-limited. Rate limit isn't an error, so we can start from 30 secs again if an
  error happens then.
2023-11-10 17:17:47 -03:00
iequidoo
ba8f1bfcfd feat: Grow sleep durations on errors in Imap::fake_idle() (#4424) 2023-11-10 17:17:47 -03:00
link2xt
d4d6ced957 fix: do not return hidden chat from dc_get_chat_id_by_contact_id 2023-11-10 20:00:28 +00:00
Hocuri
0b664e75cb docs: mention that people need to set the chatmail server to run the rpc tests 2023-11-10 19:28:29 +00:00
link2xt
1a4c2953f7 refactor: get rid of InterruptInfo
It was passed around, but the boolean inside was not used.
2023-11-10 16:38:01 +00:00
link2xt
765c95de39 refactor(imap): do not check if IDLE is supported twice
We already check if IDLE is supported outside of idle()
2023-11-10 16:38:01 +00:00
link2xt
b2ea8f54df refactor(imap): reduce indentation level in fetch_idle() 2023-11-10 16:38:01 +00:00
link2xt
d7aecabcaa fix: do not apply group changes to special chats
This is a similar check to the one we have in `save_locations`.
2023-11-10 15:46:45 +00:00
holger krekel
9ca049051c fix and streamline a little 2023-11-10 16:46:40 +01:00
Sebastian Klähn
790509676f fix: remove unused --liveconfig option
close  #4892
2023-11-10 16:46:40 +01:00
link2xt
ce016eb567 feat: add secondary verified key
When a key is gossiped for the contact in a verified chat,
it is stored in the secondary verified key slot.

The messages are then encrypted to the secondary verified key
if they are also encrypted to the contact introducing this secondary key.

Chat-Group-Member-Added no longer updates the verified key.
Verified group recovery only relies on the secondary verified key.

When a message is received from a contact
signed with a secondary verified key,
secondary verified key replaces the primary verified key.
When verified key is changed for the contact
in response to receiving a message
signed with a secondary verified key,
"Setup changed" message is added
to the same chat where the message is received.
2023-11-10 15:45:10 +00:00
link2xt
57e34abe98 fix: make UidGrouper robust against duplicate UIDs 2023-11-10 15:42:40 +00:00
link2xt
fd92b7c455 fix: remove Reporting-UA from read receipts
Do not leak Delta Chat core verison to everyone
2023-11-10 15:37:30 +00:00
bjoern
0ee68d1dfc back to two verification-check functions (#4966)
this pr keeps and refines documentation added in #4951, however, reverts
the api introduced by #4951
which turns out to be not useful for UI in practise:

UI anyway check for chat/no-chat beforehand,
so a simple condition in profiles as
`green_checkmark = chat_exist ? chat_is_protected() :
contact_is_verified()`
is more useful in practise and is waht UI need and did already in the
past. (https://github.com/deltachat/deltachat-android/pull/2836 shows a
detailed discussion)

(as a side effect, beside saving code,
this PR saves up to three database calls
(get contact from chat in UI to pass it to profile_is_verified(), get
chat from contact in core, load is_protected in core) - instead, core
can use already is_protected from already loaded chat object)

/me did check rust-tests, fingers crossed for python tests
/me should re-setup python tests on local machine at some point :)
2023-11-09 23:31:18 +01:00
link2xt
1856c622a1 test(deltachat-rpc-client): log all events as debug messages
This is necessary to debug the tests.
2023-11-09 10:06:05 +01:00
link2xt
0a48a2effa refactor: replace inviter_progress macro with a function 2023-11-09 01:58:25 +00:00
link2xt
543864f0f5 test(deltachat-rpc-client): fix securejoin tests
Wait for Bob (joiner) progress 1000
and do not return too early in test_qr_setup_contact().
2023-11-09 01:57:13 +00:00
link2xt
0fe94e47cc test: enable verified 1:1 chats in deltachat-rpc-client tests 2023-11-09 01:57:13 +00:00
link2xt
fc09210aea api: emit JoinerProgress(1000) event when Bob verifies Alice 2023-11-09 01:57:13 +00:00
Hocuri
3e194969c0 fix: Mark 1:1 chat as protected when joining a group 2023-11-09 01:57:13 +00:00
link2xt
391cffb454 docs: add dc_chat_is_protection_broken() to 1.127.0 changelog 2023-11-08 17:53:17 +00:00
Sebastian Klähn
47486f8bab Add Changelog entry for is_protection_broken (#4959)
close #4885
2023-11-08 18:41:55 +01:00
link2xt
620e363ce6 refactor(deltachat-rpc-client): use itertools for thread-safe request ID generation 2023-11-08 17:06:25 +00:00
link2xt
0c2276775d test: test that joining a group verifies Alice and vice versa 2023-11-08 01:56:45 +00:00
iequidoo
ad51a7cd85 feat: apply_group_changes: Add system messages about implicitly added members 2023-11-07 21:09:25 -03:00
B. Petersen
28952789a4 fix: raise lower auto-download limit to 160k 2023-11-07 23:27:02 +00:00
link2xt
14adcdb517 fix: treat reset state as encryption not preferred
This will still degrade 1:1 chats to no encryption,
but will not cause the group to disable encryption
simply because one user got into reset state.
2023-11-07 21:24:23 +00:00
link2xt
cc80590488 test(deltachat-rpc-client): move securejoin tests to a separate file 2023-11-07 18:21:44 +00:00
link2xt
48416289ac api: add dc_contact_is_profile_verified() 2023-11-07 18:14:33 +00:00
link2xt
003a27f625 refactor: hide ChatId::get_for_contact() from public API 2023-11-07 01:19:14 +00:00
bjoern
bff4a2259f chore: update provider-db (#4949) 2023-11-07 01:12:31 +00:00
link2xt
9adf856705 chore: upgrade toml dependency 2023-11-06 22:22:12 +00:00
link2xt
2215de5285 chore(release): prepare for 1.129.1 2023-11-06 20:05:13 +00:00
iequidoo
013467d6c6 test: Group chats device synchronisation 2023-11-06 20:02:28 +00:00
Sebastian Klähn
1f52b8af2f fix: Partial messages do not change group state (#4900)
This message makes that partial messages do not change the group state.
A simple fix and a comprehensive test is added. This is a follow up to
the former #4841 which took a different approach.
2023-11-06 20:01:55 +00:00
iequidoo
ce32f76265 fix: apply_group_changes: Don't implicitly delete members locally, add absent ones instead (#4934)
This is another approach to provide group membership consistency for all members. Considerations:
- Classical MUA users usually don't intend to remove users from an email thread, so if they removed
  a recipient then it was probably by accident.
- DC users could miss new member additions and then better to handle this in the same way as for
  classical MUA messages. Moreover, if we remove a member implicitly, they will never know that and
  continue to think they're still here.

But it shouldn't be a big problem if somebody missed a member removal, because they will likely
recreate the member list from the next received message. The problem occurs only if that "somebody"
managed to reply earlier. Really, it's a problem for big groups with high message rate, but let it
be for now.
2023-11-06 20:00:54 +00:00
link2xt
836f65376c fix(deltachat-rpc-client): add the Lock around request ID
Avoid handing out the same request ID twice.
2023-11-06 20:00:17 +00:00
link2xt
99940dd28c fix: update tokio-imap to fix Outlook STATUS parsing bug 2023-11-06 19:05:36 +00:00
link2xt
ffeb801b58 chore(release): prepare for 1.129.0 2023-11-06 11:07:03 +00:00
link2xt
339bbcf070 chore: update dependencies 2023-11-06 10:53:40 +00:00
link2xt
7b83bddc2d fix(imap): always advance expected UIDNEXT to avoid skipping IDLE in a loop
Ensure the client does not busy loop
skipping IDLE if UIDNEXT of the mailbox is higher than
the last seen UID plus 1, e.g. if the message
with UID=UIDNEXT-1 was deleted before we fetched it.

We do not fallback to UIDNEXT=1 anymore
if the STATUS command cannot determine UIDNEXT.
There are no known IMAP servers with broken STATUS so far.
This allows to guarantee that select_with_uidvalidity()
sets UIDNEXT for the mailbox and use it in fetch_new_messages()
to ensure that UIDNEXT always advances even
when there are no messages to fetch.
2023-11-06 10:30:25 +00:00
link2xt
5549733a0b test: fix flaky test_forward_increation() test 2023-11-06 04:46:10 +00:00
link2xt
4e21917c0e feat: enable sync messages by default 2023-11-05 21:11:47 +00:00
bjoern
939b4b2aab feat: add 'group created instructions' as info message (#4916)
Before, it was shown by UI when the chat is empty, however, in case of
verified groups, this is never the case any longer as the 'e2ee now
guaranteed' is always added.
2023-11-05 19:24:34 +00:00
link2xt
fd0770859d chore(deltachat-jsonrpc): remove unused node-fetch dependency 2023-11-05 18:19:18 +00:00
link2xt
d5854fb3c9 chore(node): update @types/node 2023-11-05 18:16:37 +00:00
link2xt
3aa22a27cc chore(node): remove unused node-fetch dependency 2023-11-05 18:14:38 +00:00
link2xt
10b1a2f5f5 chore(node): update prettier dependency 2023-11-05 18:12:16 +00:00
link2xt
a28a34773c docs: remove documentation for non-existing dc_accounts_new os_name param 2023-11-05 17:54:00 +00:00
link2xt
7c744d14d7 docs: contact profile view should not use dc_contact_is_verified()
Green checkmark in the contact profile
should only be displayed in the title
if the same checkmark is displayed in the title of 1:1 chat.
If 1:1 chat does not exist,
the checkmark should not be displayed in the title
of the contact profile.

Also add docs to is_protected
property of FullChat and BasicChat JSON objects.
2023-11-05 17:21:23 +00:00
link2xt
6c68f2eb7e chore: update dependencies 2023-11-05 15:54:29 +00:00
link2xt
eb2d2b7313 refactor: accept &str instead of Option<String> in idle() 2023-11-05 15:32:37 +00:00
link2xt
2e50abedaa fix: check UIDNEXT with a STATUS command before going IDLE
This prevents accidentally going IDLE
when the last new message has arrived
while the folder was closed.
For example, this happened in some tests:
1. INBOX is selected to fetch, move and delete messages.
2. One of the messages is deleted.
3. INBOX is closed to expunge the message.
4. A new message arrives.
5. INBOX is selected with (CONDSTORE) to sync flags.
6. Delta Chat goes into IDLE without downloading the new message.

To determine that a new message has arrived
we need to notice that UIDNEXT has advanced when selecting the folder.
However, some servers such as Winmail Pro Mail Server 5.1.0616
do not return UIDNEXT in response to SELECT command.

To avoid interdependencies with the code
SELECTing the folder and having to implement
STATUS fallback after each SELECT even when we
may not want to go IDLE due to interrupt or unsolicited EXISTS,
we simply call STATUS unconditionally before IDLE.
2023-11-05 09:58:58 +01:00
link2xt
ee53136ed2 refactor: add hostname to "no DNS resolution results" error message 2023-11-05 09:58:33 +01:00
iequidoo
e923983dca fix: Synchronise self-chat
It just didn't work before, sync messages were not generated.
2023-11-04 19:16:35 -03:00
iequidoo
f4753862f1 feat: Sync chat state immediately (#4817)
Sync messages are only sent on explicit user actions and only one per action, so it's safe to send
them right away not worrying about the rate limit on the server.
2023-11-04 19:16:35 -03:00
link2xt
16b40f3a19 feat: hardcode mail.sangham.net into DNS cache 2023-11-04 17:48:57 +00:00
iequidoo
9cd3a7550b fix: Switch to EncryptionPreference::Mutual on a receipt of encrypted+signed message (#4707) 2023-11-03 23:32:02 -03:00
link2xt
d840a7e6b9 api!: remove deprecated get_verifier_addr 2023-11-03 23:17:09 +00:00
link2xt
d875691955 chore(cargo): update dependencies 2023-11-03 21:12:10 +00:00
bjoern
c600bfa8ca docs: refine Contact::get_verifier_id and Contact::is_verified documentation (#4922)
Co-authored-by: link2xt <link2xt@testrun.org>
2023-11-03 21:11:03 +00:00
link2xt
973ffa1a64 fix: allow to change verified key via "member added" message
"Member added" message likely happens because
the contact adding a new member has another
chat with the contact
2023-11-03 17:51:11 +00:00
link2xt
caffc3d93c fix(json-rpc): return verifier even if the contact is not verified
This may happen if autocrypt key is changed after verification.
UI should still display who introduced the contact,
especially if the contact is still a member of some verified group.
If the contact is at the same time not verified,
i.e. its autocrypt key does not match verified key,
UI may display a crossed out checkmark instead of green checkmark.
2023-11-03 17:51:11 +00:00
link2xt
a4dcf656f3 api: add JSON-RPC get_chat_id_by_contact_id API (#4918) 2023-11-03 13:55:07 +00:00
link2xt
7bb5d48966 refactor: improve error handling in securejoin code
Result::Err is reserved for local errors,
such as database failures.
Not found peerstate in the database is a protocol failure,
so just return Ok(false) in mark_peer_as_verified().

This allows to handle more errors with `?`.
2023-11-02 15:54:35 +00:00
holger krekel
71b7b0b393 fix doc strings for qr-code joinings 2023-11-02 13:31:35 +01:00
holger krekel
bd02eea66b refactor: remove unused or useless code paths in securejoin (#4897) 2023-11-02 12:29:48 +00:00
iequidoo
cdcb10fb58 refactor: Make SyncData::AlterChat an inline struct 2023-11-02 08:47:20 -03:00
iequidoo
6cd7296001 refactor: Replace Context::nosync flag with internal functions taking enum Sync (#4817) 2023-11-02 08:47:20 -03:00
iequidoo
168021523f feat: Sync Contact::blocked across devices (#4817) 2023-11-02 08:47:20 -03:00
iequidoo
03f2635296 feat: Sync chat mute_duration across devices (#4817) 2023-11-02 08:47:20 -03:00
iequidoo
e3b08fa92b feat: Sync chat visibility across devices (#4817) 2023-11-02 08:47:20 -03:00
iequidoo
79cebe66de feat: Sync chat Blocked state across devices (#4817) 2023-11-02 08:47:20 -03:00
link2xt
0619e2a129 chore(release): prepare for 1.128.0 2023-11-02 01:53:42 +00:00
Simon Laux
64a81e4f61 nodejs: update and fix typedoc 2023-11-02 01:27:08 +00:00
link2xt
0431ae53ca hack: decrease ratelimit for .testrun.org subdomains 2023-11-02 00:30:44 +00:00
Simon Laux
89c873acd0 changed!: upgrade nodejs version to 18 (#4903) 2023-11-02 01:23:48 +01:00
B. Petersen
2e70cf9388 remove comment pointing to nothing
documentation and reasoning is fully in `delete_chat()`,
the remove line does not add much to it, also, the hint to "above" is wrong.
2023-11-01 15:46:44 +01:00
link2xt
2efd0461d1 Revert "fix: add secondary verified key"
This reverts commit 5efb100f12.
2023-11-01 13:55:39 +00:00
holger krekel
196a34684d simplify "broken bobstate" as the state still passes 2023-11-01 00:58:54 +01:00
holger krekel
402fd6850c do the actual fix (thanks alex for some help) 2023-11-01 00:58:54 +01:00
holger krekel
72515f440d write a failing test 2023-11-01 00:58:54 +01:00
link2xt
045d919cdc refactor(deltachat-rpc-client): factor out resetup_account() 2023-10-31 23:08:57 +00:00
link2xt
9b9108320e refactor: avoid loading peerstate if there is no Autocrypt-Gossip 2023-10-31 23:08:57 +00:00
link2xt
5efb100f12 fix: add secondary verified key 2023-10-31 23:08:57 +00:00
link2xt
b747dd6ae8 refactor: remove unused argument from set_verified()
It is always PeerstateVerifiedStatus::BidirectVerified
and is always passed as a constant.
2023-10-31 23:08:57 +00:00
link2xt
ed2bc9e44d fix: remove previous attempt to recover from verified key change
This approach was introduced in the C core before Rust conversion:
<ced88321eb>
It does not have tests and does not practically help,
so we remove it in favor of alternative discussed in
<https://github.com/deltachat/deltachat-core-rust/issues/4541>
2023-10-31 23:08:57 +00:00
link2xt
9e1a2149fa test: test recovery of verified group via gossip 2023-10-31 23:08:57 +00:00
link2xt
22b6d8c17b feat(deltachat-rpc-client): add Account.wait_for_incoming_msg_event() 2023-10-31 23:08:57 +00:00
link2xt
3876846410 refactor: sort member vector before deduplicating
Otherwise SELF contact in the beginning of the vector
and in to_ids may be repeated twice and not deduplicated.
dedup() only deduplicates consecutive elements.
2023-10-31 23:08:57 +00:00
link2xt
a93c79e001 fix: allow other verified group recipients to be unverified
We may not have a verified key for other members
because we lost a gossip message.
Still, if the message is signed with a verified key
of the sender, there is no reason to replace it with an error.
2023-10-31 23:08:57 +00:00
link2xt
6aae0276da test: use instant accounts instead of mailadm 2023-10-30 00:15:22 +00:00
link2xt
1d80659bc3 chore: update portable-atomic dependency
Version 1.5.0 is yanked.
2023-10-29 23:36:26 +00:00
link2xt
94d5e86d4f refactor: rename repl_msg_by_error into replace_msg_by_error
This function has been named like this since it was a C function.
`repl` is unclear because it may stand for `reply`
as well as `replace`.
2023-10-29 17:09:59 +00:00
link2xt
aecf7729d8 chore(release): prepare for 1.127.2 2023-10-29 16:29:04 +00:00
Simon Laux
f130d537b7 api(jsonrpc): add get_message_info_object 2023-10-29 16:26:01 +00:00
Ajay Gonepuri
f30f862e7e docs: fix typos 2023-10-29 13:13:44 +00:00
link2xt
81e1164358 test: compile deltachat-rpc-server in debug mode for tests
This reduces compilation times.
2023-10-29 01:09:35 +00:00
Simon Laux
542bd4cbb8 api!: jsonrpc misc_set_draft now requires setting the viewtype 2023-10-28 08:42:14 +00:00
link2xt
771b57778e test: increase pytest timeout to 10 minutes
deltachat-rpc-client tests often timeouts on CI,
this hopefully fixes the problem unless the tests actually deadlock.
2023-10-28 00:54:36 +00:00
link2xt
9be56a5e56 test(deltachat-rpc-client): test securejoin 2023-10-27 20:07:32 +00:00
link2xt
da744958c2 chore: move pytest option from pyproject.toml to tox.ini and set log level
The option from pyproject.toml was not picked up
because tox.ini has higher precedence.
2023-10-27 20:00:20 +00:00
link2xt
f6bda1e480 docs: add missing 1.127.1 link to changelog 2023-10-27 19:34:49 +00:00
link2xt
d2e24534c7 chore(release): prepare for 1.127.1 2023-10-27 19:27:40 +00:00
link2xt
df6f974eca Add scripts for running deltachat-rpc-client tests 2023-10-27 17:24:39 +00:00
link2xt
2f5c6b5e16 test(jsonrpc): test get_provider_info 2023-10-27 03:07:47 +00:00
link2xt
97176b13f1 api(jsonrpc): add id to ProviderInfo 2023-10-27 03:07:18 +00:00
link2xt
18bb7e58be refactor: move api/mod.rs to api.rs 2023-10-27 02:33:17 +00:00
Simon Laux
c2bab44bdd api: jsonrpc add .is_protection_broken to FullChat and BasicChat 2023-10-27 00:03:12 +00:00
link2xt
53bb8a9831 chore: update to async-channel 2 2023-10-26 23:41:34 +00:00
link2xt
1b66120e7d chore(release): prepare for 1.127.0 2023-10-26 15:54:48 +00:00
link2xt
1478f321ae fix: restore try_many_times workaround
Even though r2d2 connection pool is removed,
deleting accounts still fails in Windows CI.

This reverts commit e88f21c010.
`try_many_times` documentation is modified to explain
why the workaround is still needed.
2023-10-26 15:15:44 +00:00
link2xt
5fb92c78ad ci: test deltachat-rpc-client on Windows 2023-10-26 15:15:44 +00:00
link2xt
a0a792b821 chore: update sct, serde and serde_derive 2023-10-26 14:06:44 +00:00
link2xt
3feb0e648d build: switch to iroh 0.4.x fork with updated dependencies 2023-10-26 14:04:32 +00:00
link2xt
fa5358a5bf chore: update tracing 2023-10-26 13:17:54 +00:00
Sebastian Klähn
7399a398a7 api: add mailto parse api (#4829)
close #4620 

This PR introduces a new core API to parse mailto links into a uniform
data format. This could be used to unify the different implementations
on the current platforms.
To complete this PR we have to decide for which APIs we want to expose
this (now) internal API (c, python, json-rpc, etc.), and if we want such
an API at all as it doesn't have a corresponding UI-PR and is not
_really_ needed.
2023-10-26 11:46:51 +02:00
link2xt
25a78aceb9 ci: increase MSRV to 1.70.0
This is required by `anstyle v1.0.4` dependency.
2023-10-26 02:16:10 +00:00
link2xt
66708454dd chore: update dependencies 2023-10-26 02:13:15 +00:00
link2xt
bb5e3d11d8 chore: update futures-lite dependency 2023-10-26 01:11:11 +00:00
link2xt
ff54db2e5f test: adapt the test for updated chrono 2023-10-26 00:47:32 +00:00
link2xt
434d8fc35f chore: update quick-xml 2023-10-25 22:42:14 +00:00
link2xt
12eb813bc3 ci(concourse): replace master branch with main 2023-10-25 22:02:35 +00:00
link2xt
88d5576150 ci(github): replace references to master branch with main 2023-10-25 22:02:32 +00:00
link2xt
af35e4adeb chore: update dependencies 2023-10-25 21:58:13 +00:00
link2xt
eaeacb8848 ci: run only on main branch pushes 2023-10-25 21:46:09 +00:00
link2xt
f00e68e142 chore: update some dependencies 2023-10-25 21:45:22 +00:00
link2xt
113356a24e docs: fix CI badge URL in the readme 2023-10-25 19:31:22 +00:00
link2xt
b89c134e7f Merge branch 'master' into stable 2023-10-25 16:50:18 +00:00
link2xt
3748794048 fix(sql): order migrations the same as on stable branch 2023-10-25 16:37:39 +00:00
iequidoo
ccca12176e feat: Replace Config::SendSyncMsgs with SyncMsgs (#4817)
And execute sync messages only if `Config::SyncMsgs` is enabled. Earlier executing was always
enabled, the messages are force-encrypted anyway. But for users it's probably more clear whether a
device is synchronised or not.
2023-10-25 04:47:37 -03:00
dependabot[bot]
c89dd331f7 chore(cargo): bump libc from 0.2.147 to 0.2.149
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.147 to 0.2.149.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.147...0.2.149)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-25 03:10:25 +00:00
link2xt
fa81ed5f39 ci: rename async tests into JSON-RPC tests 2023-10-25 01:33:56 +00:00
link2xt
6c34f6b8d9 ci: remove misplaced comment 2023-10-25 01:33:56 +00:00
dependabot[bot]
4f21a5691d chore(cargo): bump tokio from 1.29.1 to 1.33.0
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.29.1 to 1.33.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.29.1...tokio-1.33.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-25 00:56:33 +00:00
dependabot[bot]
b2a839971b chore(cargo): bump strum_macros from 0.25.1 to 0.25.3
Bumps [strum_macros](https://github.com/Peternator7/strum) from 0.25.1 to 0.25.3.
- [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Peternator7/strum/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 23:01:25 +00:00
link2xt
8ad99be322 ci: increase MSRV to 1.67.0 2023-10-24 21:18:15 +00:00
link2xt
4e771e8727 Merge branch 'stable' 2023-10-24 17:49:23 +00:00
Sebastian Klähn
e725bdfb2b feat: add bot field to contact (#4821)
closes #4647
2023-10-24 17:42:29 +00:00
link2xt
ac557f73b3 chore: remove unneeded idna rule for cargo-deny 2023-10-24 17:02:16 +00:00
link2xt
0ba3501a46 chore: update trust-dns-resolver to hickory-resolver 2023-10-24 17:00:14 +00:00
B. Petersen
b1fe12881e document configured_addr
in fact, it was already used like that,
eg. to detect an AEAP change on android.
but it was never documented officially.
2023-10-24 17:59:19 +02:00
link2xt
c1eb33c0da Merge tag 'v1.126.1'
Release 1.126.1
2023-10-24 14:50:49 +00:00
link2xt
03bb92c942 chore(release): prepare for 1.126.1 2023-10-24 14:30:02 +00:00
link2xt
b0da5a54cc chore(cargo): update ahash to make cargo-deny happy 2023-10-23 21:56:14 +00:00
link2xt
44e056e210 ci: build Windows wheels for deltachat-rpc-server 2023-10-23 20:38:58 +00:00
link2xt
48a8680ba4 build: set 755 permission on binaries inside deltachat-rpc-server .whl 2023-10-23 20:20:28 +00:00
link2xt
b73bcc2c22 ci: build macOS wheels for deltachat-rpc-server 2023-10-23 20:20:14 +00:00
link2xt
cff42936aa ci: add missing .exe suffix to windows deltachat-rpc-server paths 2023-10-23 20:19:35 +00:00
link2xt
d3b04004b4 feat(imap): buffer STARTTLS command
Using BufWriter ensures that `STARTTLS` command is sent
as a single packet.

Also refactor the code to ensure we only convert to
Box<dyn SessionStream> in the end.
2023-10-23 16:26:29 +00:00
link2xt
5cd92f10ef ci: build deltachat-rpc-server binaries for aarch64 macOS 2023-10-23 16:02:36 +00:00
link2xt
22a3ab983b refactor: download messages without jobs 2023-10-23 11:52:47 +00:00
link2xt
83d2e6b8b4 fix: do not interrupt IMAP loop from get_connectivity_html()
Android calls get_connectivity_html()
every time connectivity changes, which in turn interrupts
IMAP loop and triggers change from "not connected" to "connecting"
state.

To avoid such infinite loop of IMAP interrupts when
there is not connectivity, update quota only when IMAP
loop is interrupted otherwise. This anyway happens
when a message is received or maybe_network is called.

Also remove outdated comments about `Action::UpdateRecentQuota` job
which does not exist anymore.
2023-10-22 18:48:14 +00:00
link2xt
4e979c5880 build: make source package for deltachat-rpc-server install fixed version 2023-10-22 17:49:03 +00:00
link2xt
71e1089139 fix: do not hardcode version in deltachat-rpc-server source package 2023-10-22 16:46:26 +00:00
link2xt
349c154a99 ci: attempt to fix artifacts download for deltachat-rpc-server
Had to do this step manually for 1.126.0,
hopefully the step will work automatically for 1.127.0.
2023-10-22 15:24:02 +00:00
link2xt
54410dbe49 Merge tag 'v1.126.0' 2023-10-22 15:16:11 +00:00
link2xt
4e08bb7b05 chore(release): prepare for 1.126.0 2023-10-22 14:01:07 +00:00
Asiel Díaz Benítez
934ca6a7d7 api: add send_draft() to JSON-RPC API (#4839) 2023-10-22 13:14:08 +00:00
link2xt
e878caebe3 ci: build Python wheels for deltachat-rpc-server 2023-10-22 13:13:04 +00:00
link2xt
088eda2983 build(scripts/zig-rpc-server.sh): move built binaries to dist/ 2023-10-22 13:13:04 +00:00
link2xt
418cd24979 build: strip release binaries
This significantly reduces binary size for deltachat-rpc-server,
from 42 MiB to 15 MiB in case of aarch64.
2023-10-22 13:13:04 +00:00
link2xt
b4fe9e3eec build: use Zig via ziglang PyPI package
This avoids cluttering workdir with unpacked tarball
and will work automatically once PEP-723 is implemented.
2023-10-22 13:13:04 +00:00
link2xt
c13bbd05cd chore: add dist/ to .gitignore 2023-10-22 13:13:04 +00:00
link2xt
58330fe8b2 ci: remove musl check
It requires installing Zig and slows down CI.
This was not broken for a while and we can do
more frequent core releases to catch problems.
2023-10-22 13:13:04 +00:00
link2xt
680d024b05 docs: document scripts/codespell.sh 2023-10-22 06:53:44 +00:00
link2xt
defcd5764b chore: spellcheck 2023-10-22 06:53:26 +00:00
link2xt
e87f785a0a test: adjust expected info message in test_verified_group_vs_delete_server_after
Test was written for stable branch
and has to be adjusted for verified 1:1 chats branch
2023-10-21 04:18:39 +00:00
link2xt
0227bbc305 fix(imap): fallback to STATUS if SELECT did not return UIDNEXT
Winmail Pro Mail Server 5.1.0616 does not return UIDNEXT
in response to SELECT, but returns it when explicitly requested
via STATUS command:

    ? SELECT INBOX
    * FLAGS (\Draft \Answered \Flagged \Deleted \Seen \Recent)
    * OK [PERMANENTFLAGS (\Draft \Answered \Flagged \Deleted \Seen)] Limited
    * 2 EXISTS
    * 0 RECENT
    * OK [UIDVALIDITY 1697802109] Ok
    ? OK [READ-WRITE] Ok SELECT completed
    ? STATUS INBOX (UIDNEXT)
    * STATUS "INBOX" (UIDNEXT 4)
    ? OK STATUS completed

Previously used FETCH method is reported to fail for some users,
the FETCH command sometimes returns no results.
Besides, there is no guarantee that the message with
the highest sequence number has the highest UID.

In the worst case if STATUS does not return UIDNEXT
in response to explicit request, we fall back to setting
UIDNEXT to 1 instead of returning an error.
2023-10-20 22:29:44 +00:00
link2xt
d05afec289 chore(cargo): update async-imap to fix STATUS command 2023-10-20 22:29:44 +00:00
link2xt
64035d3ecb fix: set soft_heap_limit on SQLite database
This should prevent unlimited growth of memory usage
by SQLite for is page cache.
2023-10-20 05:18:21 +00:00
link2xt
21e0bb28ad build: create source distribution for deltachat-rpc-server 2023-10-19 14:38:03 +00:00
link2xt
c6358169ad fix: s/env/venv/ in scripts/make-python-testenv.sh 2023-10-18 20:10:51 +00:00
Asiel Díaz Benítez
955f4fbb19 add self-address to backup filename (#4820)
close #4816

---------

Co-authored-by: B. Petersen <r10s@b44t.com>
2023-10-18 12:31:32 -04:00
adbenitez
df7c44ae42 fix: wrong type hint 2023-10-17 17:18:25 +02:00
Hocuri
8573649bf7 feat: Make broadcast lists create their own chat (#4644)
feat: Make broadcast lists create their own chat - UIs need to ask for
the name when creating broadcast lists now (see
https://github.com/deltachat/deltachat-android/pull/2653)

That's quite a minimal approach: Add a List-ID header to outgoing
broadcast lists, so that the receiving Delta Chat shows them as a
separate chat, as talked about with @r10s and @hpk42.

Done:
- [x] Fix an existing bug that the chat name isn't updated when the
broadcast/mailing list name changes (I already started this locally)

To be done in other PRs:
- [ ] Right now the receiving side shows "Mailing list" in the subtitle
of such a chat, it would be nicer if it showed "Broadcast list" (or
alternatively, rename "Broadcast list" to "Mailing list", too)
- [ ] The UIs should probably ask for a name before creating the
broadcast list, since it will actually be sent over the wire. (Android
PR: https://github.com/deltachat/deltachat-android/pull/2653)

Fixes https://github.com/deltachat/deltachat-core-rust/issues/4597

BREAKING CHANGE: This means that UIs need to ask for the name when creating a broadcast list, similar to https://github.com/deltachat/deltachat-android/pull/2653.
2023-10-17 10:40:47 +02:00
link2xt
52c46c6dca build: add script to build deltachat-rpc-server wheels 2023-10-16 17:04:55 +00:00
link2xt
54ea3ec5d6 build: workaround OpenSSL crate expecting libatomic to be available 2023-10-15 22:57:46 +00:00
Sebastian Klähn
1632035784 feat: add bot field to contact (#4821)
closes #4647
2023-10-15 12:40:32 +02:00
Sebastian Klähn
b239535964 api: allow to filter by unread in chatlist:try_load (#4824)
close #4738
2023-10-14 11:12:53 +02:00
Sebastian Klähn
0751cc50b9 api(json-rpc): force stickers to be sent as stickers (#4819)
This approach uses a param field to enable forcing the sticker
`viewtype`. The first commit has the memory-only flag implemented, but
this flag is not persistent through the database conversion needed for
draft/undraft. That's why `param` has to be used.

follow up to #4814 
fixes #4739

---------

Co-authored-by: Septias <scoreplayer2000@gmail.comclear>
2023-10-14 08:34:46 +00:00
link2xt
da5d844ec4 chore: rustfmt 2023-10-14 04:25:13 +00:00
link2xt
2775fd1fcf Merge tag 'v1.125.0'
Release 1.125.0
2023-10-14 04:24:08 +00:00
link2xt
a87635dcf4 chore(release): prepare for 1.125.0 2023-10-14 04:21:48 +00:00
link2xt
e30517e62c refactor: log MDN sending errors 2023-10-14 03:29:20 +00:00
iequidoo
a54f3c4b31 fix: Don't try to send more MDNs if there's a tmp SMTP error (#4534)
If there's a temporary SMTP error, pretend there are no more MDNs to send in send_mdn(). It's
unlikely that other MDNs could be sent successfully in case of connectivity problems. This approach
is simpler and perhaps even better than adding a progressive backoff between MDN sending retries --
MDNs just will be resent after a reconnection, which makes some sense.
2023-10-12 19:19:43 -03:00
iequidoo
bda6cea0ce feat: Make gossip period configurable (#4346)
This is needed to test periodic re-gossiping in existing chats.

Also add a test for verified groups on that even if "member added" message is missed by a device of
newly added member, after re-gossiping Autocrypt keys to the group it successfully learns these keys
and marks other members as verified.
2023-10-12 05:45:20 -03:00
iequidoo
6fece09ed7 test: test_qr_new_group_unblocked(): W/a message reordering on server
There was a recent failure of the test probably as a result of message reordering on the server:
https://github.com/deltachat/deltachat-core-rust/actions/runs/6464605602/job/17549624095?pr=4813.
2023-10-11 04:54:03 -03:00
link2xt
3917c6b2f0 test(deltachat-rpc-client): enable logs in pytest
This makes pytest setup a logger for `logging` module.
2023-10-10 19:20:42 +00:00
link2xt
96a89b5bdc fix: return verifier contacts regardless of their origin
Previously `Origin::AddressBook` was required,
resulting in a lot of
"Could not lookup contact with address ... which introduced ..."
warnings.
2023-10-10 19:20:22 +00:00
link2xt
b55027fe71 fix: set connectivity status to "connected" during fake idle
Set connectivity status to "connected" at the end of connect() call.
Otherwise for servers that do not support IMAP IDLE
connect() is called at the beginning of fake idle
and connectivity stays in "connecting" status most of the time.
2023-10-10 05:37:51 +00:00
link2xt
eacbb82399 feat: add developer option to disable IDLE 2023-10-10 00:52:18 +00:00
Sebastian Klähn
ee279f84ad fix: show all contacts in Contact::get_all for bots (#4811)
successor of #4810
2023-10-09 21:02:19 +02:00
link2xt
37383c10ac Merge 'stable' into 'master'
Resolved conflicts due to asyncio removal.
2023-10-08 01:30:46 +00:00
link2xt
a119b24eeb Merge tag 'v1.124.1' 2023-10-05 05:02:18 +00:00
link2xt
275791595c Merge tag 'v1.124.0' 2023-10-04 21:14:17 +00:00
dependabot[bot]
f3fb0dc5fe chore(cargo): bump proptest from 1.2.0 to 1.3.1
Bumps [proptest](https://github.com/proptest-rs/proptest) from 1.2.0 to 1.3.1.
- [Release notes](https://github.com/proptest-rs/proptest/releases)
- [Changelog](https://github.com/proptest-rs/proptest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/proptest-rs/proptest/compare/v1.2.0...v1.3.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-03 01:34:58 -03:00
dependabot[bot]
24ea90bd68 Merge pull request #4770 from deltachat/dependabot/cargo/thiserror-1.0.49 2023-10-03 04:30:28 +00:00
dependabot[bot]
ef3e94c7e1 Merge pull request #4777 from deltachat/dependabot/cargo/fuzz/webpki-0.22.2 2023-10-03 04:14:01 +00:00
dependabot[bot]
883832f78d Merge pull request #4768 from deltachat/dependabot/cargo/brotli-3.4.0 2023-10-03 01:21:32 +00:00
dependabot[bot]
1f03267273 Merge pull request #4773 from deltachat/dependabot/cargo/sha2-0.10.8 2023-10-03 01:21:20 +00:00
dependabot[bot]
8bc2ce1c30 chore(deps): bump webpki from 0.22.0 to 0.22.2 in /fuzz
Bumps [webpki](https://github.com/briansmith/webpki) from 0.22.0 to 0.22.2.
- [Commits](https://github.com/briansmith/webpki/commits)

---
updated-dependencies:
- dependency-name: webpki
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-02 21:39:40 +00:00
dependabot[bot]
2ae92c06e3 Merge pull request #4771 from deltachat/dependabot/cargo/regex-1.9.6 2023-10-02 17:46:17 +00:00
dependabot[bot]
4a6a214f3c Merge pull request #4769 from deltachat/dependabot/cargo/tokio-util-0.7.9 2023-10-02 16:38:54 +00:00
dependabot[bot]
c2d7011aa7 Merge pull request #4772 from deltachat/dependabot/cargo/smallvec-1.11.1 2023-10-02 16:38:16 +00:00
dependabot[bot]
c0195ab23f chore(cargo): bump sha2 from 0.10.7 to 0.10.8
Bumps [sha2](https://github.com/RustCrypto/hashes) from 0.10.7 to 0.10.8.
- [Commits](https://github.com/RustCrypto/hashes/compare/sha2-v0.10.7...sha2-v0.10.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 21:44:09 +00:00
dependabot[bot]
e4e50d0e81 chore(cargo): bump smallvec from 1.11.0 to 1.11.1
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.11.0 to 1.11.1.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.11.0...v1.11.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 21:43:50 +00:00
dependabot[bot]
573746ce54 chore(cargo): bump regex from 1.9.5 to 1.9.6
Bumps [regex](https://github.com/rust-lang/regex) from 1.9.5 to 1.9.6.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.9.5...1.9.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 21:43:32 +00:00
dependabot[bot]
6b2df13cdb chore(cargo): bump thiserror from 1.0.47 to 1.0.49
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.47 to 1.0.49.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.47...1.0.49)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 21:43:13 +00:00
dependabot[bot]
3166b44580 chore(cargo): bump tokio-util from 0.7.8 to 0.7.9
Bumps [tokio-util](https://github.com/tokio-rs/tokio) from 0.7.8 to 0.7.9.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-util-0.7.8...tokio-util-0.7.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 21:42:54 +00:00
dependabot[bot]
e500485c21 chore(cargo): bump brotli from 3.3.4 to 3.4.0
Bumps [brotli](https://github.com/dropbox/rust-brotli) from 3.3.4 to 3.4.0.
- [Release notes](https://github.com/dropbox/rust-brotli/releases)
- [Commits](https://github.com/dropbox/rust-brotli/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 21:42:27 +00:00
link2xt
59e5a63d5f Merge branch 'stable', resolving conflicts 2023-10-01 02:46:02 +00:00
link2xt
5daa6274e8 Merge stable into master 2023-09-30 12:16:51 +00:00
Hocuri
d109a1b27f Fix link to the template documentation of git-cliff
The old link gives me 404
2023-09-29 15:20:22 +00:00
dependabot[bot]
c41687586c Merge pull request #4742 from deltachat/dependabot/cargo/fuzz/quinn-proto-0.9.5 2023-09-22 22:43:28 +00:00
link2xt
59a3bc0ff4 Merge tag 'v1.123.0' 2023-09-22 22:41:08 +00:00
dependabot[bot]
a42a6ca18c chore(deps): bump quinn-proto from 0.9.2 to 0.9.5 in /fuzz
Bumps [quinn-proto](https://github.com/quinn-rs/quinn) from 0.9.2 to 0.9.5.
- [Release notes](https://github.com/quinn-rs/quinn/releases)
- [Commits](https://github.com/quinn-rs/quinn/commits)

---
updated-dependencies:
- dependency-name: quinn-proto
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-21 17:26:12 +00:00
link2xt
061d091c97 build(coredeps): only run yum if it is available
musllinux is based on Alpine and has no yum
2023-09-12 19:59:15 +00:00
link2xt
e7617f0abd build(coredeps): install perl-IPC-Cmd
It is required to configure OpenSSL 3.0.
2023-09-12 19:02:20 +00:00
link2xt
790e867af0 Merge tag 'v1.122.0' 2023-09-12 18:04:05 +00:00
link2xt
4a0585404a chore(cargo): bump webpki from 0.22.0 to 0.22.1 2023-09-08 07:00:55 +00:00
link2xt
dcbf5996c2 Merge tag 'v1.121.0' 2023-09-06 21:46:07 +00:00
dependabot[bot]
f7a47e60cd Merge pull request #4664 from deltachat/dependabot/cargo/strum_macros-0.25.2 2023-09-05 19:08:04 +00:00
Hocuri
2587ebbacd fix: Clear VerifiedOneOnOneChats config on backup (#4681)
If the user makes a backup from a UI that supports the experimental verified 1:1 chats (e.g. nightly Android) and imports it into a UI that doesn't, then this config should be cleared.

We already talked about this a long time ago after @Simon-Laux noticed this problem, but I think we didn't actually solve it back then?

Best to review with whitespace changes disabled.
2023-09-05 09:15:15 +02:00
dependabot[bot]
4815e9b990 Merge pull request #4680 from deltachat/dependabot/cargo/regex-1.9.5 2023-09-05 00:03:09 +00:00
dependabot[bot]
f05b0ddf04 chore(cargo): bump regex from 1.9.1 to 1.9.5
Bumps [regex](https://github.com/rust-lang/regex) from 1.9.1 to 1.9.5.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.9.1...1.9.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-04 19:09:31 +00:00
link2xt
f94d34c94b chore: remove idna from deny.toml 2023-09-04 19:08:49 +00:00
link2xt
e9811fb6da AsyncResolver::tokio does not return a Result anymore 2023-09-04 19:08:49 +00:00
dependabot[bot]
178fc1736d chore(cargo): bump trust-dns-resolver from 0.22.0 to 0.23.0
Bumps [trust-dns-resolver](https://github.com/bluejekyll/trust-dns) from 0.22.0 to 0.23.0.
- [Release notes](https://github.com/bluejekyll/trust-dns/releases)
- [Changelog](https://github.com/bluejekyll/trust-dns/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluejekyll/trust-dns/compare/v0.22.0...v0.23.0)

---
updated-dependencies:
- dependency-name: trust-dns-resolver
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-04 19:08:49 +00:00
dependabot[bot]
54d632adaf chore(cargo): bump axum from 0.6.19 to 0.6.20
Bumps [axum](https://github.com/tokio-rs/axum) from 0.6.19 to 0.6.20.
- [Release notes](https://github.com/tokio-rs/axum/releases)
- [Changelog](https://github.com/tokio-rs/axum/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/axum/compare/axum-v0.6.19...axum-v0.6.20)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-04 19:08:34 +00:00
Hocuri
ae939e79da Merge remote-tracking branch 'origin/stable' 2023-09-04 19:19:50 +02:00
dependabot[bot]
e12ef805a9 Merge pull request #4675 from deltachat/dependabot/cargo/backtrace-0.3.69 2023-09-03 19:50:35 +00:00
dependabot[bot]
b36acb2dc0 chore(cargo): bump log from 0.4.19 to 0.4.20
Bumps [log](https://github.com/rust-lang/log) from 0.4.19 to 0.4.20.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.19...0.4.20)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-03 02:25:33 +00:00
dependabot[bot]
1b883ae3fa chore(cargo): bump typescript-type-def from 0.5.7 to 0.5.8
Bumps [typescript-type-def](https://github.com/dbeckwith/rust-typescript-type-def) from 0.5.7 to 0.5.8.
- [Changelog](https://github.com/dbeckwith/rust-typescript-type-def/blob/master/CHANGELOG.md)
- [Commits](https://github.com/dbeckwith/rust-typescript-type-def/compare/v0.5.7...v0.5.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-03 02:25:00 +00:00
dependabot[bot]
72c94e1037 chore(cargo): bump serde from 1.0.180 to 1.0.188
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.180 to 1.0.188.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.180...v1.0.188)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-03 02:24:33 +00:00
dependabot[bot]
0a4c993bb8 chore(cargo): bump serde_json from 1.0.104 to 1.0.105
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.104 to 1.0.105.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.104...v1.0.105)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-03 00:01:58 +00:00
link2xt
ec56134583 Remove winreg entry from deny.toml 2023-09-02 23:01:00 +00:00
dependabot[bot]
d8bf1c1691 chore(cargo): bump reqwest from 0.11.18 to 0.11.20
Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.18 to 0.11.20.
- [Release notes](https://github.com/seanmonstar/reqwest/releases)
- [Changelog](https://github.com/seanmonstar/reqwest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/seanmonstar/reqwest/compare/v0.11.18...v0.11.20)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-02 23:01:00 +00:00
dependabot[bot]
8ac1754e18 chore(cargo): bump tempfile from 3.7.0 to 3.8.0
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.7.0 to 3.8.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.7.0...v3.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-02 22:05:42 +00:00
dependabot[bot]
e1f1143919 chore(cargo): bump quote from 1.0.32 to 1.0.33
Bumps [quote](https://github.com/dtolnay/quote) from 1.0.32 to 1.0.33.
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.32...1.0.33)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-02 22:05:08 +00:00
dependabot[bot]
d9e38289c4 chore(cargo): bump image from 0.24.6 to 0.24.7
Bumps [image](https://github.com/image-rs/image) from 0.24.6 to 0.24.7.
- [Changelog](https://github.com/image-rs/image/blob/master/CHANGES.md)
- [Commits](https://github.com/image-rs/image/compare/v0.24.6...v0.24.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-02 21:57:51 +00:00
dependabot[bot]
486050d0b8 chore(cargo): bump backtrace from 0.3.68 to 0.3.69
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.68 to 0.3.69.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.68...0.3.69)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-02 19:16:16 +00:00
dependabot[bot]
828c90ac3d chore(cargo): bump tokio from 1.29.1 to 1.32.0
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.29.1 to 1.32.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.29.1...tokio-1.32.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-02 19:14:54 +00:00
dependabot[bot]
ab09ecce7e chore(cargo): bump schemars from 0.8.12 to 0.8.13
Bumps [schemars](https://github.com/GREsau/schemars) from 0.8.12 to 0.8.13.
- [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.12...v0.8.13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-02 18:26:24 +00:00
dependabot[bot]
aebad2eb10 chore(cargo): bump url from 2.4.0 to 2.4.1
Bumps [url](https://github.com/servo/rust-url) from 2.4.0 to 2.4.1.
- [Release notes](https://github.com/servo/rust-url/releases)
- [Commits](https://github.com/servo/rust-url/compare/v2.4.0...v2.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-02 17:45:25 +00:00
dependabot[bot]
2a39a85d9e chore(cargo): bump thiserror from 1.0.44 to 1.0.47
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.44 to 1.0.47.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.44...1.0.47)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-02 17:44:37 +00:00
dependabot[bot]
cb0270baa7 chore(cargo): bump anyhow from 1.0.72 to 1.0.75
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.72 to 1.0.75.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.72...1.0.75)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-02 17:44:11 +00:00
dependabot[bot]
99302c9598 chore(cargo): bump base64 from 0.21.2 to 0.21.3
Bumps [base64](https://github.com/marshallpierce/rust-base64) from 0.21.2 to 0.21.3.
- [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/marshallpierce/rust-base64/compare/v0.21.2...v0.21.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-02 17:44:02 +00:00
dependabot[bot]
88ae653760 chore(cargo): bump chrono from 0.4.26 to 0.4.28
Bumps [chrono](https://github.com/chronotope/chrono) from 0.4.26 to 0.4.28.
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.26...v0.4.28)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-02 17:43:13 +00:00
dependabot[bot]
6881f9d70f chore(cargo): bump syn from 2.0.28 to 2.0.29
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.28 to 2.0.29.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.28...2.0.29)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-02 17:42:09 +00:00
dependabot[bot]
60ddbe5729 chore(cargo): bump strum_macros from 0.25.1 to 0.25.2
Bumps [strum_macros](https://github.com/Peternator7/strum) from 0.25.1 to 0.25.2.
- [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Peternator7/strum/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-01 21:09:22 +00:00
iequidoo
5e5e557c8b Merge branch 'stable'
7c7cd9cc80 is a backport from `master`, so skip it.
2023-09-01 13:23:10 -03:00
iequidoo
bc8023644c Merge commit '7c7cd9cc8084f0e425b1919b84d5e79ed150d16b~' into HEAD
Merge `stable` up to the mentioned commit.
2023-09-01 13:14:44 -03:00
iequidoo
83ef25e7de fix: Return from dc_get_chatlist(DC_GCL_FOR_FORWARDING) only chats where we can send (#4616)
I.e. exclude from the list the following chats as well:
- Read-only mailing lists.
- Chats we're not a member of.

But as for ProtectionBroken chats, we return them, as that may happen to a verified chat at any
time. It may be confusing if a chat that is normally in the list disappears suddenly. The UI need to
deal with that case anyway.
2023-09-01 10:26:22 -03:00
link2xt
9a7d1faf75 Merge tag 'v1.120.0' 2023-08-28 11:55:53 +00:00
link2xt
e59c4ee858 Merge branch 'stable' 2023-08-27 22:18:36 +00:00
link2xt
a520f0268f chore: rustfmt 2023-08-26 18:15:11 +00:00
link2xt
5e3b1fa540 Merge branch 'stable' 2023-08-26 18:12:13 +00:00
iequidoo
95f29f7b63 fix: receive_imf: Set protection only for Chattype::Single (#4597)
Also don't set protection to ProtectionBroken if it already is.

Co-authored-by: Hocuri <hocuri@gmx.de>
2023-08-26 13:19:48 -03:00
link2xt
20513475ef Merge branch 'stable' 2023-08-25 01:59:04 +00:00
link2xt
3b806320ec Merge branch 'stable' 2023-08-24 22:25:02 +00:00
dependabot[bot]
c857d6e1bd Merge pull request #4591 from deltachat/dependabot/cargo/sanitize-filename-0.5.0 2023-08-24 20:01:21 +00:00
dependabot[bot]
94cd9a713f chore(cargo): bump sanitize-filename from 0.4.0 to 0.5.0
Bumps [sanitize-filename](https://github.com/kardeiz/sanitize-filename) from 0.4.0 to 0.5.0.
- [Commits](https://github.com/kardeiz/sanitize-filename/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-24 18:42:54 +00:00
link2xt
7676473ebd fix: do not mark non-verified group chats as verified when using securejoin
Only mark the chat is verified if 1:1 verified chats are enabled
and securejoin targets a 1:1 chat.
2023-08-24 18:39:56 +00:00
link2xt
8c778b3f5c test: extend test_qr_join_chat to check that the group is not verified 2023-08-24 18:39:56 +00:00
iequidoo
a66f8bd9fc fix: Delete messages from SMTP queue only on user demand (#4579)
I.e. from delete_msgs(). Otherwise messages must not be deleted from there, e.g. if a message is
ephemeral, but a network outage lasts longer than the ephemeral message timer, the message still
must be sent upon a successful reconnection.
2023-08-24 13:39:22 -03:00
iequidoo
95b2a15930 fix: Sort old incoming messages below all outgoing ones (#4621)
If the Inbox is fetched before the Sentbox (as done currently), messages from the Sentbox will
correctly mingle with the Inbox messages in the end. So, this commit changes message ordering only
if we already have processed outgoing messages, e.g. if we just sent them in the chat as described
in #4621. Otherwise new incoming messages are displayed somewhere in the middle of the chat which
doesn't look usable.
2023-08-24 13:22:26 -03:00
iequidoo
0179ec2da9 fix: receive_imf: Update peerstate from db after handling Securejoin handshake (#4600)
Otherwise has_verified_encryption() would check a stale Peerstate object.
2023-08-24 01:29:25 +00:00
iequidoo
8f2313bb2a test: test_openrpc_command_line: Check that deltachat-rpc-server exists with 0 2023-08-23 19:30:14 +00:00
link2xt
488a3d1118 build(deny): ignore RUSTSEC-2023-0052 2023-08-23 19:30:14 +00:00
link2xt
9094df7bc7 build(python): pin sphinx to 7.1.2 2023-08-23 19:30:14 +00:00
link2xt
16aad3fa67 build(cargo-deny): ignore RUSTSEC-2022-0093
It is an API issue that can only be fixed in rPGP and iroh upstream.
2023-08-17 12:20:58 +00:00
iequidoo
3b47c3f21d ci: Run Rust tests with RUST_BACKTRACE set 2023-08-15 14:24:02 -03:00
link2xt
987ce58926 chore(python): fix lint errors 2023-08-11 17:06:15 +00:00
iequidoo
20c88743df test: W/a message reordering in test_reaction_to_partially_fetched_msg() 2023-08-08 21:02:41 -03:00
dependabot[bot]
03395b95cb chore(cargo): bump quick-xml from 0.29.0 to 0.30.0
Bumps [quick-xml](https://github.com/tafia/quick-xml) from 0.29.0 to 0.30.0.
- [Release notes](https://github.com/tafia/quick-xml/releases)
- [Changelog](https://github.com/tafia/quick-xml/blob/master/Changelog.md)
- [Commits](https://github.com/tafia/quick-xml/compare/v0.29.0...v0.30.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-08 21:02:41 -03:00
Hocuri
53f04a134a test: Don't accidentally accept that a chat protection is broken (#4550) 2023-08-08 11:35:38 +02:00
Hocuri
885f26ea8c test: Directly unwrap in TestContext::get_chat() (#4614)
Directly unwrap in TestContext::get_chat()

Turns out that all usages of get_chat() directly unwrapped, because in a
test it doesn't make sense to handle the error of there being no chat.
2023-08-08 11:34:52 +02:00
link2xt
3ab181fdf8 build: update to Zig 0.11.0 2023-08-06 19:44:48 +00:00
link2xt
e12044e6af api!(deltachat-jsonrpc): use kind as a tag for all union types 2023-08-03 23:46:24 +00:00
link2xt
954067eb6d Merge tag 'v1.119.0' 2023-08-03 17:05:00 +00:00
link2xt
aecbebd566 docs: improve JSON-RPC API documentation 2023-08-03 16:06:36 +00:00
link2xt
3111bcde5e refactor: flatten imports in deltachat-jsonrpc 2023-08-03 15:58:48 +00:00
link2xt
e6cffd537e refactor: remove Chattype::Undefined 2023-08-02 17:02:28 +00:00
link2xt
70000d9ebb build: increase MSRV to 1.67.0
This is required by time v0.3.24
2023-08-02 03:27:21 +00:00
link2xt
d95843b0bf chore(deps): update dependencies 2023-08-02 03:23:19 +00:00
link2xt
13e766bc37 feat(deltachat-rpc-server): add --openrpc option 2023-08-01 18:27:02 +00:00
link2xt
c34edc582e test: test that get_system_info() works over RPC backup import 2023-08-01 01:05:06 +00:00
link2xt
8eee389c09 refactor: use SQL transaction in MsgId.delete_from_db() 2023-07-31 20:01:35 +00:00
link2xt
8ed6d4d709 api!: make MsgId.delete_from_db() private
Use `delete_msgs()` if you are using the Delta Chat core
as a library and want to delete a message.
2023-07-31 20:01:35 +00:00
Hocuri
60bacbec47 feat: Don't show a contact as verified if their key changed since the verification (#4574)
Don't show a contact as verified if their key changed in the meantime

If a contact's key changed since the verification, then it's very
unlikely that they still have the old, verified key. So, don't show them
as verified anymore.

This also means that you can't add a contact like this to a verified
group, which is good.

The documentation actually already described this (new) behavior:

```rust
/// and if the key has not changed since this verification.
```

so, this adapts the code to the documentation.
2023-07-31 18:59:45 +02:00
link2xt
af013559de refactor: hide DcSecretKey trait from the API 2023-07-29 18:10:25 +00:00
link2xt
b784415c57 refactor: move dc_preconfigure_keypair() implementation into deltachat crate
This allows to hide `DcKey` trait from public API.
2023-07-29 18:05:05 +00:00
link2xt
85739ba6ad refactor: make last_added_location_id an Option 2023-07-29 17:45:15 +00:00
B. Petersen
a02a593f47 fix example; this was changed some time ago, see https://docs.webxdc.org/spec.html#sendupdate 2023-07-29 05:08:54 +02:00
link2xt
67f28f501a Merge branch 'stable' 2023-07-27 19:40:01 +00:00
link2xt
9b9703a48e refactor: replace DcKey.load_self trait method with functions 2023-07-27 18:23:56 +00:00
link2xt
c55a3d3873 refactor: flatten and simplify imports 2023-07-27 17:47:30 +00:00
iequidoo
f27d304f3b feat!: Add lockfile to account manager (#4310)
Opening the same account (context) from multiple processes is dangerous, can result in duplicate
downloads of the same message etc. Same for account manager, attempts to modify the same
accounts.toml even if done atomically with may result in corrupted files as atomic replacement
procedure does not expect that multiple processes may write to the same temporary file.

accounts.toml cannot be used as a lockfile because it is replaced during atomic update. Therefore, a
new file next to accounts.toml is needed to prevent starting second account manager in the same
directory.

But iOS needs to be able to open accounts from multiple processes at the same time. This is required
as the "share-to-DC extension" is a separate process by iOS design -- this process may or may not be
started while the main app is running. Accounts are not altered however by this extension, so let's
add to the `Accounts::new()` constructor an `rdwr` parameter which allows to read the accounts
config w/o locking the lockfile.
2023-07-26 16:02:25 -03:00
link2xt
6d51d19f01 refactor(e2ee): do not return anything from ensure_secret_key_exists()
The return value was never used.
2023-07-26 11:19:08 +00:00
Hocuri
170968dfc2 Update README.md 2023-07-25 16:50:10 +02:00
link2xt
f930576fd1 Merge branch 'stable' 2023-07-24 18:40:44 +00:00
link2xt
d797de7a8d refactor: use slices and vectors instead of Keyring wrapper
This change removes all traces of dc_keyring_t,
which was a C implementation of dynamically sized array.
2023-07-24 18:05:38 +00:00
link2xt
acc7bb00c5 chore(deps): update rPGP 2023-07-24 16:14:16 +00:00
link2xt
8fb8a877be chore(deps): update dependencies 2023-07-24 14:06:09 +00:00
Hocuri
b96028cd87 api!(Rust): Remove unused function is_verified_ex() (#4551)
No one used it anymore, and all occurences I could find (on
GitHub)[https://github.com/search?q=%22is_verified_ex%22&type=code&p=1]
are either forks of deltachat-core-rust or of deltachat-core (which is
the old C core).
2023-07-24 12:19:13 +02:00
Hocuri
682e241edb fix: Fix info-message orderings of verified 1:1 chats (#4545)
Correctly handle messages with old timestamps for verified chats:

 * They must not be sorted over a protection-changed info message

 * If they change the protection, then they must not be sorted over existing other messages, because then the protection-changed info message would also be above these existing messages.


This PR fixes this:

 1. Even seen messages can't be sorted into already-noticed messages anymore. **This also changes DC's behavior in the absence of verified 1:1 chats**. Before this PR, messages that are marked as seen when they are downloaded will always be sorted by their timestamp, even if it's very old.

 2. protection-changed info messages are always sorted to the bottom.

    **Edit:**

 3. There is an exception to rule 1: Outgoing messages are still allowed to be sorted purely by their timestamp, and don't influence old messages. This is to the problem described at [*].


Together, these rules also make sure that the protection-changed info message is always right above the message causing the change.

[*] If we receive messages from two different folders, e.g. `Sent` and `Inbox`, then this will lead to wrong message ordering in many cases. I need to think about this more, or maybe someone else has an idea. One new idea that came to my mind is:

 * Always sort noticed messages under the newest info message (this PR sorts them under the newest noticed message, master sorts them purely by their sent timestamp)

 * Always sort unnoticed messages under the newest noticed message (that's the same behavior as in this PR and on master)

 * Always sort protection-changed info messages to the bottom (as in this PR)


However, after a talk with @link2xt we instead decided to add rule 3. (see above) because it seemed a little bit easier.
2023-07-24 12:16:32 +02:00
Simon Laux
3a63628f1f update node constants
looks like this was fogotten when changing the chat protection stock strings
2023-07-23 09:26:01 +00:00
link2xt
3705616cd9 Merge branch 'stable' 2023-07-23 09:17:13 +00:00
Simon Laux
b8fcb660ad cargo fmt 2023-07-23 02:29:42 +02:00
Simon Laux
5673294623 api(jsonrpc): add resend_messages 2023-07-23 02:29:42 +02:00
B. Petersen
7062bb0502 clarify transitive behaviour of dc_contact_is_verfified() 2023-07-22 20:58:05 +02:00
link2xt
659cffe0cc ci: remove comment about python from rust tests 2023-07-19 13:43:20 +00:00
link2xt
a1663a98e0 build: use Rust 1.71.0 and increase MSRV to 1.66.0
Rust 1.66 is required by constant_time_eq 0.3.0.
2023-07-19 13:41:31 +00:00
link2xt
3de1dbc9e4 chore(deps): update dependencies 2023-07-19 13:26:47 +00:00
link2xt
6d37e8601e Merge branch 'stable' 2023-07-17 17:11:38 +00:00
Hocuri
d762753103 fix: Allow to save a draft if the verification is broken (#4542)
If the verification is broken, `can_send()` is false.

But if the user was typing a message right when a verification-breaking message came in, the UI still needs to be able to save it as a draft.

Steps to reproduce the bug:
  - Set a draft
  - Your chat partner breaks verification
  - Go back to the chats list
  - Go to the chat again
  - Accept the breakage
  - Expected: The draft is still there
  - Bug behavior: The draft is gone
2023-07-16 12:04:43 +02:00
link2xt
a020d5ccce Merge branch 'stable' 2023-07-14 11:23:43 +00:00
Hocuri
1e28ea9bb0 fix: Don't create 1:1 chat as protected for contact who doesn't prefer to encrypt (#4538) 2023-07-11 17:39:59 +00:00
Hocuri
17f2d33731 test: Remove unnecessary inner_set_protection() call (#4539)
1:1 chats are automatically created as protected if the contact is
verified, there is no need to explicitly do this.

Plus, by removing this call, the test also tests that automatically
creating 1:1 chats as protected works.
2023-07-11 19:15:23 +02:00
link2xt
976797d4cf build: remove examples/simple.rs
When `cargo test` is executed,
all examples are built by default
to ensure that they can be compiled.

This is a documented and expected behaviour,
even though it was previously reported as a bug:
<https://github.com/rust-lang/cargo/issues/6675>

In particular, `examples/simple.rs` is built into
a 67M binary `target/debug/examples/simple`.
This is unnecessary to do so every time
you change a line in the `deltachat` crate
and want to rerun the tests.

Workaround is to run `cargo test --tests`,
but it is easy to forget and is not discoverable
unless you read the "Target Selection" section of `cargo help test`.

We have a maintained example at https://github.com/deltachat-bot/echo,
so there is no need for an example in the core repository.
2023-07-10 21:49:31 +00:00
link2xt
31e3169433 chore: nightly clippy fixes 2023-07-10 11:38:46 +02:00
link2xt
d2b15cb629 docs: document how logs and error messages should be formatted 2023-07-09 16:18:18 +00:00
Hocuri
9cd000c4f2 feat: Verified 1:1 chats (#4315)
Implement #4188

BREAKING CHANGE: Remove unused DC_STR_PROTECTION_(EN)ABLED* strings
BREAKING CHANGE: Remove unused dc_set_chat_protection()
2023-07-09 14:06:45 +02:00
link2xt
243c035b03 chore: spellcheck 2023-07-07 21:56:59 +00:00
205 changed files with 12574 additions and 7282 deletions

View File

@@ -14,8 +14,7 @@ on:
pull_request:
push:
branches:
- master
- stable
- main
env:
RUSTFLAGS: -Dwarnings
@@ -25,7 +24,7 @@ jobs:
name: Lint Rust
runs-on: ubuntu-latest
env:
RUSTUP_TOOLCHAIN: 1.73.0
RUSTUP_TOOLCHAIN: 1.75.0
steps:
- uses: actions/checkout@v3
- name: Install rustfmt and clippy
@@ -39,10 +38,6 @@ jobs:
- name: Check
run: cargo check --workspace --all-targets --all-features
# Check with musl libc target which is used for `deltachat-rpc-server` releases.
- name: Check musl
run: scripts/zig-musl-check.sh
cargo_deny:
name: cargo deny
runs-on: ubuntu-latest
@@ -81,19 +76,15 @@ jobs:
matrix:
include:
- os: ubuntu-latest
rust: 1.73.0
rust: 1.75.0
- os: windows-latest
rust: 1.73.0
rust: 1.75.0
- os: macos-latest
rust: 1.73.0
rust: 1.75.0
# Minimum Supported Rust Version = 1.65.0
#
# Minimum Supported Python Version = 3.7
# This is the minimum version for which manylinux Python wheels are
# built.
# Minimum Supported Rust Version = 1.70.0
- os: ubuntu-latest
rust: 1.65.0
rust: 1.70.0
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
@@ -106,6 +97,8 @@ jobs:
uses: swatinem/rust-cache@v2
- name: Tests
env:
RUST_BACKTRACE: 1
run: cargo test --workspace
- name: Test cargo vendor
@@ -137,7 +130,7 @@ jobs:
name: Build deltachat-rpc-server
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
@@ -152,7 +145,7 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.os }}-deltachat-rpc-server
path: target/debug/deltachat-rpc-server
path: ${{ matrix.os == 'windows-latest' && 'target/debug/deltachat-rpc-server.exe' || 'target/debug/deltachat-rpc-server' }}
retention-days: 1
python_lint:
@@ -173,8 +166,8 @@ jobs:
working-directory: deltachat-rpc-client
run: tox -e lint
python_tests:
name: Python tests
cffi_python_tests:
name: CFFI Python tests
needs: ["c_library", "python_lint"]
strategy:
fail-fast: false
@@ -218,14 +211,14 @@ jobs:
- name: Run python tests
env:
DCC_NEW_TMP_EMAIL: ${{ secrets.DCC_NEW_TMP_EMAIL }}
CHATMAIL_DOMAIN: ${{ secrets.CHATMAIL_DOMAIN }}
DCC_RS_TARGET: debug
DCC_RS_DEV: ${{ github.workspace }}
working-directory: python
run: tox -e mypy,doc,py
aysnc_python_tests:
name: Async Python tests
rpc_python_tests:
name: JSON-RPC Python tests
needs: ["python_lint", "rpc_server"]
strategy:
fail-fast: false
@@ -235,6 +228,8 @@ jobs:
python: 3.12
- os: macos-latest
python: 3.12
- os: windows-latest
python: 3.12
# PyPy tests
- os: ubuntu-latest
@@ -265,13 +260,20 @@ jobs:
path: target/debug
- name: Make deltachat-rpc-server executable
if: ${{ matrix.os != 'windows-latest' }}
run: chmod +x target/debug/deltachat-rpc-server
- name: Add deltachat-rpc-server to path
if: ${{ matrix.os != 'windows-latest' }}
run: echo ${{ github.workspace }}/target/debug >> $GITHUB_PATH
- name: Add deltachat-rpc-server to path
if: ${{ matrix.os == 'windows-latest' }}
run: |
"${{ github.workspace }}/target/debug" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Run deltachat-rpc-client tests
env:
DCC_NEW_TMP_EMAIL: ${{ secrets.DCC_NEW_TMP_EMAIL }}
CHATMAIL_DOMAIN: ${{ secrets.CHATMAIL_DOMAIN }}
working-directory: deltachat-rpc-client
run: tox -e py

View File

@@ -26,35 +26,17 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Build
- name: Install ziglang
run: pip install wheel ziglang==0.11.0
- name: Build deltachat-rpc-server binaries
run: sh scripts/zig-rpc-server.sh
- name: Upload x86_64 binary
- name: Upload dist directory with Linux binaries
uses: actions/upload-artifact@v3
with:
name: deltachat-rpc-server-x86_64
path: target/x86_64-unknown-linux-musl/release/deltachat-rpc-server
if-no-files-found: error
- name: Upload i686 binary
uses: actions/upload-artifact@v3
with:
name: deltachat-rpc-server-i686
path: target/i686-unknown-linux-musl/release/deltachat-rpc-server
if-no-files-found: error
- name: Upload aarch64 binary
uses: actions/upload-artifact@v3
with:
name: deltachat-rpc-server-aarch64
path: target/aarch64-unknown-linux-musl/release/deltachat-rpc-server
if-no-files-found: error
- name: Upload armv7 binary
uses: actions/upload-artifact@v3
with:
name: deltachat-rpc-server-armv7
path: target/armv7-unknown-linux-musleabihf/release/deltachat-rpc-server
name: linux
path: dist/
if-no-files-found: error
build_windows:
@@ -92,39 +74,87 @@ jobs:
build_macos:
name: Build deltachat-rpc-server for macOS
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
- arch: aarch64
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: Setup rust target
run: rustup target add x86_64-apple-darwin
run: rustup target add ${{ matrix.arch }}-apple-darwin
- name: Build
run: cargo build --release --package deltachat-rpc-server --target x86_64-apple-darwin --features vendored
run: cargo build --release --package deltachat-rpc-server --target ${{ matrix.arch }}-apple-darwin --features vendored
- name: Upload binary
uses: actions/upload-artifact@v3
with:
name: deltachat-rpc-server-x86_64-macos
path: target/x86_64-apple-darwin/release/deltachat-rpc-server
name: deltachat-rpc-server-${{ matrix.arch }}-macos
path: target/${{ matrix.arch }}-apple-darwin/release/deltachat-rpc-server
if-no-files-found: error
publish:
name: Upload binaries to the release
name: Build wheels and upload binaries to the release
needs: ["build_linux", "build_windows", "build_macos"]
permissions:
contents: write
runs-on: "ubuntu-latest"
steps:
- name: Download built binaries
uses: "actions/download-artifact@v3"
- uses: actions/checkout@v3
- name: Compose dist/ directory
- name: Download Linux binaries
uses: actions/download-artifact@v3
with:
name: linux
path: dist/
- name: Download win32 binary
uses: actions/download-artifact@v3
with:
name: deltachat-rpc-server-win32.exe
path: deltachat-rpc-server-win32.exe.d
- name: Download win64 binary
uses: actions/download-artifact@v3
with:
name: deltachat-rpc-server-win64.exe
path: deltachat-rpc-server-win64.exe.d
- name: Download macOS binary for x86_64
uses: actions/download-artifact@v3
with:
name: deltachat-rpc-server-x86_64-macos
path: deltachat-rpc-server-x86_64-macos.d
- name: Download macOS binary for aarch64
uses: actions/download-artifact@v3
with:
name: deltachat-rpc-server-aarch64-macos
path: deltachat-rpc-server-aarch64-macos.d
- name: Flatten dist/ directory
run: |
mkdir dist
for x in x86_64 i686 aarch64 armv7 win32.exe win64.exe x86_64-macos; do
mv "deltachat-rpc-server-$x"/* "dist/deltachat-rpc-server-$x"
done
mv deltachat-rpc-server-win32.exe.d/deltachat-rpc-server.exe dist/deltachat-rpc-server-win32.exe
mv deltachat-rpc-server-win64.exe.d/deltachat-rpc-server.exe dist/deltachat-rpc-server-win64.exe
mv deltachat-rpc-server-x86_64-macos.d/deltachat-rpc-server dist/deltachat-rpc-server-x86_64-macos
mv deltachat-rpc-server-aarch64-macos.d/deltachat-rpc-server dist/deltachat-rpc-server-aarch64-macos
# Python 3.11 is needed for tomllib used in scripts/wheel-rpc-server.py
- name: Install python 3.12
uses: actions/setup-python@v4
with:
python-version: 3.12
- name: Install wheel
run: pip install wheel
- name: Build deltachat-rpc-server Python wheels and source package
run: scripts/wheel-rpc-server.py
- name: List downloaded artifacts
run: ls -l dist/

View File

@@ -17,7 +17,7 @@ jobs:
uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: "16"
node-version: "18"
- name: Get tag
id: tag
uses: dawidd6/action-get-tag@v1

View File

@@ -2,9 +2,9 @@ name: JSON-RPC API Test
on:
push:
branches: [master]
branches: [main]
pull_request:
branches: [master]
branches: [main]
env:
CARGO_TERM_COLOR: always
@@ -15,10 +15,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js 16.x
- name: Use Node.js 18.x
uses: actions/setup-node@v3
with:
node-version: 16.x
node-version: 18.x
- name: Add Rust cache
uses: Swatinem/rust-cache@v2
- name: npm install
@@ -31,7 +31,7 @@ jobs:
working-directory: deltachat-jsonrpc/typescript
run: npm run test
env:
DCC_NEW_TMP_EMAIL: ${{ secrets.DCC_NEW_TMP_EMAIL }}
CHATMAIL_DOMAIN: ${{ secrets.CHATMAIL_DOMAIN }}
- name: make sure websocket server version still builds
working-directory: deltachat-jsonrpc
run: cargo build --bin deltachat-jsonrpc-server --features webserver

View File

@@ -8,7 +8,7 @@ name: Generate & upload node.js documentation
on:
push:
branches:
- master
- main
jobs:
generate:
@@ -16,10 +16,10 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Use Node.js 16.x
- name: Use Node.js 18.x
uses: actions/setup-node@v3
with:
node-version: 16.x
node-version: 18.x
- name: npm install and generate documentation
working-directory: node

View File

@@ -18,7 +18,7 @@ jobs:
uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: "16"
node-version: "18"
- name: System info
run: |
rustc -vV
@@ -66,10 +66,8 @@ jobs:
runs-on: ubuntu-latest
# Build Linux prebuilds inside a container with old glibc for backwards compatibility.
# Debian 10 contained glibc 2.28 at the time of the writing (2023-06-04): https://packages.debian.org/buster/libc6
# Ubuntu 18.04 is at the End of Standard Support since June 2023, but it contains glibc 2.27,
# so we are using it to support Ubuntu 18.04 setups that are still not upgraded.
container: ubuntu:18.04
# Debian 10 contained glibc 2.28: https://packages.debian.org/buster/libc6
container: debian:10
steps:
# Working directory is owned by 1001:1001 by default.
# Change it to our user.
@@ -80,7 +78,7 @@ jobs:
uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: "16"
node-version: "18"
- run: apt-get update
# Python is needed for node-gyp
@@ -143,7 +141,7 @@ jobs:
uses: actions/checkout@v3
- uses: actions/setup-node@v2
with:
node-version: "16"
node-version: "18"
- name: Get tag
id: tag
uses: dawidd6/action-get-tag@v1

View File

@@ -13,7 +13,7 @@ on:
pull_request:
push:
branches:
- master
- main
jobs:
tests:
@@ -27,7 +27,7 @@ jobs:
uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: "16"
node-version: "18"
- name: System info
run: |
rustc -vV
@@ -63,5 +63,5 @@ jobs:
working-directory: node
run: npm run test
env:
DCC_NEW_TMP_EMAIL: ${{ secrets.DCC_NEW_TMP_EMAIL }}
CHATMAIL_DOMAIN: ${{ secrets.CHATMAIL_DOMAIN }}
NODE_OPTIONS: "--force-node-api-uncaught-exceptions-policy=true"

View File

@@ -3,8 +3,7 @@ name: Build & Deploy Documentation on rs.delta.chat
on:
push:
branches:
- master
- docs-gh-action
- main
jobs:
build:

View File

@@ -7,8 +7,7 @@ name: Build & Deploy Documentation on cffi.delta.chat
on:
push:
branches:
- master
- docs-gh-action
- main
jobs:
build:

View File

@@ -0,0 +1,25 @@
name: Build & Deploy Documentation on py.delta.chat
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetch history to calculate VCS version number.
- name: Build Python documentation
run: scripts/build-python-docs.sh
- name: Upload to py.delta.chat
uses: up9cloud/action-rsync@v1.3
env:
USER: delta
KEY: ${{ secrets.CODESPEAK_KEY }}
HOST: "lists.codespeak.net"
SOURCE: "dist/html/"
TARGET: "/home/delta/build/master"

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
/target
**/*.rs.bk
/build
/dist
# ignore vi temporaries
*~

View File

@@ -1,5 +1,546 @@
# Changelog
## [1.133.2] - 2024-01-24
### Fixes
- Downgrade OpenSSL from 3.2.0 to 3.1.4 ([#5206](https://github.com/deltachat/deltachat-core-rust/issues/5206))
- No new chats for MDNs with alias ([#5196](https://github.com/deltachat/deltachat-core-rust/issues/5196)) ([#5199](https://github.com/deltachat/deltachat-core-rust/pull/5199)).
## [1.133.1] - 2024-01-21
### API-Changes
- Add `is_bot` to cffi and jsonrpc ([#5197](https://github.com/deltachat/deltachat-core-rust/pull/5197)).
### Features / Changes
- Add system message when provider does not allow unencrypted messages ([#5195](https://github.com/deltachat/deltachat-core-rust/pull/5195)).
### Fixes
- `Chat::send_msg`: Remove encryption-related params from already sent message. This allows to send received encrypted `dc_msg_t` object to unencrypted chat, e.g. in a Python bot.
- Set message download state to Failure on IMAP errors. This avoids partially downloaded messages getting stuck in "Downloading..." state without actually being in a download queue.
- BCC-to-self even if server deletion is set to "at once". This is a workaround for SMTP servers which do not return response in time, BCC-self works as a confirmation that message was sent out successfully and does not need more retries.
- node: Run tests with native ESM modules instead of `esm` ([#5194](https://github.com/deltachat/deltachat-core-rust/pull/5194)).
- Use Quoted-Printable MIME encoding for the text part ([#3986](https://github.com/deltachat/deltachat-core-rust/pull/3986)).
### Tests
- python: Add `get_protected_chat` to testplugin.py.
## [1.133.0] - 2024-01-14
### Features / Changes
- Securejoin protocol implementation refinements
- Track forward and backward verification separately ([#5089](https://github.com/deltachat/deltachat-core-rust/pull/5089)) to avoid inconsistent states.
- Mark 1:1 chat as verified for Bob early. 1:1 chat with Alice is verified as soon as Alice's key is verified rather than at the end of the protocol.
- Put Message-ID into hidden headers and take it from there on receiver ([#4798](https://github.com/deltachat/deltachat-core-rust/pull/4798)). This works around servers which generate their own Message-ID and overwrite the one generated by Delta Chat.
- deltachat-repl: Enable INFO logging by default and add timestamps.
- Add `ConfigSynced` (`DC_EVENT_CONFIG_SYNCED`) event which is emitted when configuration is changed via synchronization message or synchronization message for configuration is sent. UI may refresh elments based on the configuration key which is a part of the event.
- Sync contact creation/rename across devices ([#5163](https://github.com/deltachat/deltachat-core-rust/pull/5163)).
- Encrypt MDNs ([#5175](https://github.com/deltachat/deltachat-core-rust/pull/5175)).
- Only try to configure non-strict TLS checks if explicitly set ([#5181](https://github.com/deltachat/deltachat-core-rust/pull/5181)).
### Build system
- Use released version of iroh 0.4.2 for "setup second device" feature.
### CI
- Update to Rust 1.75.0.
- Downgrade `chai` from 4.4.0 to 4.3.10.
### Documentation
- Add a link <https://www.ietf.org/archive/id/draft-bucksch-autoconfig-00.html> to autoconfig RFC draft.
- Update securejoin link in `standards.md` from <https://countermitm.readthedocs.io/> to <https://securejoin.readthedocs.io>.
- Restore "Constants" page in Doxygen >=1.9.8
### Fixes
- imap: Limit the rate of LOGIN attempts rather than connection attempts. This is to avoid having to wait for rate limiter right after switching from a bad or offline network to a working network while still guarding against reconnection loop.
- Do not ignore `peerstate.save_to_db()` errors.
- securejoin: Mark 1:1s as protected regardless of the Config::VerifiedOneOnOneChats.
- Delete received outgoing messages from SMTP queue ([#5115](https://github.com/deltachat/deltachat-core-rust/pull/5115)).
- imap: Fail fast on `LIST` errors to avoid busy loop when connection is lost.
- Split SMTP jobs already in `chat::create_send_msg_jobs()` ([#5115](https://github.com/deltachat/deltachat-core-rust/pull/5115)).
- Do not remove contents from unencrypted [Schleuder](https://schleuder.org/) mailing lists messages.
- Reset message error when scheduling resending ([#5119](https://github.com/deltachat/deltachat-core-rust/pull/5119)).
- Emit events more reliably when starting and stopping I/O ([#5101](https://github.com/deltachat/deltachat-core-rust/pull/5101)).
- Fix timestamp of chat protection info message for correct message ordering after restoring a backup ([#5088](https://github.com/deltachat/deltachat-core-rust/pull/5088)).
### Refactor
- sql: Recreate `config` table with UNIQUE constraint.
- sql: Recreate `keypairs` table to remove unused `addr` and `created` fields and move `is_default` flag to `config` table.
- Send `Secure-Join-Fingerprint` only in `*-request-with-auth`.
### Tests
- Test joining non-protected group.
- Test that read receipts don't degrade encryption.
- Test that changing default private key breaks backward verification.
- Test recovery from lost vc-contact-confirm.
- Use `wait_for_incoming_msg_event()` more.
## [1.132.1] - 2023-12-12
### Features / Changes
- Add "From:" to protected headers for signed-only messages.
- Sync user actions for ad-hoc groups across devices ([#5065](https://github.com/deltachat/deltachat-core-rust/pull/5065)).
### Fixes
- Add padlock to empty part if the whole message is empty.
- Renew IDLE timeout on keepalives and reduce it to 5 minutes.
- connectivity: Return false from `all_work_done()` immediately after connecting (iOS notification fix).
### API-Changes
- deltachat-jsonrpc-client: add `Account.{import,export}_self_keys`.
### CI
- Update to Rust 1.74.1.
## [1.132.0] - 2023-12-06
### Features / Changes
- Increase TCP timeouts from 30 to 60 seconds.
### Fixes
- Don't sort message creating a protected group over a protection message ([#4963](https://github.com/deltachat/deltachat-core-rust/pull/4963)).
- Do not lock accounts.toml on iOS.
- Protect groups even if some members are not verified and add `test_securejoin_after_contact_resetup` regression test.
## [1.131.9] - 2023-12-02
### API-Changes
- Remove `dc_get_http_response()`, `dc_http_response_get_mimetype()`, `dc_http_response_get_encoding()`, `dc_http_response_get_blob()`, `dc_http_response_get_size()`, `dc_http_response_unref()` and `dc_http_response_t` from cffi.
- Deprecate CFFI APIs `dc_send_reaction()`, `dc_get_msg_reactions()`, `dc_reactions_get_contacts()`, `dc_reactions_get_by_contact_id()`, `dc_reactions_unref` and `dc_reactions_t`.
- Make `Contact.is_verified()` return bool.
### Build system
- Switch from fork of iroh to iroh 0.4.2 pre-release.
### Features / Changes
- Send `Chat-Verified` headers in 1:1 chats.
- Ratelimit IMAP connections ([#4940](https://github.com/deltachat/deltachat-core-rust/pull/4940)).
- Remove receiver limit on `.xdc` size.
- Don't affect MimeMessage with "From" and secured headers from encrypted unsigned messages.
- Sync `Config::{MdnsEnabled,ShowEmails}` across devices ([#4954](https://github.com/deltachat/deltachat-core-rust/pull/4954)).
- Sync `Config::Displayname` across devices ([#4893](https://github.com/deltachat/deltachat-core-rust/pull/4893)).
- `Chat::rename_ex`: Don't send sync message if usual message is sent.
### Fixes
- Lock the database when INSERTing a webxdc update, avoid "Database is locked" errors.
- Use keyring with all private keys when decrypting a message ([#5046](https://github.com/deltachat/deltachat-core-rust/pull/5046)).
### Tests
- Make Result-returning tests produce a line number.
- Add `test_utils::sync()`.
- Test inserting lots of webxdc updates.
- Split `test_sync_alter_chat()` into smaller tests.
## [1.131.8] - 2023-11-27
### Features / Changes
- webxdc: Add unique IDs to status updates sent outside and deduplicate based on IDs.
### Fixes
- Allow IMAP servers not returning UIDNEXT on SELECT and STATUS such as mail.163.com.
- Use the correct securejoin strings used in the UI, remove old TODO ([#5047](https://github.com/deltachat/deltachat-core-rust/pull/5047)).
- Do not emit events about webxdc update events logged into debug log webxdc.
### Tests
- Check that `receive_status_update` has forward compatibility and unique webxdc IDs will be ignored by previous Delta Chat versions.
## [1.131.7] - 2023-11-24
### Fixes
- Revert "fix: check UIDNEXT with a STATUS command before going IDLE". This attempts to fix mail.163.com which has broken STATUS command.
## [1.131.6] - 2023-11-21
### Fixes
- Fail fast if IMAP FETCH cannot be parsed instead of getting stuck in infinite loop.
### Documentation
- Generate deltachat-rpc-client documentation and publish it to <https://py.delta.chat>.
## [1.131.5] - 2023-11-20
### API-Changes
- deltachat-rpc-client: Add `Message.get_sender_contact()`.
- Turn `ContactAddress` into an owned type.
### Features / Changes
- Lowercase addresses in Autocrypt and Autocrypt-Gossip headers.
- Lowercase the address in member added/removed messages.
- Lowercase `addr` when it is set.
- Do not replace the message with an error in square brackets when the sender is not a member of the protected group.
### Fixes
- `Chat::sync_contacts()`: Fetch contact addresses in a single query.
- `Chat::rename_ex()`: Sync improved chat name to other devices.
- Recognize `Chat-Group-Member-Added` of self case-insensitively.
- Compare verifier addr to peerstate addr case-insensitively.
### Tests
- Port [Secure-Join](https://securejoin.readthedocs.io/) tests to JSON-RPC.
### CI
- Test with Rust 1.74.
## [1.131.4] - 2023-11-16
### Documentation
- Document DC_DOWNLOAD_UNDECIPHERABLE.
### Fixes
- Always add "Member added" as system message.
## [1.131.3] - 2023-11-15
### Fixes
- Update async-imap to 0.9.4 which does not ignore EOF on FETCH.
- Reset gossiped timestamp on securejoin.
- sync: Ignore unknown sync items to provide forward compatibility and avoid creating empty message bubbles.
- sync: Skip sync when chat name is set to the current one.
- Return connectivity HTML with an error when IO is stopped.
## [1.131.2] - 2023-11-14
### API-Changes
- deltachat-rpc-client: add `Account.get_chat_by_contact()`.
### Features / Changes
- Do not post "... verified" messages on QR scan success.
- Never drop better message from `apply_group_changes()`.
### Fixes
- Assign MDNs to the trash chat early to prevent received MDNs from creating or unblocking 1:1 chats.
- Allow to securejoin groups when 1:1 chat with the inviter is a contact request.
- Add "setup changed" message for verified key before the message.
- Ignore special chats when calculating similar chats.
## [1.131.1] - 2023-11-13
### Fixes
- Do not skip actual message parts when group change messages are inserted.
## [1.131.0] - 2023-11-13
### Features / Changes
- Sync chat contacts across devices ([#4953](https://github.com/deltachat/deltachat-core-rust/pull/4953)).
- Sync creating broadcast lists across devices ([#4953](https://github.com/deltachat/deltachat-core-rust/pull/4953)).
- Sync Chat::name across devices ([#4953](https://github.com/deltachat/deltachat-core-rust/pull/4953)).
- Multi-device broadcast lists ([#4953](https://github.com/deltachat/deltachat-core-rust/pull/4953)).
### Fixes
- Encode chat name in the `List-ID` header to avoid SMTPUTF8 errors.
- Ignore errors from generating sync messages.
- `Context::execute_sync_items`: Ignore all errors ([#4817](https://github.com/deltachat/deltachat-core-rust/pull/4817)).
- Allow to send unverified securejoin messages to protected chats ([#4982](https://github.com/deltachat/deltachat-core-rust/pull/4982)).
## [1.130.0] - 2023-11-10
### API-Changes
- Emit JoinerProgress(1000) event when Bob verifies Alice.
- JSON-RPC: add `ContactObject.is_profile_verified` property.
- Hide `ChatId::get_for_contact()` from public API.
### Features / Changes
- Add secondary verified key.
- Add info messages about implicitly added members.
- Treat reset state as encryption not preferred.
- Grow sleep durations on errors in Imap::fake_idle() ([#4424](https://github.com/deltachat/deltachat-core-rust/pull/4424)).
### Fixes
- Mark 1:1 chat as protected when joining a group.
- Raise lower auto-download limit to 160k.
- Remove `Reporting-UA` from read receipts.
- Do not apply group changes to special chats. Avoid adding members to the trash chat.
- imap: make `UidGrouper` robust against duplicate UIDs.
- Do not return hidden chat from `dc_get_chat_id_by_contact_id`.
- Smtp_loop(): Don't grow timeout if interrupted early ([#4833](https://github.com/deltachat/deltachat-core-rust/pull/4833)).
### Refactor
- imap: Do not FETCH right after `scan_folders()`.
- deltachat-rpc-client: Use `itertools` instead of `Lock` for thread-safe request ID generation.
### Tests
- Remove unused `--liveconfig` option.
- Test chatlist can load for corrupted chats ([#4979](https://github.com/deltachat/deltachat-core-rust/pull/4979)).
### Miscellaneous Tasks
- Update provider-db ([#4949](https://github.com/deltachat/deltachat-core-rust/pull/4949)).
## [1.129.1] - 2023-11-06
### Fixes
- Update tokio-imap to fix Outlook STATUS parsing bug.
- deltachat-rpc-client: Add the Lock around request ID.
- `apply_group_changes`: Don't implicitly delete members locally, add absent ones instead ([#4934](https://github.com/deltachat/deltachat-core-rust/pull/4934)).
- Partial messages do not change group state ([#4900](https://github.com/deltachat/deltachat-core-rust/pull/4900)).
### Tests
- Group chats device synchronisation.
## [1.129.0] - 2023-11-06
### API-Changes
- Add JSON-RPC `get_chat_id_by_contact_id` API ([#4918](https://github.com/deltachat/deltachat-core-rust/pull/4918)).
- [**breaking**] Remove deprecated `get_verifier_addr`.
### Features / Changes
- Sync chat `Blocked` state, chat visibility, chat mute duration and contact blocked status across devices ([#4817](https://github.com/deltachat/deltachat-core-rust/pull/4817)).
- Add 'group created instructions' as info message ([#4916](https://github.com/deltachat/deltachat-core-rust/pull/4916)).
- Add hardcoded fallback DNS cache.
### Fixes
- Switch to `EncryptionPreference::Mutual` on a receipt of encrypted+signed message ([#4707](https://github.com/deltachat/deltachat-core-rust/pull/4707)).
- imap: Check UIDNEXT with a STATUS command before going IDLE.
- Allow to change verified key via "member added" message.
- json-rpc: Return verifier even if the contact is not "verified" (Autocrypt key does not equal Secure-Join key).
### Documentation
- Refine `Contact::get_verifier_id` and `Contact::is_verified` documentation ([#4922](https://github.com/deltachat/deltachat-core-rust/pull/4922)).
- Contact profile view should not use `dc_contact_is_verified()`.
- Remove documentation for non-existing `dc_accounts_new` `os_name` param.
### Refactor
- Remove unused or useless code paths in Secure-Join ([#4897](https://github.com/deltachat/deltachat-core-rust/pull/4897)).
- Improve error handling in Secure-Join code.
- Add hostname to "no DNS resolution results" error message.
- Accept `&str` instead of `Option<String>` in idle().
## [1.128.0] - 2023-11-02
### Build system
- [**breaking**] Upgrade nodejs version to 18 ([#4903](https://github.com/deltachat/deltachat-core-rust/pull/4903)).
### Features / Changes
- deltachat-rpc-client: Add `Account.wait_for_incoming_msg_event()`.
- Decrease ratelimit for .testrun.org subdomains.
### Fixes
- Do not fail securejoin due to unrelated pending bobstate ([#4896](https://github.com/deltachat/deltachat-core-rust/pull/4896)).
- Allow other verified group recipients to be unverified, only check the sender verification.
- Remove not working attempt to recover from verified key changes.
## [1.127.2] - 2023-10-29
### API-Changes
- [**breaking**] Jsonrpc `misc_set_draft` now requires setting the viewtype.
- jsonrpc: Add `get_message_info_object`.
### Tests
- deltachat-rpc-client: Move pytest option from pyproject.toml to tox.ini and set log level.
- deltachat-rpc-client: Test securejoin.
- Increase pytest timeout to 10 minutes.
- Compile deltachat-rpc-server in debug mode for tests.
## [1.127.1] - 2023-10-27
### API-Changes
- jsonrpc: add `.is_protection_broken` to `FullChat` and `BasicChat`.
- jsonrpc: Add `id` to `ProviderInfo`.
## [1.127.0] - 2023-10-26
### API-Changes
- [**breaking**] `dc_accounts_new` API is changed. Unused `os_name` argument is removed and `writable` argument is added.
- jsonrpc: Add `resend_messages`.
- [**breaking**] Remove unused function `is_verified_ex()` ([#4551](https://github.com/deltachat/deltachat-core-rust/pull/4551))
- [**breaking**] Make `MsgId.delete_from_db()` private.
- [**breaking**] deltachat-jsonrpc: use `kind` as a tag for all union types
- json-rpc: Force stickers to be sent as stickers ([#4819](https://github.com/deltachat/deltachat-core-rust/pull/4819)).
- Add mailto parse api ([#4829](https://github.com/deltachat/deltachat-core-rust/pull/4829)).
- [**breaking**] Remove unused `DC_STR_PROTECTION_(EN)ABLED` strings
- [**breaking**] Remove unused `dc_set_chat_protection()`
- Hide `DcSecretKey` trait from the API.
- Verified 1:1 chats ([#4315](https://github.com/deltachat/deltachat-core-rust/pull/4315)). Disabled by default, enable with `verified_one_on_one_chats` config.
- Add api `chat::Chat::is_protection_broken`
- Add `dc_chat_is_protection_broken()` C API.
### CI
- Run Rust tests with `RUST_BACKTRACE` set.
- Replace `master` branch with `main`. Run CI only on `main` branch pushes.
- Test `deltachat-rpc-client` on Windows.
### Documentation
- Document how logs and error messages should be formatted in `CONTRIBUTING.md`.
- Clarify transitive behaviour of `dc_contact_is_verfified()`.
- Document `configured_addr`.
### Features / Changes
- Add lockfile to account manager ([#4314](https://github.com/deltachat/deltachat-core-rust/pull/4314)).
- Don't show a contact as verified if their key changed since the verification ([#4574](https://github.com/deltachat/deltachat-core-rust/pull/4574)).
- deltachat-rpc-server: Add `--openrpc` option to print OpenRPC specification for JSON-RPC API. This specification can be used to generate JSON-RPC API clients.
- Track whether contact is a bot or not ([#4821](https://github.com/deltachat/deltachat-core-rust/pull/4821)).
- Replace `Config::SendSyncMsgs` with `SyncMsgs` ([#4817](https://github.com/deltachat/deltachat-core-rust/pull/4817)).
### Fixes
- Don't create 1:1 chat as protected for contact who doesn't prefer to encrypt ([#4538](https://github.com/deltachat/deltachat-core-rust/pull/4538)).
- Allow to save a draft if the verification is broken ([#4542](https://github.com/deltachat/deltachat-core-rust/pull/4542)).
- Fix info-message orderings of verified 1:1 chats ([#4545](https://github.com/deltachat/deltachat-core-rust/pull/4545)).
- Fix example; this was changed some time ago, see https://docs.webxdc.org/spec.html#sendupdate
- `receive_imf`: Update peerstate from db after handling Securejoin handshake ([#4600](https://github.com/deltachat/deltachat-core-rust/pull/4600)).
- Sort old incoming messages below all outgoing ones ([#4621](https://github.com/deltachat/deltachat-core-rust/pull/4621)).
- Do not mark non-verified group chats as verified when using securejoin.
- `receive_imf`: Set protection only for Chattype::Single ([#4597](https://github.com/deltachat/deltachat-core-rust/pull/4597)).
- Return from `dc_get_chatlist(DC_GCL_FOR_FORWARDING)` only chats where we can send ([#4616](https://github.com/deltachat/deltachat-core-rust/pull/4616)).
- Clear VerifiedOneOnOneChats config on backup ([#4615](https://github.com/deltachat/deltachat-core-rust/pull/4615)).
- Try removal of accounts multiple times with timeouts in case the database file is blocked (restore `try_many_times` workaround).
### Build system
- Remove examples/simple.rs.
- Increase MSRV to 1.70.0.
- Update dependencies.
- Switch to iroh 0.4.x fork with updated dependencies.
## [1.126.1] - 2023-10-24
### Fixes
- Do not hardcode version in deltachat-rpc-server source package.
- Do not interrupt IMAP loop from `get_connectivity_html()`.
### Features / Changes
- imap: Buffer `STARTTLS` command.
### Build system
- Build `deltachat-rpc-server` binary for aarch64 macOS.
- Build `deltachat-rpc-server` wheels for macOS and Windows.
### Refactor
- Remove job queue.
### Miscellaneous Tasks
- cargo: Update `ahash` to make `cargo-deny` happy.
## [1.126.0] - 2023-10-22
### API-Changes
- Allow to filter by unread in `chatlist:try_load` ([#4824](https://github.com/deltachat/deltachat-core-rust/pull/4824)).
- Add `misc_send_draft()` to JSON-RPC API ([#4839](https://github.com/deltachat/deltachat-core-rust/pull/4839)).
### Features / Changes
- [**breaking**] Make broadcast lists create their own chat ([#4644](https://github.com/deltachat/deltachat-core-rust/pull/4644)).
- This means that UIs need to ask for the name when creating a broadcast list, similar to <https://github.com/deltachat/deltachat-android/pull/2653>.
- Add self-address to backup filename ([#4820](https://github.com/deltachat/deltachat-core-rust/pull/4820))
### CI
- Build Python wheels for deltachat-rpc-server.
### Build system
- Strip release binaries.
- Workaround OpenSSL crate expecting libatomic to be available.
### Fixes
- Set `soft_heap_limit` on SQLite database.
- imap: Fallback to `STATUS` if `SELECT` did not return UIDNEXT.
## [1.125.0] - 2023-10-14
### API-Changes
- [**breaking**] deltachat-rpc-client: Replace `asyncio` with threads.
- Validate boolean values passed to `set_config`. Attempts to set values other than `0` and `1` will result in an error.
### CI
- Reduce required Python version for deltachat-rpc-client from 3.8 to 3.7.
### Features / Changes
- Add developer option to disable IDLE.
### Fixes
- `deltachat-rpc-client`: Run `deltachat-rpc-server` in its own process group. This prevents reception of `SIGINT` by the server when the bot is terminated with `^C`.
- python: Don't automatically set the displayname to "bot" when setting log level.
- Don't update `timestamp`, `timestamp_rcvd`, `state` when replacing partially downloaded message ([#4700](https://github.com/deltachat/deltachat-core-rust/pull/4700)).
- Assign encrypted partially downloaded group messages to 1:1 chat ([#4757](https://github.com/deltachat/deltachat-core-rust/pull/4757)).
- Return all contacts from `Contact::get_all` for bots ([#4811](https://github.com/deltachat/deltachat-core-rust/pull/4811)).
- Set connectivity status to "connected" during fake idle.
- Return verifier contacts regardless of their origin.
- Don't try to send more MDNs if there's a temporary SMTP error ([#4534](https://github.com/deltachat/deltachat-core-rust/pull/4534)).
### Refactor
- deltachat-rpc-client: Close stdin instead of sending `SIGTERM`.
- deltachat-rpc-client: Remove print() calls. Standard `logging` package is for logging instead.
### Tests
- deltachat-rpc-client: Enable logs in pytest.
## [1.124.1] - 2023-10-05
### Fixes
@@ -928,7 +1469,7 @@ Bugfix release attempting to fix the [iOS build error](https://github.com/deltac
### Changes
- Look at Authentication-Results. Don't accept Autocrypt key changes
if they come with negative authentiation results while this contact
if they come with negative authentication results while this contact
sent emails with positive authentication results in the past. #3583
- jsonrpc in cffi also sends events now #3662
- jsonrpc: new format for events and better typescript autocompletion
@@ -2514,7 +3055,7 @@ Bugfix release attempting to fix the [iOS build error](https://github.com/deltac
- delete all consumed secure-join handshake messagess #1209 #1212
- rust-level cleanups #1218 #1217 #1210 #1205
- Rust-level cleanups #1218 #1217 #1210 #1205
- python-level cleanups #1204 #1202 #1201
@@ -2879,3 +3420,28 @@ https://github.com/deltachat/deltachat-core-rust/pulls?q=is%3Apr+is%3Aclosed
[1.123.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.122.0...v1.123.0
[1.124.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.123.0...v1.124.0
[1.124.1]: https://github.com/deltachat/deltachat-core-rust/compare/v1.124.0...v1.124.1
[1.125.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.124.1...v1.125.0
[1.126.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.125.0...v1.126.0
[1.126.1]: https://github.com/deltachat/deltachat-core-rust/compare/v1.126.0...v1.126.1
[1.127.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.126.1...v1.127.0
[1.127.1]: https://github.com/deltachat/deltachat-core-rust/compare/v1.127.0...v1.127.1
[1.127.2]: https://github.com/deltachat/deltachat-core-rust/compare/v1.127.1...v1.127.2
[1.128.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.127.2...v1.128.0
[1.129.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.128.0...v1.129.0
[1.129.1]: https://github.com/deltachat/deltachat-core-rust/compare/v1.129.0...v1.129.1
[1.130.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.129.1...v1.130.0
[1.131.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.130.0...v1.131.0
[1.131.1]: https://github.com/deltachat/deltachat-core-rust/compare/v1.131.0...v1.131.1
[1.131.2]: https://github.com/deltachat/deltachat-core-rust/compare/v1.131.1...v1.131.2
[1.131.3]: https://github.com/deltachat/deltachat-core-rust/compare/v1.131.2...v1.131.3
[1.131.4]: https://github.com/deltachat/deltachat-core-rust/compare/v1.131.3...v1.131.4
[1.131.5]: https://github.com/deltachat/deltachat-core-rust/compare/v1.131.4...v1.131.5
[1.131.6]: https://github.com/deltachat/deltachat-core-rust/compare/v1.131.5...v1.131.6
[1.131.7]: https://github.com/deltachat/deltachat-core-rust/compare/v1.131.6...v1.131.7
[1.131.8]: https://github.com/deltachat/deltachat-core-rust/compare/v1.131.7...v1.131.8
[1.131.9]: https://github.com/deltachat/deltachat-core-rust/compare/v1.131.8...v1.131.9
[1.132.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.131.9...v1.132.0
[1.132.1]: https://github.com/deltachat/deltachat-core-rust/compare/v1.132.0...v1.132.1
[1.133.0]: https://github.com/deltachat/deltachat-core-rust/compare/v1.132.1...v1.133.0
[1.133.1]: https://github.com/deltachat/deltachat-core-rust/compare/v1.133.0...v1.133.1
[1.133.2]: https://github.com/deltachat/deltachat-core-rust/compare/v1.133.1...v1.133.2

View File

@@ -76,6 +76,40 @@ If you have multiple changes in one PR, create multiple conventional commits, an
[Conventional Commits]: https://www.conventionalcommits.org/
[git-cliff]: https://git-cliff.org/
### Errors
Delta Chat core mostly uses [`anyhow`](https://docs.rs/anyhow/) errors.
When using [`Context`](https://docs.rs/anyhow/latest/anyhow/trait.Context.html),
capitalize it but do not add a full stop as the contexts will be separated by `:`.
For example:
```
.with_context(|| format!("Unable to trash message {msg_id}"))
```
All errors should be handled in one of these ways:
- With `if let Err() =` (incl. logging them into `warn!()`/`err!()`).
- With `.log_err().ok()`.
- Bubbled up with `?`.
`backtrace` feature is enabled for `anyhow` crate
and `debug = 1` option is set in the test profile.
This allows to run `RUST_BACKTRACE=1 cargo test`
and get a backtrace with line numbers in resultified tests
which return `anyhow::Result`.
### Logging
For logging, use `info!`, `warn!` and `error!` macros.
Log messages should be capitalized and have a full stop in the end. For example:
```
info!(context, "Ignoring addition of {added_addr:?} to {chat_id}.");
```
Format anyhow errors with `{:#}` to print all the contexts like this:
```
error!(context, "Failed to set selfavatar timestamp: {err:#}.");
```
### Reviewing
Once a PR has an approval and passes CI, it can be merged.

1980
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,9 @@
[package]
name = "deltachat"
version = "1.124.1"
version = "1.133.2"
edition = "2021"
license = "MPL-2.0"
rust-version = "1.65"
rust-version = "1.70"
[profile.dev]
debug = 0
@@ -11,6 +11,10 @@ panic = 'abort'
opt-level = 1
[profile.test]
# Make anyhow `backtrace` feature useful.
# With `debug = 0` there are no line numbers in the backtrace
# produced with RUST_BACKTRACE=1.
debug = 1
opt-level = 0
# Always optimize dependencies.
@@ -24,10 +28,10 @@ lto = true
panic = 'abort'
opt-level = "z"
codegen-units = 1
strip = true
[patch.crates-io]
quinn-udp = { git = "https://github.com/quinn-rs/quinn", branch="main" }
quinn-proto = { git = "https://github.com/quinn-rs/quinn", branch="main" }
imap-proto = { git = "https://github.com/djc/tokio-imap.git", rev = "01ff256a7e42a9f7d2732706f8b71a16ce93427e" }
[dependencies]
deltachat_derive = { path = "./deltachat_derive" }
@@ -35,25 +39,27 @@ format-flowed = { path = "./format-flowed" }
ratelimit = { path = "./deltachat-ratelimit" }
anyhow = "1"
async-channel = "1.8.0"
async-imap = { version = "0.9.1", default-features = false, features = ["runtime-tokio"] }
async-channel = "2.0.0"
async-imap = { version = "0.9.5", 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"] }
async_zip = { version = "0.0.12", default-features = false, features = ["deflate", "fs"] }
backtrace = "0.3"
base64 = "0.21"
brotli = { version = "3.3", default-features=false, features = ["std"] }
brotli = { version = "3.4", default-features=false, features = ["std"] }
chrono = { version = "0.4", default-features=false, features = ["clock", "std"] }
email = { git = "https://github.com/deltachat/rust-email", branch = "master" }
encoded-words = { git = "https://github.com/async-email/encoded-words", branch = "master" }
escaper = "0.1"
fast-socks5 = "0.8"
fast-socks5 = "0.9"
fd-lock = "4"
futures = "0.3"
futures-lite = "1.13.0"
futures-lite = "2.0.0"
hex = "0.4.0"
hickory-resolver = "0.24"
humansize = "2"
image = { version = "0.24.6", default-features=false, features = ["gif", "jpeg", "ico", "png", "pnm", "webp", "bmp"] }
iroh = { version = "0.4.1", default-features = false }
image = { version = "0.24.7", default-features=false, features = ["gif", "jpeg", "ico", "png", "pnm", "webp", "bmp"] }
iroh = { version = "0.4.2", default-features = false }
kamadak-exif = "0.5"
lettre_email = { git = "https://github.com/deltachat/lettre", branch = "master" }
libc = "0.2"
@@ -66,16 +72,18 @@ once_cell = "1.18.0"
percent-encoding = "2.3"
parking_lot = "0.12"
pgp = { version = "0.10", default-features = false }
pin-project = "1"
pretty_env_logger = { version = "0.5", optional = true }
qrcodegen = "1.7.0"
quick-xml = "0.29"
quick-xml = "0.31"
quoted_printable = "0.5"
rand = "0.8"
regex = "1.8"
reqwest = { version = "0.11.18", features = ["json"] }
rusqlite = { version = "0.29", features = ["sqlcipher"] }
regex = "1.9"
reqwest = { version = "0.11.23", features = ["json"] }
rusqlite = { version = "0.30", features = ["sqlcipher"] }
rust-hsluv = "0.1"
sanitize-filename = "0.4"
serde_json = "1.0"
sanitize-filename = "0.5"
serde_json = "1"
serde = { version = "1.0", features = ["derive"] }
sha-1 = "0.10"
sha2 = "0.10"
@@ -89,21 +97,29 @@ tokio = { version = "1", features = ["fs", "rt-multi-thread", "macros"] }
tokio-io-timeout = "1.2.0"
tokio-stream = { version = "0.1.14", features = ["fs"] }
tokio-tar = { version = "0.3" } # TODO: integrate tokio into async-tar
tokio-util = "0.7.8"
toml = "0.7"
trust-dns-resolver = "0.22"
tokio-util = "0.7.9"
toml = "0.8"
url = "2"
uuid = { version = "1", features = ["serde", "v4"] }
# Pin OpenSSL to 3.1 releases.
# OpenSSL 3.2 has a regression tracked at <https://github.com/openssl/openssl/issues/23376>
# which results in broken `deltachat-rpc-server` binaries when cross-compiled using Zig toolchain.
# See <https://github.com/deltachat/deltachat-core-rust/issues/5206> for Delta Chat issue.
# According to <https://www.openssl.org/policies/releasestrat.html>
# 3.1 branch will be supported until 2025-03-14.
openssl-src = "~300.1"
[dev-dependencies]
ansi_term = "0.12.0"
anyhow = { version = "1", features = ["backtrace"] } # Enable `backtrace` feature in tests.
criterion = { version = "0.5.1", features = ["async_tokio"] }
futures-lite = "1.13"
futures-lite = "2.0.0"
log = "0.4"
pretty_env_logger = "0.5"
proptest = { version = "1", default-features = false, features = ["std"] }
tempfile = "3"
testdir = "0.8.0"
testdir = "0.9.0"
tokio = { version = "1", features = ["parking_lot", "rt-multi-thread", "macros"] }
pretty_assertions = "1.3.0"
@@ -118,11 +134,6 @@ members = [
"format-flowed",
]
[[example]]
name = "simple"
path = "examples/simple.rs"
[[bench]]
name = "create_account"
harness = false

View File

@@ -1,8 +1,16 @@
# Delta Chat Rust
<p align="center">
<img alt="Delta Chat Logo" height="200px" src="https://raw.githubusercontent.com/deltachat/deltachat-pages/master/assets/blog/rust-delta.png">
</p>
> Deltachat-core written in Rust
<p align="center">
<a href="https://github.com/deltachat/deltachat-core-rust/actions/workflows/ci.yml">
<img alt="Rust CI" src="https://github.com/deltachat/deltachat-core-rust/actions/workflows/ci.yml/badge.svg">
</a>
</p>
[![Rust CI](https://github.com/deltachat/deltachat-core-rust/actions/workflows/ci.yml/badge.svg)](https://github.com/deltachat/deltachat-core-rust/actions/workflows/ci.yml)
<p align="center">
The core library for Delta Chat, written in Rust
</p>
## Installing Rust and Cargo
@@ -19,7 +27,7 @@ $ curl https://sh.rustup.rs -sSf | sh
Compile and run Delta Chat Core command line utility, using `cargo`:
```
$ RUST_LOG=deltachat_repl=info cargo run -p deltachat-repl -- ~/deltachat-db
$ cargo run -p deltachat-repl -- ~/deltachat-db
```
where ~/deltachat-db is the database file. Delta Chat will create it if it does not exist.
@@ -113,7 +121,7 @@ $ cargo build -p deltachat_ffi --release
- `DCC_MIME_DEBUG`: if set outgoing and incoming message will be printed
- `RUST_LOG=deltachat_repl=info,async_imap=trace,async_smtp=trace`: enable IMAP and
- `RUST_LOG=async_imap=trace,async_smtp=trace`: enable IMAP and
SMTP tracing in addition to info messages.
### Expensive tests

View File

@@ -8,7 +8,8 @@ async fn create_accounts(n: u32) {
let dir = tempdir().unwrap();
let p: PathBuf = dir.path().join("accounts");
let mut accounts = Accounts::new(p.clone()).await.unwrap();
let writable = true;
let mut accounts = Accounts::new(p.clone(), writable).await.unwrap();
for expected_id in 2..n {
let id = accounts.add_account().await.unwrap();

View File

@@ -54,7 +54,7 @@ header = """
# Changelog\n
"""
# template for the changelog body
# https://tera.netlify.app/docs/#introduction
# https://keats.github.io/tera/docs/#templates
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}

View File

@@ -1,6 +1,6 @@
[package]
name = "deltachat_ffi"
version = "1.124.1"
version = "1.133.2"
description = "Deltachat FFI"
edition = "2018"
readme = "README.md"

View File

@@ -846,7 +846,7 @@ EXCLUDE_PATTERNS =
# exclude all test directories use the pattern */test/*
######################################################
EXCLUDE_SYMBOLS = dc_aheader_t dc_apeerstate_t dc_e2ee_helper_t dc_imap_t dc_job*_t dc_key_t dc_keyring_t dc_loginparam_t dc_mime*_t
EXCLUDE_SYMBOLS = dc_aheader_t dc_apeerstate_t dc_e2ee_helper_t dc_imap_t dc_job*_t dc_key_t dc_loginparam_t dc_mime*_t
EXCLUDE_SYMBOLS += dc_saxparser_t dc_simplify_t dc_smtp_t dc_sqlite3_t dc_strbuilder_t dc_param_t dc_hash_t dc_hashelem_t
EXCLUDE_SYMBOLS += _dc_* jsmn*
######################################################

View File

@@ -9,7 +9,7 @@
<tab type="hierarchy" visible="no" title="" intro=""/>
<tab type="classmembers" visible="no" title="" intro=""/>
</tab>
<tab type="modules" visible="yes" title="Constants" intro="Here is a list of constants:"/>
<tab type="topics" visible="yes" title="Constants" intro="Here is a list of constants:"/>
<tab type="pages" visible="yes" title="" intro=""/>
<tab type="namespaces" visible="yes" title="">
<tab type="namespacelist" visible="yes" title="" intro=""/>

View File

@@ -25,7 +25,6 @@ typedef struct _dc_event dc_event_t;
typedef struct _dc_event_emitter dc_event_emitter_t;
typedef struct _dc_jsonrpc_instance dc_jsonrpc_instance_t;
typedef struct _dc_backup_provider dc_backup_provider_t;
typedef struct _dc_http_response dc_http_response_t;
// Alias for backwards compatibility, use dc_event_emitter_t instead.
typedef struct _dc_event_emitter dc_accounts_event_emitter_t;
@@ -384,7 +383,12 @@ char* dc_get_blobdir (const dc_context_t* context);
/**
* Configure the context. The configuration is handled by key=value pairs as:
*
* - `addr` = address to display (always needed)
* - `addr` = Email address to use for configuration.
* If dc_configure() fails this is not the email address actually in use.
* Use `configured_addr` to find out the email address actually in use.
* - `configured_addr` = Email address actually in use.
* Unless for testing, do not set this value using dc_set_config().
* Instead, set `addr` and call dc_configure().
* - `mail_server` = IMAP-server, guessed if left out
* - `mail_user` = IMAP-username, guessed if left out
* - `mail_pw` = IMAP-password (always needed)
@@ -492,6 +496,9 @@ char* dc_get_blobdir (const dc_context_t* context);
* - `fetch_existing_msgs` = 1=fetch most recent existing messages on configure (default),
* 0=do not fetch existing messages on configure.
* In both cases, existing recipients are added to the contact database.
* - `disable_idle` = 1=disable IMAP IDLE even if the server supports it,
* 0=use IMAP IDLE if the server supports it.
* This is a developer option used for testing polling used as an IDLE fallback.
* - `download_limit` = Messages up to this number of bytes are downloaded automatically.
* For larger messages, only the header is downloaded and a placeholder is shown.
* These messages can be downloaded fully using dc_download_full_msg() later.
@@ -500,6 +507,16 @@ char* dc_get_blobdir (const dc_context_t* context);
* to not mess up with non-delivery-reports or read-receipts.
* 0=no limit (default).
* Changes affect future messages only.
* - `gossip_period` = How often to gossip Autocrypt keys in chats with multiple recipients, in
* seconds. 2 days by default.
* This is not supposed to be changed by UIs and only used for testing.
* - `verified_one_on_one_chats` = Feature flag for verified 1:1 chats; the UI should set it
* to 1 if it supports verified 1:1 chats.
* Regardless of this setting, `dc_chat_is_protected()` returns true while the key is verified,
* and when the key changes, an info message is posted into the chat.
* 0=Nothing else happens when the key changes.
* 1=After the key changed, `dc_chat_can_send()` returns false and `dc_chat_is_protection_broken()` returns true
* until `dc_accept_chat()` is called.
* - `ui.*` = All keys prefixed by `ui.` can be used by the user-interfaces for system-specific purposes.
* The prefix should be followed by the system and maybe subsystem,
* e.g. `ui.desktop.foo`, `ui.desktop.linux.bar`, `ui.android.foo`, `ui.dc40.bar`, `ui.bot.simplebot.baz`.
@@ -878,7 +895,8 @@ int dc_preconfigure_keypair (dc_context_t* context, const cha
* - if the flag DC_GCL_ADD_ALLDONE_HINT is set, DC_CHAT_ID_ALLDONE_HINT
* is added as needed.
* @param query_str An optional query for filtering the list. Only chats matching this query
* are returned. Give NULL for no filtering.
* are returned. Give NULL for no filtering. When `is:unread` is contained in the query,
* the chatlist is filtered such that only chats with unread messages show up.
* @param query_id An optional contact ID for filtering the list. Only chats including this contact ID
* are returned. Give 0 for no filtering.
* @return A chatlist as an dc_chatlist_t object.
@@ -1093,6 +1111,7 @@ uint32_t dc_send_videochat_invitation (dc_context_t* context, uint32_t chat_id);
* received overrides all previously received reactions. It is
* possible to remove all reactions by sending an empty string.
*
* @deprecated 2023-11-27, use jsonrpc method `send_reaction` instead
* @memberof dc_context_t
* @param context The context object.
* @param msg_id ID of the message you react to.
@@ -1105,6 +1124,7 @@ uint32_t dc_send_reaction (dc_context_t* context, uint32_t msg_id, char *reactio
/**
* Get a structure with reactions to the message.
*
* @deprecated 2023-11-27, use jsonrpc method `get_message_reactions` instead
* @memberof dc_context_t
* @param context The context object.
* @param msg_id The message ID to get reactions for.
@@ -1118,7 +1138,7 @@ dc_reactions_t* dc_get_msg_reactions (dc_context_t *context, int msg_id);
*
* In JS land, that would be mapped to something as:
* ```
* success = window.webxdc.sendUpdate('{"action":"move","src":"A3","dest":"B4"}', 'move A3 B4');
* success = window.webxdc.sendUpdate('{payload: {"action":"move","src":"A3","dest":"B4"}}', 'move A3 B4');
* ```
* `context` and `msg_id` are not needed in JS as those are unique within a webxdc instance.
* See dc_get_webxdc_status_updates() for the receiving counterpart.
@@ -1500,24 +1520,6 @@ dc_array_t* dc_get_chat_media (dc_context_t* context, uint32_t ch
uint32_t dc_get_next_media (dc_context_t* context, uint32_t msg_id, int dir, int msg_type, int msg_type2, int msg_type3);
/**
* Enable or disable protection against active attacks.
* To enable protection, it is needed that all members are verified;
* if this condition is met, end-to-end-encryption is always enabled
* and only the verified keys are used.
*
* Sends out #DC_EVENT_CHAT_MODIFIED on changes
* and #DC_EVENT_MSGS_CHANGED if a status message was sent.
*
* @memberof dc_context_t
* @param context The context object as returned from dc_context_new().
* @param chat_id The ID of the chat to change the protection for.
* @param protect 1=protect chat, 0=unprotect chat
* @return 1=success, 0=error, e.g. some members may be unverified
*/
int dc_set_chat_protection (dc_context_t* context, uint32_t chat_id, int protect);
/**
* Set chat visibility to pinned, archived or normal.
*
@@ -1711,24 +1713,12 @@ uint32_t dc_create_group_chat (dc_context_t* context, int protect
* Create a new broadcast list.
*
* Broadcast lists are similar to groups on the sending device,
* however, recipients get the messages in normal one-to-one chats
* and will not be aware of other members.
* however, recipients get the messages in a read-only chat
* and will see who the other members are.
*
* Replies to broadcasts go only to the sender
* and not to all broadcast recipients.
* Moreover, replies will not appear in the broadcast list
* but in the one-to-one chat with the person answering.
*
* The name and the image of the broadcast list is set automatically
* and is visible to the sender only.
* Not asking for these data allows more focused creation
* and we bypass the question who will get which data.
* Also, many users will have at most one broadcast list
* so, a generic name and image is sufficient at the first place.
*
* Later on, however, the name can be changed using dc_set_chat_name().
* The image cannot be changed to have a unique, recognizable icon in the chat lists.
* All in all, this is also what other messengers are doing here.
* For historical reasons, this function does not take a name directly,
* instead you have to set the name using dc_set_chat_name()
* after creating the broadcast list.
*
* @memberof dc_context_t
* @param context The context object.
@@ -2271,8 +2261,7 @@ dc_contact_t* dc_get_contact (dc_context_t* context, uint32_t co
* the backup is not encrypted.
* The backup contains all contacts, chats, images and other data and device independent settings.
* The backup does not contain device dependent settings as ringtones or LED notification settings.
* The name of the backup is typically `delta-chat-<day>.tar`, if more than one backup is create on a day,
* the format is `delta-chat-<day>-<number>.tar`
* The name of the backup is `delta-chat-backup-<day>-<number>-<addr>.tar`.
*
* - **DC_IMEX_IMPORT_BACKUP** (12) - `param1` is the file (not: directory) to import. `param2` is the passphrase.
* The file is normally created by DC_IMEX_EXPORT_BACKUP and detected by dc_imex_has_backup(). Importing a backup
@@ -2573,7 +2562,7 @@ dc_lot_t* dc_check_qr (dc_context_t* context, const char*
* the Verified-Group-Invite protocol is offered in the QR code;
* works for protected groups as well as for normal groups.
* If set to 0, the Setup-Contact protocol is offered in the QR code.
* See https://countermitm.readthedocs.io/en/latest/new.html
* See https://securejoin.readthedocs.io/en/latest/new.html
* for details about both protocols.
* @return The text that should go to the QR code,
* On errors, an empty QR code is returned, NULL is never returned.
@@ -2609,7 +2598,7 @@ char* dc_get_securejoin_qr_svg (dc_context_t* context, uint32_
*
* Subsequent calls of dc_join_securejoin() will abort previous, unfinished handshakes.
*
* See https://countermitm.readthedocs.io/en/latest/new.html
* See https://securejoin.readthedocs.io/en/latest/new.html
* for details about both protocols.
*
* @memberof dc_context_t
@@ -2953,16 +2942,18 @@ int dc_receive_backup (dc_context_t* context, const char* qr);
* use dc_accounts_remove_account().
*
* @memberof dc_accounts_t
* @param os_name
* @param dir The directory to create the context-databases in.
* If the directory does not exist,
* dc_accounts_new() will try to create it.
* @param writable Whether the returned account manager is writable, i.e. calling these functions on
* it is possible: dc_accounts_add_account(), dc_accounts_add_closed_account(),
* dc_accounts_migrate_account(), dc_accounts_remove_account(), dc_accounts_select_account().
* @return An account manager object.
* The object must be passed to the other account manager functions
* and must be freed using dc_accounts_unref() after usage.
* On errors, NULL is returned.
*/
dc_accounts_t* dc_accounts_new (const char* os_name, const char* dir);
dc_accounts_t* dc_accounts_new (const char* dir, int writable);
/**
@@ -3741,9 +3732,22 @@ int dc_chat_can_send (const dc_chat_t* chat);
/**
* Check if a chat is protected.
* Protected chats contain only verified members and encryption is always enabled.
* Protected chats are created using dc_create_group_chat() by setting the 'protect' parameter to 1.
* The status can be changed using dc_set_chat_protection().
*
* End-to-end encryption is guaranteed in protected chats
* and only verified contacts
* as determined by dc_contact_is_verified()
* can be added to protected chats.
*
* Protected chats are created using dc_create_group_chat()
* by setting the 'protect' parameter to 1.
* 1:1 chats become protected or unprotected automatically
* if `verified_one_on_one_chats` setting is enabled.
*
* UI should display a green checkmark
* in the chat title,
* in the chatlist item
* and in the chat profile
* if chat protection is enabled.
*
* @memberof dc_chat_t
* @param chat The chat object.
@@ -3752,6 +3756,26 @@ int dc_chat_can_send (const dc_chat_t* chat);
int dc_chat_is_protected (const dc_chat_t* chat);
/**
* Checks if the chat was protected, and then an incoming message broke this protection.
*
* This function is only useful if the UI enabled the `verified_one_on_one_chats` feature flag,
* otherwise it will return false for all chats.
*
* 1:1 chats are automatically set as protected when a contact is verified.
* When a message comes in that is not encrypted / signed correctly,
* the chat is automatically set as unprotected again.
* dc_chat_is_protection_broken() will return true until dc_accept_chat() is called.
*
* The UI should let the user confirm that this is OK with a message like
* `Bob sent a message from another device. Tap to learn more` and then call dc_accept_chat().
* @memberof dc_chat_t
* @param chat The chat object.
* @return 1=chat protection broken, 0=otherwise.
*/
int dc_chat_is_protection_broken (const dc_chat_t* chat);
/**
* Check if locations are sent to the chat
* at the time the object was created using dc_get_chat().
@@ -3956,7 +3980,7 @@ int64_t dc_msg_get_received_timestamp (const dc_msg_t* msg);
* Get the message time used for sorting.
* This function returns the timestamp that is used for sorting the message
* into lists as returned e.g. by dc_get_chat_msgs().
* This may be the reveived time, the sending time or another time.
* This may be the received time, the sending time or another time.
*
* To get the receiving time, use dc_msg_get_received_timestamp().
* To get the sending time, use dc_msg_get_timestamp().
@@ -4346,7 +4370,7 @@ int dc_msg_is_forwarded (const dc_msg_t* msg);
* Check if the message is an informational message, created by the
* device or by another users. Such messages are not "typed" by the user but
* created due to other actions,
* e.g. dc_set_chat_name(), dc_set_chat_profile_image(), dc_set_chat_protection()
* e.g. dc_set_chat_name(), dc_set_chat_profile_image(),
* or dc_add_contact_to_chat().
*
* These messages are typically shown in the center of the chat view,
@@ -4373,6 +4397,9 @@ int dc_msg_is_info (const dc_msg_t* msg);
* Currently, the following types are defined:
* - DC_INFO_PROTECTION_ENABLED (11) - Info-message for "Chat is now protected"
* - DC_INFO_PROTECTION_DISABLED (12) - Info-message for "Chat is no longer protected"
* - DC_INFO_INVALID_UNENCRYPTED_MAIL (13) - Info-message for "Provider requires end-to-end encryption which is not setup yet",
* the UI should change the corresponding string using #DC_STR_INVALID_UNENCRYPTED_MAIL
* and also offer a way to fix the encryption, eg. by a button offering a QR scan
*
* Even when you display an icon,
* you should still display the text of the informational message using dc_msg_get_text()
@@ -4399,6 +4426,7 @@ int dc_msg_get_info_type (const dc_msg_t* msg);
#define DC_INFO_EPHEMERAL_TIMER_CHANGED 10
#define DC_INFO_PROTECTION_ENABLED 11
#define DC_INFO_PROTECTION_DISABLED 12
#define DC_INFO_INVALID_UNENCRYPTED_MAIL 13
#define DC_INFO_WEBXDC_INFO_MESSAGE 32
/**
@@ -4557,15 +4585,18 @@ int dc_msg_has_html (dc_msg_t* msg);
* if they are larger than the limit set by the dc_set_config()-option `download_limit`.
*
* The function returns one of:
* - @ref DC_DOWNLOAD_DONE - The message does not need any further download action
* and should be rendered as usual.
* - @ref DC_DOWNLOAD_AVAILABLE - There is additional content to download.
* In addition to the usual message rendering,
* the UI shall show a download button that calls dc_download_full_msg()
* - @ref DC_DOWNLOAD_IN_PROGRESS - Download was started with dc_download_full_msg() and is still in progress.
* If the download fails or succeeds,
* the event @ref DC_EVENT_MSGS_CHANGED is emitted.
* - @ref DC_DOWNLOAD_FAILURE - Download error, the user may start over calling dc_download_full_msg() again.
* - @ref DC_DOWNLOAD_DONE - The message does not need any further download action
* and should be rendered as usual.
* - @ref DC_DOWNLOAD_AVAILABLE - There is additional content to download.
* In addition to the usual message rendering,
* the UI shall show a download button that calls dc_download_full_msg()
* - @ref DC_DOWNLOAD_IN_PROGRESS - Download was started with dc_download_full_msg() and is still in progress.
* If the download fails or succeeds,
* the event @ref DC_EVENT_MSGS_CHANGED is emitted.
*
* - @ref DC_DOWNLOAD_UNDECIPHERABLE - The message does not need any futher download action.
* It was fully downloaded, but we failed to decrypt it.
* - @ref DC_DOWNLOAD_FAILURE - Download error, the user may start over calling dc_download_full_msg() again.
*
* @memberof dc_msg_t
* @param msg The message object.
@@ -5023,10 +5054,16 @@ int dc_contact_is_blocked (const dc_contact_t* contact);
/**
* Check if a contact was verified. E.g. by a secure-join QR code scan
* and if the key has not changed since this verification.
* Check if the contact
* can be added to verified chats,
* i.e. has a verified key
* and Autocrypt key matches the verified key.
*
* The UI may draw a checkbox or something like that beside verified contacts.
* If contact is verified
* UI should display green checkmark after the contact name
* in contact list items,
* in chat member list items
* and in profiles if no chat with the contact exist (otherwise, use dc_chat_is_protected()).
*
* @memberof dc_contact_t
* @param contact The contact object.
@@ -5035,28 +5072,29 @@ int dc_contact_is_blocked (const dc_contact_t* contact);
*/
int dc_contact_is_verified (dc_contact_t* contact);
/**
* Return the address that verified a contact
*
* The UI may use this in addition to a checkmark showing the verification status
* Returns whether contact is a bot.
*
* @memberof dc_contact_t
* @param contact The contact object.
* @return
* A string containing the verifiers address. If it is the same address as the contact itself,
* we verified the contact ourself. If it is an empty string, we don't have verifier
* information or the contact is not verified.
* @deprecated 2023-09-28, use dc_contact_get_verifier_id instead
* @return 0 if the contact is not a bot, 1 otherwise.
*/
char* dc_contact_get_verifier_addr (dc_contact_t* contact);
int dc_contact_is_bot (dc_contact_t* contact);
/**
* Return the `ContactId` that verified a contact
* Return the contact ID that verified a contact.
*
* The UI may use this in addition to a checkmark showing the verification status
* If the function returns non-zero result,
* display green checkmark in the profile and "Introduced by ..." line
* with the name and address of the contact
* formatted by dc_contact_get_name_n_addr.
*
* If this function returns a verifier,
* this does not necessarily mean
* you can add the contact to verified chats.
* Use dc_contact_is_verified() to check
* if a contact can be added to a verified chat instead.
*
* @memberof dc_contact_t
* @param contact The contact object.
@@ -5161,72 +5199,6 @@ int dc_provider_get_status (const dc_provider_t* prov
void dc_provider_unref (dc_provider_t* provider);
/**
* Return an HTTP(S) GET response.
* This function can be used to download remote content for HTML emails.
*
* @memberof dc_context_t
* @param context The context object to take proxy settings from.
* @param url HTTP or HTTPS URL.
* @return The response must be released using dc_http_response_unref() after usage.
* NULL is returned on errors.
*/
dc_http_response_t* dc_get_http_response (const dc_context_t* context, const char* url);
/**
* @class dc_http_response_t
*
* An object containing an HTTP(S) GET response.
* Created by dc_get_http_response().
*/
/**
* Returns HTTP response MIME type as a string, e.g. "text/plain" or "text/html".
*
* @memberof dc_http_response_t
* @param response HTTP response as returned by dc_get_http_response().
* @return The string which must be released using dc_str_unref() after usage. May be NULL.
*/
char* dc_http_response_get_mimetype (const dc_http_response_t* response);
/**
* Returns HTTP response encoding, e.g. "utf-8".
*
* @memberof dc_http_response_t
* @param response HTTP response as returned by dc_get_http_response().
* @return The string which must be released using dc_str_unref() after usage. May be NULL.
*/
char* dc_http_response_get_encoding (const dc_http_response_t* response);
/**
* Returns HTTP response contents.
*
* @memberof dc_http_response_t
* @param response HTTP response as returned by dc_get_http_response().
* @return The blob which must be released using dc_str_unref() after usage. NULL is never returned.
*/
uint8_t* dc_http_response_get_blob (const dc_http_response_t* response);
/**
* Returns HTTP response content size.
*
* @memberof dc_http_response_t
* @param response HTTP response as returned by dc_get_http_response().
* @return The blob size.
*/
size_t dc_http_response_get_size (const dc_http_response_t* response);
/**
* Free an HTTP response object.
*
* @memberof dc_http_response_t
* @param response HTTP response as returned by dc_get_http_response().
*/
void dc_http_response_unref (const dc_http_response_t* response);
/**
* @class dc_lot_t
*
@@ -5326,6 +5298,7 @@ int64_t dc_lot_get_timestamp (const dc_lot_t* lot);
/**
* @class dc_reactions_t
* @deprecated 2023-11-27, use jsonrpc method `get_message_reactions` instead
*
* An object representing all reactions for a single message.
*/
@@ -5333,6 +5306,7 @@ int64_t dc_lot_get_timestamp (const dc_lot_t* lot);
/**
* Returns array of contacts which reacted to the given message.
*
* @deprecated 2023-11-27, use jsonrpc method `get_message_reactions` instead
* @memberof dc_reactions_t
* @param reactions The object containing message reactions.
* @return array of contact IDs. Use dc_array_get_cnt() to get array length and
@@ -5344,6 +5318,7 @@ dc_array_t* dc_reactions_get_contacts(dc_reactions_t* reactions);
/**
* Returns a string containing space-separated reactions of a single contact.
*
* @deprecated 2023-11-27, use jsonrpc method `get_message_reactions` instead
* @memberof dc_reactions_t
* @param reactions The object containing message reactions.
* @param contact_id ID of the contact.
@@ -5359,6 +5334,7 @@ char* dc_reactions_get_by_contact_id(dc_reactions_t* reactions, uint32
*
* Reactions objects are created by dc_get_msg_reactions().
*
* @deprecated 2023-11-27
* @memberof dc_reactions_t
* @param reactions The object to free.
* If NULL is given, nothing is done.
@@ -6219,6 +6195,7 @@ void dc_event_unref(dc_event_t* event);
* @param data2 (int) The progress as:
* 400=vg-/vc-request-with-auth sent, typically shown as "alice@addr verified, introducing myself."
* (Bob has verified alice and waits until Alice does the same for him)
* 1000=vg-member-added/vc-contact-confirm received
*/
#define DC_EVENT_SECUREJOIN_JOINER_PROGRESS 2061
@@ -6242,6 +6219,18 @@ void dc_event_unref(dc_event_t* event);
#define DC_EVENT_SELFAVATAR_CHANGED 2110
/**
* A multi-device synced config value changed. Maybe the app needs to refresh smth. For uniformity
* this is emitted on the source device too. The value isn't reported, otherwise it would be logged
* which might not be good for privacy. You can get the new value with
* `dc_get_config(context, data2)`.
*
* @param data1 0
* @param data2 (char*) Configuration key.
*/
#define DC_EVENT_CONFIG_SYNCED 2111
/**
* webxdc status update received.
* To get the received status update, use dc_get_webxdc_status_updates() with
@@ -6411,22 +6400,27 @@ void dc_event_unref(dc_event_t* event);
/**
* Download not needed, see dc_msg_get_download_state() for details.
*/
#define DC_DOWNLOAD_DONE 0
#define DC_DOWNLOAD_DONE 0
/**
* Download available, see dc_msg_get_download_state() for details.
*/
#define DC_DOWNLOAD_AVAILABLE 10
#define DC_DOWNLOAD_AVAILABLE 10
/**
* Download failed, see dc_msg_get_download_state() for details.
*/
#define DC_DOWNLOAD_FAILURE 20
#define DC_DOWNLOAD_FAILURE 20
/**
* Download not needed, see dc_msg_get_download_state() for details.
*/
#define DC_DOWNLOAD_UNDECIPHERABLE 30
/**
* Download in progress, see dc_msg_get_download_state() for details.
*/
#define DC_DOWNLOAD_IN_PROGRESS 1000
#define DC_DOWNLOAD_IN_PROGRESS 1000
@@ -6591,7 +6585,7 @@ void dc_event_unref(dc_event_t* event);
/// - %1$s will be replaced by the name of the verified contact
#define DC_STR_CONTACT_VERIFIED 35
/// "Cannot verify %1$s."
/// "Cannot establish guaranteed end-to-end encryption with %1$s."
///
/// Used in status messages.
/// - %1$s will be replaced by the name of the contact that cannot be verified
@@ -6781,15 +6775,6 @@ void dc_event_unref(dc_event_t* event);
/// Used in error strings.
#define DC_STR_ERROR_NO_NETWORK 87
/// "Chat protection enabled."
///
/// @deprecated Deprecated, replaced by DC_STR_MSG_YOU_ENABLED_PROTECTION and DC_STR_MSG_PROTECTION_ENABLED_BY.
#define DC_STR_PROTECTION_ENABLED 88
/// @deprecated Deprecated, replaced by DC_STR_MSG_YOU_DISABLED_PROTECTION and DC_STR_MSG_PROTECTION_DISABLED_BY.
#define DC_STR_PROTECTION_DISABLED 89
/// "Reply"
///
/// Used in summaries.
@@ -7038,6 +7023,8 @@ void dc_event_unref(dc_event_t* event);
/// "You added member %1$s."
///
/// Used in status messages.
///
/// `%1$s` will be replaced by the added member's name.
#define DC_STR_ADD_MEMBER_BY_YOU 128
/// "Member %1$s added by %2$s."
@@ -7234,26 +7221,6 @@ void dc_event_unref(dc_event_t* event);
/// `%2$s` will be replaced by name and address of the contact.
#define DC_STR_EPHEMERAL_TIMER_WEEKS_BY_OTHER 157
/// "You enabled chat protection."
///
/// Used in status messages.
#define DC_STR_PROTECTION_ENABLED_BY_YOU 158
/// "Chat protection enabled by %1$s."
///
/// `%1$s` will be replaced by name and address of the contact.
///
/// Used in status messages.
#define DC_STR_PROTECTION_ENABLED_BY_OTHER 159
/// "You disabled chat protection."
#define DC_STR_PROTECTION_DISABLED_BY_YOU 160
/// "Chat protection disabled by %1$s."
///
/// `%1$s` will be replaced by name and address of the contact.
#define DC_STR_PROTECTION_DISABLED_BY_OTHER 161
/// "Scan to set up second device for %1$s"
///
/// `%1$s` will be replaced by name and address of the account.
@@ -7264,6 +7231,36 @@ void dc_event_unref(dc_event_t* event);
/// Used as a device message after a successful backup transfer.
#define DC_STR_BACKUP_TRANSFER_MSG_BODY 163
/// "Messages are guaranteed to be end-to-end encrypted from now on."
///
/// Used in info messages.
#define DC_STR_CHAT_PROTECTION_ENABLED 170
/// "%1$s sent a message from another device."
///
/// Used in info messages.
#define DC_STR_CHAT_PROTECTION_DISABLED 171
/// "Others will only see this group after you sent a first message."
///
/// Used as the first info messages in newly created groups.
#define DC_STR_NEW_GROUP_SEND_FIRST_MESSAGE 172
/// "Member %1$s added."
///
/// Used as info messages.
///
/// `%1$s` will be replaced by the added member's name.
#define DC_STR_MESSAGE_ADD_MEMBER 173
/// "Your email provider %1$s requires end-to-end encryption which is not setup yet."
///
/// Used as info messages when a message cannot be sent because it cannot be encrypted.
///
/// `%1$s` will be replaced by the provider's domain.
#define DC_STR_INVALID_UNENCRYPTED_MAIL 174
/**
* @}
*/

View File

@@ -29,9 +29,8 @@ use deltachat::contact::{Contact, ContactId, Origin};
use deltachat::context::Context;
use deltachat::ephemeral::Timer as EphemeralTimer;
use deltachat::imex::BackupProvider;
use deltachat::key::{DcKey, DcSecretKey};
use deltachat::key::preconfigure_keypair;
use deltachat::message::MsgId;
use deltachat::net::read_url_blob;
use deltachat::qr_code_generator::{generate_backup_qr, get_securejoin_qr_svg};
use deltachat::reaction::{get_msg_reactions, send_reaction, Reactions};
use deltachat::stock_str::StockMessage;
@@ -489,7 +488,7 @@ pub unsafe extern "C" fn dc_start_io(context: *mut dc_context_t) {
if context.is_null() {
return;
}
let ctx = &*context;
let ctx = &mut *context;
block_on(ctx.start_io())
}
@@ -557,6 +556,7 @@ pub unsafe extern "C" fn dc_event_get_id(event: *mut dc_event_t) -> libc::c_int
EventType::SecurejoinJoinerProgress { .. } => 2061,
EventType::ConnectivityChanged => 2100,
EventType::SelfavatarChanged => 2110,
EventType::ConfigSynced { .. } => 2111,
EventType::WebxdcStatusUpdate { .. } => 2120,
EventType::WebxdcInstanceDeleted { .. } => 2121,
}
@@ -584,6 +584,7 @@ pub unsafe extern "C" fn dc_event_get_data1_int(event: *mut dc_event_t) -> libc:
| EventType::Error(_)
| EventType::ConnectivityChanged
| EventType::SelfavatarChanged
| EventType::ConfigSynced { .. }
| EventType::IncomingMsgBunch { .. }
| EventType::ErrorSelfNotInGroup(_) => 0,
EventType::MsgsChanged { chat_id, .. }
@@ -644,7 +645,8 @@ pub unsafe extern "C" fn dc_event_get_data2_int(event: *mut dc_event_t) -> libc:
| EventType::ConnectivityChanged
| EventType::WebxdcInstanceDeleted { .. }
| EventType::IncomingMsgBunch { .. }
| EventType::SelfavatarChanged => 0,
| EventType::SelfavatarChanged
| EventType::ConfigSynced { .. } => 0,
EventType::ChatModified(_) => 0,
EventType::MsgsChanged { msg_id, .. }
| EventType::ReactionsChanged { msg_id, .. }
@@ -723,6 +725,10 @@ pub unsafe extern "C" fn dc_event_get_data2_str(event: *mut dc_event_t) -> *mut
.to_c_string()
.unwrap_or_default()
.into_raw(),
EventType::ConfigSynced { key } => {
let data2 = key.to_string().to_c_string().unwrap_or_default();
data2.into_raw()
}
}
}
@@ -813,21 +819,12 @@ pub unsafe extern "C" fn dc_preconfigure_keypair(
return 0;
}
let ctx = &*context;
block_on(async move {
let addr = tools::EmailAddress::new(&to_string_lossy(addr))?;
let secret = key::SignedSecretKey::from_asc(&to_string_lossy(secret_data))?.0;
let public = secret.split_public_key()?;
let keypair = key::KeyPair {
addr,
public,
secret,
};
key::store_self_keypair(ctx, &keypair, key::KeyPairUse::Default).await?;
Ok::<_, anyhow::Error>(1)
})
.context("Failed to save keypair")
.log_err(ctx)
.unwrap_or(0)
let addr = to_string_lossy(addr);
let secret_data = to_string_lossy(secret_data);
block_on(preconfigure_keypair(ctx, &addr, &secret_data))
.context("Failed to save keypair")
.log_err(ctx)
.is_ok() as libc::c_int
}
#[no_mangle]
@@ -1472,32 +1469,6 @@ pub unsafe extern "C" fn dc_get_next_media(
})
}
#[no_mangle]
pub unsafe extern "C" fn dc_set_chat_protection(
context: *mut dc_context_t,
chat_id: u32,
protect: libc::c_int,
) -> libc::c_int {
if context.is_null() {
eprintln!("ignoring careless call to dc_set_chat_protection()");
return 0;
}
let ctx = &*context;
let protect = if let Some(s) = ProtectionStatus::from_i32(protect) {
s
} else {
warn!(ctx, "bad protect-value for dc_set_chat_protection()");
return 0;
};
block_on(async move {
match ChatId::new(chat_id).set_protection(ctx, protect).await {
Ok(()) => 1,
Err(_) => 0,
}
})
}
#[no_mangle]
pub unsafe extern "C" fn dc_set_chat_visibility(
context: *mut dc_context_t,
@@ -3132,6 +3103,16 @@ pub unsafe extern "C" fn dc_chat_is_protected(chat: *mut dc_chat_t) -> libc::c_i
ffi_chat.chat.is_protected() as libc::c_int
}
#[no_mangle]
pub unsafe extern "C" fn dc_chat_is_protection_broken(chat: *mut dc_chat_t) -> libc::c_int {
if chat.is_null() {
eprintln!("ignoring careless call to dc_chat_is_protection_broken()");
return 0;
}
let ffi_chat = &*chat;
ffi_chat.chat.is_protection_broken() as libc::c_int
}
#[no_mangle]
pub unsafe extern "C" fn dc_chat_is_sending_locations(chat: *mut dc_chat_t) -> libc::c_int {
if chat.is_null() {
@@ -4138,27 +4119,26 @@ pub unsafe extern "C" fn dc_contact_is_verified(contact: *mut dc_contact_t) -> l
let ffi_contact = &*contact;
let ctx = &*ffi_contact.context;
block_on(ffi_contact.contact.is_verified(ctx))
if block_on(ffi_contact.contact.is_verified(ctx))
.context("is_verified failed")
.log_err(ctx)
.unwrap_or_default() as libc::c_int
.unwrap_or_default()
{
// Return value is essentially a boolean,
// but we return 2 for true for backwards compatibility.
2
} else {
0
}
}
#[no_mangle]
pub unsafe extern "C" fn dc_contact_get_verifier_addr(
contact: *mut dc_contact_t,
) -> *mut libc::c_char {
pub unsafe extern "C" fn dc_contact_is_bot(contact: *mut dc_contact_t) -> libc::c_int {
if contact.is_null() {
eprintln!("ignoring careless call to dc_contact_get_verifier_addr()");
return "".strdup();
eprintln!("ignoring careless call to dc_contact_is_bot()");
return 0;
}
let ffi_contact = &*contact;
let ctx = &*ffi_contact.context;
block_on(ffi_contact.contact.get_verifier_addr(ctx))
.context("failed to get verifier for contact")
.log_err(ctx)
.unwrap_or_default()
.strdup()
(*contact).contact.is_bot() as libc::c_int
}
#[no_mangle]
@@ -4632,96 +4612,6 @@ pub unsafe extern "C" fn dc_provider_unref(provider: *mut dc_provider_t) {
// this may change once we start localizing string.
}
// dc_http_response_t
pub type dc_http_response_t = net::HttpResponse;
#[no_mangle]
pub unsafe extern "C" fn dc_get_http_response(
context: *const dc_context_t,
url: *const libc::c_char,
) -> *mut dc_http_response_t {
if context.is_null() || url.is_null() {
eprintln!("ignoring careless call to dc_get_http_response()");
return ptr::null_mut();
}
let context = &*context;
let url = to_string_lossy(url);
if let Ok(response) = block_on(read_url_blob(context, &url))
.context("read_url_blob")
.log_err(context)
{
Box::into_raw(Box::new(response))
} else {
ptr::null_mut()
}
}
#[no_mangle]
pub unsafe extern "C" fn dc_http_response_get_mimetype(
response: *const dc_http_response_t,
) -> *mut libc::c_char {
if response.is_null() {
eprintln!("ignoring careless call to dc_http_response_get_mimetype()");
return ptr::null_mut();
}
let response = &*response;
response.mimetype.strdup()
}
#[no_mangle]
pub unsafe extern "C" fn dc_http_response_get_encoding(
response: *const dc_http_response_t,
) -> *mut libc::c_char {
if response.is_null() {
eprintln!("ignoring careless call to dc_http_response_get_encoding()");
return ptr::null_mut();
}
let response = &*response;
response.encoding.strdup()
}
#[no_mangle]
pub unsafe extern "C" fn dc_http_response_get_blob(
response: *const dc_http_response_t,
) -> *mut libc::c_char {
if response.is_null() {
eprintln!("ignoring careless call to dc_http_response_get_blob()");
return ptr::null_mut();
}
let response = &*response;
let blob_len = response.blob.len();
let ptr = libc::malloc(blob_len);
libc::memcpy(ptr, response.blob.as_ptr() as *mut libc::c_void, blob_len);
ptr as *mut libc::c_char
}
#[no_mangle]
pub unsafe extern "C" fn dc_http_response_get_size(
response: *const dc_http_response_t,
) -> libc::size_t {
if response.is_null() {
eprintln!("ignoring careless call to dc_http_response_get_size()");
return 0;
}
let response = &*response;
response.blob.len()
}
#[no_mangle]
pub unsafe extern "C" fn dc_http_response_unref(response: *mut dc_http_response_t) {
if response.is_null() {
eprintln!("ignoring careless call to dc_http_response_unref()");
return;
}
drop(Box::from_raw(response));
}
// -- Accounts
/// Reader-writer lock wrapper for accounts manager to guarantee thread safety when using
@@ -4750,17 +4640,17 @@ pub type dc_accounts_t = AccountsWrapper;
#[no_mangle]
pub unsafe extern "C" fn dc_accounts_new(
_os_name: *const libc::c_char,
dbfile: *const libc::c_char,
dir: *const libc::c_char,
writable: libc::c_int,
) -> *mut dc_accounts_t {
setup_panic!();
if dbfile.is_null() {
if dir.is_null() {
eprintln!("ignoring careless call to dc_accounts_new()");
return ptr::null_mut();
}
let accs = block_on(Accounts::new(as_path(dbfile).into()));
let accs = block_on(Accounts::new(as_path(dir).into(), writable != 0));
match accs {
Ok(accs) => Box::into_raw(Box::new(AccountsWrapper::new(accs))),
@@ -4971,8 +4861,8 @@ pub unsafe extern "C" fn dc_accounts_start_io(accounts: *mut dc_accounts_t) {
return;
}
let accounts = &*accounts;
block_on(async move { accounts.read().await.start_io().await });
let accounts = &mut *accounts;
block_on(async move { accounts.write().await.start_io().await });
}
#[no_mangle]

View File

@@ -1,6 +1,6 @@
[package]
name = "deltachat-jsonrpc"
version = "1.124.1"
version = "1.133.2"
description = "DeltaChat JSON-RPC API"
edition = "2021"
default-run = "deltachat-jsonrpc-server"
@@ -15,26 +15,26 @@ required-features = ["webserver"]
anyhow = "1"
deltachat = { path = ".." }
num-traits = "0.2"
schemars = "0.8.11"
schemars = "0.8.13"
serde = { version = "1.0", features = ["derive"] }
tempfile = "3.6.0"
tempfile = "3.9.0"
log = "0.4"
async-channel = { version = "1.8.0" }
futures = { version = "0.3.28" }
serde_json = "1.0.99"
yerpc = { version = "0.5.1", features = ["anyhow_expose", "openrpc"] }
typescript-type-def = { version = "0.5.5", features = ["json_value"] }
tokio = { version = "1.29.1" }
sanitize-filename = "0.4"
async-channel = { version = "2.0.0" }
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.33.0" }
sanitize-filename = "0.5"
walkdir = "2.3.3"
base64 = "0.21"
# optional dependencies
axum = { version = "0.6.18", optional = true, features = ["ws"] }
axum = { version = "0.7", optional = true, features = ["ws"] }
env_logger = { version = "0.10.0", optional = true }
[dev-dependencies]
tokio = { version = "1.29.1", features = ["full", "rt-multi-thread"] }
tokio = { version = "1.33.0", features = ["full", "rt-multi-thread"] }
[features]

View File

@@ -108,10 +108,10 @@ This will build the `deltachat-jsonrpc-server` binary and then run a test suite
The test suite includes some tests that need online connectivity and a way to create test email accounts. To run these tests, talk to DeltaChat developers to get a token for the `testrun.org` service, or use a local instance of [`mailadm`](https://github.com/deltachat/docker-mailadm).
Then, set the `DCC_NEW_TMP_EMAIL` environment variable to your mailadm token before running the tests.
Then, set the `CHATMAIL_DOMAIN` environment variable to your testing email server domain.
```
DCC_NEW_TMP_EMAIL=https://testrun.org/new_email?t=yourtoken npm run test
CHATMAIL_DOMAIN=chat.example.org npm run test
```
#### Test Coverage

View File

@@ -4,30 +4,30 @@ use std::{collections::HashMap, str::FromStr};
use anyhow::{anyhow, bail, ensure, Context, Result};
pub use deltachat::accounts::Accounts;
use deltachat::message::get_msg_read_receipts;
use deltachat::qr::Qr;
use deltachat::{
chat::{
self, add_contact_to_chat, forward_msgs, get_chat_media, get_chat_msgs, get_chat_msgs_ex,
marknoticed_chat, remove_contact_from_chat, Chat, ChatId, ChatItem, MessageListOptions,
ProtectionStatus,
},
chatlist::Chatlist,
config::Config,
constants::DC_MSG_ID_DAYMARKER,
contact::{may_be_valid_addr, Contact, ContactId, Origin},
context::get_info,
ephemeral::Timer,
imex, location,
message::{self, delete_msgs, markseen_msgs, Message, MessageState, MsgId, Viewtype},
provider::get_provider_info,
qr,
qr_code_generator::{generate_backup_qr, get_securejoin_qr_svg},
reaction::{get_msg_reactions, send_reaction},
securejoin,
stock_str::StockMessage,
webxdc::StatusUpdateSerial,
use deltachat::chat::{
self, add_contact_to_chat, forward_msgs, get_chat_media, get_chat_msgs, get_chat_msgs_ex,
marknoticed_chat, remove_contact_from_chat, Chat, ChatId, ChatItem, MessageListOptions,
ProtectionStatus,
};
use deltachat::chatlist::Chatlist;
use deltachat::config::Config;
use deltachat::constants::DC_MSG_ID_DAYMARKER;
use deltachat::contact::{may_be_valid_addr, Contact, ContactId, Origin};
use deltachat::context::get_info;
use deltachat::ephemeral::Timer;
use deltachat::imex;
use deltachat::location;
use deltachat::message::get_msg_read_receipts;
use deltachat::message::{
self, delete_msgs, markseen_msgs, Message, MessageState, MsgId, Viewtype,
};
use deltachat::provider::get_provider_info;
use deltachat::qr::{self, Qr};
use deltachat::qr_code_generator::{generate_backup_qr, get_securejoin_qr_svg};
use deltachat::reaction::{get_msg_reactions, send_reaction};
use deltachat::securejoin;
use deltachat::stock_str::StockMessage;
use deltachat::webxdc::StatusUpdateSerial;
use sanitize_filename::is_sanitized;
use tokio::fs;
use tokio::sync::{watch, Mutex, RwLock};
@@ -47,7 +47,7 @@ use types::provider_info::ProviderInfo;
use types::reactions::JSONRPCReactions;
use types::webxdc::WebxdcMessageInfo;
use self::types::message::MessageLoadResult;
use self::types::message::{MessageInfo, MessageLoadResult};
use self::types::{
chat::{BasicChat, JSONRPCChatVisibility, MuteDuration},
location::JsonrpcLocation,
@@ -142,11 +142,7 @@ impl CommandApi {
}
}
#[rpc(
all_positional,
ts_outdir = "typescript/generated",
openrpc_outdir = "openrpc"
)]
#[rpc(all_positional, ts_outdir = "typescript/generated")]
impl CommandApi {
/// Test function.
async fn sleep(&self, delay: f64) {
@@ -157,12 +153,12 @@ impl CommandApi {
// Misc top level functions
// ---------------------------------------------
/// Check if an email address is valid.
/// Checks if an email address is valid.
async fn check_email_validity(&self, email: String) -> bool {
may_be_valid_addr(&email)
}
/// Get general system info.
/// Returns general system info.
async fn get_system_info(&self) -> BTreeMap<&'static str, String> {
get_info()
}
@@ -223,13 +219,15 @@ impl CommandApi {
Ok(accounts)
}
/// Starts background tasks for all accounts.
async fn start_io_for_all_accounts(&self) -> Result<()> {
self.accounts.read().await.start_io().await;
self.accounts.write().await.start_io().await;
Ok(())
}
/// Stops background tasks for all accounts.
async fn stop_io_for_all_accounts(&self) -> Result<()> {
self.accounts.read().await.stop_io().await;
self.accounts.write().await.stop_io().await;
Ok(())
}
@@ -237,14 +235,16 @@ impl CommandApi {
// Methods that work on individual accounts
// ---------------------------------------------
async fn start_io(&self, id: u32) -> Result<()> {
let ctx = self.get_context(id).await?;
/// Starts background tasks for a single account.
async fn start_io(&self, account_id: u32) -> Result<()> {
let mut ctx = self.get_context(account_id).await?;
ctx.start_io().await;
Ok(())
}
async fn stop_io(&self, id: u32) -> Result<()> {
let ctx = self.get_context(id).await?;
/// Stops background tasks for a single account.
async fn stop_io(&self, account_id: u32) -> Result<()> {
let ctx = self.get_context(account_id).await?;
ctx.stop_io().await;
Ok(())
}
@@ -311,11 +311,13 @@ impl CommandApi {
ctx.get_info().await
}
/// Sets the given configuration key.
async fn set_config(&self, account_id: u32, key: String, value: Option<String>) -> Result<()> {
let ctx = self.get_context(account_id).await?;
set_config(&ctx, &key, value.as_deref()).await
}
/// Updates a batch of configuration values.
async fn batch_set_config(
&self,
account_id: u32,
@@ -347,6 +349,7 @@ impl CommandApi {
Ok(qr_object)
}
/// Returns configuration value for the given key.
async fn get_config(&self, account_id: u32, key: String) -> Result<Option<String>> {
let ctx = self.get_context(account_id).await?;
get_config(&ctx, &key).await
@@ -380,7 +383,7 @@ impl CommandApi {
/// Configures this account with the currently set parameters.
/// Setup the credential config before calling this.
async fn configure(&self, account_id: u32) -> Result<()> {
let ctx = self.get_context(account_id).await?;
let mut ctx = self.get_context(account_id).await?;
ctx.stop_io().await;
let result = ctx.configure().await;
if result.is_err() {
@@ -675,7 +678,7 @@ impl CommandApi {
/// the Verified-Group-Invite protocol is offered in the QR code;
/// works for protected groups as well as for normal groups.
/// If not set, the Setup-Contact protocol is offered in the QR code.
/// See https://countermitm.readthedocs.io/en/latest/new.html
/// See https://securejoin.readthedocs.io/en/latest/new.html
/// for details about both protocols.
///
/// return format: `[code, svg]`
@@ -704,7 +707,7 @@ impl CommandApi {
///
/// Subsequent calls of `secure_join()` will abort previous, unfinished handshakes.
///
/// See https://countermitm.readthedocs.io/en/latest/new.html
/// See https://securejoin.readthedocs.io/en/latest/new.html
/// for details about both protocols.
///
/// **qr**: The text of the scanned QR code. Typically, the same string as given
@@ -812,24 +815,12 @@ impl CommandApi {
/// Create a new broadcast list.
///
/// Broadcast lists are similar to groups on the sending device,
/// however, recipients get the messages in normal one-to-one chats
/// and will not be aware of other members.
/// however, recipients get the messages in a read-only chat
/// and will see who the other members are.
///
/// Replies to broadcasts go only to the sender
/// and not to all broadcast recipients.
/// Moreover, replies will not appear in the broadcast list
/// but in the one-to-one chat with the person answering.
///
/// The name and the image of the broadcast list is set automatically
/// and is visible to the sender only.
/// Not asking for these data allows more focused creation
/// and we bypass the question who will get which data.
/// Also, many users will have at most one broadcast list
/// so, a generic name and image is sufficient at the first place.
///
/// Later on, however, the name can be changed using dc_set_chat_name().
/// The image cannot be changed to have a unique, recognizable icon in the chat lists.
/// All in all, this is also what other messengers are doing here.
/// For historical reasons, this function does not take a name directly,
/// instead you have to set the name using dc_set_chat_name()
/// after creating the broadcast list.
async fn create_broadcast_list(&self, account_id: u32) -> Result<u32> {
let ctx = self.get_context(account_id).await?;
chat::create_broadcast_list(&ctx)
@@ -1135,6 +1126,16 @@ impl CommandApi {
MsgId::new(message_id).get_info(&ctx).await
}
/// Returns additional information for single message.
async fn get_message_info_object(
&self,
account_id: u32,
message_id: u32,
) -> Result<MessageInfo> {
let ctx = self.get_context(account_id).await?;
MessageInfo::from_msg_id(&ctx, MsgId::new(message_id)).await
}
/// Returns contacts that sent read receipts and the time of reading.
async fn get_message_read_receipts(
&self,
@@ -1390,6 +1391,19 @@ impl CommandApi {
// chat
// ---------------------------------------------
/// Returns the [`ChatId`] for the 1:1 chat with `contact_id` if it exists.
///
/// If it does not exist, `None` is returned.
async fn get_chat_id_by_contact_id(
&self,
account_id: u32,
contact_id: u32,
) -> Result<Option<u32>> {
let ctx = self.get_context(account_id).await?;
let chat_id = ChatId::lookup_by_contact(&ctx, ContactId::new(contact_id)).await?;
Ok(chat_id.map(|id| id.to_u32()))
}
/// Returns all message IDs of the given types in a chat.
/// Typically used to show a gallery.
///
@@ -1753,6 +1767,9 @@ impl CommandApi {
let mut msg = Message::new(Viewtype::Sticker);
msg.set_file(&sticker_path, None);
// JSON-rpc does not need heuristics to turn [Viewtype::Sticker] into [Viewtype::Image]
msg.force_sticker();
let message_id = deltachat::chat::send_msg(&ctx, ChatId::new(chat_id), &mut msg).await?;
Ok(message_id.to_u32())
}
@@ -1886,7 +1903,7 @@ impl CommandApi {
.context("path conversion to string failed")
}
/// save a sticker to a collection/folder in the account's sticker folder
/// Saves a sticker to a collection/folder in the account's sticker folder.
async fn misc_save_sticker(
&self,
account_id: u32,
@@ -2039,13 +2056,19 @@ impl CommandApi {
text: Option<String>,
file: Option<String>,
quoted_message_id: Option<u32>,
view_type: Option<MessageViewtype>,
) -> Result<()> {
let ctx = self.get_context(account_id).await?;
let mut draft = Message::new(if file.is_some() {
Viewtype::File
} else {
Viewtype::Text
});
let mut draft = Message::new(view_type.map_or_else(
|| {
if file.is_some() {
Viewtype::File
} else {
Viewtype::Text
}
},
|v| v.into(),
));
draft.set_text(text.unwrap_or_default());
if let Some(file) = file {
draft.set_file(file, None);
@@ -2065,6 +2088,23 @@ impl CommandApi {
ChatId::new(chat_id).set_draft(&ctx, Some(&mut draft)).await
}
// send the chat's current set draft
async fn misc_send_draft(&self, account_id: u32, chat_id: u32) -> Result<u32> {
let ctx = self.get_context(account_id).await?;
if let Some(draft) = ChatId::new(chat_id).get_draft(&ctx).await? {
let mut draft = draft;
let msg_id = chat::send_msg(&ctx, ChatId::new(chat_id), &mut draft)
.await?
.to_u32();
Ok(msg_id)
} else {
Err(anyhow!(
"chat with id {} doesn't have draft message",
chat_id
))
}
}
}
// Helper functions (to prevent code duplication)

View File

@@ -7,7 +7,7 @@ use typescript_type_def::TypeDef;
use super::color_int_to_hex_string;
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(tag = "type")]
#[serde(tag = "kind")]
pub enum Account {
#[serde(rename_all = "camelCase")]
Configured {

View File

@@ -18,6 +18,17 @@ use super::contact::ContactObject;
pub struct FullChat {
id: u32,
name: String,
/// True if the chat is protected.
///
/// UI should display a green checkmark
/// in the chat title,
/// in the chat profile title and
/// in the chatlist item
/// if chat protection is enabled.
/// UI should also display a green checkmark
/// in the contact profile
/// if 1:1 chat with this contact exists and is protected.
is_protected: bool,
profile_image: Option<String>, //BLOBS ?
archived: bool,
@@ -31,6 +42,7 @@ pub struct FullChat {
fresh_message_counter: usize,
// is_group - please check over chat.type in frontend instead
is_contact_request: bool,
is_protection_broken: bool,
is_device_chat: bool,
self_in_group: bool,
is_muted: bool,
@@ -73,7 +85,7 @@ impl FullChat {
let can_send = chat.can_send(context).await?;
let was_seen_recently = if chat.get_type() == Chattype::Single {
match contact_ids.get(0) {
match contact_ids.first() {
Some(contact) => Contact::get_by_id(context, *contact)
.await
.context("failed to load contact for was_seen_recently")?
@@ -100,6 +112,7 @@ impl FullChat {
color,
fresh_message_counter,
is_contact_request: chat.is_contact_request(),
is_protection_broken: chat.is_protection_broken(),
is_device_chat: chat.is_device_talk(),
self_in_group: contact_ids.contains(&ContactId::SELF),
is_muted: chat.is_muted(),
@@ -126,6 +139,17 @@ impl FullChat {
pub struct BasicChat {
id: u32,
name: String,
/// True if the chat is protected.
///
/// UI should display a green checkmark
/// in the chat title,
/// in the chat profile title and
/// in the chatlist item
/// if chat protection is enabled.
/// UI should also display a green checkmark
/// in the contact profile
/// if 1:1 chat with this contact exists and is protected.
is_protected: bool,
profile_image: Option<String>, //BLOBS ?
archived: bool,
@@ -134,6 +158,7 @@ pub struct BasicChat {
is_self_talk: bool,
color: String,
is_contact_request: bool,
is_protection_broken: bool,
is_device_chat: bool,
is_muted: bool,
}
@@ -160,6 +185,7 @@ impl BasicChat {
is_self_talk: chat.is_self_talk(),
color,
is_contact_request: chat.is_contact_request(),
is_protection_broken: chat.is_protection_broken(),
is_device_chat: chat.is_device_talk(),
is_muted: chat.is_muted(),
})
@@ -167,10 +193,11 @@ impl BasicChat {
}
#[derive(Clone, Serialize, Deserialize, TypeDef, schemars::JsonSchema)]
#[serde(tag = "kind")]
pub enum MuteDuration {
NotMuted,
Forever,
Until(i64),
Until { duration: i64 },
}
impl MuteDuration {
@@ -178,13 +205,13 @@ impl MuteDuration {
match self {
MuteDuration::NotMuted => Ok(chat::MuteDuration::NotMuted),
MuteDuration::Forever => Ok(chat::MuteDuration::Forever),
MuteDuration::Until(n) => {
if n <= 0 {
MuteDuration::Until { duration } => {
if duration <= 0 {
bail!("failed to read mute duration")
}
Ok(SystemTime::now()
.checked_add(Duration::from_secs(n as u64))
.checked_add(Duration::from_secs(duration as u64))
.map_or(chat::MuteDuration::Forever, chat::MuteDuration::Until))
}
}

View File

@@ -15,7 +15,7 @@ use super::color_int_to_hex_string;
use super::message::MessageViewtype;
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(tag = "type")]
#[serde(tag = "kind")]
pub enum ChatListItemFetchResult {
#[serde(rename_all = "camelCase")]
ChatListItem {
@@ -102,7 +102,7 @@ pub(crate) async fn get_chat_list_item_by_id(
let self_in_group = chat_contacts.contains(&ContactId::SELF);
let (dm_chat_contact, was_seen_recently) = if chat.get_type() == Chattype::Single {
let contact = chat_contacts.get(0);
let contact = chat_contacts.first();
let was_seen_recently = match contact {
Some(contact) => Contact::get_by_id(ctx, *contact)
.await

View File

@@ -1,5 +1,4 @@
use anyhow::Result;
use deltachat::contact::VerifiedStatus;
use deltachat::context::Context;
use serde::Serialize;
use typescript_type_def::TypeDef;
@@ -19,14 +18,36 @@ pub struct ContactObject {
profile_image: Option<String>, // BLOBS
name_and_addr: String,
is_blocked: bool,
/// True if the contact can be added to verified groups.
///
/// If this is true
/// UI should display green checkmark after the contact name
/// in contact list items,
/// in chat member list items
/// and in profiles if no chat with the contact exist.
is_verified: bool,
/// the address that verified this contact
verifier_addr: Option<String>,
/// the id of the contact that verified this contact
/// True if the contact profile title should have a green checkmark.
///
/// This indicates whether 1:1 chat has a green checkmark
/// or will have a green checkmark if created.
is_profile_verified: bool,
/// The ID of the contact that verified this contact.
///
/// If this is present,
/// display a green checkmark and "Introduced by ..."
/// string followed by the verifier contact name and address
/// in the contact profile.
verifier_id: Option<u32>,
/// the contact's last seen timestamp
last_seen: i64,
was_seen_recently: bool,
/// If the contact is a bot.
is_bot: bool,
}
impl ContactObject {
@@ -38,19 +59,13 @@ impl ContactObject {
Some(path_buf) => path_buf.to_str().map(|s| s.to_owned()),
None => None,
};
let is_verified = contact.is_verified(context).await? == VerifiedStatus::BidirectVerified;
let is_verified = contact.is_verified(context).await?;
let is_profile_verified = contact.is_profile_verified(context).await?;
let (verifier_addr, verifier_id) = if is_verified {
(
contact.get_verifier_addr(context).await?,
contact
.get_verifier_id(context)
.await?
.map(|contact_id| contact_id.to_u32()),
)
} else {
(None, None)
};
let verifier_id = contact
.get_verifier_id(context)
.await?
.map(|contact_id| contact_id.to_u32());
Ok(ContactObject {
address: contact.get_addr().to_owned(),
@@ -64,10 +79,11 @@ impl ContactObject {
name_and_addr: contact.get_name_n_addr(),
is_blocked: contact.is_blocked(),
is_verified,
verifier_addr,
is_profile_verified,
verifier_id,
last_seen: contact.last_seen(),
was_seen_recently: contact.was_seen_recently(),
is_bot: contact.is_bot(),
})
}
}

View File

@@ -22,61 +22,43 @@ impl From<CoreEvent> for Event {
}
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(tag = "type")]
#[serde(tag = "kind")]
pub enum EventType {
/// The library-user may write an informational string to the log.
///
/// This event should *not* be reported to the end-user using a popup or something like
/// that.
Info {
msg: String,
},
Info { msg: String },
/// Emitted when SMTP connection is established and login was successful.
SmtpConnected {
msg: String,
},
SmtpConnected { msg: String },
/// Emitted when IMAP connection is established and login was successful.
ImapConnected {
msg: String,
},
ImapConnected { msg: String },
/// Emitted when a message was successfully sent to the SMTP server.
SmtpMessageSent {
msg: String,
},
SmtpMessageSent { msg: String },
/// Emitted when an IMAP message has been marked as deleted
ImapMessageDeleted {
msg: String,
},
ImapMessageDeleted { msg: String },
/// Emitted when an IMAP message has been moved
ImapMessageMoved {
msg: String,
},
ImapMessageMoved { msg: String },
/// Emitted before going into IDLE on the Inbox folder.
ImapInboxIdle,
/// Emitted when an new file in the $BLOBDIR was created
NewBlobFile {
file: String,
},
NewBlobFile { file: String },
/// Emitted when an file in the $BLOBDIR was deleted
DeletedBlobFile {
file: String,
},
DeletedBlobFile { file: String },
/// The library-user should write a warning string to the log.
///
/// This event should *not* be reported to the end-user using a popup or something like
/// that.
Warning {
msg: String,
},
Warning { msg: String },
/// The library-user should report an error to the end-user.
///
@@ -88,18 +70,14 @@ pub enum EventType {
/// it might be better to delay showing these events until the function has really
/// failed (returned false). It should be sufficient to report only the *last* error
/// in a messasge box then.
Error {
msg: String,
},
Error { msg: String },
/// An action cannot be performed because the user is not in the group.
/// Reported eg. after a call to
/// setChatName(), setChatProfileImage(),
/// addContactToChat(), removeContactFromChat(),
/// and messages sending functions.
ErrorSelfNotInGroup {
msg: String,
},
ErrorSelfNotInGroup { msg: String },
/// Messages or chats changed. One or more messages or chats changed for various
/// reasons in the database:
@@ -110,10 +88,7 @@ pub enum EventType {
/// `chatId` is set if only a single chat is affected by the changes, otherwise 0.
/// `msgId` is set if only a single message is affected by the changes, otherwise 0.
#[serde(rename_all = "camelCase")]
MsgsChanged {
chat_id: u32,
msg_id: u32,
},
MsgsChanged { chat_id: u32, msg_id: u32 },
/// Reactions for the message changed.
#[serde(rename_all = "camelCase")]
@@ -128,10 +103,7 @@ pub enum EventType {
///
/// There is no extra #DC_EVENT_MSGS_CHANGED event send together with this event.
#[serde(rename_all = "camelCase")]
IncomingMsg {
chat_id: u32,
msg_id: u32,
},
IncomingMsg { chat_id: u32, msg_id: u32 },
/// Downloading a bunch of messages just finished. This is an experimental
/// event to allow the UI to only show one notification per message bunch,
@@ -139,47 +111,31 @@ pub enum EventType {
///
/// msg_ids contains the message ids.
#[serde(rename_all = "camelCase")]
IncomingMsgBunch {
msg_ids: Vec<u32>,
},
IncomingMsgBunch { msg_ids: Vec<u32> },
/// Messages were seen or noticed.
/// chat id is always set.
#[serde(rename_all = "camelCase")]
MsgsNoticed {
chat_id: u32,
},
MsgsNoticed { chat_id: u32 },
/// A single message is sent successfully. State changed from DC_STATE_OUT_PENDING to
/// DC_STATE_OUT_DELIVERED, see `Message.state`.
#[serde(rename_all = "camelCase")]
MsgDelivered {
chat_id: u32,
msg_id: u32,
},
MsgDelivered { chat_id: u32, msg_id: u32 },
/// A single message could not be sent. State changed from DC_STATE_OUT_PENDING or DC_STATE_OUT_DELIVERED to
/// DC_STATE_OUT_FAILED, see `Message.state`.
#[serde(rename_all = "camelCase")]
MsgFailed {
chat_id: u32,
msg_id: u32,
},
MsgFailed { chat_id: u32, msg_id: u32 },
/// A single message is read by the receiver. State changed from DC_STATE_OUT_DELIVERED to
/// DC_STATE_OUT_MDN_RCVD, see `Message.state`.
#[serde(rename_all = "camelCase")]
MsgRead {
chat_id: u32,
msg_id: u32,
},
MsgRead { chat_id: u32, msg_id: u32 },
/// A single message is deleted.
#[serde(rename_all = "camelCase")]
MsgDeleted {
chat_id: u32,
msg_id: u32,
},
MsgDeleted { chat_id: u32, msg_id: u32 },
/// Chat changed. The name or the image of a chat group was changed or members were added or removed.
/// Or the verify state of a chat has changed.
@@ -189,24 +145,17 @@ pub enum EventType {
/// This event does not include ephemeral timer modification, which
/// is a separate event.
#[serde(rename_all = "camelCase")]
ChatModified {
chat_id: u32,
},
ChatModified { chat_id: u32 },
/// Chat ephemeral timer changed.
#[serde(rename_all = "camelCase")]
ChatEphemeralTimerModified {
chat_id: u32,
timer: u32,
},
ChatEphemeralTimerModified { chat_id: u32, timer: u32 },
/// Contact(s) created, renamed, blocked or deleted.
///
/// @param data1 (int) If set, this is the contact_id of an added contact that should be selected.
#[serde(rename_all = "camelCase")]
ContactsChanged {
contact_id: Option<u32>,
},
ContactsChanged { contact_id: Option<u32> },
/// Location of one or more contact has changed.
///
@@ -214,9 +163,7 @@ pub enum EventType {
/// If the locations of several contacts have been changed,
/// this parameter is set to `None`.
#[serde(rename_all = "camelCase")]
LocationChanged {
contact_id: Option<u32>,
},
LocationChanged { contact_id: Option<u32> },
/// Inform about the configuration progress started by configure().
ConfigureProgress {
@@ -234,9 +181,7 @@ pub enum EventType {
/// @param data1 (usize) 0=error, 1-999=progress in permille, 1000=success and done
/// @param data2 0
#[serde(rename_all = "camelCase")]
ImexProgress {
progress: usize,
},
ImexProgress { progress: usize },
/// A file has been exported. A file has been written by imex().
/// This event may be sent multiple times by a single call to imex().
@@ -246,9 +191,7 @@ pub enum EventType {
///
/// @param data2 0
#[serde(rename_all = "camelCase")]
ImexFileWritten {
path: String,
},
ImexFileWritten { path: String },
/// Progress information of a secure-join handshake from the view of the inviter
/// (Alice, the person who shows the QR code).
@@ -263,10 +206,7 @@ pub enum EventType {
/// 800=vg-member-added-received received, shown as "bob@addr securely joined GROUP", only sent for the verified-group-protocol.
/// 1000=Protocol finished for this contact.
#[serde(rename_all = "camelCase")]
SecurejoinInviterProgress {
contact_id: u32,
progress: usize,
},
SecurejoinInviterProgress { contact_id: u32, progress: usize },
/// Progress information of a secure-join handshake from the view of the joiner
/// (Bob, the person who scans the QR code).
@@ -277,10 +217,7 @@ pub enum EventType {
/// 400=vg-/vc-request-with-auth sent, typically shown as "alice@addr verified, introducing myself."
/// (Bob has verified alice and waits until Alice does the same for him)
#[serde(rename_all = "camelCase")]
SecurejoinJoinerProgress {
contact_id: u32,
progress: usize,
},
SecurejoinJoinerProgress { contact_id: u32, progress: usize },
/// The connectivity to the server changed.
/// This means that you should refresh the connectivity view
@@ -288,8 +225,17 @@ pub enum EventType {
/// getConnectivityHtml() for details.
ConnectivityChanged,
/// Deprecated by `ConfigSynced`.
SelfavatarChanged,
/// A multi-device synced config value changed. Maybe the app needs to refresh smth. For
/// uniformity this is emitted on the source device too. The value isn't here, otherwise it
/// would be logged which might not be good for privacy.
ConfigSynced {
/// Configuration key.
key: String,
},
#[serde(rename_all = "camelCase")]
WebxdcStatusUpdate {
msg_id: u32,
@@ -298,9 +244,7 @@ pub enum EventType {
/// Inform that a message containing a webxdc instance has been deleted
#[serde(rename_all = "camelCase")]
WebxdcInstanceDeleted {
msg_id: u32,
},
WebxdcInstanceDeleted { msg_id: u32 },
}
impl From<CoreEventType> for EventType {
@@ -396,6 +340,9 @@ impl From<CoreEventType> for EventType {
},
CoreEventType::ConnectivityChanged => ConnectivityChanged,
CoreEventType::SelfavatarChanged => SelfavatarChanged,
CoreEventType::ConfigSynced { key } => ConfigSynced {
key: key.to_string(),
},
CoreEventType::WebxdcStatusUpdate {
msg_id,
status_update_serial,

View File

@@ -19,7 +19,7 @@ use super::reactions::JSONRPCReactions;
use super::webxdc::WebxdcMessageInfo;
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase", tag = "variant")]
#[serde(rename_all = "camelCase", tag = "kind")]
pub enum MessageLoadResult {
Message(MessageObject),
LoadingError { error: String },
@@ -345,6 +345,7 @@ pub enum SystemMessageType {
SecurejoinMessage,
LocationStreamingEnabled,
LocationOnly,
InvalidUnencryptedMail,
/// Chat ephemeral message timer is changed.
EphemeralTimerChanged,
@@ -385,6 +386,7 @@ impl From<deltachat::mimeparser::SystemMessage> for SystemMessageType {
SystemMessage::MultiDeviceSync => SystemMessageType::MultiDeviceSync,
SystemMessage::WebxdcStatusUpdate => SystemMessageType::WebxdcStatusUpdate,
SystemMessage::WebxdcInfoMessage => SystemMessageType::WebxdcInfoMessage,
SystemMessage::InvalidUnencryptedMail => SystemMessageType::InvalidUnencryptedMail,
}
}
}
@@ -552,3 +554,71 @@ pub struct MessageReadReceipt {
pub contact_id: u32,
pub timestamp: i64,
}
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct MessageInfo {
rawtext: String,
ephemeral_timer: EphemeralTimer,
/// When message is ephemeral this contains the timestamp of the message expiry
ephemeral_timestamp: Option<i64>,
error: Option<String>,
rfc724_mid: String,
server_urls: Vec<String>,
hop_info: Option<String>,
}
impl MessageInfo {
pub async fn from_msg_id(context: &Context, msg_id: MsgId) -> Result<Self> {
let message = Message::load_from_db(context, msg_id).await?;
let rawtext = msg_id.rawtext(context).await?;
let ephemeral_timer = message.get_ephemeral_timer().into();
let ephemeral_timestamp = match message.get_ephemeral_timer() {
deltachat::ephemeral::Timer::Disabled => None,
deltachat::ephemeral::Timer::Enabled { .. } => Some(message.get_ephemeral_timestamp()),
};
let server_urls =
MsgId::get_info_server_urls(context, message.rfc724_mid().to_owned()).await?;
let hop_info = msg_id.hop_info(context).await?;
Ok(Self {
rawtext,
ephemeral_timer,
ephemeral_timestamp,
error: message.error(),
rfc724_mid: message.rfc724_mid().to_owned(),
server_urls,
hop_info,
})
}
}
#[derive(
Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize, TypeDef, schemars::JsonSchema,
)]
#[serde(rename_all = "camelCase", tag = "variant")]
pub enum EphemeralTimer {
/// Timer is disabled.
Disabled,
/// Timer is enabled.
Enabled {
/// Timer duration in seconds.
///
/// The value cannot be 0.
duration: u32,
},
}
impl From<deltachat::ephemeral::Timer> for EphemeralTimer {
fn from(value: deltachat::ephemeral::Timer) -> Self {
match value {
deltachat::ephemeral::Timer::Disabled => EphemeralTimer::Disabled,
deltachat::ephemeral::Timer::Enabled { duration } => {
EphemeralTimer::Enabled { duration }
}
}
}
}

View File

@@ -6,6 +6,8 @@ use typescript_type_def::TypeDef;
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct ProviderInfo {
/// Unique ID, corresponding to provider database filename.
pub id: String,
pub before_login_hint: String,
pub overview_page: String,
pub status: u32, // in reality this is an enum, but for simplicity and because it gets converted into a number anyway, we use an u32 here.
@@ -14,6 +16,7 @@ pub struct ProviderInfo {
impl ProviderInfo {
pub fn from_dc_type(provider: Option<&Provider>) -> Option<Self> {
provider.map(|p| ProviderInfo {
id: p.id.to_owned(),
before_login_hint: p.before_login_hint.to_owned(),
overview_page: p.overview_page.to_owned(),
status: p.status.to_u32().unwrap(),

View File

@@ -4,7 +4,7 @@ use typescript_type_def::TypeDef;
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename = "Qr", rename_all = "camelCase")]
#[serde(tag = "type")]
#[serde(tag = "kind")]
pub enum QrObject {
AskVerifyContact {
contact_id: u32,

View File

@@ -13,10 +13,11 @@ mod tests {
#[tokio::test(flavor = "multi_thread")]
async fn basic_json_rpc_functionality() -> anyhow::Result<()> {
let tmp_dir = TempDir::new().unwrap().path().into();
let accounts = Accounts::new(tmp_dir).await?;
let writable = true;
let accounts = Accounts::new(tmp_dir, writable).await?;
let api = CommandApi::new(accounts);
let (sender, mut receiver) = unbounded::<String>();
let (sender, receiver) = unbounded::<String>();
let (client, mut rx) = RpcClient::new();
let session = RpcSession::new(client, api);
@@ -35,17 +36,17 @@ mod tests {
let request = r#"{"jsonrpc":"2.0","method":"add_account","params":[],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","id":1,"result":1}"#;
session.handle_incoming(request).await;
let result = receiver.next().await;
let result = receiver.recv().await?;
println!("{result:?}");
assert_eq!(result, Some(response.to_owned()));
assert_eq!(result, response.to_owned());
}
{
let request = r#"{"jsonrpc":"2.0","method":"get_all_account_ids","params":[],"id":2}"#;
let response = r#"{"jsonrpc":"2.0","id":2,"result":[1]}"#;
session.handle_incoming(request).await;
let result = receiver.next().await;
let result = receiver.recv().await?;
println!("{result:?}");
assert_eq!(result, Some(response.to_owned()));
assert_eq!(result, response.to_owned());
}
Ok(())
@@ -54,10 +55,11 @@ mod tests {
#[tokio::test(flavor = "multi_thread")]
async fn test_batch_set_config() -> anyhow::Result<()> {
let tmp_dir = TempDir::new().unwrap().path().into();
let accounts = Accounts::new(tmp_dir).await?;
let writable = true;
let accounts = Accounts::new(tmp_dir, writable).await?;
let api = CommandApi::new(accounts);
let (sender, mut receiver) = unbounded::<String>();
let (sender, receiver) = unbounded::<String>();
let (client, mut rx) = RpcClient::new();
let session = RpcSession::new(client, api);
@@ -76,15 +78,15 @@ mod tests {
let request = r#"{"jsonrpc":"2.0","method":"add_account","params":[],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","id":1,"result":1}"#;
session.handle_incoming(request).await;
let result = receiver.next().await;
assert_eq!(result, Some(response.to_owned()));
let result = receiver.recv().await?;
assert_eq!(result, response.to_owned());
}
{
let request = r#"{"jsonrpc":"2.0","method":"batch_set_config","id":2,"params":[1,{"addr":"","mail_user":"","mail_pw":"","mail_server":"","mail_port":"","mail_security":"","imap_certificate_checks":"","send_user":"","send_pw":"","send_server":"","send_port":"","send_security":"","smtp_certificate_checks":"","socks5_enabled":"0","socks5_host":"","socks5_port":"","socks5_user":"","socks5_password":""}]}"#;
let response = r#"{"jsonrpc":"2.0","id":2,"result":null}"#;
session.handle_incoming(request).await;
let result = receiver.next().await;
assert_eq!(result, Some(response.to_owned()));
let result = receiver.recv().await?;
assert_eq!(result, response.to_owned());
}
Ok(())

View File

@@ -19,7 +19,8 @@ async fn main() -> Result<(), std::io::Error> {
.map(|port| port.parse::<u16>().expect("DC_PORT must be a number"))
.unwrap_or(DEFAULT_PORT);
log::info!("Starting with accounts directory `{path}`.");
let accounts = Accounts::new(PathBuf::from(&path)).await.unwrap();
let writable = true;
let accounts = Accounts::new(PathBuf::from(&path), writable).await.unwrap();
let state = CommandApi::new(accounts);
let app = Router::new()
@@ -27,15 +28,13 @@ async fn main() -> Result<(), std::io::Error> {
.layer(Extension(state.clone()));
tokio::spawn(async move {
state.accounts.read().await.start_io().await;
state.accounts.write().await.start_io().await;
});
let addr = SocketAddr::from(([127, 0, 0, 1], port));
log::info!("JSON-RPC WebSocket server listening on {}", addr);
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
axum::serve(listener, app).await.unwrap();
Ok(())
}

View File

@@ -35,7 +35,7 @@ async function run() {
const accounts = await client.rpc.getAllAccounts();
console.log("accounts loaded", accounts);
for (const account of accounts) {
if (account.type === "Configured") {
if (account.kind === "Configured") {
write(
$head,
`<a href="#" onclick="selectDeltaAccount(${account.id})">
@@ -57,7 +57,7 @@ async function run() {
clear($main);
const selectedAccount = SELECTED_ACCOUNT;
const info = await client.rpc.getAccountInfo(selectedAccount);
if (info.type !== "Configured") {
if (info.kind !== "Configured") {
return write($main, "Account is not configured");
}
write($main, `<h2>${info.addr!}</h2>`);
@@ -81,8 +81,7 @@ async function run() {
messageIds
);
for (const [_messageId, message] of Object.entries(messages)) {
if (message.variant === "message")
write($main, `<p>${message.text}</p>`);
if (message.kind === "message") write($main, `<p>${message.text}</p>`);
else write($main, `<p>loading error: ${message.error}</p>`);
}
}
@@ -93,9 +92,9 @@ async function run() {
$side,
`
<p class="message">
[<strong>${event.type}</strong> on account ${accountId}]<br>
[<strong>${event.kind}</strong> on account ${accountId}]<br>
<em>f1:</em> ${JSON.stringify(
Object.assign({}, event, { type: undefined })
Object.assign({}, event, { kind: undefined })
)}
</p>`
);

View File

@@ -9,7 +9,6 @@
"@types/chai": "^4.2.21",
"@types/chai-as-promised": "^7.1.5",
"@types/mocha": "^9.0.0",
"@types/node-fetch": "^2.5.7",
"@types/ws": "^7.2.4",
"c8": "^7.10.0",
"chai": "^4.3.4",
@@ -17,7 +16,6 @@
"esbuild": "^0.17.9",
"http-server": "^14.1.1",
"mocha": "^9.1.1",
"node-fetch": "^2.6.1",
"npm-run-all": "^4.1.5",
"prettier": "^2.6.2",
"typedoc": "^0.23.2",
@@ -55,5 +53,5 @@
},
"type": "module",
"types": "dist/deltachat.d.ts",
"version": "1.124.1"
"version": "1.133.2"
}

View File

@@ -6,22 +6,22 @@ import { WebsocketTransport, BaseTransport, Request } from "yerpc";
import { TinyEmitter } from "@deltachat/tiny-emitter";
type Events = { ALL: (accountId: number, event: EventType) => void } & {
[Property in EventType["type"]]: (
[Property in EventType["kind"]]: (
accountId: number,
event: Extract<EventType, { type: Property }>
event: Extract<EventType, { kind: Property }>
) => void;
};
type ContextEvents = { ALL: (event: EventType) => void } & {
[Property in EventType["type"]]: (
event: Extract<EventType, { type: Property }>
[Property in EventType["kind"]]: (
event: Extract<EventType, { kind: Property }>
) => void;
};
export type DcEvent = EventType;
export type DcEventType<T extends EventType["type"]> = Extract<
export type DcEventType<T extends EventType["kind"]> = Extract<
EventType,
{ type: T }
{ kind: T }
>;
export class BaseDeltaChat<
@@ -46,12 +46,12 @@ export class BaseDeltaChat<
while (true) {
const event = await this.rpc.getNextEvent();
//@ts-ignore
this.emit(event.event.type, event.contextId, event.event);
this.emit(event.event.kind, event.contextId, event.event);
this.emit("ALL", event.contextId, event.event);
if (this.contextEmitters[event.contextId]) {
this.contextEmitters[event.contextId].emit(
event.event.type,
event.event.kind,
//@ts-ignore
event.event as any
);

View File

@@ -79,6 +79,9 @@ describe("basic tests", () => {
accountId = await dc.rpc.addAccount();
});
it("should block and unblock contact", async function () {
// Cannot send sync messages to self as we do not have a self address.
await dc.rpc.setConfig(accountId, "sync_msgs", "0");
const contactId = await dc.rpc.createContact(
accountId,
"example@delta.chat",

View File

@@ -13,27 +13,27 @@ describe("online tests", function () {
before(async function () {
this.timeout(60000);
if (!process.env.DCC_NEW_TMP_EMAIL) {
if (!process.env.CHATMAIL_DOMAIN) {
if (process.env.COVERAGE && !process.env.COVERAGE_OFFLINE) {
console.error(
"CAN NOT RUN COVERAGE correctly: Missing DCC_NEW_TMP_EMAIL environment variable!\n\n",
"CAN NOT RUN COVERAGE correctly: Missing CHATMAIL_DOMAIN environment variable!\n\n",
"You can set COVERAGE_OFFLINE=1 to circumvent this check and skip the online tests, but those coverage results will be wrong, because some functions can only be tested in the online test"
);
process.exit(1);
}
console.log(
"Missing DCC_NEW_TMP_EMAIL environment variable!, skip integration tests"
"Missing CHATMAIL_DOMAIN environment variable!, skip integration tests"
);
this.skip();
}
serverHandle = await startServer();
dc = new DeltaChat(serverHandle.stdin, serverHandle.stdout, true);
dc.on("ALL", (contextId, { type }) => {
if (type !== "Info") console.log(contextId, type);
dc.on("ALL", (contextId, { kind }) => {
if (kind !== "Info") console.log(contextId, kind);
});
account1 = await createTempUser(process.env.DCC_NEW_TMP_EMAIL);
account1 = createTempUser(process.env.CHATMAIL_DOMAIN);
if (!account1 || !account1.email || !account1.password) {
console.log(
"We didn't got back an account from the api, skip integration tests"
@@ -41,7 +41,7 @@ describe("online tests", function () {
this.skip();
}
account2 = await createTempUser(process.env.DCC_NEW_TMP_EMAIL);
account2 = createTempUser(process.env.CHATMAIL_DOMAIN);
if (!account2 || !account2.email || !account2.password) {
console.log(
"We didn't got back an account2 from the api, skip integration tests"
@@ -148,7 +148,7 @@ describe("online tests", function () {
waitForEvent(dc, "IncomingMsg", accountId1),
]);
dc.rpc.miscSendTextMessage(accountId2, chatId, "super secret message");
// Check if answer arives at A and if it is encrypted
// Check if answer arrives at A and if it is encrypted
await eventPromise2;
const messageId = (
@@ -177,12 +177,12 @@ describe("online tests", function () {
});
});
async function waitForEvent<T extends DcEvent["type"]>(
async function waitForEvent<T extends DcEvent["kind"]>(
dc: DeltaChat,
eventType: T,
accountId: number,
timeout: number = EVENT_TIMEOUT
): Promise<Extract<DcEvent, { type: T }>> {
): Promise<Extract<DcEvent, { kind: T }>> {
return new Promise((resolve, reject) => {
const rejectTimeout = setTimeout(
() => reject(new Error("Timeout reached before event came in")),

View File

@@ -2,7 +2,6 @@ import { tmpdir } from "os";
import { join, resolve } from "path";
import { mkdtemp, rm } from "fs/promises";
import { spawn, exec } from "child_process";
import fetch from "node-fetch";
import { Readable, Writable } from "node:stream";
export type RpcServerHandle = {
@@ -57,15 +56,14 @@ export async function startServer(): Promise<RpcServerHandle> {
};
}
export async function createTempUser(url: string) {
const response = await fetch(url, {
method: "POST",
headers: {
"cache-control": "no-cache",
},
});
if (!response.ok) throw new Error("Received invalid response");
return response.json();
export function createTempUser(chatmailDomain: String) {
const charset = "2345789acdefghjkmnpqrstuvwxyz";
let user = "ci-";
for (let i = 0; i < 6; i++) {
user += charset[Math.floor(Math.random() * charset.length)];
}
const email = user + "@" + chatmailDomain;
return { email: email, password: user + "$" + user };
}
function getTargetDir(): Promise<string> {

View File

@@ -1,6 +1,6 @@
[package]
name = "deltachat-repl"
version = "1.124.1"
version = "1.133.2"
license = "MPL-2.0"
edition = "2021"
@@ -9,10 +9,10 @@ ansi_term = "0.12.1"
anyhow = "1"
deltachat = { path = "..", features = ["internals"]}
dirs = "5"
log = "0.4.19"
log = "0.4.20"
pretty_env_logger = "0.5"
rusqlite = "0.29"
rustyline = "12"
rusqlite = "0.30"
rustyline = "13"
tokio = { version = "1", features = ["fs", "rt-multi-thread", "macros"] }
[features]

View File

@@ -18,6 +18,7 @@ use deltachat::imex::*;
use deltachat::location;
use deltachat::log::LogExt;
use deltachat::message::{self, Message, MessageState, MsgId, Viewtype};
use deltachat::mimeparser::SystemMessage;
use deltachat::peerstate::*;
use deltachat::qr::*;
use deltachat::reaction::send_reaction;
@@ -210,7 +211,17 @@ async fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: &Message) {
} else {
"[FRESH]"
},
if msg.is_info() { "[INFO]" } else { "" },
if msg.is_info() {
if msg.get_info_type() == SystemMessage::ChatProtectionEnabled {
"[INFO 🛡️]"
} else if msg.get_info_type() == SystemMessage::ChatProtectionDisabled {
"[INFO 🛡️❌]"
} else {
"[INFO]"
}
} else {
""
},
if msg.get_viewtype() == Viewtype::VideochatInvitation {
format!(
"[VIDEOCHAT-INVITATION: {}, type={}]",
@@ -273,13 +284,8 @@ async fn log_contactlist(context: &Context, contacts: &[ContactId]) -> Result<()
let contact = Contact::get_by_id(context, *contact_id).await?;
let name = contact.get_display_name();
let addr = contact.get_addr();
let verified_state = contact.is_verified(context).await?;
let verified_str = if VerifiedStatus::Unverified != verified_state {
if verified_state == VerifiedStatus::BidirectVerified {
" √√"
} else {
""
}
let verified_str = if contact.is_verified(context).await? {
""
} else {
""
};
@@ -395,8 +401,6 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
unpin <chat-id>\n\
mute <chat-id> [<seconds>]\n\
unmute <chat-id>\n\
protect <chat-id>\n\
unprotect <chat-id>\n\
delchat <chat-id>\n\
accept <chat-id>\n\
decline <chat-id>\n\
@@ -1071,20 +1075,6 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
};
chat::set_muted(&context, chat_id, duration).await?;
}
"protect" | "unprotect" => {
ensure!(!arg1.is_empty(), "Argument <chat-id> missing.");
let chat_id = ChatId::new(arg1.parse()?);
chat_id
.set_protection(
&context,
match arg0 {
"protect" => ProtectionStatus::Protected,
"unprotect" => ProtectionStatus::Unprotected,
_ => unreachable!("arg0={:?}", arg0),
},
)
.await?;
}
"delchat" => {
ensure!(!arg1.is_empty(), "Argument <chat-id> missing.");
let chat_id = ChatId::new(arg1.parse()?);

View File

@@ -299,8 +299,8 @@ impl Highlighter for DcHelper {
self.highlighter.highlight(line, pos)
}
fn highlight_char(&self, line: &str, pos: usize) -> bool {
self.highlighter.highlight_char(line, pos)
fn highlight_char(&self, line: &str, pos: usize, forced: bool) -> bool {
self.highlighter.highlight_char(line, pos, forced)
}
}
@@ -401,7 +401,7 @@ enum ExitResult {
async fn handle_cmd(
line: &str,
ctx: Context,
mut ctx: Context,
selected_chat: &mut ChatId,
) -> Result<ExitResult, Error> {
let mut args = line.splitn(2, ' ');
@@ -481,7 +481,10 @@ async fn handle_cmd(
#[tokio::main]
async fn main() -> Result<(), Error> {
let _ = pretty_env_logger::try_init();
pretty_env_logger::formatted_timed_builder()
.parse_default_env()
.filter_module("deltachat_repl", log::LevelFilter::Info)
.init();
let args = std::env::args().collect();
start(args).await?;

View File

@@ -25,7 +25,7 @@ $ pip install .
## Testing
1. Build `deltachat-rpc-server` with `cargo build -p deltachat-rpc-server`.
2. Run `PATH="../target/debug:$PATH" tox`.
2. Run `CHATMAIL_DOMAIN=nine.testrun.org PATH="../target/debug:$PATH" tox`.
Additional arguments to `tox` are passed to pytest, e.g. `tox -- -s` does not capture test output.

4
deltachat-rpc-client/examples/echobot_advanced.py Normal file → Executable file
View File

@@ -14,9 +14,9 @@ hooks = events.HookCollection()
@hooks.on(events.RawEvent)
def log_event(event):
if event.type == EventType.INFO:
if event.kind == EventType.INFO:
logging.info(event.msg)
elif event.type == EventType.WARNING:
elif event.kind == EventType.WARNING:
logging.warning(event.msg)

8
deltachat-rpc-client/examples/echobot_no_hooks.py Normal file → Executable file
View File

@@ -40,13 +40,13 @@ def main():
while True:
event = account.wait_for_event()
if event["type"] == EventType.INFO:
if event["kind"] == EventType.INFO:
logging.info("%s", event["msg"])
elif event["type"] == EventType.WARNING:
elif event["kind"] == EventType.WARNING:
logging.warning("%s", event["msg"])
elif event["type"] == EventType.ERROR:
elif event["kind"] == EventType.ERROR:
logging.error("%s", event["msg"])
elif event["type"] == EventType.INCOMING_MSG:
elif event["kind"] == EventType.INCOMING_MSG:
logging.info("Got an incoming message")
process_messages()

View File

@@ -4,7 +4,7 @@ from warnings import warn
from ._utils import AttrDict
from .chat import Chat
from .const import ChatlistFlag, ContactFlag, SpecialContactId
from .const import ChatlistFlag, ContactFlag, EventType, SpecialContactId
from .contact import Contact
from .message import Message
@@ -111,6 +111,20 @@ class Account:
contacts = self._rpc.get_blocked_contacts(self.id)
return [AttrDict(contact=Contact(self, contact["id"]), **contact) for contact in contacts]
def get_chat_by_contact(self, contact: Union[int, Contact]) -> Optional[Chat]:
"""Return 1:1 chat for a contact if it exists."""
if isinstance(contact, Contact):
assert contact.account == self
contact_id = contact.id
elif isinstance(contact, int):
contact_id = contact
else:
raise ValueError(f"{contact!r} is not a contact")
chat_id = self._rpc.get_chat_id_by_contact_id(self.id, contact_id)
if chat_id:
return Chat(self, chat_id)
return None
def get_contacts(
self,
query: Optional[str] = None,
@@ -204,7 +218,7 @@ class Account:
The function returns immediately and the handshake runs in background, sending
and receiving several messages.
Subsequent calls of `secure_join()` will abort previous, unfinished handshakes.
See https://countermitm.readthedocs.io/en/latest/new.html for protocol details.
See https://securejoin.readthedocs.io/en/latest/new.html for protocol details.
:param qrdata: The text of the scanned QR code.
"""
@@ -250,6 +264,25 @@ class Account:
next_msg_ids = self._rpc.wait_next_msgs(self.id)
return [Message(self, msg_id) for msg_id in next_msg_ids]
def wait_for_incoming_msg_event(self):
"""Wait for incoming message event and return it."""
while True:
event = self.wait_for_event()
if event.kind == EventType.INCOMING_MSG:
return event
def wait_for_securejoin_inviter_success(self):
while True:
event = self.wait_for_event()
if event["kind"] == "SecurejoinInviterProgress" and event["progress"] == 1000:
break
def wait_for_securejoin_joiner_success(self):
while True:
event = self.wait_for_event()
if event["kind"] == "SecurejoinJoinerProgress" and event["progress"] == 1000:
break
def get_fresh_messages_in_arrival_order(self) -> List[Message]:
"""Return fresh messages list sorted in the order of their arrival, with ascending IDs."""
warn(
@@ -267,3 +300,13 @@ class Account:
def import_backup(self, path, passphrase: str = "") -> None:
"""Import backup."""
self._rpc.import_backup(self.id, str(path), passphrase)
def export_self_keys(self, path) -> None:
"""Export keys."""
passphrase = "" # Setting passphrase is currently not supported.
self._rpc.export_self_keys(self.id, str(path), passphrase)
def import_self_keys(self, path) -> None:
"""Import keys."""
passphrase = "" # Importing passphrase-protected keys is currently not supported.
self._rpc.import_self_keys(self.id, str(path), passphrase)

View File

@@ -54,14 +54,14 @@ class Chat:
"""
if duration is not None:
assert duration > 0, "Invalid duration"
dur: Union[str, dict] = {"Until": duration}
dur: dict = {"kind": "Until", "duration": duration}
else:
dur = "Forever"
dur = {"kind": "Forever"}
self._rpc.set_chat_mute_duration(self.account.id, self.id, dur)
def unmute(self) -> None:
"""Unmute this chat."""
self._rpc.set_chat_mute_duration(self.account.id, self.id, "NotMuted")
self._rpc.set_chat_mute_duration(self.account.id, self.id, {"kind": "NotMuted"})
def pin(self) -> None:
"""Pin this chat."""
@@ -160,11 +160,12 @@ class Chat:
text: Optional[str] = None,
file: Optional[str] = None,
quoted_msg: Optional[int] = None,
viewtype: Optional[str] = None,
) -> None:
"""Set draft message."""
if isinstance(quoted_msg, Message):
quoted_msg = quoted_msg.id
self._rpc.misc_set_draft(self.account.id, self.id, text, file, quoted_msg)
self._rpc.misc_set_draft(self.account.id, self.id, text, file, quoted_msg, viewtype)
def remove_draft(self) -> None:
"""Remove draft message."""

View File

@@ -3,7 +3,6 @@ import logging
from typing import (
TYPE_CHECKING,
Callable,
Coroutine,
Dict,
Iterable,
Optional,
@@ -92,7 +91,7 @@ class Client:
"""Process events forever."""
self.run_until(lambda _: False)
def run_until(self, func: Callable[[AttrDict], Union[bool, Coroutine]]) -> AttrDict:
def run_until(self, func: Callable[[AttrDict], bool]) -> AttrDict:
"""Process events until the given callable evaluates to True.
The callable should accept an AttrDict object representing the
@@ -105,10 +104,10 @@ class Client:
self._process_messages() # Process old messages.
while True:
event = self.account.wait_for_event()
event["type"] = EventType(event.type)
event["kind"] = EventType(event.kind)
event["account"] = self.account
self._on_event(event)
if event.type == EventType.INCOMING_MSG:
if event.kind == EventType.INCOMING_MSG:
self._process_messages()
stop = func(event)
@@ -196,7 +195,7 @@ class Client:
class Bot(Client):
"""Simple bot implementation that listent to events of a single account."""
"""Simple bot implementation that listens to events of a single account."""
def configure(self, email: str, password: str, **kwargs) -> None:
kwargs.setdefault("bot", "1")

View File

@@ -79,7 +79,7 @@ class RawEvent(EventFilter):
return False
def filter(self, event: "AttrDict") -> bool:
if self.types and event.type not in self.types:
if self.types and event.kind not in self.types:
return False
return self._call_func(event)

View File

@@ -42,6 +42,10 @@ class Message:
return AttrDict(reactions)
return None
def get_sender_contact(self) -> Contact:
from_id = self.get_snapshot().from_id
return self.account.get_contact_by_id(from_id)
def mark_seen(self) -> None:
"""Mark the message as seen."""
self._rpc.markseen_msgs(self.account.id, [self.id])

View File

@@ -1,6 +1,5 @@
import json
import os
import urllib.request
import random
from typing import AsyncGenerator, List, Optional
import pytest
@@ -10,12 +9,11 @@ from .rpc import Rpc
def get_temp_credentials() -> dict:
url = os.getenv("DCC_NEW_TMP_EMAIL")
assert url, "Failed to get online account, DCC_NEW_TMP_EMAIL is not set"
request = urllib.request.Request(url, method="POST")
with urllib.request.urlopen(request, timeout=60) as f:
return json.load(f)
domain = os.getenv("CHATMAIL_DOMAIN")
username = "ci-" + "".join(random.choice("2345789acdefghjkmnpqrstuvwxyz") for i in range(6))
password = f"{username}${username}"
addr = f"{username}@{domain}"
return {"email": addr, "password": password}
class ACFactory:
@@ -23,7 +21,9 @@ class ACFactory:
self.deltachat = deltachat
def get_unconfigured_account(self) -> Account:
return self.deltachat.add_account()
account = self.deltachat.add_account()
account.set_config("verified_one_on_one_chats", "1")
return account
def get_unconfigured_bot(self) -> Bot:
return Bot(self.get_unconfigured_account())
@@ -54,13 +54,23 @@ class ACFactory:
account.start_io()
while True:
event = account.wait_for_event()
if event.type == EventType.IMAP_INBOX_IDLE:
if event.kind == EventType.IMAP_INBOX_IDLE:
break
return account
def get_online_accounts(self, num: int) -> List[Account]:
return [self.get_online_account() for _ in range(num)]
def resetup_account(self, ac: Account) -> Account:
"""Resetup account from scratch, losing the encryption key."""
ac.stop_io()
ac_clone = self.get_unconfigured_account()
for i in ["addr", "mail_pw"]:
ac_clone.set_config(i, ac.get_config(i))
ac.remove()
ac_clone.configure()
return ac_clone
def send_message(
self,
to_account: Account,
@@ -95,7 +105,7 @@ class ACFactory:
group=group,
)
return to_client.run_until(lambda e: e.type == EventType.INCOMING_MSG)
return to_client.run_until(lambda e: e.kind == EventType.INCOMING_MSG)
@pytest.fixture()

View File

@@ -1,3 +1,4 @@
import itertools
import json
import logging
import os
@@ -5,7 +6,7 @@ import subprocess
import sys
from queue import Queue
from threading import Event, Thread
from typing import Any, Dict, Optional
from typing import Any, Dict, Iterator, Optional
class JsonRpcError(Exception):
@@ -23,7 +24,7 @@ class Rpc:
self._kwargs = kwargs
self.process: subprocess.Popen
self.id: int
self.id_iterator: Iterator[int]
self.event_queues: Dict[int, Queue]
# Map from request ID to `threading.Event`.
self.request_events: Dict[int, Event]
@@ -54,7 +55,7 @@ class Rpc:
preexec_fn=os.setpgrp, # noqa: PLW1509
**self._kwargs,
)
self.id = 0
self.id_iterator = itertools.count(start=1)
self.event_queues = {}
self.request_events = {}
self.request_results = {}
@@ -131,7 +132,9 @@ class Rpc:
event = self.get_next_event()
account_id = event["contextId"]
queue = self.get_queue(account_id)
queue.put(event["event"])
event = event["event"]
logging.debug("account_id=%d got an event %s", account_id, event)
queue.put(event)
except Exception:
# Log an exception if the event loop dies.
logging.exception("Exception in the event loop")
@@ -143,14 +146,12 @@ class Rpc:
def __getattr__(self, attr: str):
def method(*args) -> Any:
self.id += 1
request_id = self.id
request_id = next(self.id_iterator)
request = {
"jsonrpc": "2.0",
"method": attr,
"params": args,
"id": self.id,
"id": request_id,
}
event = Event()
self.request_events[request_id] = event

View File

@@ -0,0 +1,566 @@
import logging
import pytest
from deltachat_rpc_client import Chat, SpecialContactId
def test_qr_setup_contact(acfactory, tmp_path) -> None:
alice, bob = acfactory.get_online_accounts(2)
qr_code, _svg = alice.get_qr_code()
bob.secure_join(qr_code)
alice.wait_for_securejoin_inviter_success()
# Test that Alice verified Bob's profile.
alice_contact_bob = alice.get_contact_by_addr(bob.get_config("addr"))
alice_contact_bob_snapshot = alice_contact_bob.get_snapshot()
assert alice_contact_bob_snapshot.is_verified
bob.wait_for_securejoin_joiner_success()
# Test that Bob verified Alice's profile.
bob_contact_alice = bob.get_contact_by_addr(alice.get_config("addr"))
bob_contact_alice_snapshot = bob_contact_alice.get_snapshot()
assert bob_contact_alice_snapshot.is_verified
# Test that if Bob changes the key, backwards verification is lost.
logging.info("Bob 2 is created")
bob2 = acfactory.new_configured_account()
bob2.export_self_keys(tmp_path)
logging.info("Bob imports a key")
bob.import_self_keys(tmp_path / "private-key-default.asc")
assert bob.get_config("key_id") == "2"
bob_contact_alice_snapshot = bob_contact_alice.get_snapshot()
assert not bob_contact_alice_snapshot.is_verified
@pytest.mark.parametrize("protect", [True, False])
def test_qr_securejoin(acfactory, protect):
alice, bob = acfactory.get_online_accounts(2)
logging.info("Alice creates a verified group")
alice_chat = alice.create_group("Verified group", protect=protect)
assert alice_chat.get_basic_snapshot().is_protected == protect
logging.info("Bob joins verified group")
qr_code, _svg = alice_chat.get_qr_code()
bob.secure_join(qr_code)
# Check that at least some of the handshake messages are deleted.
for ac in [alice, bob]:
while True:
event = ac.wait_for_event()
if event["kind"] == "ImapMessageDeleted":
break
alice.wait_for_securejoin_inviter_success()
# Test that Alice verified Bob's profile.
alice_contact_bob = alice.get_contact_by_addr(bob.get_config("addr"))
alice_contact_bob_snapshot = alice_contact_bob.get_snapshot()
assert alice_contact_bob_snapshot.is_verified
bob.wait_for_securejoin_joiner_success()
snapshot = bob.get_message_by_id(bob.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert snapshot.text == "Member Me ({}) added by {}.".format(bob.get_config("addr"), alice.get_config("addr"))
assert snapshot.chat.get_basic_snapshot().is_protected == protect
# Test that Bob verified Alice's profile.
bob_contact_alice = bob.get_contact_by_addr(alice.get_config("addr"))
bob_contact_alice_snapshot = bob_contact_alice.get_snapshot()
assert bob_contact_alice_snapshot.is_verified
def test_qr_securejoin_contact_request(acfactory) -> None:
"""Alice invites Bob to a group when Bob's chat with Alice is in a contact request mode."""
alice, bob = acfactory.get_online_accounts(2)
bob_addr = bob.get_config("addr")
alice_contact_bob = alice.create_contact(bob_addr, "Bob")
alice_chat_bob = alice_contact_bob.create_chat()
alice_chat_bob.send_text("Hello!")
snapshot = bob.get_message_by_id(bob.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert snapshot.text == "Hello!"
bob_chat_alice = snapshot.chat
assert bob_chat_alice.get_basic_snapshot().is_contact_request
alice_chat = alice.create_group("Verified group", protect=True)
logging.info("Bob joins verified group")
qr_code, _svg = alice_chat.get_qr_code()
bob.secure_join(qr_code)
while True:
event = bob.wait_for_event()
if event["kind"] == "SecurejoinJoinerProgress" and event["progress"] == 1000:
break
# Chat stays being a contact request.
assert bob_chat_alice.get_basic_snapshot().is_contact_request
def test_qr_readreceipt(acfactory) -> None:
alice, bob, charlie = acfactory.get_online_accounts(3)
logging.info("Bob and Charlie setup contact with Alice")
qr_code, _svg = alice.get_qr_code()
bob.secure_join(qr_code)
charlie.secure_join(qr_code)
for joiner in [bob, charlie]:
joiner.wait_for_securejoin_joiner_success()
logging.info("Alice creates a verified group")
group = alice.create_group("Group", protect=True)
bob_addr = bob.get_config("addr")
charlie_addr = charlie.get_config("addr")
alice_contact_bob = alice.create_contact(bob_addr, "Bob")
alice_contact_charlie = alice.create_contact(charlie_addr, "Charlie")
group.add_contact(alice_contact_bob)
group.add_contact(alice_contact_charlie)
# Promote a group.
group.send_message(text="Hello")
logging.info("Bob and Charlie receive a group")
bob_msg_id = bob.wait_for_incoming_msg_event().msg_id
bob_message = bob.get_message_by_id(bob_msg_id)
bob_snapshot = bob_message.get_snapshot()
assert bob_snapshot.text == "Hello"
# Charlie receives the same "Hello" message as Bob.
charlie.wait_for_incoming_msg_event()
logging.info("Bob sends a message to the group")
bob_out_message = bob_snapshot.chat.send_message(text="Hi from Bob!")
charlie_msg_id = charlie.wait_for_incoming_msg_event().msg_id
charlie_message = charlie.get_message_by_id(charlie_msg_id)
charlie_snapshot = charlie_message.get_snapshot()
assert charlie_snapshot.text == "Hi from Bob!"
bob_contact_charlie = bob.create_contact(charlie_addr, "Charlie")
assert not bob.get_chat_by_contact(bob_contact_charlie)
logging.info("Charlie reads Bob's message")
charlie_message.mark_seen()
while True:
event = bob.wait_for_event()
if event["kind"] == "MsgRead" and event["msg_id"] == bob_out_message.id:
break
# Receiving a read receipt from Charlie
# should not unblock hidden chat with Charlie for Bob.
assert not bob.get_chat_by_contact(bob_contact_charlie)
def test_verified_group_recovery(acfactory) -> None:
"""Tests verified group recovery by reverifying a member and sending a message in a group."""
ac1, ac2, ac3 = acfactory.get_online_accounts(3)
logging.info("ac1 creates verified group")
chat = ac1.create_group("Verified group", protect=True)
assert chat.get_basic_snapshot().is_protected
logging.info("ac2 joins verified group")
qr_code, _svg = chat.get_qr_code()
ac2.secure_join(qr_code)
ac2.wait_for_securejoin_joiner_success()
# ac1 has ac2 directly verified.
ac1_contact_ac2 = ac1.get_contact_by_addr(ac2.get_config("addr"))
assert ac1_contact_ac2.get_snapshot().verifier_id == SpecialContactId.SELF
logging.info("ac3 joins verified group")
ac3_chat = ac3.secure_join(qr_code)
ac3.wait_for_securejoin_joiner_success()
ac3.wait_for_incoming_msg_event() # Member added
logging.info("ac2 logs in on a new device")
ac2 = acfactory.resetup_account(ac2)
logging.info("ac2 reverifies with ac3")
qr_code, _svg = ac3.get_qr_code()
ac2.secure_join(qr_code)
ac2.wait_for_securejoin_joiner_success()
logging.info("ac3 sends a message to the group")
assert len(ac3_chat.get_contacts()) == 3
ac3_chat.send_text("Hi!")
snapshot = ac1.get_message_by_id(ac1.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert snapshot.text == "Hi!"
msg_id = ac2.wait_for_incoming_msg_event().msg_id
message = ac2.get_message_by_id(msg_id)
snapshot = message.get_snapshot()
assert snapshot.text == "Hi!"
# ac1 contact is verified for ac2 because ac3 gossiped ac1 key in the "Hi!" message.
ac1_contact = ac2.get_contact_by_addr(ac1.get_config("addr"))
assert ac1_contact.get_snapshot().is_verified
# ac2 can write messages to the group.
snapshot.chat.send_text("Works again!")
snapshot = ac3.get_message_by_id(ac3.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert snapshot.text == "Works again!"
snapshot = ac1.get_message_by_id(ac1.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert snapshot.text == "Works again!"
ac1_chat_messages = snapshot.chat.get_messages()
ac2_addr = ac2.get_config("addr")
assert ac1_chat_messages[-2].get_snapshot().text == f"Changed setup for {ac2_addr}"
# ac2 is now verified by ac3 for ac1
ac1_contact_ac3 = ac1.get_contact_by_addr(ac3.get_config("addr"))
assert ac1_contact_ac2.get_snapshot().verifier_id == ac1_contact_ac3.id
def test_verified_group_member_added_recovery(acfactory) -> None:
"""Tests verified group recovery by reverifiying than removing and adding a member back."""
ac1, ac2, ac3 = acfactory.get_online_accounts(3)
logging.info("ac1 creates verified group")
chat = ac1.create_group("Verified group", protect=True)
assert chat.get_basic_snapshot().is_protected
logging.info("ac2 joins verified group")
qr_code, _svg = chat.get_qr_code()
ac2.secure_join(qr_code)
ac2.wait_for_securejoin_joiner_success()
# ac1 has ac2 directly verified.
ac1_contact_ac2 = ac1.get_contact_by_addr(ac2.get_config("addr"))
assert ac1_contact_ac2.get_snapshot().verifier_id == SpecialContactId.SELF
logging.info("ac3 joins verified group")
ac3_chat = ac3.secure_join(qr_code)
ac3.wait_for_securejoin_joiner_success()
ac3.wait_for_incoming_msg_event() # Member added
logging.info("ac2 logs in on a new device")
ac2 = acfactory.resetup_account(ac2)
logging.info("ac2 reverifies with ac3")
qr_code, _svg = ac3.get_qr_code()
ac2.secure_join(qr_code)
ac2.wait_for_securejoin_joiner_success()
logging.info("ac3 sends a message to the group")
assert len(ac3_chat.get_contacts()) == 3
ac3_chat.send_text("Hi!")
msg_id = ac2.wait_for_incoming_msg_event().msg_id
message = ac2.get_message_by_id(msg_id)
snapshot = message.get_snapshot()
logging.info("Received message %s", snapshot.text)
assert snapshot.text == "Hi!"
ac1.wait_for_incoming_msg_event() # Hi!
ac3_contact_ac2 = ac3.get_contact_by_addr(ac2.get_config("addr"))
ac3_chat.remove_contact(ac3_contact_ac2)
ac3_chat.add_contact(ac3_contact_ac2)
msg_id = ac2.wait_for_incoming_msg_event().msg_id
message = ac2.get_message_by_id(msg_id)
snapshot = message.get_snapshot()
assert "removed" in snapshot.text
snapshot = ac1.get_message_by_id(ac1.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert "removed" in snapshot.text
event = ac2.wait_for_incoming_msg_event()
msg_id = event.msg_id
chat_id = event.chat_id
message = ac2.get_message_by_id(msg_id)
snapshot = message.get_snapshot()
logging.info("ac2 got event message: %s", snapshot.text)
assert "added" in snapshot.text
snapshot = ac1.get_message_by_id(ac1.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert "added" in snapshot.text
chat = Chat(ac2, chat_id)
chat.send_text("Works again!")
msg_id = ac3.wait_for_incoming_msg_event().msg_id
message = ac3.get_message_by_id(msg_id)
snapshot = message.get_snapshot()
assert snapshot.text == "Works again!"
snapshot = ac1.get_message_by_id(ac1.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert snapshot.text == "Works again!"
ac1_contact_ac2 = ac1.get_contact_by_addr(ac2.get_config("addr"))
ac1_contact_ac2_snapshot = ac1_contact_ac2.get_snapshot()
assert ac1_contact_ac2_snapshot.is_verified
assert ac1_contact_ac2_snapshot.verifier_id == ac1.get_contact_by_addr(ac3.get_config("addr")).id
# ac2 is now verified by ac3 for ac1
ac1_contact_ac3 = ac1.get_contact_by_addr(ac3.get_config("addr"))
assert ac1_contact_ac2.get_snapshot().verifier_id == ac1_contact_ac3.id
def test_qr_join_chat_with_pending_bobstate_issue4894(acfactory):
"""Regression test for
issue <https://github.com/deltachat/deltachat-core-rust/issues/4894>.
"""
ac1, ac2, ac3, ac4 = acfactory.get_online_accounts(4)
logging.info("ac3: verify with ac2")
qr_code, _svg = ac2.get_qr_code()
ac3.secure_join(qr_code)
ac2.wait_for_securejoin_inviter_success()
# in order for ac2 to have pending bobstate with a verified group
# we first create a fully joined verified group, and then start
# joining a second time but interrupt it, to create pending bob state
logging.info("ac1: create verified group that ac2 fully joins")
ch1 = ac1.create_group("Group", protect=True)
qr_code, _svg = ch1.get_qr_code()
ac2.secure_join(qr_code)
ac1.wait_for_securejoin_inviter_success()
# ensure ac1 can write and ac2 receives messages in verified chat
ch1.send_text("ac1 says hello")
while 1:
snapshot = ac2.get_message_by_id(ac2.wait_for_incoming_msg_event().msg_id).get_snapshot()
if snapshot.text == "ac1 says hello":
assert snapshot.chat.get_basic_snapshot().is_protected
break
logging.info("ac1: let ac2 join again but shutoff ac1 in the middle of securejoin")
qr_code, _svg = ch1.get_qr_code()
ac2.secure_join(qr_code)
ac1.remove()
logging.info("ac2 now has pending bobstate but ac1 is shutoff")
# we meanwhile expect ac3/ac2 verification started in the beginning to have completed
assert ac3.get_contact_by_addr(ac2.get_config("addr")).get_snapshot().is_verified
assert ac2.get_contact_by_addr(ac3.get_config("addr")).get_snapshot().is_verified
logging.info("ac3: create a verified group VG with ac2")
vg = ac3.create_group("ac3-created", protect=True)
vg.add_contact(ac3.get_contact_by_addr(ac2.get_config("addr")))
# ensure ac2 receives message in VG
vg.send_text("hello")
while 1:
msg = ac2.get_message_by_id(ac2.wait_for_incoming_msg_event().msg_id).get_snapshot()
if msg.text == "hello":
assert msg.chat.get_basic_snapshot().is_protected
break
logging.info("ac3: create a join-code for group VG and let ac4 join, check that ac2 got it")
qr_code, _svg = vg.get_qr_code()
ac4.secure_join(qr_code)
ac3.wait_for_securejoin_inviter_success()
while 1:
ev = ac2.wait_for_event()
if "added by unrelated SecureJoin" in str(ev):
return
def test_qr_new_group_unblocked(acfactory):
"""Regression test for a bug introduced in core v1.113.0.
ac2 scans a verified group QR code created by ac1.
This results in creation of a blocked 1:1 chat with ac1 on ac2,
but ac1 contact is not blocked on ac2.
Then ac1 creates a group, adds ac2 there and promotes it by sending a message.
ac2 should receive a message and create a contact request for the group.
Due to a bug previously ac2 created a blocked group.
"""
ac1, ac2 = acfactory.get_online_accounts(2)
ac1_chat = ac1.create_group("Group for joining", protect=True)
qr_code, _svg = ac1_chat.get_qr_code()
ac2.secure_join(qr_code)
ac1.wait_for_securejoin_inviter_success()
ac1_new_chat = ac1.create_group("Another group")
ac1_new_chat.add_contact(ac1.get_contact_by_addr(ac2.get_config("addr")))
# Receive "Member added" message.
ac2.wait_for_incoming_msg_event()
ac1_new_chat.send_text("Hello!")
ac2_msg = ac2.get_message_by_id(ac2.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert ac2_msg.text == "Hello!"
assert ac2_msg.chat.get_basic_snapshot().is_contact_request
def test_aeap_flow_verified(acfactory):
"""Test that a new address is added to a contact when it changes its address."""
ac1, ac2, ac1new = acfactory.get_online_accounts(3)
logging.info("ac1: create verified-group QR, ac2 scans and joins")
chat = ac1.create_group("hello", protect=True)
assert chat.get_basic_snapshot().is_protected
qr_code, _svg = chat.get_qr_code()
logging.info("ac2: start QR-code based join-group protocol")
ac2.secure_join(qr_code)
ac1.wait_for_securejoin_inviter_success()
logging.info("sending first message")
msg_out = chat.send_text("old address").get_snapshot()
logging.info("receiving first message")
ac2.wait_for_incoming_msg_event() # member added message
msg_in_1 = ac2.get_message_by_id(ac2.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert msg_in_1.text == msg_out.text
logging.info("changing email account")
ac1.set_config("addr", ac1new.get_config("addr"))
ac1.set_config("mail_pw", ac1new.get_config("mail_pw"))
ac1.stop_io()
ac1.configure()
ac1.start_io()
logging.info("sending second message")
msg_out = chat.send_text("changed address").get_snapshot()
logging.info("receiving second message")
msg_in_2 = ac2.get_message_by_id(ac2.wait_for_incoming_msg_event().msg_id)
msg_in_2_snapshot = msg_in_2.get_snapshot()
assert msg_in_2_snapshot.text == msg_out.text
assert msg_in_2_snapshot.chat.id == msg_in_1.chat.id
assert msg_in_2.get_sender_contact().get_snapshot().address == ac1new.get_config("addr")
assert len(msg_in_2_snapshot.chat.get_contacts()) == 2
assert ac1new.get_config("addr") in [
contact.get_snapshot().address for contact in msg_in_2_snapshot.chat.get_contacts()
]
def test_gossip_verification(acfactory) -> None:
alice, bob, carol = acfactory.get_online_accounts(3)
# Bob verifies Alice.
qr_code, _svg = alice.get_qr_code()
bob.secure_join(qr_code)
bob.wait_for_securejoin_joiner_success()
# Bob verifies Carol.
qr_code, _svg = carol.get_qr_code()
bob.secure_join(qr_code)
bob.wait_for_securejoin_joiner_success()
bob_contact_alice = bob.create_contact(alice.get_config("addr"), "Alice")
bob_contact_carol = bob.create_contact(carol.get_config("addr"), "Carol")
carol_contact_alice = carol.create_contact(alice.get_config("addr"), "Alice")
logging.info("Bob creates an Autocrypt group")
bob_group_chat = bob.create_group("Autocrypt Group")
assert not bob_group_chat.get_basic_snapshot().is_protected
bob_group_chat.add_contact(bob_contact_alice)
bob_group_chat.add_contact(bob_contact_carol)
bob_group_chat.send_message(text="Hello Autocrypt group")
snapshot = carol.get_message_by_id(carol.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert snapshot.text == "Hello Autocrypt group"
assert snapshot.show_padlock
# Autocrypt group does not propagate verification.
carol_contact_alice_snapshot = carol_contact_alice.get_snapshot()
assert not carol_contact_alice_snapshot.is_verified
logging.info("Bob creates a Securejoin group")
bob_group_chat = bob.create_group("Securejoin Group", protect=True)
assert bob_group_chat.get_basic_snapshot().is_protected
bob_group_chat.add_contact(bob_contact_alice)
bob_group_chat.add_contact(bob_contact_carol)
bob_group_chat.send_message(text="Hello Securejoin group")
snapshot = carol.get_message_by_id(carol.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert snapshot.text == "Hello Securejoin group"
assert snapshot.show_padlock
# Securejoin propagates verification.
carol_contact_alice_snapshot = carol_contact_alice.get_snapshot()
assert carol_contact_alice_snapshot.is_verified
def test_securejoin_after_contact_resetup(acfactory) -> None:
"""
Regression test for a bug that prevented joining verified group with a QR code
if the group is already created and contains
a contact with inconsistent (Autocrypt and verified keys exist but don't match) key state.
"""
ac1, ac2, ac3 = acfactory.get_online_accounts(3)
# ac3 creates protected group with ac1.
ac3_chat = ac3.create_group("Verified group", protect=True)
# ac1 joins ac3 group.
ac3_qr_code, _svg = ac3_chat.get_qr_code()
ac1.secure_join(ac3_qr_code)
ac1.wait_for_securejoin_joiner_success()
# ac1 waits for member added message and creates a QR code.
snapshot = ac1.get_message_by_id(ac1.wait_for_incoming_msg_event().msg_id).get_snapshot()
ac1_qr_code, _svg = snapshot.chat.get_qr_code()
# ac2 verifies ac1
qr_code, _svg = ac1.get_qr_code()
ac2.secure_join(qr_code)
ac2.wait_for_securejoin_joiner_success()
# ac1 is verified for ac2.
ac2_contact_ac1 = ac2.create_contact(ac1.get_config("addr"), "")
assert ac2_contact_ac1.get_snapshot().is_verified
# ac1 resetups the account.
ac1 = acfactory.resetup_account(ac1)
# ac1 sends a message to ac2.
ac1_contact_ac2 = ac1.create_contact(ac2.get_config("addr"), "")
ac1_chat_ac2 = ac1_contact_ac2.create_chat()
ac1_chat_ac2.send_text("Hello!")
# ac2 receives a message.
snapshot = ac2.get_message_by_id(ac2.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert snapshot.text == "Hello!"
# ac1 is no longer verified for ac2 as new Autocrypt key is not the same as old verified key.
assert not ac2_contact_ac1.get_snapshot().is_verified
# ac1 goes offline.
ac1.remove()
# Scanning a QR code results in creating an unprotected group with an inviter.
# In this case inviter is ac1 which has an inconsistent key state.
# Normally inviter becomes verified as a result of Securejoin protocol
# and then the group chat becomes verified when "Member added" is received,
# but in this case ac1 is offline and this Securejoin process will never finish.
logging.info("ac2 scans ac1 QR code, this is not expected to finish")
ac2.secure_join(ac1_qr_code)
logging.info("ac2 scans ac3 QR code")
ac2.secure_join(ac3_qr_code)
logging.info("ac2 waits for joiner success")
ac2.wait_for_securejoin_joiner_success()
# Wait for member added.
logging.info("ac2 waits for member added message")
snapshot = ac2.get_message_by_id(ac2.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert snapshot.is_info
ac2_chat = snapshot.chat
assert ac2_chat.get_basic_snapshot().is_protected
assert len(ac2_chat.get_contacts()) == 3
# ac1 is still "not verified" for ac2 due to inconsistent state.
assert not ac2_contact_ac1.get_snapshot().is_verified

View File

@@ -1,4 +1,6 @@
import concurrent.futures
import json
import subprocess
from unittest.mock import MagicMock
import pytest
@@ -42,7 +44,7 @@ def test_acfactory(acfactory) -> None:
account = acfactory.new_configured_account()
while True:
event = account.wait_for_event()
if event.type == EventType.CONFIGURE_PROGRESS:
if event.kind == EventType.CONFIGURE_PROGRESS:
assert event.progress != 0 # Progress 0 indicates error.
if event.progress == 1000: # Success
break
@@ -71,7 +73,7 @@ def test_account(acfactory) -> None:
while True:
event = bob.wait_for_event()
if event.type == EventType.INCOMING_MSG:
if event.kind == EventType.INCOMING_MSG:
chat_id = event.chat_id
msg_id = event.msg_id
break
@@ -138,12 +140,9 @@ def test_chat(acfactory) -> None:
alice_chat_bob = alice_contact_bob.create_chat()
alice_chat_bob.send_text("Hello!")
while True:
event = bob.wait_for_event()
if event.type == EventType.INCOMING_MSG:
chat_id = event.chat_id
msg_id = event.msg_id
break
event = bob.wait_for_incoming_msg_event()
chat_id = event.chat_id
msg_id = event.msg_id
message = bob.get_message_by_id(msg_id)
snapshot = message.get_snapshot()
assert snapshot.chat_id == chat_id
@@ -222,12 +221,9 @@ def test_message(acfactory) -> None:
alice_chat_bob = alice_contact_bob.create_chat()
alice_chat_bob.send_text("Hello!")
while True:
event = bob.wait_for_event()
if event.type == EventType.INCOMING_MSG:
chat_id = event.chat_id
msg_id = event.msg_id
break
event = bob.wait_for_incoming_msg_event()
chat_id = event.chat_id
msg_id = event.msg_id
message = bob.get_message_by_id(msg_id)
snapshot = message.get_snapshot()
@@ -263,7 +259,7 @@ def test_is_bot(acfactory) -> None:
while True:
event = bob.wait_for_event()
if event.type == EventType.INCOMING_MSG:
if event.kind == EventType.INCOMING_MSG:
msg_id = event.msg_id
message = bob.get_message_by_id(msg_id)
snapshot = message.get_snapshot()
@@ -329,7 +325,7 @@ def test_wait_next_messages(acfactory) -> None:
next_messages_task = executor.submit(bot.wait_next_messages)
bot_addr = bot.get_config("addr")
alice_contact_bot = alice.create_contact(bot_addr, "Bob")
alice_contact_bot = alice.create_contact(bot_addr, "Bot")
alice_chat_bot = alice_contact_bot.create_chat()
alice_chat_bot.send_text("Hello!")
@@ -339,10 +335,107 @@ def test_wait_next_messages(acfactory) -> None:
assert snapshot.text == "Hello!"
def test_import_export(acfactory, tmp_path) -> None:
def test_import_export_backup(acfactory, tmp_path) -> None:
alice = acfactory.new_configured_account()
alice.export_backup(tmp_path)
files = list(tmp_path.glob("*.tar"))
alice2 = acfactory.get_unconfigured_account()
alice2.import_backup(files[0])
assert alice2.manager.get_system_info()
def test_import_export_keys(acfactory, tmp_path) -> None:
alice, bob = acfactory.get_online_accounts(2)
bob_addr = bob.get_config("addr")
alice_contact_bob = alice.create_contact(bob_addr, "Bob")
alice_chat_bob = alice_contact_bob.create_chat()
alice_chat_bob.send_text("Hello Bob!")
snapshot = bob.get_message_by_id(bob.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert snapshot.text == "Hello Bob!"
# Alice resetups account, but keeps the key.
alice_keys_path = tmp_path / "alice_keys"
alice_keys_path.mkdir()
alice.export_self_keys(alice_keys_path)
alice = acfactory.resetup_account(alice)
alice.import_self_keys(alice_keys_path)
snapshot.chat.accept()
snapshot.chat.send_text("Hello Alice!")
snapshot = alice.get_message_by_id(alice.wait_for_incoming_msg_event().msg_id).get_snapshot()
assert snapshot.text == "Hello Alice!"
assert snapshot.show_padlock
def test_openrpc_command_line() -> None:
"""Test that "deltachat-rpc-server --openrpc" command returns an OpenRPC specification."""
out = subprocess.run(["deltachat-rpc-server", "--openrpc"], capture_output=True, check=True).stdout
openrpc = json.loads(out)
assert "openrpc" in openrpc
assert "methods" in openrpc
def test_provider_info(rpc) -> None:
account_id = rpc.add_account()
provider_info = rpc.get_provider_info(account_id, "example.org")
assert provider_info["id"] == "example.com"
provider_info = rpc.get_provider_info(account_id, "uep7oiw4ahtaizuloith.org")
assert provider_info is None
# Test MX record resolution.
provider_info = rpc.get_provider_info(account_id, "github.com")
assert provider_info["id"] == "gmail"
# Disable MX record resolution.
rpc.set_config(account_id, "socks5_enabled", "1")
provider_info = rpc.get_provider_info(account_id, "github.com")
assert provider_info is None
def test_mdn_doesnt_break_autocrypt(acfactory) -> None:
alice, bob = acfactory.get_online_accounts(2)
bob_addr = bob.get_config("addr")
alice_contact_bob = alice.create_contact(bob_addr, "Bob")
# Bob creates chat manually so chat with Alice is accepted.
alice_chat_bob = alice_contact_bob.create_chat()
# Alice sends a message to Bob.
alice_chat_bob.send_text("Hello Bob!")
event = bob.wait_for_incoming_msg_event()
msg_id = event.msg_id
message = bob.get_message_by_id(msg_id)
snapshot = message.get_snapshot()
# Bob sends a message to Alice.
bob_chat_alice = snapshot.chat
bob_chat_alice.accept()
bob_chat_alice.send_text("Hello Alice!")
event = alice.wait_for_incoming_msg_event()
msg_id = event.msg_id
message = alice.get_message_by_id(msg_id)
snapshot = message.get_snapshot()
assert snapshot.show_padlock
# Alice reads Bob's message.
message.mark_seen()
while True:
event = bob.wait_for_event()
if event.kind == EventType.MSG_READ:
break
# Bob sends a message to Alice, it should also be encrypted.
bob_chat_alice.send_text("Hi Alice!")
event = alice.wait_for_incoming_msg_event()
msg_id = event.msg_id
message = alice.get_message_by_id(msg_id)
snapshot = message.get_snapshot()
assert snapshot.show_padlock

View File

@@ -11,7 +11,7 @@ def test_webxdc(acfactory) -> None:
while True:
event = bob.wait_for_event()
if event.type == EventType.INCOMING_MSG:
if event.kind == EventType.INCOMING_MSG:
bob_chat_alice = bob.get_chat_by_id(event.chat_id)
message = bob.get_message_by_id(event.msg_id)
break
@@ -43,3 +43,15 @@ def test_webxdc(acfactory) -> None:
assert status_updates == [
{"payload": "Second update", "serial": 2, "max_serial": 2},
]
def test_webxdc_insert_lots_of_updates(acfactory) -> None:
alice, bob = acfactory.get_online_accounts(2)
bob_addr = bob.get_config("addr")
alice_contact_bob = alice.create_contact(bob_addr, "Bob")
alice_chat_bob = alice_contact_bob.create_chat()
message = alice_chat_bob.send_message(text="Let's play chess!", file="../test-data/webxdc/chess.xdc")
for i in range(2000):
message.send_webxdc_status_update({"payload": str(i)}, "description")

View File

@@ -11,7 +11,7 @@ setenv =
# Avoid stack overflow when Rust core is built without optimizations.
RUST_MIN_STACK=8388608
passenv =
DCC_NEW_TMP_EMAIL
CHATMAIL_DOMAIN
deps =
pytest
pytest-timeout
@@ -28,4 +28,6 @@ commands =
ruff src/ examples/ tests/
[pytest]
timeout = 60
timeout = 300
log_cli = true
log_level = debug

View File

@@ -1,6 +1,6 @@
[package]
name = "deltachat-rpc-server"
version = "1.124.1"
version = "1.133.2"
description = "DeltaChat JSON-RPC server"
edition = "2021"
readme = "README.md"
@@ -15,13 +15,13 @@ deltachat = { path = "..", default-features = false }
anyhow = "1"
env_logger = { version = "0.10.0" }
futures-lite = "1.13.0"
futures-lite = "2.0.0"
log = "0.4"
serde_json = "1.0.99"
serde_json = "1"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.29.1", features = ["io-std"] }
tokio-util = "0.7.8"
yerpc = { version = "0.5.1", features = ["anyhow_expose"] }
tokio = { version = "1.33.0", features = ["io-std"] }
tokio-util = "0.7.9"
yerpc = { version = "0.5.2", features = ["anyhow_expose", "openrpc"] }
[features]
default = ["vendored"]

View File

@@ -32,3 +32,6 @@ languages other than Rust, for example:
1. Python: https://github.com/deltachat/deltachat-core-rust/tree/master/deltachat-rpc-client/
2. Go: https://github.com/deltachat/deltachat-rpc-client-go/
Run `deltachat-rpc-server --version` to check the version of the server.
Run `deltachat-rpc-server --openrpc` to get [OpenRPC](https://open-rpc.org/) specification of the provided JSON-RPC API.

View File

@@ -10,6 +10,7 @@ use deltachat::constants::DC_VERSION_STR;
use deltachat_jsonrpc::api::{Accounts, CommandApi};
use futures_lite::stream::StreamExt;
use tokio::io::{self, AsyncBufReadExt, BufReader};
use yerpc::RpcServer as _;
#[cfg(target_family = "unix")]
use tokio::signal::unix as signal_unix;
@@ -39,6 +40,12 @@ async fn main_impl() -> Result<()> {
}
eprintln!("{}", &*DC_VERSION_STR);
return Ok(());
} else if first_arg.to_str() == Some("--openrpc") {
if let Some(arg) = args.next() {
return Err(anyhow!("Unrecognized argument {:?}", arg));
}
println!("{}", CommandApi::openrpc_specification()?);
return Ok(());
} else {
return Err(anyhow!("Unrecognized option {:?}", first_arg));
}
@@ -56,7 +63,8 @@ async fn main_impl() -> Result<()> {
let path = std::env::var("DC_ACCOUNTS_PATH").unwrap_or_else(|_| "accounts".to_string());
log::info!("Starting with accounts directory `{}`.", path);
let accounts = Accounts::new(PathBuf::from(&path)).await?;
let writable = true;
let accounts = Accounts::new(PathBuf::from(&path), writable).await?;
log::info!("Creating JSON-RPC API.");
let accounts = Arc::new(RwLock::new(accounts));

View File

@@ -3,6 +3,13 @@ unmaintained = "allow"
ignore = [
"RUSTSEC-2020-0071",
"RUSTSEC-2022-0093",
# Timing attack on RSA.
# Delta Chat does not use RSA for new keys
# and this requires precise measurement of the decryption time by the attacker.
# There is no fix at the time of writing this (2023-11-28).
# <https://rustsec.org/advisories/RUSTSEC-2023-0071>
"RUSTSEC-2023-0071",
]
[bans]
@@ -11,7 +18,7 @@ ignore = [
# when upgrading.
# Please keep this list alphabetically sorted.
skip = [
{ name = "ahash", version = "0.7.6" },
{ name = "async-channel", version = "1.9.0" },
{ name = "base16ct", version = "0.1.1" },
{ name = "base64", version = "<0.21" },
{ name = "bitflags", version = "1.3.2" },
@@ -25,41 +32,42 @@ skip = [
{ name = "digest", version = "<0.10" },
{ name = "ed25519-dalek", version = "1.0.1" },
{ name = "ed25519", version = "1.5.3" },
{ name = "event-listener", version = "2.5.3" },
{ name = "getrandom", version = "<0.2" },
{ name = "hashbrown", version = "<0.14.0" },
{ name = "idna", version = "<0.3" },
{ name = "indexmap", version = "<2.0.0" },
{ name = "linux-raw-sys", version = "0.3.8" },
{ name = "num-derive", version = "0.3.3" },
{ name = "h2", version = "0.3.22" },
{ name = "http-body", version = "0.4.5" },
{ name = "http", version = "0.2.11" },
{ name = "hyper", version = "0.14.27" },
{ name = "idna", version = "0.4.0" },
{ name = "pem-rfc7468", version = "0.6.0" },
{ name = "pkcs8", version = "0.9.0" },
{ name = "quick-error", version = "<2.0" },
{ name = "rand_chacha", version = "<0.3" },
{ name = "rand_core", version = "<0.6" },
{ name = "rand", version = "<0.8" },
{ name = "redox_syscall", version = "0.2.16" },
{ name = "redox_syscall", version = "0.3.5" },
{ name = "regex-automata", version = "0.1.10" },
{ name = "regex-syntax", version = "0.6.29" },
{ name = "rustix", version = "0.37.21" },
{ name = "ring", version = "0.16.20" },
{ name = "sec1", version = "0.3.0" },
{ name = "sha2", version = "<0.10" },
{ name = "signature", version = "1.6.4" },
{ name = "socket2", version = "0.4.9" },
{ name = "spin", version = "<0.9.6" },
{ name = "spki", version = "0.6.0" },
{ name = "syn", version = "1.0.109" },
{ name = "time", version = "<0.3" },
{ name = "untrusted", version = "0.7.1" },
{ name = "wasi", version = "<0.11" },
{ name = "windows_aarch64_gnullvm", version = "<0.48" },
{ name = "windows_aarch64_msvc", version = "<0.48" },
{ name = "windows_i686_gnu", version = "<0.48" },
{ name = "windows_i686_msvc", version = "<0.48" },
{ name = "windows-sys", version = "<0.48" },
{ name = "windows-targets", version = "<0.48" },
{ name = "windows_x86_64_gnullvm", version = "<0.48" },
{ name = "windows_aarch64_gnullvm", version = "<0.52" },
{ name = "windows_aarch64_msvc", version = "<0.52" },
{ name = "windows_i686_gnu", version = "<0.52" },
{ name = "windows_i686_msvc", version = "<0.52" },
{ name = "windows-sys", version = "<0.52" },
{ name = "windows-targets", version = "<0.52" },
{ name = "windows", version = "0.32.0" },
{ name = "windows_x86_64_gnu", version = "<0.48" },
{ name = "windows_x86_64_msvc", version = "<0.48" },
{ name = "winreg", version = "0.10.1" },
{ name = "windows_x86_64_gnullvm", version = "<0.52" },
{ name = "windows_x86_64_gnu", version = "<0.52" },
{ name = "windows_x86_64_msvc", version = "<0.52" },
]
@@ -91,5 +99,5 @@ license-files = [
github = [
"async-email",
"deltachat",
"quinn-rs",
"djc",
]

View File

@@ -57,7 +57,7 @@ Note that usually a mail is signed by a key that has a UID matching the from add
### Notes:
- We treat protected and non-protected chats the same
- We leave the aeap transition statement away since it seems not to be needed, makes things harder on the sending side, wastes some network traffic, and is worse for privacy (since more pepole know what old addresses you had).
- We leave the aeap transition statement away since it seems not to be needed, makes things harder on the sending side, wastes some network traffic, and is worse for privacy (since more people know what old addresses you had).
- As soon as we encrypt read receipts, sending a read receipt will be enough to tell a lot of people that you transitioned
- AEAP will make the problem of inconsistent group state worse, both because it doesn't work if the message is unencrypted (even if the design allowed it, it would be problematic security-wise) and because some chat partners may have gotten the transition and some not. We should do something against this at some point in the future, like asking the user whether they want to add/remove the members to restore consistent group state.
@@ -108,7 +108,7 @@ The most obvious alternative would be to create a new contact with the new addre
#### Upsides:
- With this approach, it's easier to switch to a model where the info about the transition is encoded in the PGP key. Since the key is gossiped, the information about the transition will spread virally.
- (Also, less important: Slightly faster transition: If you send a message to e.g. "Delta Chat Dev", all members of the "sub-group" "delta android" will know of your transition.)
- It's easier to implement (if too many problems turn up, we can still switch to another approach and didn't wast that much development time.)
- It's easier to implement (if too many problems turn up, we can still switch to another approach and didn't waste that much development time.)
[full messages](https://github.com/deltachat/deltachat-core-rust/pull/2896#discussion_r852002161)

View File

@@ -1,100 +0,0 @@
use deltachat::chat::{self, ChatId};
use deltachat::chatlist::*;
use deltachat::config;
use deltachat::contact::*;
use deltachat::context::*;
use deltachat::message::Message;
use deltachat::stock_str::StockStrings;
use deltachat::{EventType, Events};
use tempfile::tempdir;
fn cb(event: EventType) {
match event {
EventType::ConfigureProgress { progress, .. } => {
log::info!("progress: {}", progress);
}
EventType::Info(msg) => {
log::info!("{}", msg);
}
EventType::Warning(msg) => {
log::warn!("{}", msg);
}
EventType::Error(msg) => {
log::error!("{}", msg);
}
event => {
log::info!("{:?}", event);
}
}
}
/// Run with `RUST_LOG=simple=info cargo run --release --example simple -- email pw`.
#[tokio::main]
async fn main() {
pretty_env_logger::try_init_timed().ok();
let dir = tempdir().unwrap();
let dbfile = dir.path().join("db.sqlite");
log::info!("creating database {:?}", dbfile);
let ctx = Context::new(&dbfile, 0, Events::new(), StockStrings::new())
.await
.expect("Failed to create context");
let info = ctx.get_info().await;
log::info!("info: {:#?}", info);
let events = ctx.get_event_emitter();
let events_spawn = tokio::task::spawn(async move {
while let Some(event) = events.recv().await {
cb(event.typ);
}
});
log::info!("configuring");
let args = std::env::args().collect::<Vec<String>>();
assert_eq!(args.len(), 3, "requires email password");
let email = args[1].clone();
let pw = args[2].clone();
ctx.set_config(config::Config::Addr, Some(&email))
.await
.unwrap();
ctx.set_config(config::Config::MailPw, Some(&pw))
.await
.unwrap();
ctx.configure().await.unwrap();
log::info!("------ RUN ------");
ctx.start_io().await;
log::info!("--- SENDING A MESSAGE ---");
let contact_id = Contact::create(&ctx, "dignifiedquire", "dignifiedquire@gmail.com")
.await
.unwrap();
let chat_id = ChatId::create_for_contact(&ctx, contact_id).await.unwrap();
for i in 0..1 {
log::info!("sending message {}", i);
chat::send_text_msg(&ctx, chat_id, format!("Hi, here is my {i}nth message!"))
.await
.unwrap();
}
// wait for the message to be sent out
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
log::info!("fetching chats..");
let chats = Chatlist::try_load(&ctx, 0, None, None).await.unwrap();
for i in 0..chats.len() {
let msg = Message::load_from_db(&ctx, chats.get_msg_id(i).unwrap().unwrap())
.await
.unwrap();
log::info!("[{}] msg: {:?}", i, msg);
}
log::info!("stopping");
ctx.stop_io().await;
log::info!("closing");
drop(ctx);
events_spawn.await.unwrap();
}

827
fuzz/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -40,7 +40,7 @@ npm install deltachat-node
## Dependencies
- Nodejs >= `v16.0.0`
- Nodejs >= `v18.0.0`
- rustup (optional if you can't use the prebuilds)
> On Windows, you may need to also install **Perl** to be able to compile deltachat-core.
@@ -113,8 +113,8 @@ Then, in the `deltachat-desktop` repository, run:
deltachat doesn't support universal (fat) binaries (that contain builds for both cpu architectures) yet, until it does you can use the following workaround to get x86_64 builds:
```
$ fnm install 17 --arch x64
$ fnm use 17
$ fnm install 19 --arch x64
$ fnm use 19
$ node -p process.arch
# result should be x64
$ rustup target add x86_64-apple-darwin
@@ -127,8 +127,8 @@ $ npm run test
If your node and electron are already build for arm64 you can also try building for arm:
```
$ fnm install 16 --arch arm64
$ fnm use 16
$ fnm install 18 --arch arm64
$ fnm use 18
$ node -p process.arch
# result should be arm64
$ npm_config_arch=arm64 npm run build
@@ -204,10 +204,10 @@ Running `npm test` ends with showing a code coverage report, which is produced b
The coverage report from `nyc` in the console is rather limited. To get a more detailed coverage report you can run `npm run coverage-html-report`. This will produce a html report from the `nyc` data and display it in a browser on your local machine.
To run the integration tests you need to set the `DCC_NEW_TMP_EMAIL` environment variables. E.g.:
To run the integration tests you need to set the `CHATMAIL_DOMAIN` environment variables. E.g.:
```
$ export DCC_NEW_TMP_EMAIL=https://testrun.org/new_email?t=[token]
$ export CHATMAIL_DOMAIN=chat.example.org
$ npm run test
```

View File

@@ -28,9 +28,11 @@ module.exports = {
DC_DOWNLOAD_DONE: 0,
DC_DOWNLOAD_FAILURE: 20,
DC_DOWNLOAD_IN_PROGRESS: 1000,
DC_DOWNLOAD_UNDECIPHERABLE: 30,
DC_EVENT_CHAT_EPHEMERAL_TIMER_MODIFIED: 2021,
DC_EVENT_CHAT_MODIFIED: 2020,
DC_EVENT_CONFIGURE_PROGRESS: 2041,
DC_EVENT_CONFIG_SYNCED: 2111,
DC_EVENT_CONNECTIVITY_CHANGED: 2100,
DC_EVENT_CONTACTS_CHANGED: 2030,
DC_EVENT_DELETED_BLOB_FILE: 151,
@@ -78,6 +80,7 @@ module.exports = {
DC_INFO_EPHEMERAL_TIMER_CHANGED: 10,
DC_INFO_GROUP_IMAGE_CHANGED: 3,
DC_INFO_GROUP_NAME_CHANGED: 2,
DC_INFO_INVALID_UNENCRYPTED_MAIL: 13,
DC_INFO_LOCATIONSTREAMING_ENABLED: 8,
DC_INFO_LOCATION_ONLY: 9,
DC_INFO_MEMBER_ADDED_TO_GROUP: 4,
@@ -159,6 +162,8 @@ module.exports = {
DC_STR_BROADCAST_LIST: 115,
DC_STR_CANNOT_LOGIN: 60,
DC_STR_CANTDECRYPT_MSG_BODY: 29,
DC_STR_CHAT_PROTECTION_DISABLED: 171,
DC_STR_CHAT_PROTECTION_ENABLED: 170,
DC_STR_CONFIGURATION_FAILED: 84,
DC_STR_CONNECTED: 107,
DC_STR_CONNTECTING: 108,
@@ -222,11 +227,13 @@ module.exports = {
DC_STR_GROUP_NAME_CHANGED_BY_YOU: 124,
DC_STR_IMAGE: 9,
DC_STR_INCOMING_MESSAGES: 103,
DC_STR_INVALID_UNENCRYPTED_MAIL: 174,
DC_STR_LAST_MSG_SENT_SUCCESSFULLY: 111,
DC_STR_LOCATION: 66,
DC_STR_LOCATION_ENABLED_BY_OTHER: 137,
DC_STR_LOCATION_ENABLED_BY_YOU: 136,
DC_STR_MESSAGES: 114,
DC_STR_MESSAGE_ADD_MEMBER: 173,
DC_STR_MSGACTIONBYME: 63,
DC_STR_MSGACTIONBYUSER: 62,
DC_STR_MSGADDMEMBER: 17,
@@ -237,6 +244,7 @@ module.exports = {
DC_STR_MSGGRPNAME: 15,
DC_STR_MSGLOCATIONDISABLED: 65,
DC_STR_MSGLOCATIONENABLED: 64,
DC_STR_NEW_GROUP_SEND_FIRST_MESSAGE: 172,
DC_STR_NOMESSAGES: 1,
DC_STR_NOT_CONNECTED: 121,
DC_STR_NOT_SUPPORTED_BY_PROVIDER: 113,
@@ -244,12 +252,6 @@ module.exports = {
DC_STR_OUTGOING_MESSAGES: 104,
DC_STR_PARTIAL_DOWNLOAD_MSG_BODY: 99,
DC_STR_PART_OF_TOTAL_USED: 116,
DC_STR_PROTECTION_DISABLED: 89,
DC_STR_PROTECTION_DISABLED_BY_OTHER: 161,
DC_STR_PROTECTION_DISABLED_BY_YOU: 160,
DC_STR_PROTECTION_ENABLED: 88,
DC_STR_PROTECTION_ENABLED_BY_OTHER: 159,
DC_STR_PROTECTION_ENABLED_BY_YOU: 158,
DC_STR_QUOTA_EXCEEDING_MSG_BODY: 98,
DC_STR_READRCPT: 31,
DC_STR_READRCPT_MAILBODY: 32,

View File

@@ -34,6 +34,7 @@ module.exports = {
2061: 'DC_EVENT_SECUREJOIN_JOINER_PROGRESS',
2100: 'DC_EVENT_CONNECTIVITY_CHANGED',
2110: 'DC_EVENT_SELFAVATAR_CHANGED',
2111: 'DC_EVENT_CONFIG_SYNCED',
2120: 'DC_EVENT_WEBXDC_STATUS_UPDATE',
2121: 'DC_EVENT_WEBXDC_INSTANCE_DELETED'
}

View File

@@ -28,9 +28,11 @@ export enum C {
DC_DOWNLOAD_DONE = 0,
DC_DOWNLOAD_FAILURE = 20,
DC_DOWNLOAD_IN_PROGRESS = 1000,
DC_DOWNLOAD_UNDECIPHERABLE = 30,
DC_EVENT_CHAT_EPHEMERAL_TIMER_MODIFIED = 2021,
DC_EVENT_CHAT_MODIFIED = 2020,
DC_EVENT_CONFIGURE_PROGRESS = 2041,
DC_EVENT_CONFIG_SYNCED = 2111,
DC_EVENT_CONNECTIVITY_CHANGED = 2100,
DC_EVENT_CONTACTS_CHANGED = 2030,
DC_EVENT_DELETED_BLOB_FILE = 151,
@@ -78,6 +80,7 @@ export enum C {
DC_INFO_EPHEMERAL_TIMER_CHANGED = 10,
DC_INFO_GROUP_IMAGE_CHANGED = 3,
DC_INFO_GROUP_NAME_CHANGED = 2,
DC_INFO_INVALID_UNENCRYPTED_MAIL = 13,
DC_INFO_LOCATIONSTREAMING_ENABLED = 8,
DC_INFO_LOCATION_ONLY = 9,
DC_INFO_MEMBER_ADDED_TO_GROUP = 4,
@@ -159,6 +162,8 @@ export enum C {
DC_STR_BROADCAST_LIST = 115,
DC_STR_CANNOT_LOGIN = 60,
DC_STR_CANTDECRYPT_MSG_BODY = 29,
DC_STR_CHAT_PROTECTION_DISABLED = 171,
DC_STR_CHAT_PROTECTION_ENABLED = 170,
DC_STR_CONFIGURATION_FAILED = 84,
DC_STR_CONNECTED = 107,
DC_STR_CONNTECTING = 108,
@@ -222,11 +227,13 @@ export enum C {
DC_STR_GROUP_NAME_CHANGED_BY_YOU = 124,
DC_STR_IMAGE = 9,
DC_STR_INCOMING_MESSAGES = 103,
DC_STR_INVALID_UNENCRYPTED_MAIL = 174,
DC_STR_LAST_MSG_SENT_SUCCESSFULLY = 111,
DC_STR_LOCATION = 66,
DC_STR_LOCATION_ENABLED_BY_OTHER = 137,
DC_STR_LOCATION_ENABLED_BY_YOU = 136,
DC_STR_MESSAGES = 114,
DC_STR_MESSAGE_ADD_MEMBER = 173,
DC_STR_MSGACTIONBYME = 63,
DC_STR_MSGACTIONBYUSER = 62,
DC_STR_MSGADDMEMBER = 17,
@@ -237,6 +244,7 @@ export enum C {
DC_STR_MSGGRPNAME = 15,
DC_STR_MSGLOCATIONDISABLED = 65,
DC_STR_MSGLOCATIONENABLED = 64,
DC_STR_NEW_GROUP_SEND_FIRST_MESSAGE = 172,
DC_STR_NOMESSAGES = 1,
DC_STR_NOT_CONNECTED = 121,
DC_STR_NOT_SUPPORTED_BY_PROVIDER = 113,
@@ -244,12 +252,6 @@ export enum C {
DC_STR_OUTGOING_MESSAGES = 104,
DC_STR_PARTIAL_DOWNLOAD_MSG_BODY = 99,
DC_STR_PART_OF_TOTAL_USED = 116,
DC_STR_PROTECTION_DISABLED = 89,
DC_STR_PROTECTION_DISABLED_BY_OTHER = 161,
DC_STR_PROTECTION_DISABLED_BY_YOU = 160,
DC_STR_PROTECTION_ENABLED = 88,
DC_STR_PROTECTION_ENABLED_BY_OTHER = 159,
DC_STR_PROTECTION_ENABLED_BY_YOU = 158,
DC_STR_QUOTA_EXCEEDING_MSG_BODY = 98,
DC_STR_READRCPT = 31,
DC_STR_READRCPT_MAILBODY = 32,
@@ -321,6 +323,7 @@ export const EventId2EventName: { [key: number]: string } = {
2061: 'DC_EVENT_SECUREJOIN_JOINER_PROGRESS',
2100: 'DC_EVENT_CONNECTIVITY_CHANGED',
2110: 'DC_EVENT_SELFAVATAR_CHANGED',
2111: 'DC_EVENT_CONFIG_SYNCED',
2120: 'DC_EVENT_WEBXDC_STATUS_UPDATE',
2121: 'DC_EVENT_WEBXDC_INSTANCE_DELETED',
}

View File

@@ -36,7 +36,7 @@ export class Context extends EventEmitter {
}
}
/** Opens a stanalone context (without an account manager)
/** Opens a standalone context (without an account manager)
* automatically starts the event handler */
static open(cwd: string): Context {
const dbFile = join(cwd, 'db.sqlite')
@@ -699,23 +699,6 @@ export class Context extends EventEmitter {
)
}
/**
*
* @param chatId
* @param protect
* @returns success boolean
*/
setChatProtection(chatId: number, protect: boolean) {
debug(`setChatProtection ${chatId} ${protect}`)
return Boolean(
binding.dcn_set_chat_protection(
this.dcn_context,
Number(chatId),
protect ? 1 : 0
)
)
}
getChatEphemeralTimer(chatId: number): number {
debug(`getChatEphemeralTimer ${chatId}`)
return binding.dcn_get_chat_ephemeral_timer(

View File

@@ -21,12 +21,15 @@ export class AccountManager extends EventEmitter {
accountDir: string
jsonRpcStarted = false
constructor(cwd: string, os = 'deltachat-node') {
constructor(cwd: string, writable = true) {
super()
debug('DeltaChat constructor')
this.accountDir = cwd
this.dcn_accounts = binding.dcn_accounts_new(os, this.accountDir)
this.dcn_accounts = binding.dcn_accounts_new(
this.accountDir,
writable ? 1 : 0
)
}
getAllAccountIds() {
@@ -175,7 +178,7 @@ export class AccountManager extends EventEmitter {
static newTemporary() {
let directory = null
while (true) {
const randomString = Math.random().toString(36).substr(2, 5)
const randomString = Math.random().toString(36).substring(2, 5)
directory = join(tmpdir(), 'deltachat-' + randomString)
if (!existsSync(directory)) break
}

View File

@@ -1399,18 +1399,6 @@ NAPI_METHOD(dcn_set_chat_name) {
NAPI_RETURN_INT32(result);
}
NAPI_METHOD(dcn_set_chat_protection) {
NAPI_ARGV(3);
NAPI_DCN_CONTEXT();
NAPI_ARGV_UINT32(chat_id, 1);
NAPI_ARGV_INT32(protect, 1);
int result = dc_set_chat_protection(dcn_context->dc_context,
chat_id,
protect);
NAPI_RETURN_INT32(result);
}
NAPI_METHOD(dcn_get_chat_ephemeral_timer) {
NAPI_ARGV(2);
NAPI_DCN_CONTEXT();
@@ -2915,8 +2903,8 @@ NAPI_METHOD(dcn_msg_get_webxdc_blob){
NAPI_METHOD(dcn_accounts_new) {
NAPI_ARGV(2);
NAPI_ARGV_UTF8_MALLOC(os_name, 0);
NAPI_ARGV_UTF8_MALLOC(dir, 1);
NAPI_ARGV_UTF8_MALLOC(dir, 0);
NAPI_ARGV_INT32(writable, 1);
TRACE("calling..");
dcn_accounts_t* dcn_accounts = calloc(1, sizeof(dcn_accounts_t));
@@ -2925,7 +2913,7 @@ NAPI_METHOD(dcn_accounts_new) {
}
dcn_accounts->dc_accounts = dc_accounts_new(os_name, dir);
dcn_accounts->dc_accounts = dc_accounts_new(dir, writable);
napi_value result;
NAPI_STATUS_THROWS(napi_create_external(env, dcn_accounts,
@@ -3491,7 +3479,6 @@ NAPI_INIT() {
NAPI_EXPORT_FUNCTION(dcn_send_msg);
NAPI_EXPORT_FUNCTION(dcn_send_videochat_invitation);
NAPI_EXPORT_FUNCTION(dcn_set_chat_name);
NAPI_EXPORT_FUNCTION(dcn_set_chat_protection);
NAPI_EXPORT_FUNCTION(dcn_get_chat_ephemeral_timer);
NAPI_EXPORT_FUNCTION(dcn_set_chat_ephemeral_timer);
NAPI_EXPORT_FUNCTION(dcn_set_chat_profile_image);

View File

@@ -1,33 +1,28 @@
// @ts-check
import DeltaChat from '../dist'
import { DeltaChat } from '../dist/index.js'
import { deepStrictEqual, strictEqual } from 'assert'
import chai, { expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { EventId2EventName, C } from '../dist/constants'
import { EventId2EventName, C } from '../dist/constants.js'
import { join } from 'path'
import { statSync } from 'fs'
import { Context } from '../dist/context'
import fetch from 'node-fetch'
import { Context } from '../dist/context.js'
import {fileURLToPath} from 'url';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
chai.use(chaiAsPromised)
chai.config.truncateThreshold = 0 // Do not truncate assertion errors.
async function createTempUser(url) {
async function postData(url = '') {
// Default options are marked with *
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
headers: {
'cache-control': 'no-cache',
},
})
if (!response.ok) {
throw new Error('request failed: ' + response.body.read())
}
return response.json() // parses JSON response into native JavaScript objects
function createTempUser(chatmailDomain) {
const charset = "2345789acdefghjkmnpqrstuvwxyz";
let user = "ci-";
for (let i = 0; i < 6; i++) {
user += charset[Math.floor(Math.random() * charset.length)];
}
return await postData(url)
const email = user + "@" + chatmailDomain;
return { email: email, password: user + "$" + user };
}
describe('static tests', function () {
@@ -270,7 +265,7 @@ describe('Basic offline Tests', function () {
'quota_exceeding',
'scan_all_folders_debounce_secs',
'selfavatar',
'send_sync_msgs',
'sync_msgs',
'sentbox_watch',
'show_emails',
'socks5_enabled',
@@ -676,9 +671,9 @@ describe('Offline Tests with unconfigured account', function () {
const lot = chatList.getSummary(0)
strictEqual(lot.getId(), 0, 'lot has no id')
strictEqual(lot.getState(), C.DC_STATE_UNDEFINED, 'correct state')
strictEqual(lot.getState(), C.DC_STATE_IN_NOTICED, 'correct state')
const text = 'No messages.'
const text = 'Others will only see this group after you sent a first message.'
context.createGroupChat('groupchat1111')
chatList = context.getChatList(0, 'groupchat1111', null)
strictEqual(
@@ -768,14 +763,7 @@ describe('Integration tests', function () {
})
this.beforeAll(async function () {
if (!process.env.DCC_NEW_TMP_EMAIL) {
console.log(
'Missing DCC_NEW_TMP_EMAIL environment variable!, skip integration tests'
)
this.skip()
}
account = await createTempUser(process.env.DCC_NEW_TMP_EMAIL)
account = createTempUser(process.env.CHATMAIL_DOMAIN)
if (!account || !account.email || !account.password) {
console.log(
"We didn't got back an account from the api, skip integration tests"

View File

@@ -13,10 +13,10 @@
},
"exclude": ["node_modules", "deltachat-core-rust", "dist", "scripts"],
"typedocOptions": {
"mode": "file",
"out": "docs",
"excludeNotExported": true,
"excludePrivate": true,
"defaultCategory": "index",
"includeVersion": true
"includeVersion": true,
"entryPoints": ["lib/index.ts"]
}
}

View File

@@ -6,7 +6,7 @@ E.g via <https://git-scm.com/download/win>
## install node
Download and install `v16` from <https://nodejs.org/en/>
Download and install `v18` from <https://nodejs.org/en/>
## install rust

View File

@@ -2,28 +2,24 @@
"dependencies": {
"debug": "^4.1.1",
"napi-macros": "^2.0.0",
"node-gyp-build": "^4.1.0"
"node-gyp-build": "^4.6.1"
},
"description": "node.js bindings for deltachat-core",
"devDependencies": {
"@types/debug": "^4.1.7",
"@types/node": "^16.11.26",
"chai": "^4.2.0",
"@types/node": "^20.8.10",
"chai": "~4.3.10",
"chai-as-promised": "^7.1.1",
"esm": "^3.2.25",
"hallmark": "^2.0.0",
"mocha": "^8.2.1",
"node-fetch": "^2.6.7",
"node-gyp": "^9.0.0",
"opn-cli": "^5.0.0",
"prebuildify": "^3.0.0",
"prebuildify-ci": "^1.0.4",
"prettier": "^2.0.5",
"typedoc": "^0.17.0",
"typescript": "^3.9.10"
"node-gyp": "^10.0.0",
"prebuildify": "^5.0.1",
"prebuildify-ci": "^1.0.5",
"prettier": "^3.0.3",
"typedoc": "^0.25.3",
"typescript": "^5.2.2"
},
"engines": {
"node": ">=16.0.0"
"node": ">=18.0.0"
},
"files": [
"node/scripts/*",
@@ -49,16 +45,15 @@
"build:core:rust": "node node/scripts/rebuild-core.js",
"clean": "rm -rf node/dist node/build node/prebuilds node/node_modules ./target",
"download-prebuilds": "prebuildify-ci download",
"hallmark": "hallmark --fix",
"install": "node node/scripts/install.js",
"install:prebuilds": "cd node && node-gyp-build \"npm run build:core\" \"npm run build:bindings:c:postinstall\"",
"lint": "prettier --check \"node/lib/**/*.{ts,tsx}\"",
"lint-fix": "prettier --write \"node/lib/**/*.{ts,tsx}\" \"node/test/**/*.js\"",
"prebuildify": "cd node && prebuildify -t 16.13.0 --napi --strip --postinstall \"node scripts/postinstall.js --prebuild\"",
"prebuildify": "cd node && prebuildify -t 18.0.0 --napi --strip --postinstall \"node scripts/postinstall.js --prebuild\"",
"test": "npm run test:lint && npm run test:mocha",
"test:lint": "npm run lint",
"test:mocha": "mocha -r esm node/test/test.js --growl --reporter=spec --bail --exit"
"test:mocha": "mocha node/test/test.mjs --growl --reporter=spec --bail --exit"
},
"types": "node/dist/index.d.ts",
"version": "1.124.1"
"version": "1.133.2"
}

View File

@@ -1,6 +1,6 @@
=========================
DeltaChat Python bindings
=========================
============================
CFFI Python Bindings
============================
This package provides `Python bindings`_ to the `deltachat-core library`_
which implements IMAP/SMTP/MIME/OpenPGP e-mail standards and offers
@@ -8,157 +8,3 @@ a low-level Chat/Contact/Message API to user interfaces and bots.
.. _`deltachat-core library`: https://github.com/deltachat/deltachat-core-rust
.. _`Python bindings`: https://py.delta.chat/
Installing pre-built packages (Linux-only)
==========================================
If you have a Linux system you may install the ``deltachat`` binary "wheel" packages
without any "build-from-source" steps.
Otherwise you need to `compile the Delta Chat bindings yourself`__.
__ sourceinstall_
We recommend to first create a fresh Python virtual environment
and activate it in your shell::
python -m venv env
source env/bin/activate
Afterwards, invoking ``python`` or ``pip install`` only
modifies files in your ``env`` directory and leaves
your system installation alone.
For Linux we build wheels for all releases and push them to a python package
index. To install the latest release::
pip install deltachat
To verify it worked::
python -c "import deltachat"
Running tests
=============
Recommended way to run tests is using `scripts/run-python-test.sh`
script provided in the core repository.
This script compiles the library in debug mode and runs the tests using `tox`_.
By default it will run all "offline" tests and skip all functional
end-to-end tests that require accounts on real e-mail servers.
.. _`tox`: https://tox.wiki
.. _livetests:
Running "live" tests with temporary accounts
--------------------------------------------
If you want to run live functional tests you can set ``DCC_NEW_TMP_EMAIL`` to a URL that creates e-mail accounts. Most developers use https://testrun.org URLs created and managed by `mailadm <https://mailadm.readthedocs.io/>`_.
Please feel free to contact us through a github issue or by e-mail and we'll send you a URL that you can then use for functional tests like this::
export DCC_NEW_TMP_EMAIL=<URL you got from us>
With this account-creation setting, pytest runs create ephemeral e-mail accounts on the http://testrun.org server.
These accounts are removed automatically as they expire.
After setting the variable, either rerun `scripts/run-python-test.sh`
or run offline and online tests with `tox` directly::
tox -e py
Each test run creates new accounts.
Developing the bindings
-----------------------
If you want to develop or debug the bindings,
you can create a testing development environment using `tox`::
export DCC_RS_DEV="$PWD"
export DCC_RS_TARGET=debug
tox -c python --devenv env -e py
. env/bin/activate
Inside this environment the bindings are installed
in editable mode (as if installed with `python -m pip install -e`)
together with the testing dependencies like `pytest` and its plugins.
You can then edit the source code in the development tree
and quickly run `pytest` manually without waiting for `tox`
to recreating the virtual environment each time.
.. _sourceinstall:
Installing bindings from source
===============================
Install Rust and Cargo first.
The easiest is probably to use `rustup <https://rustup.rs/>`_.
Bootstrap Rust and Cargo by using rustup::
curl https://sh.rustup.rs -sSf | sh
Then clone the deltachat-core-rust repo::
git clone https://github.com/deltachat/deltachat-core-rust
cd deltachat-core-rust
To install the Delta Chat Python bindings make sure you have Python3 installed.
E.g. on Debian-based systems `apt install python3 python3-pip
python3-venv` should give you a usable python installation.
First, build the core library::
cargo build --release -p deltachat_ffi --features jsonrpc
`jsonrpc` feature is required even if not used by the bindings
because `deltachat.h` includes JSON-RPC functions unconditionally.
Create the virtual environment and activate it:
python -m venv env
source env/bin/activate
Build and install the bindings:
export DCC_RS_DEV="$PWD"
export DCC_RS_TARGET=release
python -m pip install ./python
`DCC_RS_DEV` environment variable specifies the location of
the core development tree. If this variable is not set,
`libdeltachat` library and `deltachat.h` header are expected
to be installed system-wide.
When `DCC_RS_DEV` is set, `DCC_RS_TARGET` specifies
the build profile name to look up the artifacts
in the target directory.
In this case setting it can be skipped because
`DCC_RS_TARGET=release` is the default.
Building manylinux based wheels
===============================
Building portable manylinux wheels which come with libdeltachat.so
can be done with Docker_ or Podman_.
.. _Docker: https://www.docker.com/
.. _Podman: https://podman.io/
If you want to build your own wheels, build container image first::
$ cd deltachat-core-rust # cd to deltachat-core-rust working tree
$ docker build -t deltachat/coredeps scripts/coredeps
This will use the ``scripts/coredeps/Dockerfile`` to build
container image called ``deltachat/coredeps``. You can afterwards
find it with::
$ docker images
This docker image can be used to run tests and build Python wheels for all interpreters::
$ docker run -e DCC_NEW_TMP_EMAIL \
--rm -it -v $(pwd):/mnt -w /mnt \
deltachat/coredeps scripts/run_all.sh

View File

@@ -1,197 +0,0 @@
# Makefile for Sphinx documentation
#
VERSION = $(shell python -c "import conf ; print(conf.version)")
DOCZIP = devpi-$(VERSION).doc.zip
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
RSYNCOPTS = -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
export HOME=/tmp/home
export TESTHOME=$(HOME)
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# This variable is not auto generated as the order is important.
USER_MAN_CHAPTERS = commands\
user\
indices\
packages\
# userman/index.rst\
# userman/devpi_misc.rst\
# userman/devpi_concepts.rst\
#export DEVPI_CLIENTDIR=$(CURDIR)/.tmp_devpi_user_man/client
#export DEVPI_SERVERDIR=$(CURDIR)/.tmp_devpi_user_man/server
chapter = commands
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp \
epub latex latexpdf text man changes linkcheck doctest gettext install \
quickstart-releaseprocess quickstart-pypimirror quickstart-server regen \
prepare-quickstart\
regen.server-fresh regen.server-restart regen.server-clean\
regen.uman-all regen.uman
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo
@echo "User Manual Regen Targets"
@echo " regen.uman regenerates page. of the user manual chapeter e.g. regen.uman chapter=..."
@echo " regen.uman-all regenerates the user manual"
@echo " regen.uman-clean stop temp server and clean up directory"
@echo " Chapter List: $(USER_MAN_CHAPTERS)"
clean:
-rm -rf $(BUILDDIR)/*
version:
@echo "version $(VERSION)"
doczip: html
python doczip.py $(DOCZIP) _build/html
install: html
rsync -avz $(RSYNCOPTS) _build/html/ delta@py.delta.chat:build/master
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/devpi.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/devpi.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/devpi"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/devpi"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

View File

@@ -1,17 +0,0 @@
<div class="globaltoc">
<ul>
<li><a href="{{ pathto('index') }}">index</a></li>
<li><a href="{{ pathto('install') }}">install</a></li>
<li><a href="{{ pathto('api') }}">high level API</a></li>
<li><a href="{{ pathto('lapi') }}">low level API</a></li>
</ul>
<b>external links:</b>
<ul>
<li><a href="https://github.com/deltachat/deltachat-core-rust">github repository</a></li>
<li><a href="https://pypi.python.org/pypi/deltachat">pypi: deltachat</a></li>
<li><a href="https://web.libera.chat/#deltachat">#deltachat</a></li>
</ul>
</div>

View File

@@ -1 +0,0 @@
<h3>deltachat {{release}}</h3>

View File

@@ -1,5 +1,4 @@
high level API reference
High Level API Reference
========================
- :class:`deltachat.Account` (your main entry point, creates the
@@ -8,28 +7,14 @@ high level API reference
- :class:`deltachat.Chat`
- :class:`deltachat.Message`
Account
-------
.. autoclass:: deltachat.Account
:members:
Contact
-------
:members:
.. autoclass:: deltachat.Contact
:members:
Chat
----
:members:
.. autoclass:: deltachat.Chat
:members:
Message
-------
:members:
.. autoclass:: deltachat.Message
:members:
:members:

View File

@@ -1,11 +1,10 @@
examples
Examples
========
Once you have :doc:`installed deltachat bindings <install>`
you need email/password credentials for an IMAP/SMTP account.
Delta Chat developers and the CI system use a special URL to create
temporary e-mail accounts on [testrun.org](https://testrun.org) for testing.
temporary email accounts on `testrun.org <https://testrun.org/>`_ for testing.
Receiving a Chat message from the command line
----------------------------------------------
@@ -16,11 +15,11 @@ Here is a simple bot that:
- terminates the bot if the message `/quit` is sent
.. include:: ../examples/echo_and_quit.py
.. include:: ../../examples/echo_and_quit.py
:literal:
With this file in your working directory you can run the bot
by specifying a database path, an e-mail address and password of
by specifying a database path, an email address and password of
a SMTP-IMAP account::
$ cd examples
@@ -40,11 +39,11 @@ Here is a simple bot that:
- tracks member additions and removals for all chat groups
.. include:: ../examples/group_tracking.py
.. include:: ../../examples/group_tracking.py
:literal:
With this file in your working directory you can run the bot
by specifying a database path, an e-mail address and password of
by specifying a database path, an email address and password of
a SMTP-IMAP account::
python group_tracking.py --email ADDRESS --password PASSWORD /tmp/db

View File

@@ -0,0 +1,80 @@
Install
=======
Installing pre-built packages (Linux-only)
------------------------------------------
If you have a Linux system you may install the ``deltachat`` binary "wheel" packages
without any "build-from-source" steps.
Otherwise you need to `compile the Delta Chat bindings yourself`__.
__ sourceinstall_
We recommend to first create a fresh Python virtual environment
and activate it in your shell::
python -m venv env
source env/bin/activate
Afterwards, invoking ``python`` or ``pip install`` only
modifies files in your ``env`` directory and leaves
your system installation alone.
For Linux we build wheels for all releases and push them to a python package
index. To install the latest release::
pip install deltachat
To verify it worked::
python -c "import deltachat"
.. _sourceinstall:
Installing bindings from source
-------------------------------
Install Rust and Cargo first.
The easiest is probably to use `rustup <https://rustup.rs/>`_.
Bootstrap Rust and Cargo by using rustup::
curl https://sh.rustup.rs -sSf | sh
Then clone the deltachat-core-rust repo::
git clone https://github.com/deltachat/deltachat-core-rust
cd deltachat-core-rust
To install the Delta Chat Python bindings make sure you have Python3 installed.
E.g. on Debian-based systems `apt install python3 python3-pip
python3-venv` should give you a usable python installation.
First, build the core library::
cargo build --release -p deltachat_ffi --features jsonrpc
`jsonrpc` feature is required even if not used by the bindings
because `deltachat.h` includes JSON-RPC functions unconditionally.
Create the virtual environment and activate it::
python -m venv env
source env/bin/activate
Build and install the bindings::
export DCC_RS_DEV="$PWD"
export DCC_RS_TARGET=release
python -m pip install ./python
`DCC_RS_DEV` environment variable specifies the location of
the core development tree. If this variable is not set,
`libdeltachat` library and `deltachat.h` header are expected
to be installed system-wide.
When `DCC_RS_DEV` is set, `DCC_RS_TARGET` specifies
the build profile name to look up the artifacts
in the target directory.
In this case setting it can be skipped because
`DCC_RS_TARGET=release` is the default.

11
python/doc/cffi/intro.rst Normal file
View File

@@ -0,0 +1,11 @@
Introduction
============
CFFI bindings are available via the `deltachat <https://pypi.org/project/deltachat/>`_ Python package.
The package contains both the Python bindings and the Delta Chat core.
It is provided only for Linux.
The ``deltachat`` Python package provides two layers of bindings for the
core Rust-library of the https://delta.chat messaging ecosystem:
low-level CFFI bindings to the C interface of the Delta Chat core
and high-level Python bindings built on top of CFFI bindings.

View File

@@ -1,8 +1,7 @@
Low Level API Reference
=======================
low level API reference
===================================
for full doxygen-generated C-docs, defines and functions please checkout
For full doxygen-generated C-docs, defines and functions please checkout
https://c.delta.chat

View File

@@ -0,0 +1,25 @@
Building Manylinux-Based Wheels
===============================
Building portable manylinux wheels which come with libdeltachat.so
can be done with Docker_ or Podman_.
.. _Docker: https://www.docker.com/
.. _Podman: https://podman.io/
If you want to build your own wheels, build container image first::
$ cd deltachat-core-rust # cd to deltachat-core-rust working tree
$ docker build -t deltachat/coredeps scripts/coredeps
This will use the ``scripts/coredeps/Dockerfile`` to build
container image called ``deltachat/coredeps``. You can afterwards
find it with::
$ docker images
This docker image can be used to run tests and build Python wheels for all interpreters::
$ docker run -e CHATMAIL_DOMAIN \
--rm -it -v $(pwd):/mnt -w /mnt \
deltachat/coredeps scripts/run_all.sh

49
python/doc/cffi/tests.rst Normal file
View File

@@ -0,0 +1,49 @@
Running Tests
=============
Recommended way to run tests is using `scripts/run-python-test.sh`
script provided in the core repository.
This script compiles the library in debug mode and runs the tests using `tox`_.
By default it will run all "offline" tests and skip all functional
end-to-end tests that require accounts on real email servers.
.. _`tox`: https://tox.wiki
.. _livetests:
Running "Live" Tests With Temporary Accounts
--------------------------------------------
If you want to run live functional tests
you can set ``CHATMAIL_DOMAIN`` to a domain of the email server
that creates email accounts like this::
export CHATMAIL_DOMAIN=nine.testrun.org
With this account-creation setting, pytest runs create ephemeral email accounts on the server.
These accounts have the pattern `ci-{6 characters}@{CHATMAIL_DOMAIN}`.
After setting the variable, either rerun `scripts/run-python-test.sh`
or run offline and online tests with `tox` directly::
tox -e py
Each test run creates new accounts.
Developing the Bindings
-----------------------
If you want to develop or debug the bindings,
you can create a testing development environment using `tox`::
export DCC_RS_DEV="$PWD"
export DCC_RS_TARGET=debug
tox -c python --devenv env -e py
. env/bin/activate
Inside this environment the bindings are installed
in editable mode (as if installed with `python -m pip install -e`)
together with the testing dependencies like `pytest` and its plugins.
You can then edit the source code in the development tree
and quickly run `pytest` manually without waiting for `tox`
to recreating the virtual environment each time.

View File

@@ -1,4 +0,0 @@
Changelog for deltachat-core's Python bindings
==============================================
.. include:: ../CHANGELOG

View File

@@ -1,138 +1,94 @@
# -*- coding: utf-8 -*-
#
# devpi documentation build configuration file, created by
# sphinx-quickstart on Mon Jun 3 16:11:22 2013.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
from pathlib import Path
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
from deltachat import __version__ as release
version = ".".join(release.split(".")[:2])
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
#'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx.ext.viewcode',
'breathe',
#'sphinx.ext.githubpages',
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"sphinx.ext.viewcode",
"breathe",
"sphinx_rtd_theme",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
# The suffix of source filenames.
source_suffix = '.rst'
source_suffix = ".rst"
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# General information about the project.
project = u'deltachat'
copyright = u'2020, holger krekel and contributors'
project = "Delta Chat"
copyright = "2023, Delta Chat contributors"
author = "Delta Chat contributors"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['sketch', '_build', "attic"]
exclude_patterns = ["sketch", "_build", "attic", "Thumbs.db", ".DS_Store"]
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# modindex_common_prefix = []
# -- breathe options ------
breathe_projects = {
"deltachat": "../../docs/xml/"
}
breathe_projects = {"deltachat": Path("../../docs/xml/")}
breathe_default_project = "deltachat"
# -- Options for HTML output ---------------------------------------------------
sys.path.append(os.path.abspath('_themes'))
html_theme_path = ['_themes']
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
# html_theme = 'flask'
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {
'logo': '_static/delta-chat.svg',
'font_size': "1.1em",
'caption_font_size': "0.9em",
'code_font_size': "1.1em",
}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = ["_themes"]
html_theme = "sphinx_rtd_theme"
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
@@ -141,51 +97,34 @@ html_logo = "_static/delta-chat.svg"
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = '_static/favicon.ico'
html_favicon = "_static/favicon.ico"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#
html_sidebars = {
'index': [
'sidebarintro.html',
'globaltoc.html',
'searchbox.html'
],
'**': [
'sidebarintro.html',
'globaltoc.html',
'relations.html',
'searchbox.html'
]
}
# html_use_smartypants = True
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# html_split_index = False
# If true, links to the reST sources are added to the pages.
html_show_sourcelink = False
@@ -194,71 +133,65 @@ html_show_sourcelink = False
html_show_sphinx = False
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
html_use_opensearch = 'https://doc.devpi.net'
html_use_opensearch = "https://doc.devpi.net"
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'deltachat-python'
htmlhelp_basename = "deltachat-python"
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
'pointsize': '12pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '12pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'devpi.tex', u'deltachat documentation',
u'holger krekel', 'manual'),
("index", "devpi.tex", "deltachat documentation", "holger krekel", "manual"),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'deltachat', u'deltachat documentation',
[u'holger krekel'], 1)
]
man_pages = [("index", "deltachat", "deltachat documentation", ["holger krekel"], 1)]
# If true, show URL addresses after external links.
#man_show_urls = False
# man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
@@ -267,30 +200,38 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'devpi', u'devpi Documentation',
u'holger krekel', 'devpi', 'One line description of project.',
'Miscellaneous'),
(
"index",
"devpi",
"devpi Documentation",
"holger krekel",
"devpi",
"One line description of project.",
"Miscellaneous",
),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# texinfo_show_urls = 'footnote'
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'http://docs.python.org/': None}
intersphinx_mapping = {"http://docs.python.org/": None}
# autodoc options
autodoc_member_order = "bysource"
# always document __init__ functions
def skip(app, what, name, obj, skip, options):
return skip
def setup(app):
app.connect("autodoc-skip-member", skip)

View File

@@ -1,41 +1,44 @@
deltachat python bindings
=========================
Delta Chat Python bindings, new and old
=======
The ``deltachat`` Python package provides two layers of bindings for the
core Rust-library of the https://delta.chat messaging ecosystem:
- :doc:`api` is a high level interface to deltachat-core.
- :doc:`plugins` is a brief introduction into implementing plugin hooks.
- :doc:`lapi` is a lowlevel CFFI-binding to the `Rust Core
<https://github.com/deltachat/deltachat-core-rust>`_.
getting started
---------------
`Delta Chat <https://delta.chat/>`_ provides two kinds of Python bindings
to the `Rust Core <https://github.com/deltachat/deltachat-core-rust>`_:
JSON-RPC bindings and CFFI bindings.
When starting a new project it is recommended to use JSON-RPC bindings,
which are used in the Delta Chat Desktop app through generated Typescript-bindings.
The Python JSON-RPC bindings are maintained by Delta Chat core developers.
Most existing bot projects and many tests in Delta Chat's own core library
still use the CFFI-bindings, and it is going to be maintained certainly also in 2024.
New APIs might however only appear in the JSON-RPC bindings,
as the CFFI bindings are increasingly in maintenance-only mode.
.. toctree::
:maxdepth: 2
:caption: JSON-RPC Bindings
install
examples
jsonrpc/intro
jsonrpc/install
jsonrpc/examples
jsonrpc/reference
jsonrpc/develop
.. toctree::
:hidden:
:maxdepth: 2
:caption: CFFI Bindings
links
changelog
api
lapi
plugins
..
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
cffi/intro
cffi/install
cffi/examples
cffi/manylinux
cffi/tests
cffi/api
cffi/lapi
cffi/plugins
.. _`deltachat`: https://delta.chat
.. _`deltachat-core repo`: https://github.com/deltachat
.. _pip: http://pypi.org/project/pip/
.. _virtualenv: http://pypi.org/project/virtualenv/
.. _merlinux: http://merlinux.eu
.. _pypi: http://pypi.org/
.. _`issue-tracker`: https://github.com/deltachat/deltachat-core-rust

View File

@@ -1,2 +0,0 @@
.. include:: ../README.rst

View File

@@ -0,0 +1,68 @@
===========
Development
===========
To develop JSON-RPC bindings,
clone the `deltachat-core-rust <https://github.com/deltachat/deltachat-core-rust/>`_ repository::
git clone https://github.com/deltachat/deltachat-core-rust.git
Testing
=======
To run online tests, set ``CHATMAIL_DOMAIN``
to a domain of the email server
that can be used to create testing accounts::
export CHATMAIL_DOMAIN=nine.testrun.org
Then run ``scripts/run-rpc-test.sh``
to build debug version of ``deltachat-rpc-server``
and run ``deltachat-rpc-client`` tests
in a separate virtual environment managed by `tox <https://tox.wiki/>`_.
Development Environment
=======================
Creating a new virtual environment
to run the tests each time
as ``scripts/run-rpc-test.sh`` does is slow
if you are changing the tests or the code
and want to rerun the tests each time.
If you are developing the tests,
it is better to create a persistent virtual environment.
You can do this by running ``scripts/make-rpc-testenv.sh``.
This creates a virtual environment ``venv`` which you can then enter with::
. venv/bin/activate
Then you can run the tests with
::
pytest deltachat-rpc-client/tests/
Refer to `pytest documentation <https://docs.pytest.org/>` for details.
If make the changes to Delta Chat core
or Python bindings, you can rebuild the environment by rerunning
``scripts/make-rpc-testenv.sh``.
It is ok to rebuild the activated environment this way,
you do not need to deactivate or reactivate the environment each time.
Using REPL
==========
Once you have a development environment,
you can quickly test things in REPL::
$ python
>>> from deltachat_rpc_client import *
>>> rpc = Rpc()
>>> rpc.start()
>>> dc = DeltaChat(rpc)
>>> system_info = dc.get_system_info()
>>> system_info["level"]
'awesome'
>>> rpc.close()

View File

@@ -0,0 +1,19 @@
Examples
========
Echo bot
--------
.. include:: ../../../deltachat-rpc-client/examples/echobot_no_hooks.py
:literal:
Echo bot with hooks
-------------------
.. include:: ../../../deltachat-rpc-client/examples/echobot.py
:literal:
Advanced echo bot
-----------------
.. include:: ../../../deltachat-rpc-client/examples/echobot_advanced.py
:literal:

View File

@@ -0,0 +1,36 @@
Install
=======
To use JSON-RPC bindings for Delta Chat core you will need
a ``deltachat-rpc-server`` binary which provides Delta Chat core API over JSON-RPC
and a ``deltachat-rpc-client`` Python package which is a JSON-RPC client that starts ``deltachat-rpc-server`` process and uses JSON-RPC API.
`Create a virtual environment <https://docs.python.org/3/library/venv.html>`__ if you
dont have one already and activate it::
$ python -m venv venv
$ . venv/bin/activate
Install ``deltachat-rpc-server``
--------------------------------
To get ``deltachat-rpc-server`` binary you have three options:
1. Install ``deltachat-rpc-server`` from PyPI using ``pip install deltachat-rpc-server``.
2. Build and install ``deltachat-rpc-server`` from source with ``cargo install --git https://github.com/deltachat/deltachat-core-rust/ deltachat-rpc-server``.
3. Download prebuilt release from https://github.com/deltachat/deltachat-core-rust/releases and install it into ``PATH``.
Check that ``deltachat-rpc-server`` is installed and can run::
$ deltachat-rpc-server --version
1.131.4
Then install ``deltachat-rpc-client`` with ``pip install deltachat-rpc-client``.
Install ``deltachat-rpc-client``
--------------------------------
To get ``deltachat-rpc-client`` Python library you can:
1. Install ``deltachat-rpc-client`` from PyPI using ``pip install deltachat-rpc-client``.
2. Install ``deltachat-rpc-client`` from source with ``pip install git+https://github.com/deltachat/deltachat-core-rust.git@main#subdirectory=deltachat-rpc-client``.

View File

@@ -0,0 +1,8 @@
Introduction
============
JSON-RPC bindings are available via the `deltachat-rpc-client <https://pypi.org/project/deltachat-rpc-client/>`_ Python package.
This package provides only the Python bindings and requires ``deltachat-rpc-server`` binary to be installed.
`deltachat-rpc-server <https://pypi.org/project/deltachat-rpc-server/>`_ package provides ``deltachat-rpc-server`` binary for Linux, Windows, macOS and Android.
RPC client connects to standalone Delta Chat RPC server ``deltachat-rpc-server`` and provides Python interface to it.

View File

@@ -0,0 +1,5 @@
API Reference
=============
.. automodule:: deltachat_rpc_client
:members:

View File

@@ -1,11 +0,0 @@
links
================================
.. _`deltachat`: https://delta.chat
.. _`deltachat-core repo`: https://github.com/deltachat
.. _pip: http://pypi.org/project/pip/
.. _virtualenv: http://pypi.org/project/virtualenv/
.. _merlinux: http://merlinux.eu
.. _pypi: http://pypi.org/
.. _`issue-tracker`: https://github.com/deltachat/deltachat-core

View File

@@ -1,190 +0,0 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\devpi.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\devpi.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end

Some files were not shown because too many files have changed in this diff Show More