Compare commits

..

7 Commits

Author SHA1 Message Date
link2xt
8132f32e91 chore: allow passing arguments to scripts/clippy.sh
This makes it possible to run `scripts/clippy.sh --fix --allow-dirty`
to fix clippy warnings automatically.
2026-05-12 16:28:22 +00:00
dependabot[bot]
3d28951885 chore(deps): bump cachix/install-nix-action from 31.10.5 to 31.10.6
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 31.10.5 to 31.10.6.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Changelog](https://github.com/cachix/install-nix-action/blob/master/RELEASE.md)
- [Commits](ab739621df...8aa03977d8)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-version: 31.10.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-12 16:27:52 +00:00
dependabot[bot]
bc2d624a80 chore(deps): bump taiki-e/install-action from 2.75.19 to 2.77.1
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.75.19 to 2.77.1.
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](5f57d6cb7c...cca35edeb1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-12 16:27:21 +00:00
link2xt
fa8fcaaa2b refactor: use some more let..else 2026-05-12 16:26:38 +00:00
link2xt
31c74d82bd fix: fix migration 152
It was converting OutFailed to OutDraft
instead of converting OutPreparing to OutFailed.
2026-05-11 20:53:00 +00:00
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
20 changed files with 126 additions and 150 deletions

View File

@@ -143,7 +143,7 @@ jobs:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Install nextest
uses: taiki-e/install-action@5f57d6cb7cd20b14a8a27f522884c4bc8a187458
uses: taiki-e/install-action@cca35edeb1d01366c2843b68fc3ca441446d73d3
with:
tool: nextest

View File

@@ -34,7 +34,7 @@ jobs:
with:
show-progress: false
persist-credentials: false
- uses: cachix/install-nix-action@ab739621df7a23f52766f9ccc97f38da6b7af14f # v31.10.5
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- name: Build deltachat-rpc-server binaries
run: nix build .#deltachat-rpc-server-${{ matrix.arch }}-linux
@@ -58,7 +58,7 @@ jobs:
with:
show-progress: false
persist-credentials: false
- uses: cachix/install-nix-action@ab739621df7a23f52766f9ccc97f38da6b7af14f # v31.10.5
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- name: Build deltachat-rpc-server wheels
run: nix build .#deltachat-rpc-server-${{ matrix.arch }}-linux-wheel
@@ -82,7 +82,7 @@ jobs:
with:
show-progress: false
persist-credentials: false
- uses: cachix/install-nix-action@ab739621df7a23f52766f9ccc97f38da6b7af14f # v31.10.5
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- name: Build deltachat-rpc-server binaries
run: nix build .#deltachat-rpc-server-${{ matrix.arch }}
@@ -106,7 +106,7 @@ jobs:
with:
show-progress: false
persist-credentials: false
- uses: cachix/install-nix-action@ab739621df7a23f52766f9ccc97f38da6b7af14f # v31.10.5
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- name: Build deltachat-rpc-server wheels
run: nix build .#deltachat-rpc-server-${{ matrix.arch }}-wheel
@@ -157,7 +157,7 @@ jobs:
with:
show-progress: false
persist-credentials: false
- uses: cachix/install-nix-action@ab739621df7a23f52766f9ccc97f38da6b7af14f # v31.10.5
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- name: Build deltachat-rpc-server binaries
run: nix build .#deltachat-rpc-server-${{ matrix.arch }}-android
@@ -181,7 +181,7 @@ jobs:
with:
show-progress: false
persist-credentials: false
- uses: cachix/install-nix-action@ab739621df7a23f52766f9ccc97f38da6b7af14f # v31.10.5
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- name: Build deltachat-rpc-server wheels
run: nix build .#deltachat-rpc-server-${{ matrix.arch }}-android-wheel
@@ -208,7 +208,7 @@ jobs:
with:
show-progress: false
persist-credentials: false
- uses: cachix/install-nix-action@ab739621df7a23f52766f9ccc97f38da6b7af14f # v31.10.5
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- name: Download Linux aarch64 binary
uses: actions/download-artifact@v7

View File

@@ -25,7 +25,7 @@ jobs:
with:
show-progress: false
persist-credentials: false
- uses: cachix/install-nix-action@ab739621df7a23f52766f9ccc97f38da6b7af14f # v31.10.5
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- run: nix fmt flake.nix -- --check
build:
@@ -84,7 +84,7 @@ jobs:
with:
show-progress: false
persist-credentials: false
- uses: cachix/install-nix-action@ab739621df7a23f52766f9ccc97f38da6b7af14f # v31.10.5
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- run: nix build .#${{ matrix.installable }}
build-macos:
@@ -105,5 +105,5 @@ jobs:
with:
show-progress: false
persist-credentials: false
- uses: cachix/install-nix-action@ab739621df7a23f52766f9ccc97f38da6b7af14f # v31.10.5
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- run: nix build .#${{ matrix.installable }}

View File

@@ -18,7 +18,7 @@ jobs:
with:
show-progress: false
persist-credentials: false
- uses: cachix/install-nix-action@ab739621df7a23f52766f9ccc97f38da6b7af14f # v31.10.5
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- name: Build
run: nix build .#deltachat-repl-win64
- name: Upload binary

View File

@@ -41,7 +41,7 @@ jobs:
show-progress: false
persist-credentials: false
fetch-depth: 0 # Fetch history to calculate VCS version number.
- uses: cachix/install-nix-action@ab739621df7a23f52766f9ccc97f38da6b7af14f # v31.10.5
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- name: Build Python documentation
run: nix build .#python-docs
- name: Upload to py.delta.chat
@@ -63,7 +63,7 @@ jobs:
show-progress: false
persist-credentials: false
fetch-depth: 0 # Fetch history to calculate VCS version number.
- uses: cachix/install-nix-action@ab739621df7a23f52766f9ccc97f38da6b7af14f # v31.10.5
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- name: Build C documentation
run: nix build .#docs
- name: Upload to c.delta.chat

View File

@@ -251,7 +251,12 @@ def test_realtime_large_webxdc(acfactory, path_to_large_webxdc):
ac1_ac2_chat = ac1.create_chat(ac2)
ac1_webxdc_msg = ac1_ac2_chat.send_message(text="realtime check", file=path_to_large_webxdc)
# Receive pre-message.
ac2_webxdc_msg = ac2.wait_for_incoming_msg()
# Receive post-message.
ac2_webxdc_msg = ac2.wait_for_msg(EventType.MSGS_CHANGED)
ac2_webxdc_msg.send_webxdc_realtime_advertisement()
event = ac1.wait_for_event(EventType.WEBXDC_REALTIME_ADVERTISEMENT_RECEIVED)
assert event.msg_id == ac1_webxdc_msg.id

View File

@@ -865,6 +865,10 @@ def test_delete_fully_downloaded_msg(acfactory, tmp_path, direct_imap):
msg = bob.wait_for_incoming_msg()
msg_snapshot = msg.get_snapshot()
assert msg_snapshot.download_state == DownloadState.AVAILABLE
msgs_changed_event = bob.wait_for_msgs_changed_event()
assert msgs_changed_event.msg_id == msg.id
msg_snapshot = msg.get_snapshot()
assert msg_snapshot.download_state == DownloadState.DONE
bob_direct_imap = direct_imap(bob)
@@ -895,6 +899,10 @@ def test_imap_autodelete_fully_downloaded_msg(acfactory, tmp_path, direct_imap):
msg = bob.wait_for_incoming_msg()
msg_snapshot = msg.get_snapshot()
assert msg_snapshot.download_state == DownloadState.AVAILABLE
msgs_changed_event = bob.wait_for_msgs_changed_event()
assert msgs_changed_event.msg_id == msg.id
msg_snapshot = msg.get_snapshot()
assert msg_snapshot.download_state == DownloadState.DONE
bob_direct_imap = direct_imap(bob)
@@ -1371,5 +1379,7 @@ def test_large_message(acfactory) -> None:
)
msg = bob.wait_for_incoming_msg()
msgs_changed_event = bob.wait_for_msgs_changed_event()
assert msg.id == msgs_changed_event.msg_id
snapshot = msg.get_snapshot()
assert snapshot.text == "Hello World, this message is bigger than 5 bytes"

