To be precise, when sending a message,
reuse the existing draft message's ID.
Closes https://github.com/chatmail/core/issues/8485.
Closes https://github.com/chatmail/core/issues/4643.
Supersedes https://github.com/chatmail/core/pull/6426.
This feature already works in CFFI, however CFFI API requires
a fully formed `Message` object, with all its fields set,
and this is probably not something that public API should offer
or require.
I decided not to go for exposing the draft ID in the JSON-RPC API,
and go for `bool reuse_existing_draft` instead.
Exposing and requiring the ID would make the API more complex,
yet I can't come up with an example of how this bool API
could be problematic, at least in the case
where there aren't multiple concurrent users of the same
account's database.
Perhaps the ID system would make sense
if it was possible to have multiple drafts per chat,
and treat those like "almost sent messages" that you can edit
before finally sending (or deleting) them,
but it's not what we have now.
This adds the check for whether the .xdc file
gets replaced or removed and creates a new draft message if so,
which makes sure that old WebXDC status updates
don't apply to the new app, as was suggested in
https://github.com/chatmail/core/pull/6426#issuecomment-2585657331.
So the API user doesn't have to be careful not to ask Core
to reuse the draft when that would be incorrect.
Calling `send_msg()` with a draft message that was already sent
(by specifying `msg.id`)
would mutate that message in the DB and try to send it again.
Additionally, `prepare_msg_raw` now errors out
if the draft is not present in the database.
Previosuly the `UPDATE` query would simply update 0 rows
and we would proceed with trying to send a message
without having it in the `msgs` table.
The bug has been introduced in cf33db3dcb
(https://github.com/chatmail/core/pull/2887).
Semantically this makes `prepare_msg_raw` API less generic,
narrowing down its `update_msg_id` function only to drafts.
The "update draft" is anyway the only use case so far
for this parameter.
Thus this also removes the ability to specify an ID
that is different from `msg.id`, as was suggested in
https://github.com/chatmail/core/pull/2887#discussion_r767256419.
These IDs were always the same anyway.
Maybe it would make sense to, instead of returning an error
if the draft is already sent or does not exist,
simply upsert a new message without looking at `msg.id`,
as we would do with non-draft `msg.state`s,
but I wasn't sure how CFFI users (DC Android and DC iOS)
would take that.
So for now let's simply return an error instead of messing up the DB.
Due to a gap between `get_draft_msg_id()` and `Message::load_from_db`.
Possibly can happen if the draft gets sent
while `get_draft()` is in progress.
Solved by doing both queries in a transaction.
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>
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.
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
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.
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.
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.
- 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.
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.
Unifies internal naming of single/direct/1:1/normal chats
to match the naming used in the API.
Closes: #8368
Signed-off-by: Jagoda Ślązak <jslazak@jslazak.com>
---------
Signed-off-by: Jagoda Ślązak <jslazak@jslazak.com>
`unwrap_or` is eagerly evaluated,
which caused always printing the WARN log,
even if EXIF orientation value is correct
(and not ignored).
Signed-off-by: Jagoda Ślązak <jslazak@jslazak.com>
The `FolderMeaning` and the `target_folder()` function and related code
were needed for the message moving logic. The message moving logic isn't
needed anymore, so, this PR is a first step to remove it.
We only ever look at one folder by now (usually the Inbox folder), so,
any message moving logic isn't needed anymore because we will never
notice a message that is supposed to be moved.
The `target` column of the `imap` table is mostly the same as the
`folder` column now. Except when the message is supposed to be deleted,
then it's an empty string.