mirror of
https://github.com/chatmail/core.git
synced 2026-05-22 16:26:31 +03:00
feat(imap): detect NOTIFY extension
This commit is contained in:
@@ -296,6 +296,12 @@ pub enum Config {
|
|||||||
#[strum(props(default = "0"))]
|
#[strum(props(default = "0"))]
|
||||||
DisableIdle,
|
DisableIdle,
|
||||||
|
|
||||||
|
/// Whether to avoid using IMAP NOTIFY even if the server supports it.
|
||||||
|
///
|
||||||
|
/// This is a developer option for testing prefetch without NOTIFY.
|
||||||
|
#[strum(props(default = "0"))]
|
||||||
|
DisableNotify,
|
||||||
|
|
||||||
/// Defines the max. size (in bytes) of messages downloaded automatically.
|
/// Defines the max. size (in bytes) of messages downloaded automatically.
|
||||||
/// 0 = no limit.
|
/// 0 = no limit.
|
||||||
#[strum(props(default = "0"))]
|
#[strum(props(default = "0"))]
|
||||||
|
|||||||
@@ -595,6 +595,7 @@ impl Context {
|
|||||||
let bcc_self = self.get_config_int(Config::BccSelf).await?;
|
let bcc_self = self.get_config_int(Config::BccSelf).await?;
|
||||||
let sync_msgs = self.get_config_int(Config::SyncMsgs).await?;
|
let sync_msgs = self.get_config_int(Config::SyncMsgs).await?;
|
||||||
let disable_idle = self.get_config_bool(Config::DisableIdle).await?;
|
let disable_idle = self.get_config_bool(Config::DisableIdle).await?;
|
||||||
|
let disable_notify = self.get_config_bool(Config::DisableNotify).await?;
|
||||||
|
|
||||||
let prv_key_cnt = self.sql.count("SELECT COUNT(*) FROM keypairs;", ()).await?;
|
let prv_key_cnt = self.sql.count("SELECT COUNT(*) FROM keypairs;", ()).await?;
|
||||||
|
|
||||||
@@ -708,6 +709,7 @@ impl Context {
|
|||||||
res.insert("bcc_self", bcc_self.to_string());
|
res.insert("bcc_self", bcc_self.to_string());
|
||||||
res.insert("sync_msgs", sync_msgs.to_string());
|
res.insert("sync_msgs", sync_msgs.to_string());
|
||||||
res.insert("disable_idle", disable_idle.to_string());
|
res.insert("disable_idle", disable_idle.to_string());
|
||||||
|
res.insert("disable_notify", disable_notify.to_string());
|
||||||
res.insert("private_key_count", prv_key_cnt.to_string());
|
res.insert("private_key_count", prv_key_cnt.to_string());
|
||||||
res.insert("public_key_count", pub_key_cnt.to_string());
|
res.insert("public_key_count", pub_key_cnt.to_string());
|
||||||
res.insert("fingerprint", fingerprint_str);
|
res.insert("fingerprint", fingerprint_str);
|
||||||
|
|||||||
28
src/imap.rs
28
src/imap.rs
@@ -448,6 +448,22 @@ impl Imap {
|
|||||||
self.session = None;
|
self.session = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tries to setup NOTIFY.
|
||||||
|
pub async fn setup_notify(&mut self, context: &Context) -> Result<()> {
|
||||||
|
let session = self
|
||||||
|
.session
|
||||||
|
.as_mut()
|
||||||
|
.context("no IMAP connection established")?;
|
||||||
|
if session.can_notify() && !session.notify_set {
|
||||||
|
let cmd = format!("NOTIFY SET (selected (Messagenew {PREFETCH_FLAGS} messageexpunge))");
|
||||||
|
session.run_command_and_check_ok(cmd).await?;
|
||||||
|
info!(context, "Enabled NOTIFY");
|
||||||
|
session.notify_set = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// FETCH-MOVE-DELETE iteration.
|
/// FETCH-MOVE-DELETE iteration.
|
||||||
///
|
///
|
||||||
/// Prefetches headers and downloads new message from the folder, moves messages away from the
|
/// Prefetches headers and downloads new message from the folder, moves messages away from the
|
||||||
@@ -720,7 +736,9 @@ impl Imap {
|
|||||||
.await
|
.await
|
||||||
.context("prefetch_existing_msgs")?
|
.context("prefetch_existing_msgs")?
|
||||||
} else {
|
} else {
|
||||||
self.prefetch(old_uid_next).await.context("prefetch")?
|
self.prefetch(context, old_uid_next)
|
||||||
|
.await
|
||||||
|
.context("prefetch")?
|
||||||
};
|
};
|
||||||
let read_cnt = msgs.len();
|
let read_cnt = msgs.len();
|
||||||
|
|
||||||
@@ -1329,7 +1347,13 @@ impl Imap {
|
|||||||
|
|
||||||
/// Prefetch all messages greater than or equal to `uid_next`. Returns a list of fetch results
|
/// Prefetch all messages greater than or equal to `uid_next`. Returns a list of fetch results
|
||||||
/// in the order of ascending delivery time to the server (INTERNALDATE).
|
/// in the order of ascending delivery time to the server (INTERNALDATE).
|
||||||
async fn prefetch(&mut self, uid_next: u32) -> Result<Vec<(u32, async_imap::types::Fetch)>> {
|
async fn prefetch(
|
||||||
|
&mut self,
|
||||||
|
context: &Context,
|
||||||
|
uid_next: u32,
|
||||||
|
) -> Result<Vec<(u32, async_imap::types::Fetch)>> {
|
||||||
|
self.setup_notify(context).await?;
|
||||||
|
|
||||||
let session = self
|
let session = self
|
||||||
.session
|
.session
|
||||||
.as_mut()
|
.as_mut()
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ pub(crate) struct Capabilities {
|
|||||||
/// <https://tools.ietf.org/html/rfc2177>
|
/// <https://tools.ietf.org/html/rfc2177>
|
||||||
pub can_idle: bool,
|
pub can_idle: bool,
|
||||||
|
|
||||||
|
/// True if the server has NOTIFY capability as defined in
|
||||||
|
/// <https://tools.ietf.org/html/rfc5465>
|
||||||
|
pub can_notify: bool,
|
||||||
|
|
||||||
/// True if the server has MOVE capability as defined in
|
/// True if the server has MOVE capability as defined in
|
||||||
/// <https://tools.ietf.org/html/rfc6851>
|
/// <https://tools.ietf.org/html/rfc6851>
|
||||||
pub can_move: bool,
|
pub can_move: bool,
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ async fn determine_capabilities(
|
|||||||
};
|
};
|
||||||
let capabilities = Capabilities {
|
let capabilities = Capabilities {
|
||||||
can_idle: caps.has_str("IDLE"),
|
can_idle: caps.has_str("IDLE"),
|
||||||
|
can_notify: caps.has_str("NOTIFY"),
|
||||||
can_move: caps.has_str("MOVE"),
|
can_move: caps.has_str("MOVE"),
|
||||||
can_check_quota: caps.has_str("QUOTA"),
|
can_check_quota: caps.has_str("QUOTA"),
|
||||||
can_condstore: caps.has_str("CONDSTORE"),
|
can_condstore: caps.has_str("CONDSTORE"),
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ pub(crate) struct Session {
|
|||||||
pub selected_mailbox: Option<Mailbox>,
|
pub selected_mailbox: Option<Mailbox>,
|
||||||
|
|
||||||
pub selected_folder_needs_expunge: bool,
|
pub selected_folder_needs_expunge: bool,
|
||||||
|
|
||||||
|
/// True if NOTIFY SET command was executed in this session.
|
||||||
|
pub notify_set: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for Session {
|
impl Deref for Session {
|
||||||
@@ -46,6 +49,7 @@ impl Session {
|
|||||||
selected_folder: None,
|
selected_folder: None,
|
||||||
selected_mailbox: None,
|
selected_mailbox: None,
|
||||||
selected_folder_needs_expunge: false,
|
selected_folder_needs_expunge: false,
|
||||||
|
notify_set: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,6 +57,10 @@ impl Session {
|
|||||||
self.capabilities.can_idle
|
self.capabilities.can_idle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn can_notify(&self) -> bool {
|
||||||
|
self.capabilities.can_notify
|
||||||
|
}
|
||||||
|
|
||||||
pub fn can_move(&self) -> bool {
|
pub fn can_move(&self) -> bool {
|
||||||
self.capabilities.can_move
|
self.capabilities.can_move
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user