1use crate::header_value_parser::{create_header, EmailHeader};
2use std::collections::HashMap;
3#[derive(Debug)]
6pub struct Email {
7 pub headers: HashMap<String, EmailHeader>,
9
10 pub body: EmailBody,
13
14 pub children: Vec<Email>,
16}
17
18type EmailBody = String;
20
21impl Email {
22 pub fn from_str(s: String) -> Email {
24 let mut allheaders = HashMap::new();
25
26 let val: Vec<&str> = s.split("\n\n").collect();
27 println!("{:?}", val);
28 let mut headers = Some(val[0]);
29
30 while let Some(_) = headers {
31 match Email::get_one_header(headers.unwrap()) {
32 (Some(headerval), rest) => {
33 let key_val: Vec<&str> = headerval.rsplitn(2, ':').collect();
34 allheaders.insert(
35 String::from(key_val[1].to_lowercase()),
36 create_header(key_val[1], key_val[0].trim_start()),
37 );
38 headers = rest;
39 }
40 _ => break,
41 }
42 }
43
44 if let Some(EmailHeader::ContentType {
45 maintype,
46 subtype,
47 value,
48 }) = allheaders.get("content-type")
49 {
50 if maintype == "multipart" {
51 println!("Found a multipart email.")
52 }
53 }
54
55 Email {
56 headers: allheaders,
57 body: val[1].to_string(),
58 children: vec![],
59 }
60 }
61
62 fn get_one_header(_s: &str) -> (Option<String>, Option<&str>) {
65 let mut header_line = String::new();
66 let mut last = 0;
67 let bytes = _s.as_bytes();
68 for (i, &x) in bytes.iter().enumerate() {
69 last = i;
70 if x == b'\n' {
71 if bytes[i + 1] == b' ' {
72 continue;
75 } else {
76 break;
77 }
78 } else {
79 header_line.push(x as char);
80 }
81 }
82
83 let mut rest = Some(&_s[last + 1..]);
84 if last + 1 == _s.len() {
85 rest = None;
86 }
87 (Some(header_line), rest)
88 }
89
90 fn from_bytes() -> Email {
92 unimplemented!();
93 }
94
95 fn from_file() -> Email {
97 unimplemented!();
98 }
99
100 fn new() -> Email {
102 unimplemented!();
103 }
104}
105
106#[test]
107fn test_get_one_simple_header() {
108 let headers = "From: Someone
109To: Person
110Date: Today";
111 assert_eq!(
112 Email::get_one_header(headers),
113 (
114 Some("From: Someone".to_string()),
115 Some("To: Person\nDate: Today")
116 )
117 )
118}
119
120#[test]
121fn test_get_one_multiline_header() {
122 let headers = "From: acomplexheader
123Subject: This is a complex header which goes to
124 2nd line identified by whitespace at the
125 start of each next line of header.";
126 let (header, rest) = Email::get_one_header(headers);
127 assert_eq!(header, Some("From: acomplexheader".to_string()));
128 assert_eq!(rest.is_some(), true);
129 let (header, rest) = Email::get_one_header(rest.unwrap());
130 assert_eq!(
131 header,
132 Some(
133 "Subject: This is a complex \
134 header which goes to 2nd line identified by whitespace at \
135 the start of each next line of header."
136 .to_string()
137 )
138 );
139 assert_eq!(rest, None);
140}