View File

@@ -1,3 +1,9 @@
#!/bin/sh
# Run clippy for all Rust code in the project.
cargo clippy --workspace --all-targets --all-features -- -D warnings
#
# To check, run
# scripts/clippy.sh
#
# To automatically fix warnings, run
# scripts/clippy.sh --fix --allow-dirty
cargo clippy --workspace --all-targets --all-features "$@" -- -D warnings

View File

@@ -2970,6 +2970,15 @@ WHERE id=?
)?;
for recipients_chunk in recipients.chunks(chunk_size) {
let recipients_chunk = recipients_chunk.join(" ");
if let Some(pre_msg) = &rendered_pre_msg {
let row_id = stmt.execute((
&pre_msg.rfc724_mid,
&recipients_chunk,
&pre_msg.message,
msg.id,
))?;
row_ids.push(row_id.try_into()?);
}
let row_id = stmt.execute((
&rendered_msg.rfc724_mid,
&recipients_chunk,
@@ -2977,16 +2986,6 @@ WHERE id=?
msg.id,
))?;
row_ids.push(row_id.try_into()?);
let Some(pre_msg) = &rendered_pre_msg else {
continue;
};
let row_id = stmt.execute((
&pre_msg.rfc724_mid,
&recipients_chunk,
&pre_msg.message,
msg.id,
))?;
row_ids.push(row_id.try_into()?);
}
Ok(row_ids)
};

