mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
Send MDNs for messages deleted on the server
Now MarkseenMsgOnImap sends MDN even if it can't mark the message as seen on the server. To prevent multiple MDNs from being sent, MarkseenMsgOnImap is postponed until the message is detected in a folder from which it is not going to be moved.
This commit is contained in:
committed by
link2xt
parent
2aa808756e
commit
7bb6890f26
@@ -1542,7 +1542,6 @@ class TestOnlineAccount:
|
||||
assert msg.is_encrypted(), "Message is not encrypted"
|
||||
assert msg.chat == ac2.create_chat(ac4)
|
||||
|
||||
@pytest.mark.xfail
|
||||
def test_immediate_autodelete(self, acfactory, lp):
|
||||
ac1 = acfactory.get_online_configuring_account()
|
||||
ac2 = acfactory.get_online_configuring_account(mvbox=False, move=False, sentbox=False)
|
||||
|
||||
@@ -15,12 +15,10 @@ use crate::contact::*;
|
||||
use crate::dc_tools::duration_to_str;
|
||||
use crate::error::*;
|
||||
use crate::events::{Event, EventEmitter, Events};
|
||||
use crate::job::{self, Action};
|
||||
use crate::key::{DcKey, SignedPublicKey};
|
||||
use crate::login_param::LoginParam;
|
||||
use crate::lot::Lot;
|
||||
use crate::message::{self, Message, MessengerMessage, MsgId};
|
||||
use crate::param::Params;
|
||||
use crate::message::{self, MsgId};
|
||||
use crate::scheduler::Scheduler;
|
||||
use crate::sql::Sql;
|
||||
use std::time::SystemTime;
|
||||
@@ -460,34 +458,6 @@ impl Context {
|
||||
self.get_config(Config::ConfiguredMvboxFolder).await
|
||||
== Some(folder_name.as_ref().to_string())
|
||||
}
|
||||
|
||||
pub async fn do_heuristics_moves(&self, folder: &str, msg_id: MsgId) {
|
||||
if !self.get_config_bool(Config::MvboxMove).await {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.is_mvbox(folder).await {
|
||||
return;
|
||||
}
|
||||
if let Ok(msg) = Message::load_from_db(self, msg_id).await {
|
||||
if msg.is_setupmessage() {
|
||||
// do not move setup messages;
|
||||
// there may be a non-delta device that wants to handle it
|
||||
return;
|
||||
}
|
||||
|
||||
match msg.is_dc_message {
|
||||
MessengerMessage::No => {}
|
||||
MessengerMessage::Yes | MessengerMessage::Reply => {
|
||||
job::add(
|
||||
self,
|
||||
job::Job::new(Action::MoveMsg, msg.id.to_u32(), Params::new(), 0),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InnerContext {
|
||||
|
||||
@@ -224,12 +224,18 @@ pub async fn dc_receive_imf(
|
||||
)
|
||||
.await;
|
||||
}
|
||||
} else {
|
||||
} else if insert_msg_id
|
||||
.needs_move(context, server_folder.as_ref())
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
{
|
||||
// Move message if we don't delete it immediately.
|
||||
context
|
||||
.do_heuristics_moves(server_folder.as_ref(), insert_msg_id)
|
||||
job::add(
|
||||
context,
|
||||
job::Job::new(Action::MoveMsg, insert_msg_id.to_u32(), Params::new(), 0),
|
||||
)
|
||||
.await;
|
||||
if !mime_parser.mdn_reports.is_empty() && mime_parser.has_chat_version() {
|
||||
} else if !mime_parser.mdn_reports.is_empty() && mime_parser.has_chat_version() {
|
||||
// This is a Delta Chat MDN. Mark as read.
|
||||
job::add(
|
||||
context,
|
||||
@@ -243,7 +249,6 @@ pub async fn dc_receive_imf(
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info!(
|
||||
context,
|
||||
|
||||
@@ -23,7 +23,7 @@ use crate::events::Event;
|
||||
use crate::headerdef::{HeaderDef, HeaderDefMap};
|
||||
use crate::job::{self, Action};
|
||||
use crate::login_param::{CertificateChecks, LoginParam};
|
||||
use crate::message::{self, update_server_uid};
|
||||
use crate::message::{self, update_server_uid, MessageState};
|
||||
use crate::mimeparser;
|
||||
use crate::oauth2::dc_get_oauth2_access_token;
|
||||
use crate::param::Params;
|
||||
@@ -1366,15 +1366,27 @@ async fn precheck_imf(
|
||||
let delete_server_after = context.get_config_delete_server_after().await;
|
||||
|
||||
if delete_server_after != Some(0) {
|
||||
context
|
||||
.do_heuristics_moves(server_folder.as_ref(), msg_id)
|
||||
if msg_id
|
||||
.needs_move(context, server_folder)
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
{
|
||||
// If the bcc-self message is not moved, directly
|
||||
// add MarkSeen job, otherwise MarkSeen job is
|
||||
// added after the Move Job completed.
|
||||
job::add(
|
||||
context,
|
||||
job::Job::new(Action::MoveMsg, msg_id.to_u32(), Params::new(), 0),
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
job::add(
|
||||
context,
|
||||
job::Job::new(Action::MarkseenMsgOnImap, msg_id.to_u32(), Params::new(), 0),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
} else if old_server_folder != server_folder {
|
||||
info!(
|
||||
context,
|
||||
@@ -1408,6 +1420,13 @@ async fn precheck_imf(
|
||||
|
||||
if old_server_folder != server_folder || old_server_uid != server_uid {
|
||||
update_server_uid(context, rfc724_mid, server_folder, server_uid).await;
|
||||
if let Ok(MessageState::InSeen) = msg_id.get_state(context).await {
|
||||
job::add(
|
||||
context,
|
||||
job::Job::new(Action::MarkseenMsgOnImap, msg_id.to_u32(), Params::new(), 0),
|
||||
)
|
||||
.await;
|
||||
};
|
||||
context
|
||||
.interrupt_inbox(InterruptInfo::new(false, Some(msg_id)))
|
||||
.await;
|
||||
|
||||
16
src/job.rs
16
src/job.rs
@@ -639,7 +639,21 @@ impl Job {
|
||||
let msg = job_try!(Message::load_from_db(context, MsgId::new(self.foreign_id)).await);
|
||||
|
||||
let folder = msg.server_folder.as_ref().unwrap();
|
||||
match imap.set_seen(context, folder, msg.server_uid).await {
|
||||
|
||||
let result = if msg.server_uid == 0 {
|
||||
// The message is moved or deleted by us.
|
||||
//
|
||||
// Do not call set_seen with zero UID, as it will return
|
||||
// ImapActionResult::RetryLater, but we do not want to
|
||||
// retry. If the message was moved, we will create another
|
||||
// job to mark the message as seen later. If it was
|
||||
// deleted, there is nothing to do.
|
||||
ImapActionResult::Failed
|
||||
} else {
|
||||
imap.set_seen(context, folder, msg.server_uid).await
|
||||
};
|
||||
|
||||
match result {
|
||||
ImapActionResult::RetryLater => Status::RetryLater,
|
||||
ImapActionResult::AlreadyDone => Status::Finished(Ok(())),
|
||||
ImapActionResult::Success | ImapActionResult::Failed => {
|
||||
|
||||
@@ -6,6 +6,7 @@ use lazy_static::lazy_static;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::chat::{self, Chat, ChatId};
|
||||
use crate::config::Config;
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::context::*;
|
||||
@@ -68,6 +69,40 @@ impl MsgId {
|
||||
self.0 == 0
|
||||
}
|
||||
|
||||
/// Returns message state.
|
||||
pub async fn get_state(self, context: &Context) -> crate::sql::Result<MessageState> {
|
||||
let result = context
|
||||
.sql
|
||||
.query_get_value_result("SELECT state FROM msgs WHERE id=?", paramsv![self])
|
||||
.await?
|
||||
.unwrap_or_default();
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Returns true if the message needs to be moved from `folder`.
|
||||
pub async fn needs_move(self, context: &Context, folder: &str) -> Result<bool, Error> {
|
||||
if !context.get_config_bool(Config::MvboxMove).await {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
if context.is_mvbox(folder).await {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let msg = Message::load_from_db(context, self).await?;
|
||||
|
||||
if msg.is_setupmessage() {
|
||||
// do not move setup messages;
|
||||
// there may be a non-delta device that wants to handle it
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
match msg.is_dc_message {
|
||||
MessengerMessage::No => Ok(false),
|
||||
MessengerMessage::Yes | MessengerMessage::Reply => Ok(true),
|
||||
}
|
||||
}
|
||||
|
||||
/// Put message into trash chat and delete message text.
|
||||
///
|
||||
/// It means the message is deleted locally, but not on the server
|
||||
|
||||
Reference in New Issue
Block a user