mirror of
https://github.com/chatmail/core.git
synced 2026-04-23 00:16:34 +03:00
Merge branch 'stable'
This commit is contained in:
55
src/imap.rs
55
src/imap.rs
@@ -747,9 +747,51 @@ impl Imap {
|
||||
}
|
||||
};
|
||||
|
||||
// Get the Message-ID or generate a fake one to identify the message in the database.
|
||||
let message_id = prefetch_get_or_create_message_id(&headers);
|
||||
let target = target_folder(context, folder, folder_meaning, &headers).await?;
|
||||
let message_id = prefetch_get_message_id(&headers);
|
||||
|
||||
// Determine the target folder where the message should be moved to.
|
||||
//
|
||||
// If we have seen the message on the IMAP server before, do not move it.
|
||||
// This is required to avoid infinite MOVE loop on IMAP servers
|
||||
// that alias `DeltaChat` folder to other names.
|
||||
// For example, some Dovecot servers alias `DeltaChat` folder to `INBOX.DeltaChat`.
|
||||
// In this case Delta Chat configured with `DeltaChat` as the destination folder
|
||||
// would detect messages in the `INBOX.DeltaChat` folder
|
||||
// and try to move them to the `DeltaChat` folder.
|
||||
// Such move to the same folder results in the messages
|
||||
// getting a new UID, so the messages will be detected as new
|
||||
// in the `INBOX.DeltaChat` folder again.
|
||||
let target = if let Some(message_id) = &message_id {
|
||||
if context
|
||||
.sql
|
||||
.exists(
|
||||
"SELECT COUNT (*) FROM imap WHERE rfc724_mid=?",
|
||||
(message_id,),
|
||||
)
|
||||
.await?
|
||||
{
|
||||
info!(
|
||||
context,
|
||||
"Not moving the message {} that we have seen before.", &message_id
|
||||
);
|
||||
folder.to_string()
|
||||
} else {
|
||||
target_folder(context, folder, folder_meaning, &headers).await?
|
||||
}
|
||||
} else {
|
||||
// Do not move the messages without Message-ID.
|
||||
// We cannot reliably determine if we have seen them before,
|
||||
// so it is safer not to move them.
|
||||
warn!(
|
||||
context,
|
||||
"Not moving the message that does not have a Message-ID."
|
||||
);
|
||||
folder.to_string()
|
||||
};
|
||||
|
||||
// Generate a fake Message-ID to identify the message in the database
|
||||
// if the message has no real Message-ID.
|
||||
let message_id = message_id.unwrap_or_else(create_message_id);
|
||||
|
||||
context
|
||||
.sql
|
||||
@@ -2060,16 +2102,15 @@ fn get_fetch_headers(prefetch_msg: &Fetch) -> Result<Vec<mailparse::MailHeader>>
|
||||
}
|
||||
}
|
||||
|
||||
fn prefetch_get_message_id(headers: &[mailparse::MailHeader]) -> Option<String> {
|
||||
pub(crate) fn prefetch_get_message_id(headers: &[mailparse::MailHeader]) -> Option<String> {
|
||||
headers
|
||||
.get_header_value(HeaderDef::XMicrosoftOriginalMessageId)
|
||||
.or_else(|| headers.get_header_value(HeaderDef::MessageId))
|
||||
.and_then(|msgid| mimeparser::parse_message_id(&msgid).ok())
|
||||
}
|
||||
|
||||
pub(crate) fn prefetch_get_or_create_message_id(headers: &[mailparse::MailHeader]) -> String {
|
||||
prefetch_get_message_id(headers)
|
||||
.unwrap_or_else(|| format!("{}{}", GENERATED_PREFIX, create_id()))
|
||||
pub(crate) fn create_message_id() -> String {
|
||||
format!("{}{}", GENERATED_PREFIX, create_id())
|
||||
}
|
||||
|
||||
/// Returns chat by prefetched headers.
|
||||
|
||||
@@ -74,7 +74,8 @@ pub async fn receive_imf(
|
||||
seen: bool,
|
||||
) -> Result<Option<ReceivedMsg>> {
|
||||
let mail = parse_mail(imf_raw).context("can't parse mail")?;
|
||||
let rfc724_mid = imap::prefetch_get_or_create_message_id(&mail.headers);
|
||||
let rfc724_mid =
|
||||
imap::prefetch_get_message_id(&mail.headers).unwrap_or_else(imap::create_message_id);
|
||||
receive_imf_inner(context, &rfc724_mid, imf_raw, seen, None, false).await
|
||||
}
|
||||
|
||||
@@ -1193,8 +1194,9 @@ SET rfc724_mid=excluded.rfc724_mid, chat_id=excluded.chat_id,
|
||||
mime_compressed=excluded.mime_compressed, mime_in_reply_to=excluded.mime_in_reply_to,
|
||||
mime_references=excluded.mime_references, mime_modified=excluded.mime_modified, error=excluded.error, ephemeral_timer=excluded.ephemeral_timer,
|
||||
ephemeral_timestamp=excluded.ephemeral_timestamp, download_state=excluded.download_state, hop_info=excluded.hop_info
|
||||
RETURNING id
|
||||
"#)?;
|
||||
stmt.execute(params![
|
||||
let row_id: MsgId = stmt.query_row(params![
|
||||
replace_msg_id,
|
||||
rfc724_mid,
|
||||
if trash { DC_CHAT_ID_TRASH } else { chat_id },
|
||||
@@ -1233,8 +1235,12 @@ SET rfc724_mid=excluded.rfc724_mid, chat_id=excluded.chat_id,
|
||||
DownloadState::Done
|
||||
},
|
||||
mime_parser.hop_info
|
||||
])?;
|
||||
let row_id = conn.last_insert_rowid();
|
||||
],
|
||||
|row| {
|
||||
let msg_id: MsgId = row.get(0)?;
|
||||
Ok(msg_id)
|
||||
}
|
||||
)?;
|
||||
Ok(row_id)
|
||||
})
|
||||
.await?;
|
||||
@@ -1243,7 +1249,8 @@ SET rfc724_mid=excluded.rfc724_mid, chat_id=excluded.chat_id,
|
||||
// afterwards insert additional parts.
|
||||
replace_msg_id = None;
|
||||
|
||||
created_db_entries.push(MsgId::new(u32::try_from(row_id)?));
|
||||
debug_assert!(!row_id.is_special());
|
||||
created_db_entries.push(row_id);
|
||||
}
|
||||
|
||||
// check all parts whether they contain a new logging webxdc
|
||||
|
||||
@@ -1177,7 +1177,7 @@ mod tests {
|
||||
assert_eq!(bob_instance.download_state, DownloadState::Available);
|
||||
|
||||
// Bob downloads instance, updates should be assigned correctly
|
||||
receive_imf_inner(
|
||||
let received_msg = receive_imf_inner(
|
||||
&bob,
|
||||
&alice_instance.rfc724_mid,
|
||||
sent1.payload().as_bytes(),
|
||||
@@ -1185,7 +1185,9 @@ mod tests {
|
||||
None,
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
.await?
|
||||
.unwrap();
|
||||
assert_eq!(*received_msg.msg_ids.get(0).unwrap(), bob_instance.id);
|
||||
let bob_instance = bob.get_last_msg().await;
|
||||
assert_eq!(bob_instance.viewtype, Viewtype::Webxdc);
|
||||
assert_eq!(bob_instance.download_state, DownloadState::Done);
|
||||
|
||||
Reference in New Issue
Block a user