unselect implemented rfc3691
This commit is contained in:
parent
b9a0c1e6ec
commit
7ebc708aca
3 changed files with 25 additions and 6 deletions
|
@ -6,8 +6,11 @@ use crate::imap::flow;
|
||||||
use crate::imap::response::Response;
|
use crate::imap::response::Response;
|
||||||
|
|
||||||
pub(crate) fn capability(tag: Tag<'static>) -> Result<(Response<'static>, flow::Transition)> {
|
pub(crate) fn capability(tag: Tag<'static>) -> Result<(Response<'static>, flow::Transition)> {
|
||||||
let capabilities: NonEmptyVec<Capability> =
|
let capabilities: NonEmptyVec<Capability> = (vec![
|
||||||
(vec![Capability::Imap4Rev1, Capability::Idle]).try_into()?;
|
Capability::Imap4Rev1,
|
||||||
|
Capability::try_from("UNSELECT").unwrap(),
|
||||||
|
])
|
||||||
|
.try_into()?;
|
||||||
let res = Response::build()
|
let res = Response::build()
|
||||||
.tag(tag)
|
.tag(tag)
|
||||||
.message("Server capabilities")
|
.message("Server capabilities")
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub async fn dispatch(ctx: ExaminedContext<'_>) -> Result<(Response<'static>, fl
|
||||||
|
|
||||||
// Specific to the EXAMINE state (specialization of the SELECTED state)
|
// Specific to the EXAMINE state (specialization of the SELECTED state)
|
||||||
// ~3 commands -> close, fetch, search + NOOP
|
// ~3 commands -> close, fetch, search + NOOP
|
||||||
CommandBody::Close => ctx.close().await,
|
CommandBody::Close => ctx.close("CLOSE").await,
|
||||||
CommandBody::Fetch {
|
CommandBody::Fetch {
|
||||||
sequence_set,
|
sequence_set,
|
||||||
macro_or_item_names,
|
macro_or_item_names,
|
||||||
|
@ -44,10 +44,13 @@ pub async fn dispatch(ctx: ExaminedContext<'_>) -> Result<(Response<'static>, fl
|
||||||
Response::build()
|
Response::build()
|
||||||
.to_req(ctx.req)
|
.to_req(ctx.req)
|
||||||
.message("Forbidden command: can't write in read-only mode (EXAMINE)")
|
.message("Forbidden command: can't write in read-only mode (EXAMINE)")
|
||||||
.bad()?,
|
.no()?,
|
||||||
flow::Transition::None,
|
flow::Transition::None,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
|
// UNSELECT extension (rfc3691)
|
||||||
|
CommandBody::Unselect => ctx.close("UNSELECT").await,
|
||||||
|
|
||||||
// In examined mode, we fallback to authenticated when needed
|
// In examined mode, we fallback to authenticated when needed
|
||||||
_ => {
|
_ => {
|
||||||
authenticated::dispatch(authenticated::AuthenticatedContext {
|
authenticated::dispatch(authenticated::AuthenticatedContext {
|
||||||
|
@ -64,11 +67,11 @@ pub async fn dispatch(ctx: ExaminedContext<'_>) -> Result<(Response<'static>, fl
|
||||||
impl<'a> ExaminedContext<'a> {
|
impl<'a> ExaminedContext<'a> {
|
||||||
/// CLOSE in examined state is not the same as in selected state
|
/// CLOSE in examined state is not the same as in selected state
|
||||||
/// (in selected state it also does an EXPUNGE, here it doesn't)
|
/// (in selected state it also does an EXPUNGE, here it doesn't)
|
||||||
async fn close(self) -> Result<(Response<'static>, flow::Transition)> {
|
async fn close(self, kind: &str) -> Result<(Response<'static>, flow::Transition)> {
|
||||||
Ok((
|
Ok((
|
||||||
Response::build()
|
Response::build()
|
||||||
.to_req(self.req)
|
.to_req(self.req)
|
||||||
.message("CLOSE completed")
|
.message(format!("{} completed", kind))
|
||||||
.ok()?,
|
.ok()?,
|
||||||
flow::Transition::Unselect,
|
flow::Transition::Unselect,
|
||||||
))
|
))
|
||||||
|
|
|
@ -59,6 +59,9 @@ pub async fn dispatch<'a>(
|
||||||
uid,
|
uid,
|
||||||
} => ctx.copy(sequence_set, mailbox, uid).await,
|
} => ctx.copy(sequence_set, mailbox, uid).await,
|
||||||
|
|
||||||
|
// UNSELECT extension (rfc3691)
|
||||||
|
CommandBody::Unselect => ctx.unselect().await,
|
||||||
|
|
||||||
// In selected mode, we fallback to authenticated when needed
|
// In selected mode, we fallback to authenticated when needed
|
||||||
_ => {
|
_ => {
|
||||||
authenticated::dispatch(authenticated::AuthenticatedContext {
|
authenticated::dispatch(authenticated::AuthenticatedContext {
|
||||||
|
@ -84,6 +87,16 @@ impl<'a> SelectedContext<'a> {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn unselect(self) -> Result<(Response<'static>, flow::Transition)> {
|
||||||
|
Ok((
|
||||||
|
Response::build()
|
||||||
|
.to_req(self.req)
|
||||||
|
.message("UNSELECT completed")
|
||||||
|
.ok()?,
|
||||||
|
flow::Transition::Unselect,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn fetch(
|
pub async fn fetch(
|
||||||
self,
|
self,
|
||||||
sequence_set: &SequenceSet,
|
sequence_set: &SequenceSet,
|
||||||
|
|
Loading…
Reference in a new issue