email_format/rfc5322/
headers.rs

1
2use std::io::Write;
3use std::io::Error as IoError;
4use ::TryFrom;
5use super::{Parsable, ParseError, Streamable};
6use super::types::{DateTime, MailboxList, Mailbox, AddressList, CFWS, MsgId,
7                   Unstructured, Phrase, ReceivedToken, Path, FieldName};
8
9macro_rules! req_name {
10    ($rem:ident, $str:expr) => {
11        let len: usize = $str.as_bytes().len();
12        if $rem.len() < len ||
13            &(&$rem[0..len]).to_ascii_lowercase().as_slice() != &$str.as_bytes()
14        {
15            return Err(ParseError::NotFound($str));
16        }
17        $rem = &$rem[len..];
18    };
19}
20
21macro_rules! req_crlf {
22    ($rem:ident) => {
23        if $rem.len() < 2 {
24            return Err(ParseError::NotFound("CRLF"));
25        }
26        if &$rem[..2] != b"\r\n" {
27            return Err(ParseError::NotFound("CRLF"));
28        }
29        $rem = &$rem[2..];
30    }
31}
32
33macro_rules! impl_try_from {
34    ($from:ident, $to:ident) => {
35        impl<'a> TryFrom<&'a [u8]> for $to {
36            type Error = ParseError;
37            fn try_from(input: &'a [u8]) -> Result<$to, ParseError> {
38                let (out,rem) = $from::parse(input)?;
39                if rem.len() > 0 {
40                    return Err(ParseError::TrailingInput("$to", input.len() - rem.len()));
41                }
42                Ok($to(out))
43            }
44        }
45        impl<'a> TryFrom<&'a str> for $to {
46            type Error = ParseError;
47            fn try_from(input: &'a str) -> Result<$to, ParseError> {
48                TryFrom::try_from(input.as_bytes())
49            }
50        }
51        impl<'a> TryFrom<$from> for $to {
52            type Error = ParseError;
53            fn try_from(input: $from) -> Result<$to, ParseError> {
54                Ok($to(input))
55            }
56        }
57    }
58}
59
60// 3.6.1
61// orig-date       =   "Date:" date-time CRLF
62#[derive(Debug, Clone, PartialEq)]
63pub struct OrigDate(pub DateTime);
64impl Parsable for OrigDate {
65    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
66        if input.len() == 0 { return Err(ParseError::Eof("Date")); }
67        let mut rem = input;
68        req_name!(rem, "date:");
69        match parse!(DateTime, rem) {
70            Ok(dt) => {
71                req_crlf!(rem);
72                Ok((OrigDate(dt), rem))
73            },
74            Err(e) => Err(ParseError::Parse("Date", Box::new(e)))
75        }
76    }
77}
78impl Streamable for OrigDate {
79    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
80        Ok(w.write(b"Date:")?
81           + self.0.stream(w)?
82           + w.write(b"\r\n")?)
83    }
84}
85impl_try_from!(DateTime, OrigDate);
86#[cfg(feature="time")]
87impl<'a> TryFrom<&'a ::time::Tm> for OrigDate {
88    type Error = ParseError;
89    fn try_from(input: &'a ::time::Tm) -> Result<OrigDate, ParseError> {
90        let s = match input.strftime("%a, %d %b %Y %T %z") {
91            Ok(s) => format!("{}",s),
92            Err(_) => return Err(ParseError::InternalError),
93        };
94        TryFrom::try_from(s.as_bytes())
95    }
96}
97#[cfg(feature="chrono")]
98impl<'a, Tz: ::chrono::TimeZone> TryFrom<&'a ::chrono::DateTime<Tz>> for OrigDate
99    where Tz::Offset: ::std::fmt::Display
100{
101    type Error = ParseError;
102    fn try_from(input: &'a ::chrono::DateTime<Tz>) -> Result<OrigDate, ParseError> {
103        let s = input.format("%a, %d %b %Y %T %z").to_string();
104        TryFrom::try_from(s.as_bytes())
105    }
106}
107impl_display!(OrigDate);
108
109// 3.6.2
110// from            =   "From:" mailbox-list CRLF
111#[derive(Debug, Clone, PartialEq)]
112pub struct From(pub MailboxList);
113impl Parsable for From {
114    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
115        if input.len() == 0 { return Err(ParseError::Eof("From")); }
116        let mut rem = input;
117        req_name!(rem, "from:");
118        match parse!(MailboxList, rem) {
119            Ok(mbl) => {
120                req_crlf!(rem);
121                return Ok((From(mbl), rem));
122            },
123            Err(e) => Err(ParseError::Parse("From", Box::new(e)))
124        }
125    }
126}
127impl Streamable for From {
128    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
129        Ok(w.write(b"From:")?
130           + self.0.stream(w)?
131           + w.write(b"\r\n")?)
132    }
133}
134impl_try_from!(MailboxList, From);
135impl_display!(From);
136
137// 3.6.2
138// sender          =   "Sender:" mailbox CRLF
139#[derive(Debug, Clone, PartialEq)]
140pub struct Sender(pub Mailbox);
141impl Parsable for Sender {
142    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
143        if input.len() == 0 { return Err(ParseError::Eof("Sender")); }
144        let mut rem = input;
145        req_name!(rem, "sender:");
146        match parse!(Mailbox, rem) {
147            Ok(mb) => {
148                req_crlf!(rem);
149                return Ok((Sender(mb), rem));
150            },
151            Err(e) => Err(ParseError::Parse("Sender", Box::new(e)))
152        }
153    }
154}
155impl Streamable for Sender {
156    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
157        Ok(w.write(b"Sender:")?
158           + self.0.stream(w)?
159           + w.write(b"\r\n")?)
160    }
161}
162impl_try_from!(Mailbox, Sender);
163impl_display!(Sender);
164
165// 3.6.2
166// reply-to        =   "Reply-To:" address-list CRLF
167#[derive(Debug, Clone, PartialEq)]
168pub struct ReplyTo(pub AddressList);
169impl Parsable for ReplyTo {
170    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
171        if input.len() == 0 { return Err(ParseError::Eof("Reply-To")); }
172        let mut rem = input;
173        req_name!(rem, "reply-to:");
174        match parse!(AddressList, rem) {
175            Ok(x) => {
176                req_crlf!(rem);
177                return Ok((ReplyTo(x), rem));
178            },
179            Err(e) => Err(ParseError::Parse("Reply-To", Box::new(e)))
180        }
181    }
182}
183impl Streamable for ReplyTo {
184    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
185        Ok(w.write(b"Reply-To:")?
186           + self.0.stream(w)?
187           + w.write(b"\r\n")?)
188    }
189}
190impl_try_from!(AddressList, ReplyTo);
191impl_display!(ReplyTo);
192
193// 3.6.3
194// to              =   "To:" address-list CRLF
195#[derive(Debug, Clone, PartialEq)]
196pub struct To(pub AddressList);
197impl Parsable for To {
198    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
199        if input.len() == 0 { return Err(ParseError::Eof("To")); }
200        let mut rem = input;
201        req_name!(rem, "to:");
202        match parse!(AddressList, rem) {
203            Ok(x) => {
204                req_crlf!(rem);
205                return Ok((To(x), rem));
206            },
207            Err(e) => Err(ParseError::Parse("To", Box::new(e))),
208        }
209    }
210}
211impl Streamable for To {
212    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
213        Ok(w.write(b"To:")?
214           + self.0.stream(w)?
215           + w.write(b"\r\n")?)
216    }
217}
218impl_try_from!(AddressList, To);
219impl_display!(To);
220
221// 3.6.3
222// cc              =   "Cc:" address-list CRLF
223#[derive(Debug, Clone, PartialEq)]
224pub struct Cc(pub AddressList);
225impl Parsable for Cc {
226    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
227        if input.len() == 0 { return Err(ParseError::Eof("Cc")); }
228        let mut rem = input;
229        req_name!(rem, "cc:");
230        match parse!(AddressList, rem) {
231            Ok(x) => {
232                req_crlf!(rem);
233                return Ok((Cc(x), rem));
234            },
235            Err(e) => Err(ParseError::Parse("Cc", Box::new(e))),
236        }
237    }
238}
239impl Streamable for Cc {
240    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
241        Ok(w.write(b"Cc:")?
242           + self.0.stream(w)?
243           + w.write(b"\r\n")?)
244    }
245}
246impl_try_from!(AddressList, Cc);
247impl_display!(Cc);
248
249// 3.6.3
250// bcc             =   "Bcc:" [address-list / CFWS] CRLF
251#[derive(Debug, Clone, PartialEq)]
252pub enum Bcc {
253    AddressList(AddressList),
254    CFWS(CFWS),
255    Empty
256}
257impl Parsable for Bcc {
258    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
259        if input.len() == 0 { return Err(ParseError::Eof("Bcc")); }
260        let mut rem = input;
261        req_name!(rem, "bcc:");
262        if let Ok(x) = parse!(AddressList, rem) {
263            req_crlf!(rem);
264            return Ok((Bcc::AddressList(x), rem));
265        }
266        if let Ok(x) = parse!(CFWS, rem) {
267            req_crlf!(rem);
268            return Ok((Bcc::CFWS(x), rem));
269        }
270        req_crlf!(rem);
271        return Ok((Bcc::Empty, rem));
272    }
273}
274impl Streamable for Bcc {
275    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
276        let mut count: usize = 0;
277        count += w.write(b"Bcc:")?;
278        count += match *self {
279            Bcc::AddressList(ref al) => al.stream(w)?,
280            Bcc::CFWS(ref cfws) => cfws.stream(w)?,
281            Bcc::Empty => 0,
282        };
283        count += w.write(b"\r\n")?;
284        Ok(count)
285    }
286}
287impl<'a> TryFrom<&'a [u8]> for Bcc {
288    type Error = ParseError;
289    fn try_from(input: &'a [u8]) -> Result<Bcc, ParseError> {
290        let (out,rem) = AddressList::parse(input)?;
291        if rem.len() > 0 {
292            return Err(ParseError::TrailingInput("Bcc", input.len() - rem.len()));
293        }
294        Ok(Bcc::AddressList(out))
295    }
296}
297impl<'a> TryFrom<&'a str> for Bcc {
298    type Error = ParseError;
299    fn try_from(input: &'a str) -> Result<Bcc, ParseError> {
300        TryFrom::try_from(input.as_bytes())
301    }
302}
303impl<'a> TryFrom<AddressList> for Bcc {
304    type Error = ParseError;
305    fn try_from(input: AddressList) -> Result<Bcc, ParseError> {
306        Ok(Bcc::AddressList(input))
307    }
308}
309impl_display!(Bcc);
310
311// 3.6.4
312// message-id      =   "Message-ID:" msg-id CRLF
313#[derive(Debug, Clone, PartialEq)]
314pub struct MessageId(pub MsgId);
315impl Parsable for MessageId {
316    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
317        if input.len() == 0 { return Err(ParseError::Eof("MessageId")); }
318        let mut rem = input;
319        req_name!(rem, "message-id:");
320        match parse!(MsgId, rem) {
321            Ok(x) => {
322                req_crlf!(rem);
323                return Ok((MessageId(x), rem));
324            },
325            Err(e) => Err(ParseError::Parse("Message-Id", Box::new(e))),
326        }
327    }
328}
329impl Streamable for MessageId {
330    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
331        Ok(w.write(b"Message-ID:")?
332           + self.0.stream(w)?
333           + w.write(b"\r\n")?)
334    }
335}
336impl_try_from!(MsgId, MessageId);
337impl_display!(MessageId);
338
339// 3.6.4
340// in-reply-to     =   "In-Reply-To:" 1*msg-id CRLF
341#[derive(Debug, Clone, PartialEq)]
342pub struct InReplyTo(pub Vec<MsgId>);
343impl Parsable for InReplyTo {
344    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
345        if input.len() == 0 { return Err(ParseError::Eof("InReplyTo")); }
346        let mut rem = input;
347        let mut contents: Vec<MsgId> = Vec::new();
348        req_name!(rem, "in-reply-to:");
349        let err;
350        loop {
351            match parse!(MsgId, rem) {
352                Ok(x) => contents.push(x),
353                Err(e) => { err = e; break; }
354            }
355        }
356        if contents.len() == 0 {
357            return Err(ParseError::Parse("In-Reply-To", Box::new(err)));
358        }
359        req_crlf!(rem);
360        Ok((InReplyTo(contents), rem))
361    }
362}
363impl Streamable for InReplyTo {
364    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
365        let mut count: usize = 0;
366        count += w.write(b"In-Reply-To:")?;
367        for msgid in &self.0 {
368            count += msgid.stream(w)?
369        }
370        count += w.write(b"\r\n")?;
371        Ok(count)
372    }
373}
374impl<'a> TryFrom<&'a [u8]> for InReplyTo {
375    type Error = ParseError;
376    fn try_from(input: &'a [u8]) -> Result<InReplyTo, ParseError> {
377        let mut msgids: Vec<MsgId> = Vec::new();
378        let mut rem = input;
379        while let Ok(x) = parse!(MsgId, rem) {
380            msgids.push(x);
381        }
382        if rem.len() > 0 {
383            Err(ParseError::TrailingInput("In-Reply-To", input.len() - rem.len()))
384        } else {
385            Ok(InReplyTo(msgids))
386        }
387    }
388}
389impl<'a> TryFrom<&'a str> for InReplyTo {
390    type Error = ParseError;
391    fn try_from(input: &'a str) -> Result<InReplyTo, ParseError> {
392        TryFrom::try_from(input.as_bytes())
393    }
394}
395impl<'a> TryFrom<Vec<MsgId>> for InReplyTo {
396    type Error = ParseError;
397    fn try_from(input: Vec<MsgId>) -> Result<InReplyTo, ParseError> {
398        Ok(InReplyTo(input))
399    }
400}
401impl_display!(InReplyTo);
402
403// 3.6.4
404// references      =   "References:" 1*msg-id CRLF
405#[derive(Debug, Clone, PartialEq)]
406pub struct References(pub Vec<MsgId>);
407impl Parsable for References {
408    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
409        if input.len() == 0 { return Err(ParseError::Eof("References")); }
410        let mut rem = input;
411        let mut contents: Vec<MsgId> = Vec::new();
412        req_name!(rem, "references:");
413        let err;
414        loop {
415            match parse!(MsgId, rem) {
416                Ok(x) => contents.push(x),
417                Err(e) => { err = e; break }
418            }
419        }
420        if contents.len() == 0 {
421            return Err(ParseError::Parse("References", Box::new(err)));
422        }
423        req_crlf!(rem);
424        Ok((References(contents), rem))
425    }
426}
427impl Streamable for References {
428    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
429        let mut count: usize = 0;
430        count += w.write(b"References:")?;
431        for msgid in &self.0 {
432            count += msgid.stream(w)?
433        }
434        count += w.write(b"\r\n")?;
435        Ok(count)
436    }
437}
438impl<'a> TryFrom<&'a [u8]> for References {
439    type Error = ParseError;
440    fn try_from(input: &'a [u8]) -> Result<References, ParseError> {
441        let mut msgids: Vec<MsgId> = Vec::new();
442        let mut rem = input;
443        while let Ok(x) = parse!(MsgId, rem) {
444            msgids.push(x);
445        }
446        if rem.len() > 0 {
447            Err(ParseError::TrailingInput("References", input.len() - rem.len()))
448        } else {
449            Ok(References(msgids))
450        }
451    }
452}
453impl<'a> TryFrom<&'a str> for References {
454    type Error = ParseError;
455    fn try_from(input: &'a str) -> Result<References, ParseError> {
456        TryFrom::try_from(input.as_bytes())
457    }
458}
459impl<'a> TryFrom<Vec<MsgId>> for References {
460    type Error = ParseError;
461    fn try_from(input: Vec<MsgId>) -> Result<References, ParseError> {
462        Ok(References(input))
463    }
464}
465impl_display!(References);
466
467// 3.6.5
468// subject         =   "Subject:" unstructured CRLF
469#[derive(Debug, Clone, PartialEq)]
470pub struct Subject(pub Unstructured);
471impl Parsable for Subject {
472    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
473        if input.len() == 0 { return Err(ParseError::Eof("Subject")); }
474        let mut rem = input;
475        req_name!(rem, "subject:");
476        match parse!(Unstructured, rem) {
477            Ok(x) => {
478                req_crlf!(rem);
479                return Ok((Subject(x), rem));
480            },
481            Err(e) => Err(ParseError::Parse("Subject", Box::new(e))),
482        }
483    }
484}
485impl Streamable for Subject {
486    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
487        Ok(w.write(b"Subject:")?
488           + self.0.stream(w)?
489           + w.write(b"\r\n")?)
490    }
491}
492impl_try_from!(Unstructured, Subject);
493impl_display!(Subject);
494
495// 3.6.5
496// comments        =   "Comments:" unstructured CRLF
497#[derive(Debug, Clone, PartialEq)]
498pub struct Comments(pub Unstructured);
499impl Parsable for Comments {
500    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
501        if input.len() == 0 { return Err(ParseError::Eof("Comments")); }
502        let mut rem = input;
503        req_name!(rem, "comments:");
504        match parse!(Unstructured, rem) {
505            Ok(x) => {
506                req_crlf!(rem);
507                return Ok((Comments(x), rem));
508            },
509            Err(e) => Err(ParseError::Parse("Comments", Box::new(e))),
510        }
511    }
512}
513impl Streamable for Comments {
514    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
515        Ok(w.write(b"Comments:")?
516           + self.0.stream(w)?
517           + w.write(b"\r\n")?)
518    }
519}
520impl_try_from!(Unstructured, Comments);
521impl_display!(Comments);
522
523// 3.6.5
524// keywords        =   "Keywords:" phrase *("," phrase) CRLF
525#[derive(Debug, Clone, PartialEq)]
526pub struct Keywords(pub Vec<Phrase>);
527impl Parsable for Keywords {
528    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
529        if input.len() == 0 { return Err(ParseError::Eof("Keywords")); }
530        let mut rem = input;
531        req_name!(rem, "keywords:");
532        let mut output: Vec<Phrase> = Vec::new();
533        let err;
534        loop {
535            match parse!(Phrase, rem) {
536                Ok(x) => output.push(x),
537                Err(e) => { err = e; break; }
538            }
539        }
540        if output.len()==0 {
541            return Err(ParseError::Parse("Keywords", Box::new(err)));
542        }
543        req_crlf!(rem);
544        Ok((Keywords(output), rem))
545    }
546}
547impl Streamable for Keywords {
548    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
549        let mut count: usize = 0;
550        count += w.write(b"Keywords:")?;
551        let mut virgin = true;
552        for phrase in &self.0 {
553            if ! virgin {
554                count += w.write(b",")?;
555            }
556            count += phrase.stream(w)?;
557            virgin = false
558        }
559        count += w.write(b"\r\n")?;
560        Ok(count)
561    }
562}
563impl<'a> TryFrom<&'a [u8]> for Keywords {
564    type Error = ParseError;
565    fn try_from(input: &'a [u8]) -> Result<Keywords, ParseError> {
566        let mut msgids: Vec<Phrase> = Vec::new();
567        let mut rem = input;
568        while let Ok(x) = parse!(Phrase, rem) {
569            msgids.push(x);
570        }
571        if rem.len() > 0 {
572            Err(ParseError::TrailingInput("Keywords", input.len() - rem.len()))
573        } else {
574            Ok(Keywords(msgids))
575        }
576    }
577}
578impl<'a> TryFrom<&'a str> for Keywords {
579    type Error = ParseError;
580    fn try_from(input: &'a str) -> Result<Keywords, ParseError> {
581        TryFrom::try_from(input.as_bytes())
582    }
583}
584impl<'a> TryFrom<Vec<Phrase>> for Keywords {
585    type Error = ParseError;
586    fn try_from(input: Vec<Phrase>) -> Result<Keywords, ParseError> {
587        Ok(Keywords(input))
588    }
589}
590impl_display!(Keywords);
591
592// 3.6.6
593// resent-date     =   "Resent-Date:" date-time CRLF
594#[derive(Debug, Clone, PartialEq)]
595pub struct ResentDate(pub DateTime);
596impl Parsable for ResentDate {
597    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
598        if input.len() == 0 { return Err(ParseError::Eof("Resent-Date")); }
599        let mut rem = input;
600        req_name!(rem, "resent-date:");
601        match parse!(DateTime, rem) {
602            Ok(dt) => {
603                req_crlf!(rem);
604                Ok((ResentDate(dt), rem))
605            },
606            Err(e) => Err(ParseError::Parse("Resent-Date", Box::new(e)))
607        }
608    }
609}
610impl Streamable for ResentDate {
611    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
612        Ok(w.write(b"Resent-Date:")?
613           + self.0.stream(w)?
614           + w.write(b"\r\n")?)
615    }
616}
617impl_try_from!(DateTime, ResentDate);
618impl_display!(ResentDate);
619
620// 3.6.6
621// resent-from     =   "Resent-From:" mailbox-list CRLF
622#[derive(Debug, Clone, PartialEq)]
623pub struct ResentFrom(pub MailboxList);
624impl Parsable for ResentFrom {
625    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
626        if input.len() == 0 { return Err(ParseError::Eof("Resent-From")); }
627        let mut rem = input;
628        req_name!(rem, "resent-from:");
629        match parse!(MailboxList, rem) {
630            Ok(mbl) => {
631                req_crlf!(rem);
632                return Ok((ResentFrom(mbl), rem));
633            },
634            Err(e) => Err(ParseError::Parse("Resent-From", Box::new(e))),
635        }
636    }
637}
638impl Streamable for ResentFrom {
639    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
640        Ok(w.write(b"Resent-From:")?
641           + self.0.stream(w)?
642           + w.write(b"\r\n")?)
643    }
644}
645impl_try_from!(MailboxList, ResentFrom);
646impl_display!(ResentFrom);
647
648// 3.6.6
649// resent-sender   =   "Resent-Sender:" mailbox CRLF
650#[derive(Debug, Clone, PartialEq)]
651pub struct ResentSender(pub Mailbox);
652impl Parsable for ResentSender {
653    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
654        if input.len() == 0 { return Err(ParseError::Eof("Resent-Sender")); }
655        let mut rem = input;
656        req_name!(rem, "resent-sender:");
657        match parse!(Mailbox, rem) {
658            Ok(mb) => {
659                req_crlf!(rem);
660                return Ok((ResentSender(mb), rem));
661            },
662            Err(e) => Err(ParseError::Parse("Resent-Sender", Box::new(e))),
663        }
664    }
665}
666impl Streamable for ResentSender {
667    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
668        Ok(w.write(b"Resent-Sender:")?
669           + self.0.stream(w)?
670           + w.write(b"\r\n")?)
671    }
672}
673impl_try_from!(Mailbox, ResentSender);
674impl_display!(ResentSender);
675
676// 3.6.6
677// resent-to       =   "Resent-To:" address-list CRLF
678#[derive(Debug, Clone, PartialEq)]
679pub struct ResentTo(pub AddressList);
680impl Parsable for ResentTo {
681    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
682        if input.len() == 0 { return Err(ParseError::Eof("Resent-To")); }
683        let mut rem = input;
684        req_name!(rem, "resent-to:");
685        match parse!(AddressList, rem) {
686            Ok(x) => {
687                req_crlf!(rem);
688                return Ok((ResentTo(x), rem));
689            },
690            Err(e) => Err(ParseError::Parse("Resent-To", Box::new(e))),
691        }
692    }
693}
694impl Streamable for ResentTo {
695    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
696        Ok(w.write(b"Resent-To:")?
697           + self.0.stream(w)?
698           + w.write(b"\r\n")?)
699    }
700}
701impl_try_from!(AddressList, ResentTo);
702impl_display!(ResentTo);
703
704// 3.6.6
705// resent-cc       =   "Resent-Cc:" address-list CRLF
706#[derive(Debug, Clone, PartialEq)]
707pub struct ResentCc(pub AddressList);
708impl Parsable for ResentCc {
709    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
710        if input.len() == 0 { return Err(ParseError::Eof("Resent-Cc")); }
711        let mut rem = input;
712        req_name!(rem, "resent-cc:");
713        match parse!(AddressList, rem) {
714            Ok(x) => {
715                req_crlf!(rem);
716                return Ok((ResentCc(x), rem));
717            },
718            Err(e) => Err(ParseError::Parse("Resent-Cc", Box::new(e)))
719        }
720    }
721}
722impl Streamable for ResentCc {
723    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
724        Ok(w.write(b"Resent-Cc:")?
725           + self.0.stream(w)?
726           + w.write(b"\r\n")?)
727    }
728}
729impl_try_from!(AddressList, ResentCc);
730impl_display!(ResentCc);
731
732// 3.6.6
733// resent-bcc      =   "Resent-Bcc:" [address-list / CFWS] CRLF
734#[derive(Debug, Clone, PartialEq)]
735pub enum ResentBcc {
736    AddressList(AddressList),
737    CFWS(CFWS),
738    Empty
739}
740impl Parsable for ResentBcc {
741    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
742        if input.len() == 0 { return Err(ParseError::Eof("Resent-Bcc")); }
743        let mut rem = input;
744        req_name!(rem, "resent-bcc:");
745        if let Ok(x) = parse!(AddressList, rem) {
746            req_crlf!(rem);
747            return Ok((ResentBcc::AddressList(x), rem));
748        }
749        if let Ok(x) = parse!(CFWS, rem) {
750            req_crlf!(rem);
751            return Ok((ResentBcc::CFWS(x), rem));
752        }
753        req_crlf!(rem);
754        return Ok((ResentBcc::Empty, rem));
755    }
756}
757impl Streamable for ResentBcc {
758    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
759        let mut count: usize = 0;
760        count += w.write(b"Resent-Bcc:")?;
761        count += match *self {
762            ResentBcc::AddressList(ref al) => al.stream(w)?,
763            ResentBcc::CFWS(ref cfws) => cfws.stream(w)?,
764            ResentBcc::Empty => 0,
765        };
766        count += w.write(b"\r\n")?;
767        Ok(count)
768    }
769}
770impl<'a> TryFrom<&'a [u8]> for ResentBcc {
771    type Error = ParseError;
772    fn try_from(input: &'a [u8]) -> Result<ResentBcc, ParseError> {
773        let (out,rem) = AddressList::parse(input)?;
774        if rem.len() > 0 {
775            return Err(ParseError::TrailingInput("Resent-Bcc", input.len() - rem.len()));
776        }
777        Ok(ResentBcc::AddressList(out))
778    }
779}
780impl<'a> TryFrom<&'a str> for ResentBcc {
781    type Error = ParseError;
782    fn try_from(input: &'a str) -> Result<ResentBcc, ParseError> {
783        TryFrom::try_from(input.as_bytes())
784    }
785}
786impl<'a> TryFrom<AddressList> for ResentBcc {
787    type Error = ParseError;
788    fn try_from(input: AddressList) -> Result<ResentBcc, ParseError> {
789        Ok(ResentBcc::AddressList(input))
790    }
791}
792impl_display!(ResentBcc);
793
794// 3.6.6
795// resent-msg-id   =   "Resent-Message-ID:" msg-id CRLF
796#[derive(Debug, Clone, PartialEq)]
797pub struct ResentMessageId(pub MsgId);
798impl Parsable for ResentMessageId {
799    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
800        if input.len() == 0 { return Err(ParseError::Eof("Resent-Message-ID")); }
801        let mut rem = input;
802        req_name!(rem, "resent-message-id:");
803        match parse!(MsgId, rem) {
804            Ok(x) => {
805                req_crlf!(rem);
806                return Ok((ResentMessageId(x), rem));
807            },
808            Err(e) => Err(ParseError::Parse("Resent-Message-Id", Box::new(e))),
809        }
810    }
811}
812impl Streamable for ResentMessageId {
813    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
814        Ok(w.write(b"Resent-Message-ID:")?
815           + self.0.stream(w)?
816           + w.write(b"\r\n")?)
817    }
818}
819impl_try_from!(MsgId, ResentMessageId);
820impl_display!(ResentMessageId);
821
822// 3.6.7
823// received        =   "Received:" *received-token ";" date-time CRLF
824// Errata ID 3979:
825// received        =   "Received:" [1*received-token / CFWS]
826//                     ";" date-time CRLF
827#[derive(Debug, Clone, PartialEq)]
828pub enum ReceivedTokens {
829    Tokens(Vec<ReceivedToken>),
830    Comment(CFWS),
831}
832#[derive(Debug, Clone, PartialEq)]
833pub struct Received {
834    pub received_tokens: ReceivedTokens,
835    pub date_time: DateTime,
836}
837impl Parsable for Received {
838    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
839        if input.len() == 0 { return Err(ParseError::Eof("Received")); }
840        let mut rem = input;
841        req_name!(rem, "received:");
842        let mut tokens: Vec<ReceivedToken> = Vec::new();
843        let err;
844        loop {
845            match parse!(ReceivedToken, rem) {
846                Ok(r) => tokens.push(r),
847                Err(e) => { err = e; break; }
848            }
849        }
850        let received_tokens = if tokens.len()==0 {
851            if let Ok(cfws) = parse!(CFWS, rem) {
852                ReceivedTokens::Comment(cfws)
853            } else {
854                return Err(ParseError::Parse("Received", Box::new(err)));
855            }
856        } else {
857            ReceivedTokens::Tokens(tokens)
858        };
859        req!(rem, b";", input);
860        match parse!(DateTime, rem) {
861            Ok(dt) => {
862                req_crlf!(rem);
863                return Ok((Received {
864                    received_tokens: received_tokens,
865                    date_time: dt
866                }, rem));
867            },
868            Err(e) => Err(ParseError::Parse("Received", Box::new(e))),
869        }
870    }
871}
872impl Streamable for Received {
873    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
874        let mut count: usize = 0;
875        count += w.write(b"Received:")?;
876        match self.received_tokens {
877            ReceivedTokens::Tokens(ref vec) => {
878                for token in vec {
879                    count += token.stream(w)?;
880                }
881            },
882            ReceivedTokens::Comment(ref c) => {
883                count += c.stream(w)?;
884            },
885        }
886        count += w.write(b";")?;
887        count += self.date_time.stream(w)?;
888        count += w.write(b"\r\n")?;
889        Ok(count)
890    }
891}
892impl<'a> TryFrom<&'a [u8]> for Received {
893    type Error = ParseError;
894    fn try_from(input: &'a [u8]) -> Result<Received, ParseError> {
895        let mut fudged_input: Vec<u8> = "Received:".as_bytes().to_owned();
896        fudged_input.extend(&*input);
897        fudged_input.extend("\r\n".as_bytes());
898        let (out,rem) = Received::parse(input)?;
899        if rem.len() > 0 {
900            return Err(ParseError::TrailingInput("Received", input.len() - rem.len()));
901        } else {
902            Ok(out)
903        }
904    }
905}
906impl<'a> TryFrom<&'a str> for Received {
907    type Error = ParseError;
908    fn try_from(input: &'a str) -> Result<Received, ParseError> {
909        TryFrom::try_from(input.as_bytes())
910    }
911}
912impl<'a> TryFrom<(ReceivedTokens, DateTime)> for Received {
913    type Error = ParseError;
914    fn try_from(input: (ReceivedTokens, DateTime)) -> Result<Received, ParseError> {
915        Ok(Received {
916            received_tokens: input.0,
917            date_time: input.1 })
918    }
919}
920impl_display!(Received);
921
922// 3.6.7
923// return          =   "Return-Path:" path CRLF
924#[derive(Debug, Clone, PartialEq)]
925pub struct Return(pub Path);
926impl Parsable for Return {
927    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
928        let mut rem = input;
929        req_name!(rem, "return-path:");
930        match parse!(Path, rem) {
931            Ok(path) => {
932                req_crlf!(rem);
933                return Ok((Return(path), rem));
934            },
935            Err(e) => Err(ParseError::Parse("Return-Path", Box::new(e))),
936        }
937    }
938}
939impl Streamable for Return {
940    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
941        Ok(w.write(b"Return-Path:")?
942           + self.0.stream(w)?
943           + w.write(b"\r\n")?)
944    }
945}
946impl_try_from!(Path, Return);
947impl_display!(Return);
948
949// 3.6.8
950// optional-field  =   field-name ":" unstructured CRLF
951#[derive(Debug, Clone, PartialEq)]
952pub struct OptionalField {
953    pub name: FieldName,
954    pub value: Unstructured,
955}
956impl Parsable for OptionalField {
957    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
958        let mut rem = input;
959
960        match parse!(FieldName, rem) {
961            Ok(name) => {
962                req!(rem, b":", input);
963                match parse!(Unstructured, rem) {
964                    Ok(value) => {
965                        req_crlf!(rem);
966                        return Ok((OptionalField {
967                            name: name,
968                            value: value,
969                        }, rem));
970                    },
971                    Err(e) => Err(ParseError::Parse("Optional Field", Box::new(e))),
972                }
973            },
974            Err(e) => Err(ParseError::Parse("Optional Field", Box::new(e))),
975        }
976    }
977}
978impl Streamable for OptionalField {
979    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
980        Ok(self.name.stream(w)?
981           + w.write(b":")?
982           + self.value.stream(w)?
983           + w.write(b"\r\n")?)
984    }
985}
986impl<'a> TryFrom<(FieldName, Unstructured)> for OptionalField {
987    type Error = ParseError;
988    fn try_from(input: (FieldName, Unstructured)) -> Result<OptionalField, ParseError> {
989        Ok(OptionalField {
990            name: input.0,
991            value: input.1 })
992    }
993}
994impl<'a,'b> TryFrom<(&'a [u8], &'b [u8])> for OptionalField {
995    type Error = ParseError;
996    fn try_from(input: (&'a [u8], &'b [u8])) -> Result<OptionalField, ParseError> {
997        let (name,rem) = FieldName::parse(input.0)?;
998        if rem.len() > 0 {
999            return Err(ParseError::TrailingInput("Optional Field", input.0.len() - rem.len()));
1000        }
1001        let (value,rem) = Unstructured::parse(input.1)?;
1002        if rem.len() > 0 {
1003            return Err(ParseError::TrailingInput("Optional Field", input.1.len() - rem.len()));
1004        }
1005        Ok(OptionalField {
1006            name: name,
1007            value: value,
1008        })
1009    }
1010}
1011impl<'a,'b> TryFrom<(&'a str, &'b str)> for OptionalField {
1012    type Error = ParseError;
1013    fn try_from(input: (&'a str, &'b str)) -> Result<OptionalField, ParseError> {
1014        TryFrom::try_from((input.0.as_bytes(), input.1.as_bytes()))
1015    }
1016}
1017impl_display!(OptionalField);