Skip to content

Commit bcbd75b

Browse files
Simon-LauxiequidooHocuri
authored andcommitted
feat: send pre-message on messages with large attachments (#7410)
part of #7367 progress / what's to do: - [x] send pre-message - [x] The message's state must be set to MessageState::OutDelivered only after both messages are sent. If a read receipt is received, the message can be OutMdnRcvd or OutPending; let's just do whatever is easiest for now. Take care not to revert from OutMdnReceived to OutDelivered if we first receive a read receipt and then deliver the full message. - this is already the case: - `OutDelivered` is set when a message is sent out and has no remaining send jobs in the smtp table for this message id - so already works since full message and pre message have same msgId in that table. - `OutMdnRcvd` is a "virtual" state (#7367 (comment)), so going back to `OutDelivered` can't happen anymore - [x] delimit `ChatFullMessageId` with `<` and `>` like the other message ids - [x] add tests - [x] test that pre message is sent for attachment larger than X - test that correct headers are present on both messages - also test that Autocrypt-gossip and selfavatar should never go into full-messages - [x] test that no pre message is sent for attachment smaller than X - no "is full message" header should be present - [x] test that pre message is not send for large webxdc update or large text - [x] fix test `receive_imf::receive_imf_tests::test_dont_reverify_by_self_on_outgoing_msg` --------- Co-authored-by: iequidoo <117991069+iequidoo@users.noreply.github.com> Co-authored-by: Hocuri <hocuri@gmx.de>
1 parent 02f45ab commit bcbd75b

File tree

5 files changed

+521
-17
lines changed

5 files changed

+521
-17
lines changed

src/chat.rs

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,17 @@ use crate::constants::{
2727
use crate::contact::{self, Contact, ContactId, Origin};
2828
use crate::context::Context;
2929
use crate::debug_logging::maybe_set_logging_xdc;
30-
use crate::download::DownloadState;
30+
use crate::download::{
31+
DownloadState, PRE_MSG_ATTACHMENT_SIZE_THRESHOLD, PRE_MSG_SIZE_WARNING_THRESHOLD,
32+
};
3133
use crate::ephemeral::{Timer as EphemeralTimer, start_chat_ephemeral_timers};
3234
use crate::events::EventType;
3335
use crate::key::self_fingerprint;
3436
use crate::location;
3537
use crate::log::{LogExt, warn};
3638
use crate::logged_debug_assert;
3739
use crate::message::{self, Message, MessageState, MsgId, Viewtype};
38-
use crate::mimefactory::MimeFactory;
40+
use crate::mimefactory::{MimeFactory, RenderedEmail};
3941
use crate::mimeparser::SystemMessage;
4042
use crate::param::{Param, Params};
4143
use crate::receive_imf::ReceivedMsg;
@@ -2728,6 +2730,52 @@ async fn prepare_send_msg(
27282730
Ok(row_ids)
27292731
}
27302732

2733+
/// Renders the message or Full-Message and Pre-Message.
2734+
///
2735+
/// Pre-Message is a small message with metadata which announces a larger Full-Message.
2736+
/// Full messages are not downloaded in the background.
2737+
///
2738+
/// If pre-message is not nessesary this returns a normal message instead.
2739+
async fn render_mime_message_and_pre_message(
2740+
context: &Context,
2741+
msg: &mut Message,
2742+
mimefactory: MimeFactory,
2743+
) -> Result<(RenderedEmail, Option<RenderedEmail>)> {
2744+
let needs_pre_message = msg.viewtype.has_file()
2745+
&& mimefactory.will_be_encrypted() // unencrypted is likely email, we don't want to spam by sending multiple messages
2746+
&& msg
2747+
.get_filebytes(context)
2748+
.await?
2749+
.context("filebytes not available, even though message has attachment")?
2750+
> PRE_MSG_ATTACHMENT_SIZE_THRESHOLD;
2751+
2752+
if needs_pre_message {
2753+
let mut mimefactory_full_msg = mimefactory.clone();
2754+
mimefactory_full_msg.set_as_full_message();
2755+
let rendered_msg = mimefactory_full_msg.render(context).await?;
2756+
2757+
let mut mimefactory_pre_msg = mimefactory;
2758+
mimefactory_pre_msg.set_as_pre_message_for(&rendered_msg);
2759+
let rendered_pre_msg = mimefactory_pre_msg
2760+
.render(context)
2761+
.await
2762+
.context("pre-message failed to render")?;
2763+
2764+
if rendered_pre_msg.message.len() > PRE_MSG_SIZE_WARNING_THRESHOLD {
2765+
warn!(
2766+
context,
2767+
"Pre-message for message (MsgId={}) is larger than expected: {}.",
2768+
msg.id,
2769+
rendered_pre_msg.message.len()
2770+
);
2771+
}
2772+
2773+
Ok((rendered_msg, Some(rendered_pre_msg)))
2774+
} else {
2775+
Ok((mimefactory.render(context).await?, None))
2776+
}
2777+
}
2778+
27312779
/// Constructs jobs for sending a message and inserts them into the appropriate table.
27322780
///
27332781
/// Updates the message `GuaranteeE2ee` parameter and persists it
@@ -2799,13 +2847,14 @@ pub(crate) async fn create_send_msg_jobs(context: &Context, msg: &mut Message) -
27992847
return Ok(Vec::new());
28002848
}
28012849

2802-
let rendered_msg = match mimefactory.render(context).await {
2803-
Ok(res) => Ok(res),
2804-
Err(err) => {
2805-
message::set_msg_failed(context, msg, &err.to_string()).await?;
2806-
Err(err)
2807-
}
2808-
}?;
2850+
let (rendered_msg, rendered_pre_msg) =
2851+
match render_mime_message_and_pre_message(context, msg, mimefactory).await {
2852+
Ok(res) => Ok(res),
2853+
Err(err) => {
2854+
message::set_msg_failed(context, msg, &err.to_string()).await?;
2855+
Err(err)
2856+
}
2857+
}?;
28092858

28102859
if needs_encryption && !rendered_msg.is_encrypted {
28112860
/* unrecoverable */
@@ -2864,12 +2913,26 @@ pub(crate) async fn create_send_msg_jobs(context: &Context, msg: &mut Message) -
28642913
} else {
28652914
for recipients_chunk in recipients.chunks(chunk_size) {
28662915
let recipients_chunk = recipients_chunk.join(" ");
2916+
// send pre-message before actual message
2917+
if let Some(pre_msg) = &rendered_pre_msg {
2918+
let row_id = t.execute(
2919+
"INSERT INTO smtp (rfc724_mid, recipients, mime, msg_id)
2920+
VALUES (?1, ?2, ?3, ?4)",
2921+
(
2922+
&pre_msg.rfc724_mid,
2923+
&recipients_chunk,
2924+
&pre_msg.message,
2925+
msg.id,
2926+
),
2927+
)?;
2928+
row_ids.push(row_id.try_into()?);
2929+
}
28672930
let row_id = t.execute(
2868-
"INSERT INTO smtp (rfc724_mid, recipients, mime, msg_id) \
2931+
"INSERT INTO smtp (rfc724_mid, recipients, mime, msg_id)
28692932
VALUES (?1, ?2, ?3, ?4)",
28702933
(
28712934
&rendered_msg.rfc724_mid,
2872-
recipients_chunk,
2935+
&recipients_chunk,
28732936
&rendered_msg.message,
28742937
msg.id,
28752938
),

0 commit comments

Comments
 (0)