Skip to content

Commit 1ec5606

Browse files
Simon-LauxiequidooHocuri
authored
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 <[email protected]> Co-authored-by: Hocuri <[email protected]>
1 parent 6d7f453 commit 1ec5606

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, error, info, 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;
@@ -2733,6 +2735,52 @@ async fn prepare_send_msg(
27332735
Ok(row_ids)
27342736
}
27352737

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

2807-
let rendered_msg = match mimefactory.render(context).await {
2808-
Ok(res) => Ok(res),
2809-
Err(err) => {
2810-
message::set_msg_failed(context, msg, &err.to_string()).await?;
2811-
Err(err)
2812-
}
2813-
}?;
2855+
let (rendered_msg, rendered_pre_msg) =
2856+
match render_mime_message_and_pre_message(context, msg, mimefactory).await {
2857+
Ok(res) => Ok(res),
2858+
Err(err) => {
2859+
message::set_msg_failed(context, msg, &err.to_string()).await?;
2860+
Err(err)
2861+
}
2862+
}?;
28142863

28152864
if needs_encryption && !rendered_msg.is_encrypted {
28162865
/* unrecoverable */
@@ -2870,12 +2919,26 @@ pub(crate) async fn create_send_msg_jobs(context: &Context, msg: &mut Message) -
28702919
} else {
28712920
for recipients_chunk in recipients.chunks(chunk_size) {
28722921
let recipients_chunk = recipients_chunk.join(" ");
2922+
// send pre-message before actual message
2923+
if let Some(pre_msg) = &rendered_pre_msg {
2924+
let row_id = t.execute(
2925+
"INSERT INTO smtp (rfc724_mid, recipients, mime, msg_id)
2926+
VALUES (?1, ?2, ?3, ?4)",
2927+
(
2928+
&pre_msg.rfc724_mid,
2929+
&recipients_chunk,
2930+
&pre_msg.message,
2931+
msg.id,
2932+
),
2933+
)?;
2934+
row_ids.push(row_id.try_into()?);
2935+
}
28732936
let row_id = t.execute(
2874-
"INSERT INTO smtp (rfc724_mid, recipients, mime, msg_id) \
2937+
"INSERT INTO smtp (rfc724_mid, recipients, mime, msg_id)
28752938
VALUES (?1, ?2, ?3, ?4)",
28762939
(
28772940
&rendered_msg.rfc724_mid,
2878-
recipients_chunk,
2941+
&recipients_chunk,
28792942
&rendered_msg.message,
28802943
msg.id,
28812944
),

0 commit comments

Comments
 (0)