Add support for flags

This commit is contained in:
Quentin 2022-06-27 11:40:45 +02:00
parent 22d0f11173
commit d3f8a6627c
Signed by: quentin
GPG Key ID: E9602264D639FF68
3 changed files with 41 additions and 3 deletions

View File

@ -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),

View File

@ -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,
});
}

View File

@ -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 ----