Skip to content

Commit 2906e6d

Browse files
authored
Add support for googles x-gm-labels extension (#138)
1 parent b25513a commit 2906e6d

File tree

5 files changed

+70
-1
lines changed

5 files changed

+70
-1
lines changed

imap-proto/src/builders/command.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ fn push_attr(cmd: &mut Vec<u8>, attr: Attribute) {
253253
Attribute::Rfc822Size => "RFC822.SIZE",
254254
Attribute::Rfc822Text => "RFC822.TEXT",
255255
Attribute::Uid => "UID",
256+
Attribute::GmailLabels => "X-GM-LABELS",
256257
}
257258
.as_bytes(),
258259
);

imap-proto/src/parser/gmail.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use std::borrow::Cow;
2+
3+
use nom::branch::alt;
4+
use nom::bytes::streaming::tag_no_case;
5+
use nom::combinator::map;
6+
use nom::sequence::preceded;
7+
use nom::IResult;
8+
9+
use crate::{AttributeValue, MailboxDatum};
10+
11+
use super::core::{parenthesized_list, quoted_utf8};
12+
use super::rfc3501::flag;
13+
14+
pub(crate) fn gmail_label_list(i: &[u8]) -> IResult<&[u8], Vec<Cow<str>>> {
15+
preceded(
16+
tag_no_case("X-GM-LABELS "),
17+
parenthesized_list(map(alt((flag, quoted_utf8)), Cow::Borrowed)),
18+
)(i)
19+
}
20+
21+
pub(crate) fn msg_att_gmail_labels(i: &[u8]) -> IResult<&[u8], AttributeValue> {
22+
map(gmail_label_list, AttributeValue::GmailLabels)(i)
23+
}
24+
25+
pub(crate) fn mailbox_data_gmail_labels(i: &[u8]) -> IResult<&[u8], MailboxDatum> {
26+
map(gmail_label_list, MailboxDatum::GmailLabels)(i)
27+
}
28+
29+
#[cfg(test)]
30+
mod tests {
31+
use crate::types::*;
32+
#[test]
33+
fn test_gmail_labels() {
34+
let env = br#"X-GM-LABELS (\Inbox \Sent Important "Muy Importante") "#;
35+
match super::msg_att_gmail_labels(env) {
36+
Ok((_, AttributeValue::GmailLabels(labels))) => {
37+
println!("{:?}", labels);
38+
assert_eq!(
39+
["\\Inbox", "\\Sent", "Important", "Muy Importante"].to_vec(),
40+
labels
41+
);
42+
}
43+
rsp => {
44+
let e = rsp.unwrap_err();
45+
if let nom::Err::Error(i) = &e {
46+
println!("{:?}", std::str::from_utf8(i.input));
47+
}
48+
panic!("unexpected response {:?}", e);
49+
}
50+
}
51+
}
52+
}

imap-proto/src/parser/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use nom::{branch::alt, IResult};
44
pub mod core;
55

66
pub mod bodystructure;
7+
pub mod gmail;
78
pub mod rfc2087;
89
pub mod rfc3501;
910
pub mod rfc4315;

imap-proto/src/parser/rfc3501/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ use crate::{
2525
types::*,
2626
};
2727

28+
use super::gmail;
29+
2830
pub mod body;
2931
pub mod body_structure;
3032

@@ -69,7 +71,7 @@ fn flag_extension(i: &[u8]) -> IResult<&[u8], &str> {
6971
)(i)
7072
}
7173

72-
fn flag(i: &[u8]) -> IResult<&[u8], &str> {
74+
pub(crate) fn flag(i: &[u8]) -> IResult<&[u8], &str> {
7375
alt((flag_extension, atom))(i)
7476
}
7577

@@ -361,6 +363,7 @@ fn mailbox_data(i: &[u8]) -> IResult<&[u8], MailboxDatum> {
361363
mailbox_data_status,
362364
mailbox_data_recent,
363365
mailbox_data_search,
366+
gmail::mailbox_data_gmail_labels,
364367
rfc5256::mailbox_data_sort,
365368
))(i)
366369
}
@@ -555,6 +558,7 @@ fn msg_att(i: &[u8]) -> IResult<&[u8], AttributeValue> {
555558
msg_att_rfc822_size,
556559
msg_att_rfc822_text,
557560
msg_att_uid,
561+
gmail::msg_att_gmail_labels,
558562
))(i)
559563
}
560564

imap-proto/src/types.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ pub enum MailboxDatum<'a> {
220220
mailbox: Cow<'a, str>,
221221
values: Vec<Cow<'a, str>>,
222222
},
223+
GmailLabels(Vec<Cow<'a, str>>),
223224
}
224225

225226
impl<'a> MailboxDatum<'a> {
@@ -260,6 +261,9 @@ impl<'a> MailboxDatum<'a> {
260261
values: values.into_iter().map(to_owned_cow).collect(),
261262
}
262263
}
264+
MailboxDatum::GmailLabels(labels) => {
265+
MailboxDatum::GmailLabels(labels.into_iter().map(to_owned_cow).collect())
266+
}
263267
}
264268
}
265269
}
@@ -293,6 +297,8 @@ pub enum Attribute {
293297
Rfc822Size,
294298
Rfc822Text,
295299
Uid,
300+
/// https://developers.google.com/gmail/imap/imap-extensions#access_to_gmail_labels_x-gm-labels
301+
GmailLabels,
296302
}
297303

298304
#[derive(Debug, Eq, PartialEq)]
@@ -327,6 +333,8 @@ pub enum AttributeValue<'a> {
327333
Rfc822Size(u32),
328334
Rfc822Text(Option<Cow<'a, [u8]>>),
329335
Uid(u32),
336+
/// https://developers.google.com/gmail/imap/imap-extensions#access_to_gmail_labels_x-gm-labels
337+
GmailLabels(Vec<Cow<'a, str>>),
330338
}
331339

332340
impl<'a> AttributeValue<'a> {
@@ -353,6 +361,9 @@ impl<'a> AttributeValue<'a> {
353361
AttributeValue::Rfc822Size(v) => AttributeValue::Rfc822Size(v),
354362
AttributeValue::Rfc822Text(v) => AttributeValue::Rfc822Text(v.map(to_owned_cow)),
355363
AttributeValue::Uid(v) => AttributeValue::Uid(v),
364+
AttributeValue::GmailLabels(v) => {
365+
AttributeValue::GmailLabels(v.into_iter().map(to_owned_cow).collect())
366+
}
356367
}
357368
}
358369
}

0 commit comments

Comments
 (0)