mirror of
https://github.com/chatmail/core.git
synced 2026-05-19 06:46:32 +03:00
refactor(imap): make select_folder() accept non-optional folder
If no folder should be selected, `maybe_close_folder()` can be called directly.
This commit is contained in:
@@ -184,7 +184,7 @@ impl Session {
|
|||||||
bail!("Attempt to fetch UID 0");
|
bail!("Attempt to fetch UID 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.select_folder(context, Some(folder)).await?;
|
self.select_folder(context, folder).await?;
|
||||||
|
|
||||||
// we are connected, and the folder is selected
|
// we are connected, and the folder is selected
|
||||||
info!(context, "Downloading message {}/{} fully...", folder, uid);
|
info!(context, "Downloading message {}/{} fully...", folder, uid);
|
||||||
|
|||||||
10
src/imap.rs
10
src/imap.rs
@@ -838,7 +838,7 @@ impl Session {
|
|||||||
// Collect pairs of UID and Message-ID.
|
// Collect pairs of UID and Message-ID.
|
||||||
let mut msgs = BTreeMap::new();
|
let mut msgs = BTreeMap::new();
|
||||||
|
|
||||||
self.select_folder(context, Some(folder)).await?;
|
self.select_folder(context, folder).await?;
|
||||||
|
|
||||||
let mut list = self
|
let mut list = self
|
||||||
.uid_fetch("1:*", RFC724MID_UID)
|
.uid_fetch("1:*", RFC724MID_UID)
|
||||||
@@ -1039,7 +1039,7 @@ impl Session {
|
|||||||
// MOVE/DELETE operations. This does not result in multiple SELECT commands
|
// MOVE/DELETE operations. This does not result in multiple SELECT commands
|
||||||
// being sent because `select_folder()` does nothing if the folder is already
|
// being sent because `select_folder()` does nothing if the folder is already
|
||||||
// selected.
|
// selected.
|
||||||
self.select_folder(context, Some(folder)).await?;
|
self.select_folder(context, folder).await?;
|
||||||
|
|
||||||
// Empty target folder name means messages should be deleted.
|
// Empty target folder name means messages should be deleted.
|
||||||
if target.is_empty() {
|
if target.is_empty() {
|
||||||
@@ -1087,7 +1087,7 @@ impl Session {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
for (folder, rowid_set, uid_set) in UidGrouper::from(rows) {
|
for (folder, rowid_set, uid_set) in UidGrouper::from(rows) {
|
||||||
self.select_folder(context, Some(&folder))
|
self.select_folder(context, &folder)
|
||||||
.await
|
.await
|
||||||
.context("failed to select folder")?;
|
.context("failed to select folder")?;
|
||||||
|
|
||||||
@@ -1131,7 +1131,7 @@ impl Session {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.select_folder(context, Some(folder))
|
self.select_folder(context, folder)
|
||||||
.await
|
.await
|
||||||
.context("failed to select folder")?;
|
.context("failed to select folder")?;
|
||||||
|
|
||||||
@@ -1563,7 +1563,7 @@ impl Session {
|
|||||||
) -> Result<Option<&'a str>> {
|
) -> Result<Option<&'a str>> {
|
||||||
// Close currently selected folder if needed.
|
// Close currently selected folder if needed.
|
||||||
// We are going to select folders using low-level EXAMINE operations below.
|
// We are going to select folders using low-level EXAMINE operations below.
|
||||||
self.select_folder(context, None).await?;
|
self.maybe_close_folder(context).await?;
|
||||||
|
|
||||||
for folder in folders {
|
for folder in folders {
|
||||||
info!(context, "Looking for MVBOX-folder \"{}\"...", &folder);
|
info!(context, "Looking for MVBOX-folder \"{}\"...", &folder);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ impl Session {
|
|||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
use futures::future::FutureExt;
|
use futures::future::FutureExt;
|
||||||
|
|
||||||
self.select_folder(context, Some(folder)).await?;
|
self.select_folder(context, folder).await?;
|
||||||
|
|
||||||
if self.server_sent_unsolicited_exists(context)? {
|
if self.server_sent_unsolicited_exists(context)? {
|
||||||
return Ok(self);
|
return Ok(self);
|
||||||
|
|||||||
@@ -55,15 +55,13 @@ impl ImapSession {
|
|||||||
pub(crate) async fn select_folder(
|
pub(crate) async fn select_folder(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
folder: Option<&str>,
|
folder: &str,
|
||||||
) -> Result<NewlySelected> {
|
) -> Result<NewlySelected> {
|
||||||
// if there is a new folder and the new folder is equal to the selected one, there's nothing to do.
|
// if there is a new folder and the new folder is equal to the selected one, there's nothing to do.
|
||||||
// if there is _no_ new folder, we continue as we might want to expunge below.
|
// if there is _no_ new folder, we continue as we might want to expunge below.
|
||||||
if let Some(folder) = folder {
|
if let Some(selected_folder) = &self.selected_folder {
|
||||||
if let Some(selected_folder) = &self.selected_folder {
|
if folder == selected_folder {
|
||||||
if folder == selected_folder {
|
return Ok(NewlySelected::No);
|
||||||
return Ok(NewlySelected::No);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,34 +69,30 @@ impl ImapSession {
|
|||||||
self.maybe_close_folder(context).await?;
|
self.maybe_close_folder(context).await?;
|
||||||
|
|
||||||
// select new folder
|
// select new folder
|
||||||
if let Some(folder) = folder {
|
let res = if self.can_condstore() {
|
||||||
let res = if self.can_condstore() {
|
self.select_condstore(folder).await
|
||||||
self.select_condstore(folder).await
|
|
||||||
} else {
|
|
||||||
self.select(folder).await
|
|
||||||
};
|
|
||||||
|
|
||||||
// <https://tools.ietf.org/html/rfc3501#section-6.3.1>
|
|
||||||
// says that if the server reports select failure we are in
|
|
||||||
// authenticated (not-select) state.
|
|
||||||
|
|
||||||
match res {
|
|
||||||
Ok(mailbox) => {
|
|
||||||
self.selected_folder = Some(folder.to_string());
|
|
||||||
self.selected_mailbox = Some(mailbox);
|
|
||||||
Ok(NewlySelected::Yes)
|
|
||||||
}
|
|
||||||
Err(async_imap::error::Error::ConnectionLost) => Err(Error::ConnectionLost),
|
|
||||||
Err(async_imap::error::Error::Validate(_)) => {
|
|
||||||
Err(Error::BadFolderName(folder.to_string()))
|
|
||||||
}
|
|
||||||
Err(async_imap::error::Error::No(response)) => {
|
|
||||||
Err(Error::NoFolder(folder.to_string(), response))
|
|
||||||
}
|
|
||||||
Err(err) => Err(Error::Other(err.to_string())),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Ok(NewlySelected::No)
|
self.select(folder).await
|
||||||
|
};
|
||||||
|
|
||||||
|
// <https://tools.ietf.org/html/rfc3501#section-6.3.1>
|
||||||
|
// says that if the server reports select failure we are in
|
||||||
|
// authenticated (not-select) state.
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok(mailbox) => {
|
||||||
|
self.selected_folder = Some(folder.to_string());
|
||||||
|
self.selected_mailbox = Some(mailbox);
|
||||||
|
Ok(NewlySelected::Yes)
|
||||||
|
}
|
||||||
|
Err(async_imap::error::Error::ConnectionLost) => Err(Error::ConnectionLost),
|
||||||
|
Err(async_imap::error::Error::Validate(_)) => {
|
||||||
|
Err(Error::BadFolderName(folder.to_string()))
|
||||||
|
}
|
||||||
|
Err(async_imap::error::Error::No(response)) => {
|
||||||
|
Err(Error::NoFolder(folder.to_string(), response))
|
||||||
|
}
|
||||||
|
Err(err) => Err(Error::Other(err.to_string())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +102,7 @@ impl ImapSession {
|
|||||||
context: &Context,
|
context: &Context,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
) -> anyhow::Result<NewlySelected> {
|
) -> anyhow::Result<NewlySelected> {
|
||||||
match self.select_folder(context, Some(folder)).await {
|
match self.select_folder(context, folder).await {
|
||||||
Ok(newly_selected) => Ok(newly_selected),
|
Ok(newly_selected) => Ok(newly_selected),
|
||||||
Err(err) => match err {
|
Err(err) => match err {
|
||||||
Error::NoFolder(..) => {
|
Error::NoFolder(..) => {
|
||||||
@@ -118,7 +112,7 @@ impl ImapSession {
|
|||||||
info!(context, "Couldn't select folder, then create() failed: {err:#}.");
|
info!(context, "Couldn't select folder, then create() failed: {err:#}.");
|
||||||
// Need to recheck, could have been created in parallel.
|
// Need to recheck, could have been created in parallel.
|
||||||
}
|
}
|
||||||
let select_res = self.select_folder(context, Some(folder)).await.with_context(|| format!("failed to select newely created folder {folder}"));
|
let select_res = self.select_folder(context, folder).await.with_context(|| format!("failed to select newely created folder {folder}"));
|
||||||
if select_res.is_err() {
|
if select_res.is_err() {
|
||||||
create_res?;
|
create_res?;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user