imap: add current_mailbox enum MailboxSelection
Add enum to track the currently selected Mailbox in the IMAP connectionasync
parent
ca7bbd9de4
commit
f8b84a192c
|
@ -296,7 +296,7 @@ impl MailBackend for ImapType {
|
||||||
|
|
||||||
/* first SELECT the mailbox to get READ/WRITE permissions (because EXAMINE only
|
/* first SELECT the mailbox to get READ/WRITE permissions (because EXAMINE only
|
||||||
* returns READ-ONLY for both cases) */
|
* returns READ-ONLY for both cases) */
|
||||||
conn.select_mailbox(mailbox_hash, &mut response)
|
conn.select_mailbox(mailbox_hash, &mut response, true)
|
||||||
.chain_err_summary(|| {
|
.chain_err_summary(|| {
|
||||||
format!("Could not select mailbox {}", mailbox_path)
|
format!("Could not select mailbox {}", mailbox_path)
|
||||||
})?;
|
})?;
|
||||||
|
@ -360,7 +360,7 @@ impl MailBackend for ImapType {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
/* reselecting the same mailbox with EXAMINE prevents expunging it */
|
/* reselecting the same mailbox with EXAMINE prevents expunging it */
|
||||||
conn.examine_mailbox(mailbox_hash, &mut response)?;
|
conn.examine_mailbox(mailbox_hash, &mut response, true)?;
|
||||||
if examine_response.uidnext == 0 {
|
if examine_response.uidnext == 0 {
|
||||||
/* UIDNEXT shouldn't be 0, since exists != 0 at this point */
|
/* UIDNEXT shouldn't be 0, since exists != 0 at this point */
|
||||||
conn.send_command(
|
conn.send_command(
|
||||||
|
@ -782,7 +782,9 @@ impl MailBackend for ImapType {
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
{
|
{
|
||||||
let mut conn_lck = try_lock(&self.connection, None)?;
|
let mut conn_lck = try_lock(&self.connection, None)?;
|
||||||
if !mailboxes[&mailbox_hash].no_select && conn_lck.current_mailbox == Some(mailbox_hash)
|
if !mailboxes[&mailbox_hash].no_select
|
||||||
|
&& (conn_lck.current_mailbox == MailboxSelection::Examine(mailbox_hash)
|
||||||
|
|| conn_lck.current_mailbox == MailboxSelection::Select(mailbox_hash))
|
||||||
{
|
{
|
||||||
/* make sure mailbox is not selected before it gets deleted, otherwise
|
/* make sure mailbox is not selected before it gets deleted, otherwise
|
||||||
* connection gets dropped by server */
|
* connection gets dropped by server */
|
||||||
|
@ -998,7 +1000,7 @@ impl MailBackend for ImapType {
|
||||||
|
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
let mut conn = try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
let mut conn = try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
||||||
conn.examine_mailbox(mailbox_hash, &mut response)?;
|
conn.examine_mailbox(mailbox_hash, &mut response, false)?;
|
||||||
conn.send_command(format!("UID SEARCH CHARSET UTF-8 {}", query_str).as_bytes())?;
|
conn.send_command(format!("UID SEARCH CHARSET UTF-8 {}", query_str).as_bytes())?;
|
||||||
conn.read_response(&mut response, RequiredResponses::SEARCH)?;
|
conn.read_response(&mut response, RequiredResponses::SEARCH)?;
|
||||||
debug!(&response);
|
debug!(&response);
|
||||||
|
|
|
@ -49,13 +49,25 @@ pub struct ImapStream {
|
||||||
protocol: ImapProtocol,
|
protocol: ImapProtocol,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
pub enum MailboxSelection {
|
||||||
|
None,
|
||||||
|
Select(MailboxHash),
|
||||||
|
Examine(MailboxHash),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MailboxSelection {
|
||||||
|
pub fn take(&mut self) -> Self {
|
||||||
|
std::mem::replace(self, MailboxSelection::None)
|
||||||
|
}
|
||||||
|
}
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ImapConnection {
|
pub struct ImapConnection {
|
||||||
pub stream: Result<ImapStream>,
|
pub stream: Result<ImapStream>,
|
||||||
pub server_conf: ImapServerConf,
|
pub server_conf: ImapServerConf,
|
||||||
pub capabilities: Capabilities,
|
pub capabilities: Capabilities,
|
||||||
pub uid_store: Arc<UIDStore>,
|
pub uid_store: Arc<UIDStore>,
|
||||||
pub current_mailbox: Option<MailboxHash>,
|
pub current_mailbox: MailboxSelection,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for ImapStream {
|
impl Drop for ImapStream {
|
||||||
|
@ -395,7 +407,7 @@ impl ImapConnection {
|
||||||
server_conf: server_conf.clone(),
|
server_conf: server_conf.clone(),
|
||||||
capabilities: Capabilities::default(),
|
capabilities: Capabilities::default(),
|
||||||
uid_store,
|
uid_store,
|
||||||
current_mailbox: None,
|
current_mailbox: MailboxSelection::None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,7 +543,15 @@ impl ImapConnection {
|
||||||
Err(MeliError::new("Connection timed out"))
|
Err(MeliError::new("Connection timed out"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_mailbox(&mut self, mailbox_hash: MailboxHash, ret: &mut String) -> Result<()> {
|
pub fn select_mailbox(
|
||||||
|
&mut self,
|
||||||
|
mailbox_hash: MailboxHash,
|
||||||
|
ret: &mut String,
|
||||||
|
force: bool,
|
||||||
|
) -> Result<()> {
|
||||||
|
if !force && self.current_mailbox == MailboxSelection::Select(mailbox_hash) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
self.send_command(
|
self.send_command(
|
||||||
format!(
|
format!(
|
||||||
"SELECT \"{}\"",
|
"SELECT \"{}\"",
|
||||||
|
@ -541,11 +561,19 @@ impl ImapConnection {
|
||||||
)?;
|
)?;
|
||||||
self.read_response(ret, RequiredResponses::SELECT_REQUIRED)?;
|
self.read_response(ret, RequiredResponses::SELECT_REQUIRED)?;
|
||||||
debug!("select response {}", ret);
|
debug!("select response {}", ret);
|
||||||
self.current_mailbox = Some(mailbox_hash);
|
self.current_mailbox = MailboxSelection::Select(mailbox_hash);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn examine_mailbox(&mut self, mailbox_hash: MailboxHash, ret: &mut String) -> Result<()> {
|
pub fn examine_mailbox(
|
||||||
|
&mut self,
|
||||||
|
mailbox_hash: MailboxHash,
|
||||||
|
ret: &mut String,
|
||||||
|
force: bool,
|
||||||
|
) -> Result<()> {
|
||||||
|
if !force && self.current_mailbox == MailboxSelection::Examine(mailbox_hash) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
self.send_command(
|
self.send_command(
|
||||||
format!(
|
format!(
|
||||||
"EXAMINE \"{}\"",
|
"EXAMINE \"{}\"",
|
||||||
|
@ -555,29 +583,32 @@ impl ImapConnection {
|
||||||
)?;
|
)?;
|
||||||
self.read_response(ret, RequiredResponses::EXAMINE_REQUIRED)?;
|
self.read_response(ret, RequiredResponses::EXAMINE_REQUIRED)?;
|
||||||
debug!("examine response {}", ret);
|
debug!("examine response {}", ret);
|
||||||
self.current_mailbox = Some(mailbox_hash);
|
self.current_mailbox = MailboxSelection::Examine(mailbox_hash);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unselect(&mut self) -> Result<()> {
|
pub fn unselect(&mut self) -> Result<()> {
|
||||||
if let Some(mailbox_hash) = self.current_mailbox.take() {
|
match self.current_mailbox.take() {
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
MailboxSelection::Examine(mailbox_hash) | MailboxSelection::Select(mailbox_hash) => {
|
||||||
if self
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
.capabilities
|
if self
|
||||||
.iter()
|
.capabilities
|
||||||
.any(|cap| cap.eq_ignore_ascii_case(b"UNSELECT"))
|
.iter()
|
||||||
{
|
.any(|cap| cap.eq_ignore_ascii_case(b"UNSELECT"))
|
||||||
self.send_command(b"UNSELECT")?;
|
{
|
||||||
self.read_response(&mut response, RequiredResponses::empty())?;
|
self.send_command(b"UNSELECT")?;
|
||||||
} else {
|
self.read_response(&mut response, RequiredResponses::empty())?;
|
||||||
/* `RFC3691 - UNSELECT Command` states: "[..] IMAP4 provides this
|
} else {
|
||||||
* functionality (via a SELECT command with a nonexistent mailbox name or
|
/* `RFC3691 - UNSELECT Command` states: "[..] IMAP4 provides this
|
||||||
* reselecting the same mailbox with EXAMINE command)[..]
|
* functionality (via a SELECT command with a nonexistent mailbox name or
|
||||||
*/
|
* reselecting the same mailbox with EXAMINE command)[..]
|
||||||
|
*/
|
||||||
self.select_mailbox(mailbox_hash, &mut response)?;
|
|
||||||
self.examine_mailbox(mailbox_hash, &mut response)?;
|
self.select_mailbox(mailbox_hash, &mut response, true)?;
|
||||||
}
|
self.examine_mailbox(mailbox_hash, &mut response, true)?;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MailboxSelection::None => {},
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -596,13 +627,7 @@ impl ImapConnection {
|
||||||
pub fn create_uid_msn_cache(&mut self, mailbox_hash: MailboxHash, low: usize) -> Result<()> {
|
pub fn create_uid_msn_cache(&mut self, mailbox_hash: MailboxHash, low: usize) -> Result<()> {
|
||||||
debug_assert!(low > 0);
|
debug_assert!(low > 0);
|
||||||
let mut response = String::new();
|
let mut response = String::new();
|
||||||
if self
|
self.examine_mailbox(mailbox_hash, &mut response, false)?;
|
||||||
.current_mailbox
|
|
||||||
.map(|h| h != mailbox_hash)
|
|
||||||
.unwrap_or(true)
|
|
||||||
{
|
|
||||||
self.examine_mailbox(mailbox_hash, &mut response)?;
|
|
||||||
}
|
|
||||||
self.send_command(format!("UID SEARCH {}:*", low).as_bytes())?;
|
self.send_command(format!("UID SEARCH {}:*", low).as_bytes())?;
|
||||||
self.read_response(&mut response, RequiredResponses::SEARCH)?;
|
self.read_response(&mut response, RequiredResponses::SEARCH)?;
|
||||||
debug!("uid search response {:?}", &response);
|
debug!("uid search response {:?}", &response);
|
||||||
|
|
|
@ -81,7 +81,7 @@ impl BackendOp for ImapOp {
|
||||||
{
|
{
|
||||||
let mut conn =
|
let mut conn =
|
||||||
try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
||||||
conn.examine_mailbox(self.mailbox_hash, &mut response)?;
|
conn.examine_mailbox(self.mailbox_hash, &mut response, false)?;
|
||||||
conn.send_command(format!("UID FETCH {} (FLAGS RFC822)", self.uid).as_bytes())?;
|
conn.send_command(format!("UID FETCH {} (FLAGS RFC822)", self.uid).as_bytes())?;
|
||||||
conn.read_response(&mut response, RequiredResponses::FETCH_REQUIRED)?;
|
conn.read_response(&mut response, RequiredResponses::FETCH_REQUIRED)?;
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ impl BackendOp for ImapOp {
|
||||||
&self.connection,
|
&self.connection,
|
||||||
Some(std::time::Duration::new(2, 0))
|
Some(std::time::Duration::new(2, 0))
|
||||||
));
|
));
|
||||||
or_return_default!(conn.examine_mailbox(self.mailbox_hash, &mut response));
|
or_return_default!(conn.examine_mailbox(self.mailbox_hash, &mut response, false));
|
||||||
or_return_default!(
|
or_return_default!(
|
||||||
conn.send_command(format!("UID FETCH {} FLAGS", self.uid).as_bytes())
|
conn.send_command(format!("UID FETCH {} FLAGS", self.uid).as_bytes())
|
||||||
);
|
);
|
||||||
|
@ -170,7 +170,7 @@ impl BackendOp for ImapOp {
|
||||||
|
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
let mut conn = try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
let mut conn = try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
||||||
conn.select_mailbox(self.mailbox_hash, &mut response)?;
|
conn.select_mailbox(self.mailbox_hash, &mut response, false)?;
|
||||||
debug!(&response);
|
debug!(&response);
|
||||||
conn.send_command(
|
conn.send_command(
|
||||||
format!(
|
format!(
|
||||||
|
@ -205,7 +205,7 @@ impl BackendOp for ImapOp {
|
||||||
fn set_tag(&mut self, envelope: &mut Envelope, tag: String, value: bool) -> Result<()> {
|
fn set_tag(&mut self, envelope: &mut Envelope, tag: String, value: bool) -> Result<()> {
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
let mut conn = try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
let mut conn = try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
||||||
conn.select_mailbox(self.mailbox_hash, &mut response)?;
|
conn.select_mailbox(self.mailbox_hash, &mut response, false)?;
|
||||||
conn.send_command(
|
conn.send_command(
|
||||||
format!(
|
format!(
|
||||||
"UID STORE {} {}FLAGS.SILENT ({})",
|
"UID STORE {} {}FLAGS.SILENT ({})",
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use super::ImapConnection;
|
use super::{ImapConnection, MailboxSelection};
|
||||||
use crate::backends::imap::protocol_parser::{
|
use crate::backends::imap::protocol_parser::{
|
||||||
ImapLineSplit, RequiredResponses, UidFetchResponse, UntaggedResponse,
|
ImapLineSplit, RequiredResponses, UidFetchResponse, UntaggedResponse,
|
||||||
};
|
};
|
||||||
|
@ -51,11 +51,9 @@ impl ImapConnection {
|
||||||
} else { Ok(()) }?;)+
|
} else { Ok(()) }?;)+
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
//FIXME
|
let mailbox_hash = match self.current_mailbox {
|
||||||
let mailbox_hash = if let Some(mailbox_hash) = self.current_mailbox {
|
MailboxSelection::Select(h) | MailboxSelection::Examine(h) => h,
|
||||||
mailbox_hash
|
MailboxSelection::None => return Ok(false),
|
||||||
} else {
|
|
||||||
return Ok(false);
|
|
||||||
};
|
};
|
||||||
let mailbox =
|
let mailbox =
|
||||||
std::clone::Clone::clone(&self.uid_store.mailboxes.read().unwrap()[&mailbox_hash]);
|
std::clone::Clone::clone(&self.uid_store.mailboxes.read().unwrap()[&mailbox_hash]);
|
||||||
|
|
|
@ -281,7 +281,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
conn.examine_mailbox(mailbox_hash, &mut response)
|
conn.examine_mailbox(mailbox_hash, &mut response, false)
|
||||||
conn.send_command(b"UID SEARCH RECENT")
|
conn.send_command(b"UID SEARCH RECENT")
|
||||||
conn.read_response(&mut response, RequiredResponses::SEARCH)
|
conn.read_response(&mut response, RequiredResponses::SEARCH)
|
||||||
);
|
);
|
||||||
|
@ -459,7 +459,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
conn.examine_mailbox(mailbox_hash, &mut response)
|
conn.examine_mailbox(mailbox_hash, &mut response, false)
|
||||||
conn.send_command(
|
conn.send_command(
|
||||||
&[
|
&[
|
||||||
b"FETCH",
|
b"FETCH",
|
||||||
|
@ -567,7 +567,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
conn.examine_mailbox(mailbox_hash, &mut response)
|
conn.examine_mailbox(mailbox_hash, &mut response, false)
|
||||||
conn.send_command(
|
conn.send_command(
|
||||||
&[
|
&[
|
||||||
b"UID SEARCH ",
|
b"UID SEARCH ",
|
||||||
|
@ -648,7 +648,7 @@ pub fn examine_updates(
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
conn.examine_mailbox(mailbox_hash, &mut response)
|
conn.examine_mailbox(mailbox_hash, &mut response, true)
|
||||||
);
|
);
|
||||||
*uid_store.is_online.lock().unwrap() = (Instant::now(), Ok(()));
|
*uid_store.is_online.lock().unwrap() = (Instant::now(), Ok(()));
|
||||||
let uidvalidity;
|
let uidvalidity;
|
||||||
|
|
Loading…
Reference in New Issue