Add support for flags
This commit is contained in:
parent
22d0f11173
commit
d3f8a6627c
3 changed files with 41 additions and 3 deletions
|
@ -1,7 +1,8 @@
|
|||
use anyhow::{anyhow, Error, Result};
|
||||
use boitalettres::proto::Response;
|
||||
use imap_codec::types::command::CommandBody;
|
||||
use imap_codec::types::core::Tag;
|
||||
use imap_codec::types::core::{Atom, Tag};
|
||||
use imap_codec::types::flag::Flag;
|
||||
use imap_codec::types::mailbox::{ListMailbox, Mailbox as MailboxCodec};
|
||||
use imap_codec::types::response::{Code, Data, Response as ImapRes, Status};
|
||||
|
||||
|
@ -10,6 +11,14 @@ use crate::imap::flow;
|
|||
use crate::imap::session::InnerContext;
|
||||
use crate::mailbox::Mailbox;
|
||||
|
||||
const DEFAULT_FLAGS: [Flag; 5] = [
|
||||
Flag::Seen,
|
||||
Flag::Answered,
|
||||
Flag::Flagged,
|
||||
Flag::Deleted,
|
||||
Flag::Draft,
|
||||
];
|
||||
|
||||
pub async fn dispatch<'a>(
|
||||
inner: InnerContext<'a>,
|
||||
user: &'a flow::User,
|
||||
|
@ -114,7 +123,6 @@ impl<'a> StateContext<'a> {
|
|||
"First unseen UID",
|
||||
)
|
||||
.map_err(Error::msg)?;
|
||||
//let r_permanentflags = Status::ok(None, Some(Code::
|
||||
|
||||
let mut res = Vec::<ImapRes>::new();
|
||||
|
||||
|
@ -122,7 +130,21 @@ impl<'a> StateContext<'a> {
|
|||
|
||||
res.push(ImapRes::Data(Data::Recent(sum.recent)));
|
||||
|
||||
res.push(ImapRes::Data(Data::Flags(vec![])));
|
||||
let mut flags: Vec<Flag> = sum.flags.map(|f| match f.chars().next() {
|
||||
Some('\\') => None,
|
||||
Some('$') if f == "$unseen" => None,
|
||||
Some(_) => match Atom::try_from(f.clone()) {
|
||||
Err(_) => {
|
||||
tracing::error!(username=%self.user.name, mailbox=%name, flag=%f, "Unable to encode flag as IMAP atom");
|
||||
None
|
||||
},
|
||||
Ok(a) => Some(Flag::Keyword(a)),
|
||||
},
|
||||
None => None,
|
||||
}).flatten().collect();
|
||||
flags.extend_from_slice(&DEFAULT_FLAGS);
|
||||
|
||||
res.push(ImapRes::Data(Data::Flags(flags.clone())));
|
||||
|
||||
let uid_validity = Status::ok(
|
||||
None,
|
||||
|
@ -149,6 +171,14 @@ impl<'a> StateContext<'a> {
|
|||
res.push(ImapRes::Status(status_unseen));
|
||||
}
|
||||
|
||||
flags.push(Flag::Permanent);
|
||||
let permanent_flags = Status::ok(
|
||||
None,
|
||||
Some(Code::PermanentFlags(flags)),
|
||||
"Flags permitted",
|
||||
).map_err(Error::msg)?;
|
||||
res.push(ImapRes::Status(permanent_flags));
|
||||
|
||||
let last = Status::ok(
|
||||
Some(self.tag.clone()),
|
||||
Some(Code::ReadWrite),
|
||||
|
|
|
@ -15,6 +15,7 @@ pub struct Summary<'a> {
|
|||
pub next: ImapUid,
|
||||
pub exists: u32,
|
||||
pub recent: u32,
|
||||
pub flags: FlagIter<'a>,
|
||||
pub unseen: Option<&'a ImapUid>,
|
||||
}
|
||||
impl std::fmt::Display for Summary<'_> {
|
||||
|
@ -69,6 +70,7 @@ impl Mailbox {
|
|||
next: state.uidnext,
|
||||
exists: u32::try_from(state.idx_by_uid.len())?,
|
||||
recent: u32::try_from(recent)?,
|
||||
flags: state.idx_by_flag.flags(),
|
||||
unseen,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -164,6 +164,7 @@ impl BayouState for UidIndex {
|
|||
// ---- FlagIndex implementation ----
|
||||
#[derive(Clone)]
|
||||
pub struct FlagIndex(HashMap<Flag, OrdSet<ImapUid>>);
|
||||
pub type FlagIter<'a> = im::hashmap::Keys<'a, Flag, OrdSet<ImapUid>>;
|
||||
|
||||
impl FlagIndex {
|
||||
fn new() -> Self {
|
||||
|
@ -182,9 +183,14 @@ impl FlagIndex {
|
|||
self.0.get_mut(flag).and_then(|set| set.remove(&uid));
|
||||
});
|
||||
}
|
||||
|
||||
pub fn get(&self, f: &Flag) -> Option<&OrdSet<ImapUid>> {
|
||||
self.0.get(f)
|
||||
}
|
||||
|
||||
pub fn flags(&self) -> FlagIter {
|
||||
self.0.keys()
|
||||
}
|
||||
}
|
||||
|
||||
// ---- CUSTOM SERIALIZATION AND DESERIALIZATION ----
|
||||
|
|
Loading…
Reference in a new issue