View File

@@ -10,7 +10,6 @@ use crate::context::Context;
use crate::imap::session::Session;
use crate::log::warn;
use crate::message::{self, Message, MsgId, rfc724_mid_exists};
use crate::tools;
use crate::{EventType, chatlist_events};
pub(crate) mod post_msg_metadata;
@@ -321,22 +320,12 @@ pub(crate) async fn download_known_post_messages_without_pre_message(
context: &Context,
session: &mut Session,
) -> Result<()> {
const PRE_MSG_WAIT_TIME: i64 = 30;
let now = tools::time();
let rfc724_mids = context
.sql
.query_map_vec(
"
SELECT rfc724_mid FROM available_post_msgs
WHERE timestamp<=? OR timestamp>?
ORDER BY timestamp, rowid
",
(now.saturating_sub(PRE_MSG_WAIT_TIME), now),
|row| {
let rfc724_mid: String = row.get(0)?;
Ok(rfc724_mid)
},
)
.query_map_vec("SELECT rfc724_mid FROM available_post_msgs", (), |row| {
let rfc724_mid: String = row.get(0)?;
Ok(rfc724_mid)
})
.await?;
for rfc724_mid in &rfc724_mids {
if msg_is_downloaded_for(context, rfc724_mid).await? {

View File

@@ -601,7 +601,7 @@ impl Imap {
let _fetch_msgs_lock_guard = context.fetch_msgs_mutex.lock().await;
let mut uids_fetch: Vec<u32> = Vec::new();
let mut available_post_msgs: Vec<(String, i64)> = Vec::new();
let mut available_post_msgs: Vec<String> = Vec::new();
let mut download_later: Vec<String> = Vec::new();
let mut uid_message_ids = BTreeMap::new();
let mut largest_uid_skipped = None;
@@ -689,7 +689,7 @@ impl Imap {
.is_some()
{
info!(context, "{message_id:?} is a post-message.");
available_post_msgs.push((message_id.clone(), time()));
available_post_msgs.push(message_id.clone());
let is_bot = context.get_config_bool(Config::Bot).await?;
if is_bot && download_limit.is_none_or(|download_limit| size <= download_limit)
@@ -793,10 +793,9 @@ impl Imap {
download_later.len(),
);
let trans_fn = |t: &mut rusqlite::Transaction| {
let mut stmt =
t.prepare("INSERT OR IGNORE INTO available_post_msgs VALUES (?,?)")?;
for entry in available_post_msgs {
stmt.execute(entry)
let mut stmt = t.prepare("INSERT OR IGNORE INTO available_post_msgs VALUES (?)")?;
for rfc724_mid in available_post_msgs {
stmt.execute((rfc724_mid,))
.context("INSERT OR IGNORE INTO available_post_msgs")?;
}
let mut stmt =

View File

@@ -427,18 +427,16 @@ mod tests {
let self_chat = ctx1.get_self_chat().await;
let msgs = get_chat_msgs(&ctx1, self_chat.id).await.unwrap();
assert_eq!(msgs.len(), 2);
let msgid = match msgs.first().unwrap() {
ChatItem::Message { msg_id } => msg_id,
_ => panic!("wrong chat item"),
let ChatItem::Message { msg_id } = msgs.first().unwrap() else {
panic!("wrong chat item");
};
let msg = Message::load_from_db(&ctx1, *msgid).await.unwrap();
let msg = Message::load_from_db(&ctx1, *msg_id).await.unwrap();
let text = msg.get_text();
assert_eq!(text, "hi there");
let msgid = match msgs.get(1).unwrap() {
ChatItem::Message { msg_id } => msg_id,
_ => panic!("wrong chat item"),
let ChatItem::Message { msg_id } = msgs.get(1).unwrap() else {
panic!("wrong chat item");
};
let msg = Message::load_from_db(&ctx1, *msgid).await.unwrap();
let msg = Message::load_from_db(&ctx1, *msg_id).await.unwrap();
let path = msg.get_file(&ctx1).unwrap();
assert_eq!(

View File

@@ -1723,19 +1723,23 @@ impl MimeFactory {
let footer = if is_reaction { "" } else { &self.selfstatus };
let message_text = format!(
"{}{}{}{}{}{}",
fwdhint.unwrap_or_default(),
quoted_text.unwrap_or_default(),
escape_message_footer_marks(final_text),
if !final_text.is_empty() && !footer.is_empty() {
"\r\n\r\n"
} else {
""
},
if !footer.is_empty() { "-- \r\n" } else { "" },
footer
);
let message_text = if self.pre_message_mode == PreMessageMode::Post {
"".to_string()
} else {
format!(
"{}{}{}{}{}{}",
fwdhint.unwrap_or_default(),
quoted_text.unwrap_or_default(),
escape_message_footer_marks(final_text),
if !final_text.is_empty() && !footer.is_empty() {
"\r\n\r\n"
} else {
""
},
if !footer.is_empty() { "-- \r\n" } else { "" },
footer
)
};
let mut main_part = MimePart::new("text/plain", message_text);
if is_reaction {

View File

@@ -525,10 +525,18 @@ pub(crate) async fn receive_imf_inner(
"Receiving message {rfc724_mid_orig:?}, seen={seen}...",
);
let msg_id = message::rfc724_mid_exists(context, rfc724_mid_orig).await?;
if let Some(msg_id) = msg_id
&& !mime_parser.incoming
{
// These checks must be done before processing of SecureJoin and other special messages.
if mime_parser.pre_message == mimeparser::PreMessageMode::Post {
// Post-Message just replaces the attachment and modifies Params, not the whole message.
// This is done in the `handle_post_message` method.
} else if let Some(msg_id) = message::rfc724_mid_exists(context, rfc724_mid_orig).await? {
info!(
context,
"Message {rfc724_mid} is already in some chat or deleted."
);
if mime_parser.incoming {
return Ok(None);
}
// For the case if we missed a successful SMTP response. Be optimistic that the message is
// delivered also.
let self_addr = context.get_primary_self_addr().await?;
@@ -543,16 +551,6 @@ pub(crate) async fn receive_imf_inner(
if !msg_has_pending_smtp_job(context, msg_id).await? {
msg_id.set_delivered(context).await?;
}
}
// These checks must be done before processing of SecureJoin and other special messages.
if mime_parser.pre_message == mimeparser::PreMessageMode::Post {
// Post-Message just replaces the attachment and modifies Params, not the whole message.
// This is done in the `update_from_post_msg` method.
} else if msg_id.is_some() {
info!(
context,
"Message {rfc724_mid} is already in some chat or deleted."
);
return Ok(None);
}
@@ -2081,7 +2079,7 @@ async fn add_parts(
}
handle_edit_delete(context, mime_parser, from_id).await?;
update_from_post_msg(context, mime_parser, from_id, state).await?;
handle_post_message(context, mime_parser, from_id, state).await?;
if mime_parser.is_system_message == SystemMessage::CallAccepted
|| mime_parser.is_system_message == SystemMessage::CallEnded
@@ -2275,7 +2273,8 @@ INSERT INTO msgs
// Maybe set logging xdc and add gossip topics for webxdcs.
for (part, msg_id) in mime_parser.parts.iter().zip(&created_db_entries) {
if part.typ == Viewtype::Webxdc
if mime_parser.pre_message != PreMessageMode::Post
&& part.typ == Viewtype::Webxdc
&& let Some(topic) = mime_parser.get_header(HeaderDef::IrohGossipTopic)
{
let topic = iroh_topic_from_str(topic)?;
@@ -2422,7 +2421,7 @@ async fn handle_edit_delete(
Ok(())
}
async fn update_from_post_msg(
async fn handle_post_message(
context: &Context,
mime_parser: &MimeMessage,
from_id: ContactId,
@@ -2440,7 +2439,7 @@ async fn update_from_post_msg(
let Some(msg_id) = message::rfc724_mid_exists(context, &rfc724_mid).await? else {
warn!(
context,
"update_from_post_msg: {rfc724_mid}: Database entry does not exist."
"handle_post_message: {rfc724_mid}: Database entry does not exist."
);
return Ok(());
};
@@ -2448,7 +2447,7 @@ async fn update_from_post_msg(
// else: message is processed like a normal message
warn!(
context,
"update_from_post_msg: {rfc724_mid}: Pre-message was not downloaded yet so treat as normal message."
"handle_post_message: {rfc724_mid}: Pre-message was not downloaded yet so treat as normal message."
);
return Ok(());
};
@@ -2459,7 +2458,7 @@ async fn update_from_post_msg(
// Do nothing if safety checks fail, the worst case is the message modifies the chat if the
// sender is a member.
if from_id != original_msg.from_id {
warn!(context, "update_from_post_msg: {rfc724_mid}: Bad sender.");
warn!(context, "handle_post_message: {rfc724_mid}: Bad sender.");
return Ok(());
}
let post_msg_showpadlock = part
@@ -2467,17 +2466,14 @@ async fn update_from_post_msg(
.get_bool(Param::GuaranteeE2ee)
.unwrap_or_default();
if !post_msg_showpadlock && original_msg.get_showpadlock() {
warn!(
context,
"update_from_post_msg: {rfc724_mid}: Not encrypted."
);
warn!(context, "handle_post_message: {rfc724_mid}: Not encrypted.");
return Ok(());
}
if !part.typ.has_file() {
warn!(
context,
"update_from_post_msg: {rfc724_mid}: First mime part's message-viewtype has no file."
"handle_post_message: {rfc724_mid}: First mime part's message-viewtype has no file."
);
return Ok(());
}
@@ -2508,10 +2504,7 @@ WHERE id=?
part.typ,
part.bytes as isize,
part.error.as_deref().unwrap_or_default(),
match mime_parser.incoming {
true => state,
false => MessageState::Undefined,
},
state,
DownloadState::Done as u32,
original_msg.id,
),

View File

@@ -704,10 +704,10 @@ async fn test_parse_ndn_group_msg() -> Result<()> {
assert_eq!(msg.state, MessageState::OutFailed);
let msgs = chat::get_chat_msgs(&t, msg.chat_id).await?;
let ChatItem::Message { msg_id } = *msgs.last().unwrap() else {
panic!("Wrong item type");
};
assert_eq!(msg_id, msg.id);
assert!(matches!(
*msgs.last().unwrap(),
ChatItem::Message { msg_id } if msg_id == msg.id
));
Ok(())
}
@@ -1598,9 +1598,7 @@ async fn test_in_reply_to() {
// Load the first message from the same chat.
let msgs = chat::get_chat_msgs(&t, msg.chat_id).await.unwrap();
let msg_id = if let ChatItem::Message { msg_id } = msgs.first().unwrap() {
msg_id
} else {
let ChatItem::Message { msg_id } = msgs.first().unwrap() else {
panic!("Wrong item type");
};
@@ -5592,27 +5590,27 @@ async fn test_mark_message_as_delivered_only_after_sent_out_fully() -> Result<()
.await
.unwrap();
let (post_msg_id, post_msg_payload) = first_row_in_smtp_queue(alice).await;
assert_eq!(msg_id, post_msg_id);
assert!(post_msg_payload.len() > file_bytes.len());
assert_eq!(msg_id.get_state(alice).await?, MessageState::OutPending);
// Alice receives her own post-message because of bcc_self
// This should not yet mark the message as delivered,
// because not everything was sent,
// but it does remove the post-message from the SMTP queue.
receive_imf(alice, post_msg_payload.as_bytes(), false).await?;
assert_eq!(msg_id.get_state(alice).await?, MessageState::OutPending);
let (pre_msg_id, pre_msg_payload) = first_row_in_smtp_queue(alice).await;
assert_eq!(msg_id, pre_msg_id);
assert!(pre_msg_payload.len() < file_bytes.len());
assert_eq!(msg_id.get_state(alice).await?, MessageState::OutPending);
// Alice receives her own pre-message because of bcc_self
// This should not yet mark the message as delivered,
// because not everything was sent,
// but it does remove the pre-message from the SMTP queue
receive_imf(alice, pre_msg_payload.as_bytes(), false).await?;
assert_eq!(msg_id.get_state(alice).await?, MessageState::OutPending);
let (post_msg_id, post_msg_payload) = first_row_in_smtp_queue(alice).await;
assert_eq!(msg_id, post_msg_id);
assert!(post_msg_payload.len() > file_bytes.len());
assert_eq!(msg_id.get_state(alice).await?, MessageState::OutPending);
// Alice receives her own post-message because of bcc_self
// This should now mark the message as delivered,
// because everything was sent by now.
receive_imf(alice, pre_msg_payload.as_bytes(), false).await?;
receive_imf(alice, post_msg_payload.as_bytes(), false).await?;
assert_eq!(msg_id.get_state(alice).await?, MessageState::OutDelivered);
Ok(())

View File

@@ -379,7 +379,7 @@ pub(crate) async fn send_msg_to_smtp(
if retries > 6 {
context
.sql
.execute("DELETE FROM smtp WHERE msg_id=?", (msg_id,))
.execute("DELETE FROM smtp WHERE id=?", (rowid,))
.await
.context("Failed to remove message with exceeded retry limit from smtp table")?;
if let Some(mut msg) = Message::load_from_db_optional(context, msg_id).await? {

View File

@@ -2378,20 +2378,7 @@ ALTER TABLE contacts ADD COLUMN name_normalized TEXT;
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?;
}
inc_and_check(&mut migration_version, 153)?;
if dbversion < migration_version {
sql.execute_migration(
"
CREATE INDEX smtp_index_msg_id ON smtp (msg_id, id);
ALTER TABLE available_post_msgs ADD COLUMN timestamp INTEGER DEFAULT 0 NOT NULL;
CREATE INDEX available_post_msgs_timestamp ON available_post_msgs (timestamp);
UPDATE msgs SET state=24 WHERE state=18; -- Change OutPreparing to OutFailed.
",
migration_version,
)

View File

@@ -722,14 +722,12 @@ ORDER BY id"
})
}
/// Returns `SentMessage` instances representing `smtp` rows for the given message. Returned
/// items go in reverse order for historical reasons.
pub async fn get_smtp_rows_for_msg<'a>(&'a self, msg_id: MsgId) -> Vec<SentMessage<'a>> {
let sent_msgs = self
.ctx
.sql
.query_map_vec(
"SELECT id, msg_id, mime, recipients FROM smtp WHERE msg_id=? ORDER BY id DESC",
"SELECT id, msg_id, mime, recipients FROM smtp WHERE msg_id=?",
(msg_id,),
|row| {
let _id: MsgId = row.get(0)?;
@@ -1057,17 +1055,9 @@ ORDER BY id"
/// This is not hooked up to any SMTP-IMAP pipeline, so the other account must call
/// [`TestContext::recv_msg`] with the returned [`SentMessage`] if it wants to receive
/// the message.
///
/// Removes SMTP jobs existed before and marks the corresponding messages as delivered, as
/// tracking of these jobs is probably already lost by the test code.
pub async fn send_msg(&self, chat_id: ChatId, msg: &mut Message) -> SentMessage<'_> {
while self.pop_sent_msg_opt(Duration::ZERO).await.is_some() {}
let msg_id = chat::send_msg(self, chat_id, msg).await.unwrap();
let rev_order = false;
let res = self
.pop_sent_msg_ex(rev_order, Duration::ZERO)
.await
.unwrap();
let res = self.pop_sent_msg().await;
assert_eq!(
res.sender_msg_id, msg_id,
"Apparently the message was not actually sent out"
@@ -1567,9 +1557,7 @@ pub(crate) async fn get_chat_msg(
asserted_msgs_count,
msgs.len()
);
let msg_id = if let ChatItem::Message { msg_id } = msgs[index] {
msg_id
} else {
let ChatItem::Message { msg_id } = msgs[index] else {
panic!("Wrong item type");
};
Message::load_from_db(&t.ctx, msg_id).await.unwrap()

View File

@@ -106,7 +106,7 @@ async fn test_receive_both() -> Result<()> {
assert_eq!(msg.text, "test".to_owned());
forward_msgs(alice, &[alice_msg_id], alice_chat_id).await?;
let rev_order = true;
let rev_order = false;
let msg = bob
.recv_msg(
&alice

View File

@@ -257,7 +257,7 @@ async fn test_lost_pre_msg() -> Result<()> {
let _pre_msg = alice.pop_sent_msg().await;
let msg = bob.recv_msg(&full_msg).await;
assert_eq!(msg.download_state, DownloadState::Done);
assert_eq!(msg.text, "populate");
assert_eq!(msg.text, "");
Ok(())
}
@@ -547,8 +547,8 @@ async fn test_webxdc_updates_in_post_message_after_pre_message() -> Result<()> {
.await?;
send_msg(alice, alice_chat_id, &mut alice_instance).await?;
let pre_message = alice.pop_sent_msg().await;
let post_message = alice.pop_sent_msg().await;
let pre_message = alice.pop_sent_msg().await;
let bob_instance = bob.recv_msg(&pre_message).await;
assert_eq!(bob_instance.download_state, DownloadState::Available);
@@ -588,8 +588,8 @@ async fn test_webxdc_updates_in_post_message_without_pre_message() -> Result<()>
.await?;
send_msg(alice, alice_chat_id, &mut alice_instance).await?;
let pre_message = alice.pop_sent_msg().await;
let post_message = alice.pop_sent_msg().await;
let pre_message = alice.pop_sent_msg().await;
// Bob receives post-message first.
let bob_instance = bob.recv_msg(&post_message).await;