Add support for Gmail Labels
This commit is contained in:
parent
afbc5118f2
commit
b22ce3a605
5 changed files with 18 additions and 85 deletions
|
|
@ -22,7 +22,7 @@ native-tls = { version = "0.2.2", optional = true }
|
||||||
rustls-connector = { version = "0.16.1", optional = true }
|
rustls-connector = { version = "0.16.1", optional = true }
|
||||||
regex = "1.0"
|
regex = "1.0"
|
||||||
bufstream = "0.1.3"
|
bufstream = "0.1.3"
|
||||||
imap-proto = "0.15.0"
|
imap-proto = "0.16.0"
|
||||||
nom = { version = "7.1.0", default-features = false }
|
nom = { version = "7.1.0", default-features = false }
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
chrono = { version = "0.4", default-features = false, features = ["std"]}
|
chrono = { version = "0.4", default-features = false, features = ["std"]}
|
||||||
|
|
|
||||||
|
|
@ -417,7 +417,7 @@ mod tests {
|
||||||
let first = names.get(0).unwrap();
|
let first = names.get(0).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
first.attributes(),
|
first.attributes(),
|
||||||
&[NameAttribute::from("\\HasNoChildren")]
|
&[NameAttribute::Extension(Cow::Borrowed("\\HasNoChildren"))]
|
||||||
);
|
);
|
||||||
assert_eq!(first.delimiter(), Some("."));
|
assert_eq!(first.delimiter(), Some("."));
|
||||||
assert_eq!(first.name(), "INBOX");
|
assert_eq!(first.name(), "INBOX");
|
||||||
|
|
@ -507,7 +507,7 @@ mod tests {
|
||||||
let first = names.get(0).unwrap();
|
let first = names.get(0).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
first.attributes(),
|
first.attributes(),
|
||||||
&[NameAttribute::from("\\HasNoChildren")]
|
&[NameAttribute::Extension(Cow::Borrowed("\\HasNoChildren"))]
|
||||||
);
|
);
|
||||||
assert_eq!(first.delimiter(), Some("."));
|
assert_eq!(first.delimiter(), Some("."));
|
||||||
assert_eq!(first.name(), "INBOX");
|
assert_eq!(first.name(), "INBOX");
|
||||||
|
|
|
||||||
|
|
@ -219,6 +219,17 @@ impl<'a> Fetch<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract the `X-GM-LABELS` of a `FETCH` response
|
||||||
|
///
|
||||||
|
/// This is a Gmail-specific extension. See their
|
||||||
|
/// [developer's page](https://developers.google.com/gmail/imap/imap-extensions) for details.
|
||||||
|
pub fn gmail_labels(&'a self) -> Option<impl Iterator<Item = &'a str>> {
|
||||||
|
self.fetch.iter().find_map(|av| match av {
|
||||||
|
AttributeValue::GmailLabels(labels) => Some(labels.iter().map(|cow| cow.as_ref())),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Get an owned copy of the [`Fetch`].
|
/// Get an owned copy of the [`Fetch`].
|
||||||
pub fn into_owned(self) -> Fetch<'static> {
|
pub fn into_owned(self) -> Fetch<'static> {
|
||||||
Fetch {
|
Fetch {
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ mod mailbox;
|
||||||
pub use self::mailbox::Mailbox;
|
pub use self::mailbox::Mailbox;
|
||||||
|
|
||||||
mod name;
|
mod name;
|
||||||
pub use self::name::{Name, NameAttribute, Names};
|
pub use self::name::{Name, Names};
|
||||||
|
|
||||||
mod capabilities;
|
mod capabilities;
|
||||||
pub use self::capabilities::Capabilities;
|
pub use self::capabilities::Capabilities;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::parse::{parse_many_into, MapOrNot};
|
use crate::parse::{parse_many_into, MapOrNot};
|
||||||
use crate::types::UnsolicitedResponse;
|
use crate::types::UnsolicitedResponse;
|
||||||
use imap_proto::{MailboxDatum, Response};
|
use imap_proto::{MailboxDatum, NameAttribute, Response};
|
||||||
use ouroboros::self_referencing;
|
use ouroboros::self_referencing;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::slice::Iter;
|
use std::slice::Iter;
|
||||||
|
|
@ -28,11 +28,11 @@ impl Names {
|
||||||
let mut names = Vec::new();
|
let mut names = Vec::new();
|
||||||
parse_many_into(input, &mut names, unsolicited, |response| match response {
|
parse_many_into(input, &mut names, unsolicited, |response| match response {
|
||||||
Response::MailboxData(MailboxDatum::List {
|
Response::MailboxData(MailboxDatum::List {
|
||||||
flags,
|
name_attributes,
|
||||||
delimiter,
|
delimiter,
|
||||||
name,
|
name,
|
||||||
}) => Ok(MapOrNot::Map(Name {
|
}) => Ok(MapOrNot::Map(Name {
|
||||||
attributes: flags.into_iter().map(NameAttribute::from).collect(),
|
attributes: name_attributes,
|
||||||
delimiter,
|
delimiter,
|
||||||
name,
|
name,
|
||||||
})),
|
})),
|
||||||
|
|
@ -73,84 +73,6 @@ pub struct Name<'a> {
|
||||||
pub(crate) name: Cow<'a, str>,
|
pub(crate) name: Cow<'a, str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An attribute set for an IMAP name.
|
|
||||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
|
||||||
pub enum NameAttribute<'a> {
|
|
||||||
/// It is not possible for any child levels of hierarchy to exist
|
|
||||||
/// under this name; no child levels exist now and none can be
|
|
||||||
/// created in the future.
|
|
||||||
NoInferiors,
|
|
||||||
|
|
||||||
/// It is not possible to use this name as a selectable mailbox.
|
|
||||||
NoSelect,
|
|
||||||
|
|
||||||
/// The mailbox has been marked "interesting" by the server; the
|
|
||||||
/// mailbox probably contains messages that have been added since
|
|
||||||
/// the last time the mailbox was selected.
|
|
||||||
Marked,
|
|
||||||
|
|
||||||
/// The mailbox does not contain any additional messages since the
|
|
||||||
/// last time the mailbox was selected.
|
|
||||||
Unmarked,
|
|
||||||
|
|
||||||
/// A non-standard user- or server-defined name attribute.
|
|
||||||
Custom(Cow<'a, str>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NameAttribute<'static> {
|
|
||||||
fn system(s: &str) -> Option<Self> {
|
|
||||||
match s {
|
|
||||||
"\\Noinferiors" => Some(NameAttribute::NoInferiors),
|
|
||||||
"\\Noselect" => Some(NameAttribute::NoSelect),
|
|
||||||
"\\Marked" => Some(NameAttribute::Marked),
|
|
||||||
"\\Unmarked" => Some(NameAttribute::Unmarked),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> NameAttribute<'a> {
|
|
||||||
fn into_owned(self) -> NameAttribute<'static> {
|
|
||||||
match self {
|
|
||||||
NameAttribute::NoInferiors => NameAttribute::NoInferiors,
|
|
||||||
NameAttribute::NoSelect => NameAttribute::NoSelect,
|
|
||||||
NameAttribute::Marked => NameAttribute::Marked,
|
|
||||||
NameAttribute::Unmarked => NameAttribute::Unmarked,
|
|
||||||
NameAttribute::Custom(cow) => NameAttribute::Custom(Cow::Owned(cow.into_owned())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<String> for NameAttribute<'a> {
|
|
||||||
fn from(s: String) -> Self {
|
|
||||||
if let Some(f) = NameAttribute::system(&s) {
|
|
||||||
f
|
|
||||||
} else {
|
|
||||||
NameAttribute::Custom(Cow::Owned(s))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<Cow<'a, str>> for NameAttribute<'a> {
|
|
||||||
fn from(s: Cow<'a, str>) -> Self {
|
|
||||||
if let Some(f) = NameAttribute::system(&*s) {
|
|
||||||
f
|
|
||||||
} else {
|
|
||||||
NameAttribute::Custom(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<&'a str> for NameAttribute<'a> {
|
|
||||||
fn from(s: &'a str) -> Self {
|
|
||||||
if let Some(f) = NameAttribute::system(s) {
|
|
||||||
f
|
|
||||||
} else {
|
|
||||||
NameAttribute::Custom(Cow::Borrowed(s))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Name<'a> {
|
impl<'a> Name<'a> {
|
||||||
/// Attributes of this name.
|
/// Attributes of this name.
|
||||||
pub fn attributes(&self) -> &[NameAttribute<'a>] {
|
pub fn attributes(&self) -> &[NameAttribute<'a>] {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue