Commit Graph

10488 Commits

Author SHA1 Message Date
Hocuri
2b60bb1eb8 clippy 2026-08-07 16:53:00 +02:00
Hocuri
8f6c9622f0 fix: Don't show "Not Connected" just because one of the relays can't connect
With multi-relay, it can happen that one of the relays can't connect or is stuck in "Connecting...". In this case, right now we show "Not Connected"/"Connecting" as the connectivity, which multiple users already complained about, esp. since it's not obvious how to remove an unpublished, not working relay.

Instead, the new logic is:
- If any relay is working, then we signal this to the user, to signal that new messages may come in.
- Only show "Connecting..." or "Not Connected" if all of the relays are failing to connect, because if any of the relays can connect then things are mostly fine.
2026-08-07 13:43:08 +02:00
B. Petersen
1247d5da36 use Chat-Broadcast-States: header insted of -Reactions:
the wire format is already prepared to carry information additionally to reactions,
so let the header name reflect that as well.

in practise, we might want to use a `pinned` flag very soon
in case pinned messages got resent in channels.
it makes sense if that flag goes to the message as such,
and not to an extra message.
and then it makes sense to not introduce a new things.

ftr, this is about resending state to other members,
it is not about syncing across devices for the same user.

the code as such is not changed by this PR,
it is only a wording preparation, of a header that is not even visible.
if we semantically put things other than reactions to the wire format,
we may want to move it out of `broadcast_reactions.rs`
2026-08-05 14:32:27 +02:00
biørn
93d9a4be1c feat: allow only default reactions (#8545)
the UIs are currently advised
to only allow the five default reactions in broadcast channels.
this PR ensures that from sending site as well as receiving site.

soon, we probably want to make the possible reactions configurable, this
PR is mainly for some safety until then. once we have an API to change
default reactions, we can also easily test "invalid" reactions on the
receiving side; currently only sending is tested

successor of https://github.com/chatmail/core/pull/8450

---------

Co-authored-by: Jagoda Estera Ślązak <128227338+j-g00da@users.noreply.github.com>
2026-08-05 10:22:19 +02:00
biørn
b13b150997 resend broadcast reactions together with message (#8496)
this PR resends reactions together with channel messages.
2026-08-04 19:24:23 +02:00
biørn
bd846c6e43 broadcast channel reactions (#8450)
this PR adds support for reactions in broadcast channels.

> the idea of broadcast reactions is that they are sent as usual from
subscribers to owner. after some time, the owner broadcasts them to all
subscribers, who only get to see reaction+count, not who-reacted-what

the PR is quite large, but a good share are tests and otherwise many
things are straight forward.

review should be done by-file, not by-commit. to make review easier,
here is a high-level overview:

first a change in the existing internal `Reactions` object was required.
before this PR, `Reactions` had a "contact to reaction map" only, and
the "frequencies map", that are actually mainly needed for UI, were
calculated as needed. with this PR, the "frequencies map" is the field
that always exist, the "contact map" is only available on top of that.
moreover, this PR shifts that part to the core, it was unfortunately in
the bindings before.

with that preparation things done as follows:

1. reactions from broadcast channel subscriber (`Chattype::InBroadcast`)
to broadcast channel owner (`Chattype::OutBroadcast`) are sent as usual,
only change for that step was to allow sending them at all

2. the owner receives reactions and saves them to the existing
`reactions` table as usual. additionally, the changed message is
remembered in `reactions_need_broadcast` table

3. in the IMAP loop, when ~10 minutes have passed, and
`reactions_need_broadcast` contains entries, a single, hidden message
with accumulated reactions is sent. this message may contain reactions
to different messages. for each message, all known reactions are sent as
reaction+count.

4. subscriber receive that message and save the accumulated reactions in
`reactions_broadcasted`

6. `get_message_reactions` is adapted so that `frequencies` are set
independently of who-reacted-what (the old and only field).
who-reacted-what is called `by_contact` now. it is always set for
compatibility reasons, however, it is not exhaustive for subscribers.
in general, UI should work with frequencies, the API itself, however,
has not changed.

other tweaks:

- outgoing channels are muted on creation, and UI shall allow to
unmute/mute them as all other chats. reason is that reactions are
notified, but in many cases not of large interest. this is also what
telegram is doing

- to have an intermediate feedback when reacting, the local state should
include ones own reaction, even if it is not yet broadcasted. for that,
we modify `reactions_broadcasted` using `modify_frequencies()` as needed
when sending an reaction. there are still some situations where the
update may not include ones own reaction, in this case it is added
lately by `refine_frequencies()`, so that `get_message_reactions()`
always contain SELF.
(in a first implementation, we always increased SELF reaction in
refine_frequencies(), however, that was worse and led to SELF counted
twice once the owner sent broadcast)

<details>
<summary>wire format</summary>

wire format is a JSON in the `Broadcast-Reactions:` header.
additionally, `Content-Disposition: reaction` is set to not show the
hidden message on existing devices.

using a header also allows us to broadcast reactions with resent channel
messages (on joining) later.

```
{
  "messages": [
    {
      "id": "12345678",
      "reactions": [
        { "emoji": "👍", "count": 4 },
        { "emoji": "🎉", "count": 2 }
      ]
    },
    {
      "id": "23456789",
      "reactions": []
    }
  ]
}
```

for `id`, the wire format needs to use `rfc724_mid` as `msg_id` are
local only.

</details>

### known issues

- if the channel owner uses multiple devices, broadcasted reaction
updates are sent from each device. the updates are not that big, so that
is probably not a big deal. if it turns out that this is an issue, we
can think about fixes in another PR. might be done by restarting our
10-minute-wait once we see an update from another device

- we cannot set contact_id for DC_EVENT_REACTIONS_CHANGED - but i doubt
it was ever used

### for another pr

- ~~add `Broadcast-Reactions:` header also for resent channel messages,
so that new subscriber do not only get the latest messages, but also
their reactions. for that, the `Broadcast-Reactions:` header can go to
the corresponding message, no need to send extra messages. we would need
to change the sending part to send all reactions for a given message. on
receiving part, we need to make sure, `receive_broadcast_reactions()` is
called when the message actually exist.~~
EDIT: subsequent PR for resending broadcast reactions at
https://github.com/chatmail/core/pull/8496

- add api to allow only a subset of reactions, fiter incoming reactions
before broadcasting

### misc.

ui pr: https://github.com/deltachat/deltachat-ios/pull/3225 and
https://github.com/deltachat/deltachat-android/pull/4560 , which both
were tested successfully with this core PR already. desktop is meant to
be done once this is merged

---------

Co-authored-by: l <link2xt@testrun.org>
2026-08-04 18:54:17 +02:00
Hocuri
547d22a3e3 test: Add test for unencrypted headers (#8538)
This adds a test for the unencrypted headers, because
https://github.com/chatmail/core/pull/8345/ changes how these are
rendered, and so far we didn't have any tests for them.
2026-08-04 11:57:57 +00:00
link2xt
7990e17859 refactor(mimefactory): separate rendering of message payload and sendable message
This change separates rendering into two separate steps:
1. Rendering of the message payload without the From, Date and Autocrypt headers.
2. Adding the From, Date and Autocrypt headers and possibly encrypting the message.

The goal is to have serializable result of the first step
that can be persisted in the database and sent later with any email address.
This way it will be possible to send queued messages over any relay.

This will make it possible not to remove all messages from the queue
when the sending relay is changed.
Currently changing `configured_addr` deletes everything from `smtp` table.

This change is however only a refactoring and does not implement any features.
2026-08-04 11:57:57 +00:00
Hocuri
487d33f4d7 clippy 2026-08-04 11:47:26 +02:00
Hocuri
e45667b547 test: Make the test check for the exact set of recipients 2026-08-04 11:47:26 +02:00
Hocuri
5eab324751 test: Add test_bcc_self 2026-08-04 11:47:26 +02:00
holger krekel
15387690c8 follow link2xt review comments 2026-08-04 11:47:26 +02:00
holger krekel
ba35814d34 fix: recognize self addresses in various places (instead of just the "primary") 2026-08-04 11:47:26 +02:00
link2xt
2ac217ddd4 feat: send messages to 5 relays instead of the newest 3 ones
Otherwise users may add up to 5 relays, but 2 oldest relays
are actually ignored.

Having the maximum number of published relays
and the number of relays used the same between all clients
makes the order of relays in the key irrelevant.
We may even remove sorting by `add_timestamp`
from `get_all_self_addrs()` in the future.
2026-08-03 14:04:15 +00:00
link2xt
8e60ed7d89 perf: Box::pin iroh::endpoint::Builder::bind
It is has a size of 13k and increases the size of all futures calling it as a result,
while only being used for initialization.
2026-08-03 13:54:49 +00:00
link2xt
fab974f31e feat: collect ICE servers from all relays 2026-08-03 13:38:40 +00:00
dependabot[bot]
154e47dace chore(cargo): bump libc from 0.2.186 to 0.2.189
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.186 to 0.2.189.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.189/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.186...0.2.189)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-02 18:40:19 +00:00
link2xt
99d202a973 api(ffi): store reference-counted Context in dc_chatlist_t 2026-08-02 17:22:56 +00:00
link2xt
ae02b6dcfc api!: remove dc_chatlist_get_context()
This API is dangerous because returned pointer
is only valid until the chatlist is freed,
and may accidentally be passed into dc_context_unref().
2026-08-02 17:22:56 +00:00
link2xt
e1f5858fa3 api(ffi): store reference-counted Context in dc_contact_t 2026-08-02 17:22:56 +00:00
link2xt
abfc1b9a76 api(ffi): store reference-counted Context in dc_msg_t
The change is similar to the change done to dc_chat_t
in b5acbaa31c
2026-08-02 17:22:56 +00:00
dependabot[bot]
77d2d037f2 chore(cargo): bump thiserror from 2.0.18 to 2.0.19
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 2.0.18 to 2.0.19.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.18...2.0.19)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-02 17:10:27 +00:00
link2xt
057d6c0c5e refactor: reduce the scope of unsafe in dc_context_unref() 2026-08-02 17:09:56 +00:00
dependabot[bot]
21e08d7e95 chore(cargo): bump serde from 1.0.228 to 1.0.229
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.228 to 1.0.229.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.228...v1.0.229)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-02 04:13:46 +00:00
dependabot[bot]
03c1ea9942 chore(cargo): bump anyhow from 1.0.103 to 1.0.104
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.103 to 1.0.104.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.103...1.0.104)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-02 04:13:27 +00:00
link2xt
cf5f87c81b chore(cargo): introduce syn 3 dependency
It is now used by at the latest versions of anyhow and thiserror,
so we will eventually have this duplicate dependency anyway.
2026-08-02 02:31:45 +00:00
dependabot[bot]
7021a3e899 chore(deps): bump actions/setup-python from 6.3.0 to 7.0.0
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6.3.0 to 7.0.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v6.3.0...v7.0.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-02 02:27:47 +00:00
dependabot[bot]
a794e5f359 chore(deps): bump pypa/gh-action-pypi-publish from 1.14.0 to 1.14.1
Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.14.0 to 1.14.1.
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](cef221092e...ba38be9e46)

