Add support for IMAP ID extension

This commit is contained in:
link2xt
2022-06-23 10:58:30 +00:00
parent d738371848
commit 51aead6b58
7 changed files with 28 additions and 5 deletions

View File

@@ -416,6 +416,9 @@ async fn configure(ctx: &Context, param: &mut LoginParam) -> Result<()> {
let create_mvbox = ctx.should_watch_mvbox().await?;
// Send client ID as soon as possible before doing anything else.
imap.determine_capabilities(ctx).await?;
imap.configure_folders(ctx, create_mvbox).await?;
imap.select_with_uidvalidity(ctx, "INBOX")

View File

@@ -61,6 +61,11 @@ pub struct InnerContext {
/// Set to `None` if quota was never tried to load.
pub(crate) quota: RwLock<Option<QuotaInfo>>,
/// Server ID response if ID capability is supported
/// and the server returned non-NIL on the inbox connection.
/// <https://datatracker.ietf.org/doc/html/rfc2971>
pub(crate) server_id: RwLock<Option<HashMap<String, String>>>,
pub(crate) last_full_folder_scan: Mutex<Option<Instant>>,
/// ID for this `Context` in the current process.
@@ -190,6 +195,7 @@ impl Context {
scheduler: RwLock::new(None),
ratelimit: RwLock::new(Ratelimit::new(Duration::new(60, 0), 3.0)), // Allow to send 3 messages immediately, no more than once every 20 seconds.
quota: RwLock::new(None),
server_id: RwLock::new(None),
creation_time: std::time::SystemTime::now(),
last_full_folder_scan: Mutex::new(None),
last_error: std::sync::RwLock::new("".to_string()),
@@ -429,6 +435,11 @@ impl Context {
res.insert("socks5_enabled", socks5_enabled.to_string());
res.insert("entered_account_settings", l.to_string());
res.insert("used_account_settings", l2.to_string());
let server_id = self.server_id.read().await;
res.insert("imap_server_id", format!("{:?}", server_id));
drop(server_id);
res.insert("secondary_addrs", secondary_addrs);
res.insert(
"fetch_existing_msgs",

View File

@@ -451,7 +451,9 @@ impl Imap {
}
/// Determine server capabilities if not done yet.
async fn determine_capabilities(&mut self) -> Result<()> {
///
/// If server supports ID capability, send our client ID.
pub(crate) async fn determine_capabilities(&mut self, context: &Context) -> Result<()> {
if self.capabilities_determined {
return Ok(());
}
@@ -463,6 +465,12 @@ impl Imap {
.capabilities()
.await
.context("CAPABILITY command error")?;
if caps.has_str("ID") {
let server_id = session.id([("name", Some("Delta Chat"))]).await?;
info!(context, "Server ID: {:?}", server_id);
let mut lock = context.server_id.write().await;
*lock = server_id;
}
self.config.can_idle = caps.has_str("IDLE");
self.config.can_move = caps.has_str("MOVE");
self.config.can_check_quota = caps.has_str("QUOTA");
@@ -481,8 +489,8 @@ impl Imap {
return Err(err);
}
self.determine_capabilities(context).await?;
self.ensure_configured_folders(context, true).await?;
self.determine_capabilities().await?;
Ok(())
}