add address parsing
This commit is contained in:
parent
424706d9a0
commit
daa3b8cd61
4 changed files with 108 additions and 26 deletions
|
@ -174,24 +174,35 @@ fn build_envelope(pair: Pair<Rule>) -> Envelope {
|
||||||
let mut pairs = pair.into_inner();
|
let mut pairs = pair.into_inner();
|
||||||
let date = build_nstring(unwrap1(pairs.next().unwrap()));
|
let date = build_nstring(unwrap1(pairs.next().unwrap()));
|
||||||
let subject = build_nstring(unwrap1(pairs.next().unwrap()));
|
let subject = build_nstring(unwrap1(pairs.next().unwrap()));
|
||||||
pairs.next().unwrap(); // env_from
|
|
||||||
pairs.next().unwrap(); // env_sender
|
let address1 = |r: Rule, pair: Pair<Rule>| -> Option<Vec<Address>> {
|
||||||
pairs.next().unwrap(); // env_reply_to
|
assert!(matches!(pair.as_rule(), r));
|
||||||
pairs.next().unwrap(); // env_to
|
let pair = unwrap1(pair);
|
||||||
pairs.next().unwrap(); // env_cc
|
match pair.as_rule() {
|
||||||
pairs.next().unwrap(); // env_bcc
|
Rule::nil => None,
|
||||||
|
Rule::env_address1 => Some(pair.into_inner().map(build_address).collect()),
|
||||||
|
_ => unreachable!("{:?}", pair),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let from = address1(Rule::env_from, pairs.next().unwrap());
|
||||||
|
let sender = address1(Rule::env_sender, pairs.next().unwrap());
|
||||||
|
let reply_to = address1(Rule::env_reply_to, pairs.next().unwrap());
|
||||||
|
let to = address1(Rule::env_to, pairs.next().unwrap());
|
||||||
|
let cc = address1(Rule::env_cc, pairs.next().unwrap());
|
||||||
|
let bcc = address1(Rule::env_bcc, pairs.next().unwrap());
|
||||||
let in_reply_to = build_nstring(unwrap1(pairs.next().unwrap()));
|
let in_reply_to = build_nstring(unwrap1(pairs.next().unwrap()));
|
||||||
let message_id = build_nstring(unwrap1(pairs.next().unwrap()));
|
let message_id = build_nstring(unwrap1(pairs.next().unwrap()));
|
||||||
|
|
||||||
Envelope {
|
Envelope {
|
||||||
date,
|
date,
|
||||||
subject,
|
subject,
|
||||||
from: None,
|
from,
|
||||||
sender: None,
|
sender,
|
||||||
reply_to: None,
|
reply_to,
|
||||||
to: None,
|
to,
|
||||||
cc: None,
|
cc,
|
||||||
bcc: None,
|
bcc,
|
||||||
in_reply_to,
|
in_reply_to,
|
||||||
message_id,
|
message_id,
|
||||||
}
|
}
|
||||||
|
@ -483,6 +494,8 @@ fn build_zone(pair: Pair<Rule>) -> FixedOffset {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_date_time(pair: Pair<Rule>) -> DateTime<FixedOffset> {
|
fn build_date_time(pair: Pair<Rule>) -> DateTime<FixedOffset> {
|
||||||
|
assert!(matches!(pair.as_rule(), Rule::date_time));
|
||||||
|
|
||||||
let mut pairs = pair.into_inner();
|
let mut pairs = pair.into_inner();
|
||||||
let pair = pairs.next().unwrap();
|
let pair = pairs.next().unwrap();
|
||||||
assert!(matches!(pair.as_rule(), Rule::date_day_fixed));
|
assert!(matches!(pair.as_rule(), Rule::date_day_fixed));
|
||||||
|
@ -523,3 +536,31 @@ fn build_date_time(pair: Pair<Rule>) -> DateTime<FixedOffset> {
|
||||||
|
|
||||||
zone.ymd(year, month, day).and_hms(hour, minute, second)
|
zone.ymd(year, month, day).and_hms(hour, minute, second)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_address(pair: Pair<Rule>) -> Address {
|
||||||
|
assert!(matches!(pair.as_rule(), Rule::address));
|
||||||
|
|
||||||
|
let mut pairs = pair.into_inner();
|
||||||
|
let pair = pairs.next().unwrap();
|
||||||
|
assert!(matches!(pair.as_rule(), Rule::addr_name));
|
||||||
|
let name = build_nstring(unwrap1(pair));
|
||||||
|
|
||||||
|
let pair = pairs.next().unwrap();
|
||||||
|
assert!(matches!(pair.as_rule(), Rule::addr_adl));
|
||||||
|
let adl = build_nstring(unwrap1(pair));
|
||||||
|
|
||||||
|
let pair = pairs.next().unwrap();
|
||||||
|
assert!(matches!(pair.as_rule(), Rule::addr_mailbox));
|
||||||
|
let mailbox = build_nstring(unwrap1(pair));
|
||||||
|
|
||||||
|
let pair = pairs.next().unwrap();
|
||||||
|
assert!(matches!(pair.as_rule(), Rule::addr_host));
|
||||||
|
let host = build_nstring(unwrap1(pair));
|
||||||
|
|
||||||
|
Address {
|
||||||
|
name,
|
||||||
|
adl,
|
||||||
|
mailbox,
|
||||||
|
host,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -44,16 +44,17 @@ date_month = { "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun" | "Jul" | "Aug" | "
|
||||||
date_time = { dquote_ ~ date_day_fixed ~ "-" ~ date_month ~ "-" ~ date_year ~ sp ~ time ~ sp ~ zone ~ dquote_ }
|
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' }
|
digit_nz = @{ '\x31'..'\x39' }
|
||||||
env_bcc = { "(" ~ address{1,} ~ ")" | nil }
|
env_address1 = { "(" ~ address{1,} ~ ")" }
|
||||||
env_cc = { "(" ~ address{1,} ~ ")" | nil }
|
env_bcc = { env_address1 | nil }
|
||||||
|
env_cc = { env_address1 | nil }
|
||||||
env_date = { nstring }
|
env_date = { nstring }
|
||||||
env_from = { "(" ~ address{1,} ~ ")" | nil }
|
env_from = { env_address1 | nil }
|
||||||
env_in_reply_to = { nstring }
|
env_in_reply_to = { nstring }
|
||||||
env_message_id = { nstring }
|
env_message_id = { nstring }
|
||||||
env_reply_to = { "(" ~ address{1,} ~ ")" | nil }
|
env_reply_to = { env_address1 | nil }
|
||||||
env_sender = { "(" ~ address{1,} ~ ")" | nil }
|
env_sender = { env_address1 | nil }
|
||||||
env_subject = { nstring }
|
env_subject = { nstring }
|
||||||
env_to = { "(" ~ address{1,} ~ ")" | nil }
|
env_to = { env_address1 | 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 ~ ")" }
|
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 = { "\\Answered" | "\\Flagged" | "\\Deleted" | "\\Seen" | "\\Draft" | flag_keyword | flag_extension }
|
||||||
flag_extension = @{ "\\" ~ atom }
|
flag_extension = @{ "\\" ~ atom }
|
||||||
|
|
|
@ -22,6 +22,21 @@ fn test_literal() {
|
||||||
assert_eq!(p("{7}\r\nhellosu"), Ok("hellosu".to_owned()));
|
assert_eq!(p("{7}\r\nhellosu"), Ok("hellosu".to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_address() -> Result<()> {
|
||||||
|
let p = parse(Rule::address, build_address);
|
||||||
|
assert_eq!(
|
||||||
|
p(r#"("Terry Gray" NIL "gray" "cac.washington.edu")"#)?,
|
||||||
|
Address {
|
||||||
|
name: Some("Terry Gray".to_owned()),
|
||||||
|
adl: None,
|
||||||
|
mailbox: Some("gray".to_owned()),
|
||||||
|
host: Some("cac.washington.edu".to_owned()),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_zone() {
|
fn test_zone() {
|
||||||
let p = parse(Rule::zone, build_zone);
|
let p = parse(Rule::zone, build_zone);
|
||||||
|
@ -133,6 +148,31 @@ fn test_section_8() {
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let terry_addr = Address {
|
||||||
|
name: Some("Terry Gray".to_owned()),
|
||||||
|
adl: None,
|
||||||
|
mailbox: Some("gray".to_owned()),
|
||||||
|
host: Some("cac.washington.edu".to_owned()),
|
||||||
|
};
|
||||||
|
let imap_addr = Address {
|
||||||
|
name: None,
|
||||||
|
adl: None,
|
||||||
|
mailbox: Some("imap".to_owned()),
|
||||||
|
host: Some("cac.washington.edu".to_owned()),
|
||||||
|
};
|
||||||
|
let minutes_addr = Address {
|
||||||
|
name: None,
|
||||||
|
adl: None,
|
||||||
|
mailbox: Some("minutes".to_owned()),
|
||||||
|
host: Some("CNRI.Reston.VA.US".to_owned()),
|
||||||
|
};
|
||||||
|
let john_addr = Address {
|
||||||
|
name: Some("John Klensin".to_owned()),
|
||||||
|
adl: None,
|
||||||
|
mailbox: Some("KLENSIN".to_owned()),
|
||||||
|
host: Some("MIT.EDU".to_owned()),
|
||||||
|
};
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_response(concat!(
|
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" 302892))"#,
|
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))"#,
|
||||||
|
@ -149,11 +189,11 @@ fn test_section_8() {
|
||||||
AttributeValue::Envelope(Envelope {
|
AttributeValue::Envelope(Envelope {
|
||||||
date: Some("Wed, 17 Jul 1996 02:23:25 -0700 (PDT)".to_owned()),
|
date: Some("Wed, 17 Jul 1996 02:23:25 -0700 (PDT)".to_owned()),
|
||||||
subject: Some("IMAP4rev1 WG mtg summary and minutes".to_owned()),
|
subject: Some("IMAP4rev1 WG mtg summary and minutes".to_owned()),
|
||||||
from: None,
|
from: Some(vec![terry_addr.clone()]),
|
||||||
sender: None,
|
sender: Some(vec![terry_addr.clone()]),
|
||||||
reply_to: None,
|
reply_to: Some(vec![terry_addr.clone()]),
|
||||||
to: None,
|
to: Some(vec![imap_addr.clone()]),
|
||||||
cc: None,
|
cc: Some(vec![minutes_addr.clone(), john_addr.clone()]),
|
||||||
bcc: None,
|
bcc: None,
|
||||||
in_reply_to: None,
|
in_reply_to: None,
|
||||||
message_id: Some("<B27397-0100000@cac.washington.edu>".to_owned()),
|
message_id: Some("<B27397-0100000@cac.washington.edu>".to_owned()),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use chrono::{DateTime, Duration, Local, Datelike};
|
use chrono::{DateTime, Datelike, Duration, Local};
|
||||||
use chrono_humanize::HumanTime;
|
use chrono_humanize::HumanTime;
|
||||||
use panorama_imap::response::Envelope;
|
use panorama_imap::response::Envelope;
|
||||||
use tui::{
|
use tui::{
|
||||||
|
@ -35,7 +35,7 @@ fn humanize_timestamp(date: DateTime<Local>) -> String {
|
||||||
|
|
||||||
if diff < Duration::days(1) {
|
if diff < Duration::days(1) {
|
||||||
HumanTime::from(date).to_string()
|
HumanTime::from(date).to_string()
|
||||||
}else if date.year() == now.year() {
|
} else if date.year() == now.year() {
|
||||||
date.format("%b %e %T").to_string()
|
date.format("%b %e %T").to_string()
|
||||||
} else {
|
} else {
|
||||||
date.to_rfc2822()
|
date.to_rfc2822()
|
||||||
|
@ -73,7 +73,7 @@ impl MailTabState {
|
||||||
"".to_owned(),
|
"".to_owned(),
|
||||||
id.to_string(),
|
id.to_string(),
|
||||||
meta.map(|m| humanize_timestamp(m.date)).unwrap_or_default(),
|
meta.map(|m| humanize_timestamp(m.date)).unwrap_or_default(),
|
||||||
"".to_owned(),
|
meta.map(|m| m.from.clone()).unwrap_or_default(),
|
||||||
meta.map(|m| m.subject.clone()).unwrap_or_default(),
|
meta.map(|m| m.subject.clone()).unwrap_or_default(),
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue