Compare commits

..

11 Commits

Author SHA1 Message Date
link2xt
6fb2f27831 Revert "fix: set dir to "auto" in body tag when converting plain-text to HTML (#8227)"
This reverts commit 58a09df49a
which was merged with failing CI.
2026-05-08 22:11:33 +02:00
adb
58a09df49a fix: set dir to "auto" in body tag when converting plain-text to HTML (#8227)
close #8223
2026-05-08 20:20:00 +02:00
iequidoo
ca70fb9b3a feat: Get rid of MessageState::{OutPreparing,OutMdnRcvd} in the db
`OutPreparing` is deprecated since 2024-12-07, replace it with `OutFailed`, such messages are
probably not interesting anymore. `OutMdnRcvd` is not used in the db for new messages since
a30c6ae1f7, `OutDelivered` is stored instead.
2026-05-07 20:37:11 -03:00
iequidoo
045b586569 feat: Never remove primary transport when applying SyncTransports message
If we missed a message changing the primary transport, we shouldn't remove it when applying
a SyncTransports message, such a state doesn't look correct even if it's temporary.
2026-05-07 20:04:22 -03:00
iequidoo
18e1ecbb94 fix: Generate new pre-message Message-ID when forwarding
Otherwise if it's forwarded to a device that already has the original
message, the pre-message isn't received and this results in a message
having no text and `Forwarded` param.

Co-authored-by: Hocuri <hocuri@gmx.de>
2026-05-07 19:35:03 -03:00
iequidoo
6fdee2b92d docs: Remove outdated comment about "quota warning" device message
The device message was removed in 7de58f5329.
2026-05-07 19:31:38 -03:00
dependabot[bot]
9ebd4769f5 chore(cargo): bump openssl from 0.10.78 to 0.10.79
Bumps [openssl](https://github.com/rust-openssl/rust-openssl) from 0.10.78 to 0.10.79.
- [Release notes](https://github.com/rust-openssl/rust-openssl/releases)
- [Commits](https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.78...openssl-v0.10.79)

---
updated-dependencies:
- dependency-name: openssl
  dependency-version: 0.10.79
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-07 09:13:45 -03:00
dependabot[bot]
741d1beed8 chore(cargo): bump data-encoding from 2.10.0 to 2.11.0
Bumps [data-encoding](https://github.com/ia0/data-encoding) from 2.10.0 to 2.11.0.
- [Commits](https://github.com/ia0/data-encoding/compare/v2.10.0...v2.11.0)

---
updated-dependencies:
- dependency-name: data-encoding
  dependency-version: 2.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-04 14:10:58 -03:00
dependabot[bot]
ac8b2d2fca chore(cargo): bump colorutils-rs from 0.7.6 to 0.8.0
Bumps [colorutils-rs](https://github.com/awxkee/colorutils-rs) from 0.7.6 to 0.8.0.
- [Release notes](https://github.com/awxkee/colorutils-rs/releases)
- [Commits](https://github.com/awxkee/colorutils-rs/compare/0.7.6...0.8.0)
2026-05-04 13:42:52 -03:00
link2xt
d75c05e717 ci: do not store Rust cache from PRs
<https://github.com/swatinem/rust-cache>
caches only dependencies, and
dependencies don't change most of the time,
so PRs store the same cache
as already stored
by the main branch commit PRs are based on.

Hash of Cargo.{toml,lock} is part of the
cache key, so for dependency updating PRs
the cache key is new. Such PRs
rebuild everything from scratch,
which is a separate problem.
Storing such cache from PR is however
not useful because most of the time
dependency updating PR is going
to be rebased again before merging
as Dependabot PRs are opened in a batch
and then merged one by one
while Dependabot rebases remaining PRs.
2026-05-04 11:21:33 +00:00
dependabot[bot]
35ceb51ffc chore(cargo): bump libc from 0.2.184 to 0.2.186
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.184 to 0.2.186.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.186/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.184...0.2.186)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-04 04:16:07 +00:00
17 changed files with 98 additions and 135 deletions

View File

@@ -41,6 +41,8 @@ jobs:
shell: bash shell: bash
- name: Cache rust cargo artifacts - name: Cache rust cargo artifacts
uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Run rustfmt - name: Run rustfmt
run: cargo fmt --all -- --check run: cargo fmt --all -- --check
- name: Run clippy - name: Run clippy
@@ -92,6 +94,8 @@ jobs:
persist-credentials: false persist-credentials: false
- name: Cache rust cargo artifacts - name: Cache rust cargo artifacts
uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Rustdoc - name: Rustdoc
run: cargo doc --document-private-items --no-deps run: cargo doc --document-private-items --no-deps
@@ -135,6 +139,8 @@ jobs:
- name: Cache rust cargo artifacts - name: Cache rust cargo artifacts
uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Install nextest - name: Install nextest
uses: taiki-e/install-action@5f57d6cb7cd20b14a8a27f522884c4bc8a187458 uses: taiki-e/install-action@5f57d6cb7cd20b14a8a27f522884c4bc8a187458
@@ -169,6 +175,8 @@ jobs:
- name: Cache rust cargo artifacts - name: Cache rust cargo artifacts
uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Build C library - name: Build C library
run: cargo build -p deltachat_ffi run: cargo build -p deltachat_ffi
@@ -195,6 +203,8 @@ jobs:
- name: Cache rust cargo artifacts - name: Cache rust cargo artifacts
uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Build deltachat-rpc-server - name: Build deltachat-rpc-server
run: cargo build -p deltachat-rpc-server run: cargo build -p deltachat-rpc-server

23
Cargo.lock generated
View File

@@ -934,9 +934,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]] [[package]]
name = "colorutils-rs" name = "colorutils-rs"
version = "0.7.6" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e2fc25857fa523662de5cae84225b0e7bfb24a2a3f9ed8802fecf03df7252b1" checksum = "69abc9a8ed011e2b7946769f460b9e76e8b659ece9ef4001b9d8bba3489f796d"
dependencies = [ dependencies = [
"erydanos", "erydanos",
"half", "half",
@@ -1301,9 +1301,9 @@ dependencies = [
[[package]] [[package]]
name = "data-encoding" name = "data-encoding"
version = "2.10.0" version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8"
[[package]] [[package]]
name = "dbl" name = "dbl"
@@ -2662,7 +2662,7 @@ dependencies = [
"hyper", "hyper",
"libc", "libc",
"pin-project-lite", "pin-project-lite",
"socket2 0.5.9", "socket2 0.6.3",
"tokio", "tokio",
"tower-service", "tower-service",
"tracing", "tracing",
@@ -3268,9 +3268,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.184" version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]] [[package]]
name = "libm" name = "libm"
@@ -3941,15 +3941,14 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]] [[package]]
name = "openssl" name = "openssl"
version = "0.10.78" version = "0.10.79"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" checksum = "bf0b434746ee2832f4f0baf10137e1cabb18cbe6912c69e2e33263c45250f542"
dependencies = [ dependencies = [
"bitflags 2.11.0", "bitflags 2.11.0",
"cfg-if", "cfg-if",
"foreign-types", "foreign-types",
"libc", "libc",
"once_cell",
"openssl-macros", "openssl-macros",
"openssl-sys", "openssl-sys",
] ]
@@ -3982,9 +3981,9 @@ dependencies = [
[[package]] [[package]]
name = "openssl-sys" name = "openssl-sys"
version = "0.9.114" version = "0.9.115"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" checksum = "158fe5b292746440aa6e7a7e690e55aeb72d41505e2804c23c6973ad0e9c9781"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",

View File

@@ -53,7 +53,7 @@ blake3 = "1.8.2"
brotli = { version = "8", default-features=false, features = ["std"] } brotli = { version = "8", default-features=false, features = ["std"] }
bytes = "1" bytes = "1"
chrono = { workspace = true, features = ["alloc", "clock", "std"] } chrono = { workspace = true, features = ["alloc", "clock", "std"] }
colorutils-rs = { version = "0.7.5", default-features = false } colorutils-rs = { version = "0.8.0", default-features = false }
data-encoding = "2.9.0" data-encoding = "2.9.0"
escaper = "0.1" escaper = "0.1"
fast-socks5 = "1" fast-socks5 = "1"

View File

@@ -4003,8 +4003,6 @@ int dc_msg_get_viewtype (const dc_msg_t* msg);
* Marked as read on IMAP and MDN may be sent. Use dc_markseen_msgs() to mark messages as being seen. * Marked as read on IMAP and MDN may be sent. Use dc_markseen_msgs() to mark messages as being seen.
* *
* Outgoing message states: * Outgoing message states:
* - @ref DC_STATE_OUT_PREPARING - For files which need time to be prepared before they can be sent,
* the message enters this state before @ref DC_STATE_OUT_PENDING. Deprecated.
* - @ref DC_STATE_OUT_DRAFT - Message saved as draft using dc_set_draft() * - @ref DC_STATE_OUT_DRAFT - Message saved as draft using dc_set_draft()
* - @ref DC_STATE_OUT_PENDING - The user has pressed the "send" button but the * - @ref DC_STATE_OUT_PENDING - The user has pressed the "send" button but the
* message is not yet sent and is pending in some way. Maybe we're offline (no checkmark). * message is not yet sent and is pending in some way. Maybe we're offline (no checkmark).
@@ -5589,13 +5587,6 @@ int64_t dc_lot_get_timestamp (const dc_lot_t* lot);
*/ */
#define DC_STATE_IN_SEEN 16 #define DC_STATE_IN_SEEN 16
/**
* Outgoing message being prepared. See dc_msg_get_state() for details.
*
* @deprecated 2024-12-07
*/
#define DC_STATE_OUT_PREPARING 18
/** /**
* Outgoing message drafted. See dc_msg_get_state() for details. * Outgoing message drafted. See dc_msg_get_state() for details.
*/ */

View File

@@ -230,7 +230,6 @@ pub enum LotState {
MsgInFresh = 10, MsgInFresh = 10,
MsgInNoticed = 13, MsgInNoticed = 13,
MsgInSeen = 16, MsgInSeen = 16,
MsgOutPreparing = 18,
MsgOutDraft = 19, MsgOutDraft = 19,
MsgOutPending = 20, MsgOutPending = 20,
MsgOutFailed = 24, MsgOutFailed = 24,
@@ -246,7 +245,6 @@ impl From<MessageState> for LotState {
InFresh => LotState::MsgInFresh, InFresh => LotState::MsgInFresh,
InNoticed => LotState::MsgInNoticed, InNoticed => LotState::MsgInNoticed,
InSeen => LotState::MsgInSeen, InSeen => LotState::MsgInSeen,
OutPreparing => LotState::MsgOutPreparing,
OutDraft => LotState::MsgOutDraft, OutDraft => LotState::MsgOutDraft,
OutPending => LotState::MsgOutPending, OutPending => LotState::MsgOutPending,
OutFailed => LotState::MsgOutFailed, OutFailed => LotState::MsgOutFailed,

View File

@@ -190,7 +190,6 @@ class MessageState(IntEnum):
IN_FRESH = 10 IN_FRESH = 10
IN_NOTICED = 13 IN_NOTICED = 13
IN_SEEN = 16 IN_SEEN = 16
OUT_PREPARING = 18
OUT_DRAFT = 19 OUT_DRAFT = 19
OUT_PENDING = 20 OUT_PENDING = 20
OUT_FAILED = 24 OUT_FAILED = 24

View File

@@ -271,15 +271,6 @@ class Chat:
sent out. This is the same object as was passed in, which sent out. This is the same object as was passed in, which
has been modified with the new state of the core. has been modified with the new state of the core.
""" """
if msg.is_out_preparing():
assert msg.id != 0
# get a fresh copy of dc_msg, the core needs it
maybe_msg = Message.from_db(self.account, msg.id)
if maybe_msg is not None:
msg = maybe_msg
else:
raise ValueError("message does not exist")
sent_id = lib.dc_send_msg(self.account._dc_context, self.id, msg._dc_msg) sent_id = lib.dc_send_msg(self.account._dc_context, self.id, msg._dc_msg)
if sent_id == 0: if sent_id == 0:
raise ValueError("message could not be sent") raise ValueError("message could not be sent")
@@ -333,26 +324,6 @@ class Chat:
raise ValueError("message could not be sent") raise ValueError("message could not be sent")
return Message.from_db(self.account, sent_id) return Message.from_db(self.account, sent_id)
def send_prepared(self, message):
"""send a previously prepared message.
:param message: a :class:`Message` instance previously returned by
:meth:`prepare_file`.
:raises ValueError: if message can not be sent.
:returns: a :class:`deltachat.message.Message` instance as sent out.
"""
assert message.id != 0 and message.is_out_preparing()
# get a fresh copy of dc_msg, the core needs it
msg = Message.from_db(self.account, message.id)
# pass 0 as chat-id because core-docs say it's ok when out-preparing
sent_id = lib.dc_send_msg(self.account._dc_context, 0, msg._dc_msg)
if sent_id == 0:
raise ValueError("message could not be sent")
assert sent_id == msg.id
# modify message in place to avoid bad state for the caller
msg._dc_msg = Message.from_db(self.account, sent_id)._dc_msg
def set_draft(self, message): def set_draft(self, message):
"""set message as draft. """set message as draft.

View File

@@ -351,17 +351,12 @@ class Message:
def is_outgoing(self): def is_outgoing(self):
"""Return True if Message is outgoing.""" """Return True if Message is outgoing."""
return lib.dc_msg_get_state(self._dc_msg) in ( return lib.dc_msg_get_state(self._dc_msg) in (
const.DC_STATE_OUT_PREPARING,
const.DC_STATE_OUT_PENDING, const.DC_STATE_OUT_PENDING,
const.DC_STATE_OUT_FAILED, const.DC_STATE_OUT_FAILED,
const.DC_STATE_OUT_MDN_RCVD, const.DC_STATE_OUT_MDN_RCVD,
const.DC_STATE_OUT_DELIVERED, const.DC_STATE_OUT_DELIVERED,
) )
def is_out_preparing(self):
"""Return True if Message is outgoing, but its file is being prepared."""
return self._msgstate == const.DC_STATE_OUT_PREPARING
def is_out_pending(self): def is_out_pending(self):
"""Return True if Message is outgoing, but is pending (no single checkmark).""" """Return True if Message is outgoing, but is pending (no single checkmark)."""
return self._msgstate == const.DC_STATE_OUT_PENDING return self._msgstate == const.DC_STATE_OUT_PENDING

View File

@@ -2613,7 +2613,7 @@ pub async fn send_msg(context: &Context, chat_id: ChatId, msg: &mut Message) ->
"chat_id cannot be a special chat: {chat_id}" "chat_id cannot be a special chat: {chat_id}"
); );
if msg.state != MessageState::Undefined && msg.state != MessageState::OutPreparing { if msg.state != MessageState::Undefined {
msg.param.remove(Param::GuaranteeE2ee); msg.param.remove(Param::GuaranteeE2ee);
msg.param.remove(Param::ForcePlaintext); msg.param.remove(Param::ForcePlaintext);
// create_send_msg_jobs() will update `param` in the db. // create_send_msg_jobs() will update `param` in the db.
@@ -2721,10 +2721,7 @@ async fn prepare_send_msg(
None None
}; };
if matches!( if msg.state == MessageState::Undefined
msg.state,
MessageState::Undefined | MessageState::OutPreparing
)
// Legacy SecureJoin "v*-request" messages are unencrypted. // Legacy SecureJoin "v*-request" messages are unencrypted.
&& msg.param.get_cmd() != SystemMessage::SecurejoinMessage && msg.param.get_cmd() != SystemMessage::SecurejoinMessage
&& chat.is_encrypted(context).await? && chat.is_encrypted(context).await?
@@ -2937,8 +2934,8 @@ pub(crate) async fn create_send_msg_jobs(context: &Context, msg: &mut Message) -
UPDATE msgs SET UPDATE msgs SET
timestamp=( timestamp=(
SELECT MAX(timestamp) FROM msgs INDEXED BY msgs_index7 WHERE SELECT MAX(timestamp) FROM msgs INDEXED BY msgs_index7 WHERE
-- From `InFresh` to `OutMdnRcvd` inclusive except `OutDraft`. -- From `InFresh` to `OutDelivered` inclusive, except `OutDraft`.
state IN(10,13,16,18,20,24,26,28) AND state IN(10,13,16,18,20,24,26) AND
hidden IN(0,1) AND hidden IN(0,1) AND
chat_id=? AND chat_id=? AND
id<=? id<=?
@@ -4539,6 +4536,7 @@ pub async fn forward_msgs_2ctx(
msg.state = MessageState::OutPending; msg.state = MessageState::OutPending;
msg.rfc724_mid = create_outgoing_rfc724_mid(); msg.rfc724_mid = create_outgoing_rfc724_mid();
msg.pre_rfc724_mid.clear();
msg.timestamp_sort = curr_timestamp; msg.timestamp_sort = curr_timestamp;
chat.prepare_msg_raw(ctx_dst, &mut msg, None).await?; chat.prepare_msg_raw(ctx_dst, &mut msg, None).await?;

View File

@@ -1381,13 +1381,8 @@ pub enum MessageState {
/// IMAP and MDN may be sent. /// IMAP and MDN may be sent.
InSeen = 16, InSeen = 16,
/// For files which need time to be prepared before they can be // Deprecated 2024-12-07. Removed 2026-04.
/// sent, the message enters this state before // OutPreparing = 18,
/// OutPending.
///
/// Deprecated 2024-12-07.
OutPreparing = 18,
/// Message saved as draft. /// Message saved as draft.
OutDraft = 19, OutDraft = 19,
@@ -1420,7 +1415,6 @@ impl std::fmt::Display for MessageState {
Self::InFresh => "Fresh", Self::InFresh => "Fresh",
Self::InNoticed => "Noticed", Self::InNoticed => "Noticed",
Self::InSeen => "Seen", Self::InSeen => "Seen",
Self::OutPreparing => "Preparing",
Self::OutDraft => "Draft", Self::OutDraft => "Draft",
Self::OutPending => "Pending", Self::OutPending => "Pending",
Self::OutFailed => "Failed", Self::OutFailed => "Failed",
@@ -1437,7 +1431,7 @@ impl MessageState {
use MessageState::*; use MessageState::*;
matches!( matches!(
self, self,
OutPreparing | OutPending | OutDelivered | OutMdnRcvd // OutMdnRcvd can still fail because it could be a group message and only some recipients failed. OutPending | OutDelivered | OutMdnRcvd // OutMdnRcvd can still fail because it could be a group message and only some recipients failed.
) )
} }
@@ -1446,7 +1440,7 @@ impl MessageState {
use MessageState::*; use MessageState::*;
matches!( matches!(
self, self,
OutPreparing | OutDraft | OutPending | OutFailed | OutDelivered | OutMdnRcvd OutDraft | OutPending | OutFailed | OutDelivered | OutMdnRcvd
) )
} }

View File

@@ -231,10 +231,7 @@ static DNS_PRELOAD: LazyLock<HashMap<&'static str, Vec<IpAddr>>> = LazyLock::new
HashMap::from([ HashMap::from([
( (
"imap.163.com", "imap.163.com",
vec![ vec![IpAddr::V4(Ipv4Addr::new(111, 124, 203, 45))],
IpAddr::V4(Ipv4Addr::new(111, 124, 203, 45)),
IpAddr::V4(Ipv4Addr::new(111, 124, 203, 50)),
],
), ),
( (
"smtp.163.com", "smtp.163.com",
@@ -425,12 +422,12 @@ static DNS_PRELOAD: LazyLock<HashMap<&'static str, Vec<IpAddr>>> = LazyLock::new
"nine.testrun.org", "nine.testrun.org",
vec![ vec![
IpAddr::V4(Ipv4Addr::new(128, 140, 126, 197)), IpAddr::V4(Ipv4Addr::new(128, 140, 126, 197)),
IpAddr::V4(Ipv4Addr::new(116, 202, 233, 236)),
IpAddr::V4(Ipv4Addr::new(216, 144, 228, 100)), IpAddr::V4(Ipv4Addr::new(216, 144, 228, 100)),
IpAddr::V4(Ipv4Addr::new(77, 42, 49, 41)), IpAddr::V6(Ipv6Addr::new(0x2a01, 0x4f8, 0x241, 0x4ce8, 0, 0, 0, 2)),
IpAddr::V6(Ipv6Addr::new( IpAddr::V6(Ipv6Addr::new(
0x2001, 0x41d0, 0x701, 0x1100, 0, 0, 0, 0x8ab1, 0x2001, 0x41d0, 0x701, 0x1100, 0, 0, 0, 0x8ab1,
)), )),
IpAddr::V6(Ipv6Addr::new(0x2a01, 0x4f9, 0xfff1, 0x59, 0, 0, 0, 1)),
], ],
), ),
( (
@@ -700,10 +697,6 @@ static DNS_PRELOAD: LazyLock<HashMap<&'static str, Vec<IpAddr>>> = LazyLock::new
"chatmail.hackea.org", "chatmail.hackea.org",
vec![IpAddr::V4(Ipv4Addr::new(82, 165, 11, 85))], vec![IpAddr::V4(Ipv4Addr::new(82, 165, 11, 85))],
), ),
(
"chat.adminforge.de",
vec![IpAddr::V4(Ipv4Addr::new(94, 130, 17, 142))],
),
( (
"chika.aangat.lahat.computer", "chika.aangat.lahat.computer",
vec![IpAddr::V4(Ipv4Addr::new(71, 19, 150, 113))], vec![IpAddr::V4(Ipv4Addr::new(71, 19, 150, 113))],
@@ -745,46 +738,6 @@ static DNS_PRELOAD: LazyLock<HashMap<&'static str, Vec<IpAddr>>> = LazyLock::new
"danneskjold.de", "danneskjold.de",
vec![IpAddr::V4(Ipv4Addr::new(46, 62, 216, 132))], vec![IpAddr::V4(Ipv4Addr::new(46, 62, 216, 132))],
), ),
(
"chat.in-the.eu",
vec![IpAddr::V4(Ipv4Addr::new(78, 46, 190, 129))],
),
(
"chat.nuvon.app",
vec![IpAddr::V4(Ipv4Addr::new(178, 238, 38, 165))],
),
(
"nibblehole.com",
vec![IpAddr::V4(Ipv4Addr::new(94, 247, 42, 209))],
),
(
"chat.zashm.org",
vec![IpAddr::V4(Ipv4Addr::new(91, 245, 76, 39))],
),
(
"chat.sus.fr",
vec![IpAddr::V4(Ipv4Addr::new(152, 67, 76, 190))],
),
(
"delta.thelab.uno",
vec![IpAddr::V4(Ipv4Addr::new(146, 59, 228, 39))],
),
(
"chat.vim.wtf",
vec![IpAddr::V4(Ipv4Addr::new(116, 203, 206, 170))],
),
(
"uninterest.ing",
vec![IpAddr::V4(Ipv4Addr::new(172, 245, 70, 237))],
),
(
"sweetfern.net",
vec![IpAddr::V4(Ipv4Addr::new(178, 156, 228, 133))],
),
(
"delta.disobey.net",
vec![IpAddr::V4(Ipv4Addr::new(37, 74, 102, 44))],
),
( (
"darkrun.dev", "darkrun.dev",
vec![IpAddr::V4(Ipv4Addr::new(72, 11, 149, 146))], vec![IpAddr::V4(Ipv4Addr::new(72, 11, 149, 146))],

View File

@@ -66,12 +66,6 @@ impl Context {
/// Updates `quota.recent`, sets `quota.modified` to the current time /// Updates `quota.recent`, sets `quota.modified` to the current time
/// and emits an event to let the UIs update connectivity view. /// and emits an event to let the UIs update connectivity view.
///
/// Moreover, once each time quota gets larger than `QUOTA_WARN_THRESHOLD_PERCENTAGE`,
/// a device message is added.
/// As the message is added only once, the user is not spammed
/// in case for some providers the quota is always at ~100%
/// and new space is allocated as needed.
pub(crate) async fn update_recent_quota( pub(crate) async fn update_recent_quota(
&self, &self,
session: &mut ImapSession, session: &mut ImapSession,

View File

@@ -806,8 +806,6 @@ UPDATE config SET value=? WHERE keyname='configured_addr' AND value!=?1
if transport_changed { if transport_changed {
info!(context, "Primary transport changed to {from_addr:?}."); info!(context, "Primary transport changed to {from_addr:?}.");
context.sql.uncache_raw_config("configured_addr").await; context.sql.uncache_raw_config("configured_addr").await;
// Regenerate User ID in V4 keys.
context.self_public_key.lock().await.take(); context.self_public_key.lock().await.take();
context.emit_event(EventType::TransportsModified); context.emit_event(EventType::TransportsModified);

View File

@@ -2373,6 +2373,18 @@ ALTER TABLE contacts ADD COLUMN name_normalized TEXT;
.await?; .await?;
} }
inc_and_check(&mut migration_version, 152)?;
if dbversion < migration_version {
sql.execute_migration(
"
UPDATE msgs SET state=26 WHERE state=28; -- Change OutMdnRcvd to OutDelivered.
UPDATE msgs SET state=19 WHERE state=24; -- Change OutPreparing to OutFailed.
",
migration_version,
)
.await?;
}
let new_version = sql let new_version = sql
.get_raw_config_int(VERSION_CFG) .get_raw_config_int(VERSION_CFG)
.await? .await?

View File

@@ -1,4 +1,6 @@
//! Tests about forwarding and saving Pre-Messages //! Tests about forwarding and saving Pre-Messages
use std::time::Duration;
use anyhow::Result; use anyhow::Result;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
@@ -8,6 +10,7 @@ use crate::chatlist::get_last_message_for_chat;
use crate::download::{DownloadState, PRE_MSG_ATTACHMENT_SIZE_THRESHOLD}; use crate::download::{DownloadState, PRE_MSG_ATTACHMENT_SIZE_THRESHOLD};
use crate::message::{Message, Viewtype}; use crate::message::{Message, Viewtype};
use crate::test_utils::TestContextManager; use crate::test_utils::TestContextManager;
use crate::tests::pre_messages::util::send_large_file_message;
/// Test that forwarding Pre-Message should forward additional text to not be empty /// Test that forwarding Pre-Message should forward additional text to not be empty
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -86,6 +89,43 @@ async fn test_forwarding_pre_message_empty_text() -> Result<()> {
Ok(()) Ok(())
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_receive_both() -> Result<()> {
let mut tcm = TestContextManager::new();
let alice = &tcm.alice().await;
let bob = &tcm.bob().await;
let alice_chat_id = alice.create_group_with_members("", &[bob]).await;
let (pre_message, post_message, alice_msg_id) =
send_large_file_message(alice, alice_chat_id, Viewtype::File, &vec![0u8; 200_000]).await?;
let msg = bob.recv_msg(&pre_message).await;
let _ = bob.recv_msg_trash(&post_message).await;
let msg = Message::load_from_db(bob, msg.id).await?;
assert_eq!(msg.download_state(), DownloadState::Done);
assert_eq!(msg.text, "test".to_owned());
forward_msgs(alice, &[alice_msg_id], alice_chat_id).await?;
let rev_order = false;
let msg = bob
.recv_msg(
&alice
.pop_sent_msg_ex(rev_order, Duration::ZERO)
.await
.unwrap(),
)
.await;
assert_eq!(msg.download_state(), DownloadState::Available);
assert_eq!(msg.is_forwarded(), true);
assert_eq!(msg.text, "test".to_owned());
let _ = bob.recv_msg_trash(&alice.pop_sent_msg().await).await;
let msg = Message::load_from_db(bob, msg.id).await?;
assert_eq!(msg.download_state(), DownloadState::Done);
assert_eq!(msg.is_forwarded(), true);
assert_eq!(msg.text, "test".to_owned());
Ok(())
}
/// Test that forwarding Pre-Message should forward additional text to not be empty /// Test that forwarding Pre-Message should forward additional text to not be empty
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_saving_pre_message_empty_text() -> Result<()> { async fn test_saving_pre_message_empty_text() -> Result<()> {

View File

@@ -791,7 +791,18 @@ pub(crate) async fn sync_transports(
context context
.sql .sql
.transaction(|transaction| { .transaction(|transaction| {
let configured_addr = transaction.query_row(
"SELECT value FROM config WHERE keyname='configured_addr'",
(),
|row| {
let addr: String = row.get(0)?;
Ok(addr)
},
)?;
for RemovedTransportData { addr, timestamp } in removed_transports { for RemovedTransportData { addr, timestamp } in removed_transports {
if *addr == configured_addr {
continue;
}
modified |= transaction.execute( modified |= transaction.execute(
"DELETE FROM transports "DELETE FROM transports
WHERE addr=? AND add_timestamp<=?", WHERE addr=? AND add_timestamp<=?",

View File

@@ -550,7 +550,7 @@ impl Context {
let send_now = !matches!( let send_now = !matches!(
instance.state, instance.state,
MessageState::Undefined | MessageState::OutPreparing | MessageState::OutDraft MessageState::Undefined | MessageState::OutDraft
); );
status_update.uid = Some(create_id()); status_update.uid = Some(create_id());