some more stubs for the example scenario

This commit is contained in:
Michael Zhang 2021-02-23 21:21:47 -06:00
parent f616cffef0
commit f27f5419fe
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
7 changed files with 6182 additions and 283 deletions

265
Cargo.lock generated
View file

@ -15,12 +15,6 @@ version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1"
[[package]]
name = "ascii_utils"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a"
[[package]]
name = "assert_matches"
version = "1.5.0"
@ -55,15 +49,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "base64"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
dependencies = [
"byteorder",
]
[[package]]
name = "base64"
version = "0.13.0"
@ -97,12 +82,6 @@ dependencies = [
"byte-tools",
]
[[package]]
name = "bufstream"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8"
[[package]]
name = "bumpalo"
version = "3.6.1"
@ -294,15 +273,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "fast_chemail"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "495a39d30d624c2caabe6312bfead73e7717692b44e0b32df168c275a2e8e9e4"
dependencies = [
"ascii_utils",
]
[[package]]
name = "fern"
version = "0.6.0"
@ -319,21 +289,6 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "format-bytes"
version = "0.2.0"
@ -460,17 +415,6 @@ dependencies = [
"typenum",
]
[[package]]
name = "getrandom"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "heck"
version = "0.3.2"
@ -489,16 +433,6 @@ dependencies = [
"libc",
]
[[package]]
name = "hostname"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e"
dependencies = [
"libc",
"winutil",
]
[[package]]
name = "ident_case"
version = "1.0.1"
@ -536,12 +470,6 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "itoa"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "js-sys"
version = "0.3.47"
@ -557,24 +485,6 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lettre"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "338d9a248c4b3ef60c51941c678bb8f64e244c0a98f1eb71db027d1e777a5700"
dependencies = [
"base64 0.10.1",
"bufstream",
"fast_chemail",
"hostname",
"log",
"native-tls",
"nom",
"serde",
"serde_derive",
"serde_json",
]
[[package]]
name = "libc"
version = "0.2.86"
@ -634,34 +544,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "native-tls"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4"
dependencies = [
"lazy_static",
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]]
name = "nom"
version = "4.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
dependencies = [
"memchr",
"version_check 0.1.5",
]
[[package]]
name = "ntapi"
version = "0.3.6"
@ -712,39 +594,12 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
name = "openssl"
version = "0.10.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"lazy_static",
"libc",
"openssl-sys",
]
[[package]]
name = "openssl-probe"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
[[package]]
name = "openssl-sys"
version = "0.9.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6"
dependencies = [
"autocfg",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "panorama"
version = "0.0.1"
@ -758,7 +613,6 @@ dependencies = [
"format-bytes",
"futures",
"inotify",
"lettre",
"log",
"panorama-imap",
"parking_lot",
@ -893,18 +747,6 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "ppv-lite86"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@ -915,7 +757,7 @@ dependencies = [
"proc-macro2",
"quote",
"syn",
"version_check 0.9.2",
"version_check",
]
[[package]]
@ -926,7 +768,7 @@ checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check 0.9.2",
"version_check",
]
[[package]]
@ -959,46 +801,6 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
dependencies = [
"rand_core",
]
[[package]]
name = "redox_syscall"
version = "0.2.5"
@ -1008,15 +810,6 @@ dependencies = [
"bitflags",
]
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "ring"
version = "0.16.20"
@ -1038,7 +831,7 @@ version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "064fd21ff87c6e87ed4506e68beb42459caa4a0e2eb144932e6776768556980b"
dependencies = [
"base64 0.13.0",
"base64",
"log",
"ring",
"sct",
@ -1069,12 +862,6 @@ dependencies = [
"security-framework",
]
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "schannel"
version = "0.1.19"
@ -1144,17 +931,6 @@ dependencies = [
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sha-1"
version = "0.8.2"
@ -1263,20 +1039,6 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "tempfile"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
"cfg-if",
"libc",
"rand",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
name = "textwrap"
version = "0.11.0"
@ -1412,24 +1174,12 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "vcpkg"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
[[package]]
name = "version_check"
version = "0.9.2"
@ -1547,15 +1297,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "winutil"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e"
dependencies = [
"winapi",
]
[[package]]
name = "xdg"
version = "2.2.0"

View file

@ -21,7 +21,6 @@ fern = { version = "0.6.0", features = ["colored"] }
format-bytes = "0.2.0"
futures = "0.3.12"
inotify = { version = "0.9.2", features = ["stream"] }
lettre = "0.9.5"
log = "0.4.14"
panorama-imap = { path = "imap", version = "0" }
parking_lot = "0.11.1"

View file

@ -68,6 +68,23 @@ fn build_response(pair: Pair<Rule>) -> Response {
}
Rule::mailbox_data => Response::MailboxData(build_mailbox_data(pair)),
Rule::capability_data => Response::Capabilities(build_capabilities(pair)),
Rule::message_data => {
let mut pairs = pair.into_inner();
let pair = pairs.next().unwrap();
let seq: u32 = build_number(pair);
let pair = pairs.next().unwrap();
match pair.as_rule() {
Rule::message_data_expunge => Response::Expunge(seq),
Rule::message_data_fetch => {
let mut pairs = pair.into_inner();
let msg_att = pairs.next().unwrap();
let attrs = msg_att.into_inner().map(build_msg_att).collect();
Response::Fetch(seq, attrs)
}
_ => unreachable!("{:#?}", pair),
}
}
_ => unreachable!("{:#?}", pair),
}
}
@ -75,6 +92,50 @@ fn build_response(pair: Pair<Rule>) -> Response {
}
}
fn build_msg_att(pair: Pair<Rule>) -> AttributeValue {
if !matches!(pair.as_rule(), Rule::msg_att_dyn_or_stat) {
unreachable!("{:#?}", pair);
}
let mut pairs = pair.into_inner();
let pair = pairs.next().unwrap();
match pair.as_rule() {
Rule::msg_att_dynamic => AttributeValue::Flags(pair.into_inner().map(build_flag).collect()),
Rule::msg_att_static => build_msg_att_static(pair),
_ => unreachable!("{:#?}", pair),
}
}
fn build_msg_att_static(pair: Pair<Rule>) -> AttributeValue {
if !matches!(pair.as_rule(), Rule::msg_att_static) {
unreachable!("{:#?}", pair);
}
let mut pairs = pair.into_inner();
let pair = pairs.next().unwrap();
match pair.as_rule() {
Rule::msg_att_static_internaldate => {
AttributeValue::InternalDate(extract_string(unwrap1(pair)))
}
Rule::msg_att_static_rfc822_size => AttributeValue::Rfc822Size(build_number(unwrap1(pair))),
Rule::msg_att_static_envelope => AttributeValue::Envelope(build_envelope(unwrap1(pair))),
// TODO: do this
Rule::msg_att_static_body => AttributeValue::BodySection {
section: None,
index: None,
data: None,
},
_ => unreachable!("{:#?}", pair),
}
}
fn build_envelope(pair: Pair<Rule>) -> Envelope {
// TODO: do this
Envelope::default()
}
fn build_resp_cond_state(pair: Pair<Rule>) -> (Status, Option<ResponseCode>, Option<String>) {
if !matches!(pair.as_rule(), Rule::resp_cond_state) {
unreachable!("{:#?}", pair);
@ -109,8 +170,8 @@ fn build_resp_code(pair: Pair<Rule>) -> Option<ResponseCode> {
Some(match pair.as_rule() {
Rule::capability_data => ResponseCode::Capabilities(build_capabilities(pair)),
Rule::resp_text_code_readwrite => ResponseCode::ReadWrite,
Rule::resp_text_code_uidvalidity => ResponseCode::UidValidity(build_number(pair)),
Rule::resp_text_code_unseen => ResponseCode::Unseen(build_number(pair)),
Rule::resp_text_code_uidvalidity => ResponseCode::UidValidity(build_number(unwrap1(pair))),
Rule::resp_text_code_unseen => ResponseCode::Unseen(build_number(unwrap1(pair))),
_ => unreachable!("{:#?}", pair),
})
}
@ -160,7 +221,16 @@ fn build_flag_list(pair: Pair<Rule>) -> Vec<MailboxFlag> {
pair.into_inner().map(build_flag).collect()
}
fn build_flag(pair: Pair<Rule>) -> MailboxFlag {
fn build_flag(mut pair: Pair<Rule>) -> MailboxFlag {
if matches!(pair.as_rule(), Rule::flag_fetch) {
let mut pairs = pair.into_inner();
pair = pairs.next().unwrap();
if matches!(pair.as_rule(), Rule::flag_fetch_recent) {
return MailboxFlag::Recent;
}
}
if !matches!(pair.as_rule(), Rule::flag) {
unreachable!("{:#?}", pair);
}
@ -184,14 +254,14 @@ fn build_mailbox_data(pair: Pair<Rule>) -> MailboxData {
let mut pairs = pair.into_inner();
let pair = pairs.next().unwrap();
match pair.as_rule() {
Rule::mailbox_data_exists => MailboxData::Exists(build_number(pair)),
Rule::mailbox_data_exists => MailboxData::Exists(build_number(unwrap1(pair))),
Rule::mailbox_data_flags => {
let mut pairs = pair.into_inner();
let pair = pairs.next().unwrap();
let flags = build_flag_list(pair);
MailboxData::Flags(flags)
}
Rule::mailbox_data_recent => MailboxData::Recent(build_number(pair)),
Rule::mailbox_data_recent => MailboxData::Recent(build_number(unwrap1(pair))),
Rule::mailbox_data_list => {
let mut pairs = pair.into_inner();
let pair = pairs.next().unwrap();
@ -213,13 +283,17 @@ fn build_mailbox_list(pair: Pair<Rule>) -> (Vec<String>, Option<String>, String)
let mut pairs = pair.into_inner();
let mut pair = pairs.next().unwrap();
// let mut flags = Vec::new();
if let Rule::mailbox_list_flags = pair.as_rule() {
let pairs = pair.into_inner();
for pair in pairs {
debug!("pair: {:?}", pair);
let flags = build_mbx_list_flags(pair);
debug!("flags: {:?}", flags);
}
}
// debug!("pair: {:#?}", pair);
todo!()
}
@ -232,16 +306,27 @@ fn build_mbx_list_flags(pair: Pair<Rule>) -> Vec<String> {
todo!()
}
fn unwrap1(pair: Pair<Rule>) -> Pair<Rule> {
let mut pairs = pair.into_inner();
pairs.next().unwrap()
}
fn build_number<T>(pair: Pair<Rule>) -> T
where
T: FromStr,
T::Err: Debug,
{
let mut pairs = pair.into_inner();
let pair = pairs.next().unwrap();
if !matches!(pair.as_rule(), Rule::nz_number | Rule::number) {
unreachable!("not a number {:#?}", pair);
}
pair.as_str().parse::<T>().unwrap()
}
fn extract_string(pair: Pair<Rule>) -> String {
// TODO: actually get rid of the quotes and escaped chars
pair.as_str().to_owned()
}
#[cfg(test)]
mod tests {
use super::*;
@ -342,10 +427,23 @@ mod tests {
assert_eq!(
parse_response(concat!(
r#"* 12 FETCH (FLAGS (\Seen) INTERNALDATE "17-Jul-1996 02:44:25 -0700" RFC822.SIZE 4286 ENVELOPE ("Wed, 17 Jul 1996 02:23:25 -0700 (PDT)" "IMAP4rev1 WG mtg summary and minutes" (("Terry Gray" NIL "gray" "cac.washington.edu")) (("Terry Gray" NIL "gray" "cac.washington.edu")) (("Terry Gray" NIL "gray" "cac.washington.edu")) ((NIL NIL "imap" "cac.washington.edu")) ((NIL NIL "minutes" "CNRI.Reston.VA.US") ("John Klensin" NIL "KLENSIN" "MIT.EDU")) NIL NIL "<B27397-0100000@cac.washington.edu>") BODY ("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 3028 92))"#,
r#"* 12 FETCH (FLAGS (\Seen) INTERNALDATE "17-Jul-1996 02:44:25 -0700" RFC822.SIZE 4286 ENVELOPE ("Wed, 17 Jul 1996 02:23:25 -0700 (PDT)" "IMAP4rev1 WG mtg summary and minutes" (("Terry Gray" NIL "gray" "cac.washington.edu")) (("Terry Gray" NIL "gray" "cac.washington.edu")) (("Terry Gray" NIL "gray" "cac.washington.edu")) ((NIL NIL "imap" "cac.washington.edu")) ((NIL NIL "minutes" "CNRI.Reston.VA.US")("John Klensin" NIL "KLENSIN" "MIT.EDU")) NIL NIL "<B27397-0100000@cac.washington.edu>") BODY ("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 302892))"#,
"\r\n",
)),
Ok(Response::Fetch(12, vec![]))
Ok(Response::Fetch(
12,
vec![
AttributeValue::Flags(vec![MailboxFlag::Seen]),
AttributeValue::InternalDate("\"17-Jul-1996 02:44:25 -0700\"".to_owned()),
AttributeValue::Rfc822Size(4286),
AttributeValue::Envelope(Envelope::default()),
AttributeValue::BodySection {
section: None,
index: None,
data: None,
},
]
))
);
}
}

View file

@ -40,7 +40,7 @@ continue_req = { "+" ~ sp ~ (resp_text | base64) ~ crlf }
date_day_fixed = { (sp ~ digit) | digit{2} }
date_month = { "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun" | "Jul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec" }
date_time = { dquote ~ date_day_fixed ~ "-" ~ date_month ~ "-" ~ date_year ~ sp ~ time ~ sp ~ zone ~ dquote }
date_year = { digit{4} }
date_year = @{ digit{4} }
digit_nz = @{ '\x31'..'\x39' }
env_bcc = { "(" ~ address{1,} ~ ")" | nil }
env_cc = { "(" ~ address{1,} ~ ")" | nil }
@ -55,7 +55,8 @@ env_to = { "(" ~ address{1,} ~ ")" | nil }
envelope = { "(" ~ env_date ~ sp ~ env_subject ~ sp ~ env_from ~ sp ~ env_sender ~ sp ~ env_reply_to ~ sp ~ env_to ~ sp ~ env_cc ~ sp ~ env_bcc ~ sp ~ env_in_reply_to ~ sp ~ env_message_id ~ ")" }
flag = { "\\Answered" | "\\Flagged" | "\\Deleted" | "\\Seen" | "\\Draft" | flag_keyword | flag_extension }
flag_extension = @{ "\\" ~ atom }
flag_fetch = { flag | "\\Recent" }
flag_fetch = { flag | flag_fetch_recent }
flag_fetch_recent = { "\\Recent" }
flag_keyword = @{ atom }
flag_list = { "(" ~ (flag ~ (sp ~ flag)*)? ~ ")" }
flag_perm = { flag | "\\*" }
@ -79,10 +80,17 @@ media_basic = { ((dquote ~ ("APPLICATION" | "AUDIO" | "IMAGE" | "MESSAGE" | "VID
media_message = { dquote ~ "MESSAGE" ~ dquote ~ sp ~ dquote ~ "RFC822" ~ dquote }
media_subtype = { string }
media_text = { dquote ~ "TEXT" ~ dquote ~ sp ~ media_subtype }
message_data = { nz_number ~ sp ~ (^"EXPUNGE" | (^"FETCH" ~ sp ~ msg_att)) }
msg_att = { "(" ~ (msg_att_dynamic | msg_att_static) ~ (sp ~ (msg_att_dynamic | msg_att_static))* ~ ")" }
message_data = { nz_number ~ sp ~ (message_data_expunge | message_data_fetch) }
message_data_expunge = { ^"EXPUNGE" }
message_data_fetch = { ^"FETCH" ~ sp ~ msg_att }
msg_att = { "(" ~ msg_att_dyn_or_stat ~ (sp ~ msg_att_dyn_or_stat)* ~ ")" }
msg_att_dyn_or_stat = { msg_att_dynamic | msg_att_static }
msg_att_dynamic = { ^"FLAGS" ~ sp ~ "(" ~ (flag_fetch ~ (sp ~ flag_fetch)*)? ~ ")" }
msg_att_static = { (^"ENVELOPE" ~ sp ~ envelope) | (^"INTERNALDATE" ~ sp ~ date_time) | (^"RFC822" ~ (^".HEADER" | ^".TEXT") ~ sp ~ nstring) | (^"RFC822.SIZE" ~ sp ~ number) | (^"BODY" ~ ^"STRUCTURE"? ~ sp ~ body) | (^"BODY" ~ section ~ ("<" ~ number ~ ">")? ~ sp ~ nstring) | (^"UID" ~ sp ~ uniqueid) }
msg_att_static = { msg_att_static_envelope | msg_att_static_internaldate | (^"RFC822" ~ (^".HEADER" | ^".TEXT") ~ sp ~ nstring) | msg_att_static_rfc822_size | msg_att_static_body | (^"BODY" ~ section ~ ("<" ~ number ~ ">")? ~ sp ~ nstring) | (^"UID" ~ sp ~ uniqueid) }
msg_att_static_envelope = { ^"ENVELOPE" ~ sp ~ envelope }
msg_att_static_internaldate = { ^"INTERNALDATE" ~ sp ~ date_time }
msg_att_static_rfc822_size = { ^"RFC822.SIZE" ~ sp ~ number }
msg_att_static_body = { ^"BODY" ~ ^"STRUCTURE"? ~ sp ~ body }
nil = { ^"NIL" }
nstring = { string | nil }
number = @{ digit{1,} }
@ -117,9 +125,9 @@ tag = @{ tag_char{1,} }
tag_char = @{ !"+" ~ astring_char }
text = @{ text_char{1,} }
text_char = @{ !cr ~ !lf ~ char }
time = { digit{2} ~ ":" ~ digit{2} ~ ":" ~ digit{2} }
time = @{ digit{2} ~ ":" ~ digit{2} ~ ":" ~ digit{2} }
uniqueid = { nz_number }
zone = { ("+" | "-") ~ digit{4} }
zone = @{ ("+" | "-") ~ digit{4} }
// core rules from https://tools.ietf.org/html/rfc2234#section-6.1
alpha = @{ '\x41'..'\x5a' | '\x61'..'\x7a' }

View file

@ -67,8 +67,8 @@ pub enum AttributeValue {
data: Option<String>,
},
BodyStructure(BodyStructure),
Envelope(Box<Envelope>),
Flags(Vec<String>),
Envelope(Envelope),
Flags(Vec<MailboxFlag>),
InternalDate(String),
ModSeq(u64), // RFC 4551, section 3.3.2
Rfc822(Option<String>),
@ -155,7 +155,7 @@ pub enum BodyExtension {
List(Vec<BodyExtension>),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Default, Debug, PartialEq, Eq)]
pub struct Envelope {
pub date: Option<String>,
pub subject: Option<String>,
@ -236,6 +236,7 @@ pub enum MailboxFlag {
Deleted,
Seen,
Draft,
Recent,
Ext(String),
}

1
rfc/.ignore Normal file
View file

@ -0,0 +1 @@
*

6051
rfc/rfc3501.txt Normal file

File diff suppressed because it is too large Load diff