mirror of
https://github.com/chatmail/core.git
synced 2026-10-08 06:00:17 +03:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4866fa18bd | ||
|
|
f83712537f |
@@ -174,5 +174,17 @@ pub(crate) fn login_param_from_host(host: &str) -> EnteredLoginParam {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn send_key_update_messages(context: &Context) -> Result<()> {
|
||||
let contacts_to_update: Vec<ContactId> = contacts_to_update(context).await?;
|
||||
|
||||
let chunks = contacts_to_update.chunks(20);
|
||||
|
||||
for chunk in chunks {
|
||||
send_key_update_message(context, chunk).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod automatic_relay_management_tests;
|
||||
|
||||
+20
-4
@@ -146,6 +146,18 @@ pub(crate) struct ServerMetadata {
|
||||
pub app_versions: Option<String>,
|
||||
}
|
||||
|
||||
/// Selects the most actionable error from failed IMAP connection candidates.
|
||||
///
|
||||
/// A login error proves that a connection succeeded, so it takes precedence over network errors.
|
||||
fn select_connect_error(
|
||||
first_connection_error: Option<anyhow::Error>,
|
||||
first_login_error: Option<anyhow::Error>,
|
||||
) -> anyhow::Error {
|
||||
first_login_error
|
||||
.or(first_connection_error)
|
||||
.unwrap_or_else(|| format_err!("No IMAP connection candidates provided"))
|
||||
}
|
||||
|
||||
struct UidGrouper<T: Iterator<Item = (i64, u32, String)>> {
|
||||
inner: Peekable<T>,
|
||||
}
|
||||
@@ -314,7 +326,8 @@ impl Imap {
|
||||
self.conn_backoff_ms = max(BACKOFF_MIN_MS, self.conn_backoff_ms);
|
||||
|
||||
let login_params = prioritize_server_login_params(&context.sql, &self.lp, "imap").await?;
|
||||
let mut first_error = None;
|
||||
let mut first_connection_error = None;
|
||||
let mut first_login_error = None;
|
||||
'candidate: for lp in login_params {
|
||||
info!(context, "IMAP trying to connect to {}.", lp.connection);
|
||||
let connection_candidate = lp.connection.clone();
|
||||
@@ -330,7 +343,7 @@ impl Imap {
|
||||
Ok(client) => client,
|
||||
Err(err) => {
|
||||
warn!(context, "{err:#}.");
|
||||
first_error.get_or_insert(err);
|
||||
first_connection_error.get_or_insert(err);
|
||||
continue 'candidate;
|
||||
}
|
||||
};
|
||||
@@ -410,7 +423,7 @@ impl Imap {
|
||||
let message = stock_str::cannot_login(context, &imap_user);
|
||||
|
||||
warn!(context, "IMAP failed to login: {err:#}.");
|
||||
first_error.get_or_insert(format_err!("{message} ({err:#})"));
|
||||
first_login_error.get_or_insert(format_err!("{message} ({err:#})"));
|
||||
|
||||
// If it looks like the password is wrong, send a notification:
|
||||
let _lock = context.wrong_pw_warning_mutex.lock().await;
|
||||
@@ -446,7 +459,10 @@ impl Imap {
|
||||
}
|
||||
}
|
||||
|
||||
Err(first_error.unwrap_or_else(|| format_err!("No IMAP connection candidates provided")))
|
||||
Err(select_connect_error(
|
||||
first_connection_error,
|
||||
first_login_error,
|
||||
))
|
||||
}
|
||||
|
||||
/// Prepare a new IMAP session.
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
use super::*;
|
||||
use crate::test_utils::TestContext;
|
||||
|
||||
#[test]
|
||||
fn test_connect_prefers_login_error() {
|
||||
let connection_error = format_err!("All connection attempts failed");
|
||||
let login_error = format_err!("Cannot login, please check the password");
|
||||
|
||||
let error = select_connect_error(Some(connection_error), Some(login_error));
|
||||
|
||||
assert_eq!(error.to_string(), "Cannot login, please check the password");
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_set_uid_next_validity() {
|
||||
let t = TestContext::new_alice().await;
|
||||
|
||||
@@ -2511,6 +2511,71 @@ pub(crate) async fn render_symm_encrypted_securejoin_message(
|
||||
Ok(rendered_mail.message)
|
||||
}
|
||||
|
||||
pub(crate) async fn render_key_update_message(
|
||||
context: &Context,
|
||||
rfc724_mid: &str,
|
||||
) -> Result<String> {
|
||||
let message: MimePart<'static> = MimePart::new("text/plain", "Secure-Join");
|
||||
|
||||
let mut headers = Vec::<(&'static str, HeaderType<'static>)>::new();
|
||||
|
||||
let to: Vec<Address<'static>> = vec![hidden_recipients()];
|
||||
headers.push((
|
||||
"To",
|
||||
mail_builder::headers::address::Address::new_list(to.clone()).into(),
|
||||
));
|
||||
|
||||
let timestamp = time();
|
||||
let date = chrono::DateTime::<chrono::Utc>::from_timestamp(timestamp, 0)
|
||||
.unwrap()
|
||||
.to_rfc2822();
|
||||
headers.push(("Date", mail_builder::headers::raw::Raw::new(date).into()));
|
||||
|
||||
// Automatic Response headers <https://www.rfc-editor.org/rfc/rfc3834>
|
||||
if context.get_config_bool(Config::Bot).await? {
|
||||
headers.push((
|
||||
"Auto-Submitted",
|
||||
mail_builder::headers::raw::Raw::new("auto-generated".to_string()).into(),
|
||||
));
|
||||
}
|
||||
|
||||
let message = add_headers_to_encrypted_part(message, headers);
|
||||
|
||||
// No need to sign; key updates are applied from whatever message.
|
||||
let should_sign = false;
|
||||
let should_attach_pubkey = true;
|
||||
let should_compress = true;
|
||||
|
||||
let raw_message = part_to_bytes(message);
|
||||
|
||||
let encryption = todo!();
|
||||
|
||||
let queued_mail = QueuedMail {
|
||||
raw_message,
|
||||
display_name: String::new(),
|
||||
rfc724_mid: rfc724_mid.to_string(),
|
||||
encryption,
|
||||
should_attach_pubkey,
|
||||
should_sign,
|
||||
should_compress,
|
||||
};
|
||||
|
||||
let public_key = key::load_self_public_key(context).await?;
|
||||
let secret_key = key::load_self_secret_key(context).await?;
|
||||
let side_effects = RenderSideEffects::default();
|
||||
|
||||
let from_addr = context.get_primary_self_addr().await?;
|
||||
let rendered_mail = render_queued_mail(
|
||||
queued_mail,
|
||||
&public_key,
|
||||
&secret_key,
|
||||
from_addr,
|
||||
side_effects,
|
||||
)?;
|
||||
|
||||
Ok(rendered_mail.message)
|
||||
}
|
||||
|
||||
/// Renders MIME part into a vector of bytes.
|
||||
pub(crate) fn part_to_bytes(message: MimePart<'static>) -> Vec<u8> {
|
||||
let mut raw_message = Vec::new();
|
||||
|
||||
Reference in New Issue
Block a user