---
updated-dependencies:
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-02 02:14:02 +00:00
dependabot[bot]
f7ffb924bf chore(cargo): bump serde_json from 1.0.150 to 1.0.151
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.150 to 1.0.151.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.150...v1.0.151)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-02 02:13:44 +00:00
dependabot[bot]
61f7107d0f chore(deps): bump taiki-e/install-action from 2.83.4 to 2.85.1
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.83.4 to 2.85.1.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](07b4745e0c...3d7d7cd5ac)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-version: 2.85.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-02 02:13:23 +00:00
dependabot[bot]
710e33bc48 chore(deps): bump zizmorcore/zizmor-action from 0.6.0 to 0.6.1
Bumps [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) from 0.6.0 to 0.6.1.
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](6599ee8b7a...6fc4b00623)

---
updated-dependencies:
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.6.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-02 02:12:46 +00:00
dependabot[bot]
2df5ea038b chore(cargo): bump tokio-util from 0.7.18 to 0.7.19
Bumps [tokio-util](https://github.com/tokio-rs/tokio) from 0.7.18 to 0.7.19.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-util-0.7.18...tokio-util-0.7.19)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-02 02:12:31 +00:00
Hocuri
dc267fe1fb fix: Don't download pre-message again if it is known already (#8488)
There was a bug in prefetch_should_download() that it made it return
true for pre-messages even when they were already downloaded. This meant
that pre-messages were downloaded from all relays, rather than just one,
wasting internet data.

The fix is in rfc724_mid_download_tried(), which is used by
prefetch_should_download() to determine whether a message was already
downloaded.

---------

Co-authored-by: l <link2xt@testrun.org>
2026-08-01 10:48:24 +00:00
link2xt
62d3f3877f refactor: mark enabled ephemeral timer duration as NonZero
Now the type system ensures that Timer::Enabled
never stores 0 value inside accidentally,
it is impossible to put 0 there without unsafe code.
2026-07-31 23:55:49 +00:00
link2xt
fb4fdeb470 fix(python): create event emitter when EventThread is initialized
EventThread is created in Account.__init__,
but the thread start may be scheduled later.
If the thread only cals dc_get_event_emitter()
after some events have been emitted,
EventThread will never capture such events
and the tests will timeout waiting for the event.

This happened in CI on a Linux runner
with test_markseen_invalid_message_ids
timing out waiting for DC_EVENT_MSGS_CHANGED
right after sending a message.
2026-07-31 23:20:17 +00:00
Hocuri
db13d08f6c feat: Basic multi-relay onboarding (#8444)
If multi-relay onboarding config is set from UIs, automatically add
relays until there are 3 relays. For now, there will be a hardcoded list
of relay candidates.

- We need a list of chatmail relays that we somehow trust, and that
agree to be in the list. Then, we add all of them to the candidate list
(a new SQL table with colums "host" and "last_tried").
- Before going to IMAP IDLE: When there are less than 3 relays, fill it
up with relays from the candidate list. If creating an account fails,
try again with another relay from the list. For each candidate, we need
to remember the last time we tried to add a transport there, and try at
most once a week or so per candidate.
- For now, this will be behind an off-by-default config option, which at
least DC Android will enable when creating a new profile. UIs can then
opt in on their own pace but will likely need to disable it for tests.
- Right now, the backoff times are: Try to add a relay at most once per
hour, and try to add the same relay at most once per week
2026-07-31 13:14:43 +02:00
holger krekel
9476f9ec7f test: fix flaky test_no_markseen_in_team_profile (#8500)
fixes https://github.com/chatmail/core/issues/8446
2026-07-31 09:12:28 +00:00
holger krekel
020e477662 test: fix flaky test_markseen_message_and_mdn test 2026-07-31 00:20:14 +02:00
link2xt
3d50f3c9a3 refactor: do not clean imap_send table on transport change
imap_send table is not unused anymore
and should eventually be deleted.
It only exists for compatibility
and no other SQL statements use it anymore.
2026-07-30 16:54:04 +00:00
holger krekel
35555ca753 api!: remove getPushState() and core's internal tracking of it.
Since https://github.com/deltachat/deltachat-ios/pull/3224 pushstate is not used
(android, desktop etc. never used it, only ios)
2026-07-30 17:32:54 +02:00
holger krekel
0bb3d88bc6 feat: stop requiring XDELTAPUSH capability for push notifications
register device token if XDELTAPUSH IMAP capability is available (current relay setup provides it)
or if "maxsmtprecipients" IMAP metadata key is available (relays since May 2026 provide it),
allowing chatmail relay setups to drop XDELTAPUSH capability marker with the next release
while retaining push notification support.
2026-07-30 17:32:54 +02:00
link2xt
e74ffb6e93 docs: add missing slash to ConnectionSecurity::Starttls doc comment 2026-07-29 23:50:59 +00:00
link2xt
bbcfa5e40e chore: disable "large futures" lint again
The lint is reasonable, but without some work
to bring the future sizes way below the limit,
this lint is frequently triggered in unrelated PRs
that just add some local variables to async functions
or extend some structure that is passed on the stack.
2026-07-29 00:47:39 +00:00
WofWca
7223d7ed74 refactor: un-nest prepare_msg_blob 2026-07-28 12:22:42 +04:00
link2xt
733bec326a fix: mark as_path() function unsafe 2026-07-27 23:48:11 +00:00
link2xt
2d7af15124 build: update all crates to Rust 2024 edition
Largest change is in the FFI crate.
With 2024 (but not 2021) edition unsafe code
inside unsafe functions should be marked separately
so we can mark exactly the code that is unsafe.
Some CFFI functions even have no unsafe code inside.

Most interesting change is that .strdup()
functions are not marked as unsafe anymore.
They are allocating memory and return raw pointers,
but there is nothing unsafe about it.
Only using the returned raw pointers is unsafe.
This way calls to .strdup() don't have to be marked
with unsafe{} blocks.
2026-07-27 23:48:11 +00:00
holger krekel
00e1d00dfa fix: send MDNs to all authentic relays of a contact, not just whatever get_addr() returns. 2026-07-27 21:54:42 +02:00
holger krekel
856ea29c47 feat: reduce unncessary gossipping of keys in group chats
- treat an Autocrypt header as a kind of Autocrypt-Gossip: addr=<self>
  letting it participate in the existing cooperative key gossipping mechanics.

- speed up processing of incoming autocrypt-gossip headers by using
  1 sql commit for N gossip headers instead of the current N commits.
2026-07-27 21:54:42 +02:00
holger krekel
6a07a2b222 feat: send Autocrypt pgp key in MDNs occassionally and when relaylist changes 2026-07-27 21:54:42 +02:00
holger krekel
411ad16ea9 fix(deltachat-rpc-client): don't depend on execnet for importing pytest plugin, remove deprecated "py" usage
unsuspecting consumers will otherwise require execnet to run pytest with deltachat-rpc-client installed.
"import py" is discouraged for pytest these days but still supported in compatibility mode.
2026-07-27 21:45:34 +02:00