email_format/rfc5322/
mod.rs

1// Format validated types representing lexical tokens defined in
2// RFC 5322 (as well as some referred from RFC 5234)
3// in order to support SMTP (RFC 5321)
4
5// Macro for defining sequences of characters within a character class
6macro_rules! def_cclass {
7    ( $typ:ident, $test:ident) => {
8        #[derive(Debug, Clone, PartialEq)]
9        pub struct $typ(pub Vec<u8>);
10        impl Parsable for $typ {
11            fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
12                let mut pos: usize = 0;
13                let mut output: Vec<u8> = Vec::new();
14                while pos < input.len() && $test(input[pos]) {
15                    output.push(input[pos]);
16                    pos += 1;
17                }
18                if output.len() > 0 {
19                    Ok( ($typ(output), &input[pos..]) )
20                }
21                else {
22                    if pos >= input.len() { Err( ParseError::Eof("$typ") ) }
23                    else { Err( ParseError::NotFound("$typ") ) }
24                }
25            }
26        }
27        impl Streamable for $typ {
28            fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
29                Ok(w.write(&self.0[..])?)
30            }
31        }
32    };
33}
34
35// Macro for assigning the returned remaining input of a parse function to an existing
36// variable
37macro_rules! parse {
38    ($pth:ident, $rem:ident) => {
39        {
40            $pth::parse($rem).map(|(value, r)| { $rem = r; value })
41        }
42    };
43}
44
45macro_rules! req {
46    ($rem:ident, $bytes:expr, $input:ident) => {
47        let len: usize = $bytes.len();
48        if $rem.len() < len {
49            return Err(ParseError::Eof("$bytes"));
50        }
51        if &$rem[0..len] != $bytes {
52            return Err(ParseError::Expected($bytes.to_vec()));
53        }
54        $rem = &$rem[len..];
55    };
56}
57
58macro_rules! impl_display {
59    ($t:ty) => {
60        impl ::std::fmt::Display for $t {
61            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
62                let mut output: Vec<u8> = Vec::new();
63                if let Err(_) = self.stream(&mut output) {
64                    return Err(::std::fmt::Error);
65                }
66                unsafe {
67                    // rfc5322 formatted emails fall within utf8
68                    write!(f, "{}", ::std::str::from_utf8_unchecked(&*output))
69                }
70            }
71        }
72    }
73}
74
75pub mod error;
76pub use self::error::ParseError;
77pub mod types;
78pub mod headers;
79pub mod email_address;
80
81use std::io::Write;
82use std::io::Error as IoError;
83use buf_read_ext::BufReadExt;
84use ::TryFrom;
85use self::headers::{Return, Received};
86use self::headers::{ResentDate, ResentFrom, ResentSender, ResentTo, ResentCc, ResentBcc,
87                    ResentMessageId};
88use self::headers::{OrigDate, From, Sender, ReplyTo, To, Cc, Bcc, MessageId, InReplyTo,
89                    References, Subject, Comments, Keywords, OptionalField};
90
91pub trait Parsable: Sized {
92    /// Parse the object off of the beginning of the `input`.  If found, returns Some object,
93    /// and a slice containing the remainer of the input.
94    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError>;
95}
96
97pub trait Streamable {
98    /// Serializes and sends the content out to `w`, returning the number of bytes written.
99    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError>;
100}
101
102// 3.6.7
103// trace           =   [return]
104//                     1*received
105#[derive(Debug, Clone, PartialEq)]
106pub struct Trace {
107    return_path: Option<Return>,
108    received: Vec<Received>
109}
110impl Parsable for Trace {
111    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
112        let mut rem = input;
113        let maybe_return = parse!(Return, rem).ok();
114        let mut received: Vec<Received> = Vec::new();
115        while let Ok(r) = parse!(Received, rem) {
116            received.push(r);
117        }
118        if received.len() < 1 { return Err(ParseError::NotFound("Trace")); }
119        Ok((Trace {
120            return_path: maybe_return,
121            received: received,
122        }, rem))
123    }
124}
125impl Streamable for Trace {
126    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
127        let mut count: usize = 0;
128        if let Some(ref rp) = self.return_path {
129            count += rp.stream(w)?;
130        }
131        for r in &self.received {
132            count += r.stream(w)?;
133        }
134        Ok(count)
135    }
136}
137impl_display!(Trace);
138
139#[derive(Debug, Clone, PartialEq)]
140pub enum ResentField {
141    Date(ResentDate),
142    From(ResentFrom),
143    Sender(ResentSender),
144    To(ResentTo),
145    Cc(ResentCc),
146    Bcc(ResentBcc),
147    MessageId(ResentMessageId),
148}
149impl Parsable for ResentField {
150    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
151        let mut rem = input;
152        if let Ok(x) = parse!(ResentDate, rem) {
153            return Ok((ResentField::Date(x), rem));
154        }
155        if let Ok(x) = parse!(ResentFrom, rem) {
156            return Ok((ResentField::From(x), rem));
157        }
158        if let Ok(x) = parse!(ResentSender, rem) {
159            return Ok((ResentField::Sender(x), rem));
160        }
161        if let Ok(x) = parse!(ResentTo, rem) {
162            return Ok((ResentField::To(x), rem));
163        }
164        if let Ok(x) = parse!(ResentCc, rem) {
165            return Ok((ResentField::Cc(x), rem));
166        }
167        if let Ok(x) = parse!(ResentBcc, rem) {
168            return Ok((ResentField::Bcc(x), rem));
169        }
170        if let Ok(x) = parse!(ResentMessageId, rem) {
171            return Ok((ResentField::MessageId(x), rem));
172        }
173        Err(ParseError::NotFound("Resent-Field"))
174    }
175}
176impl Streamable for ResentField {
177    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
178        match *self {
179            ResentField::Date(ref x) => x.stream(w),
180            ResentField::From(ref x) => x.stream(w),
181            ResentField::Sender(ref x) => x.stream(w),
182            ResentField::To(ref x) => x.stream(w),
183            ResentField::Cc(ref x) => x.stream(w),
184            ResentField::Bcc(ref x) => x.stream(w),
185            ResentField::MessageId(ref x) => x.stream(w),
186        }
187    }
188}
189impl_display!(ResentField);
190
191// 3.6
192// a sub part of the Fields definition
193#[derive(Debug, Clone, PartialEq)]
194pub enum Field {
195    OrigDate(OrigDate),
196    From(From),
197    Sender(Sender),
198    ReplyTo(ReplyTo),
199    To(To),
200    Cc(Cc),
201    Bcc(Bcc),
202    MessageId(MessageId),
203    InReplyTo(InReplyTo),
204    References(References),
205    Subject(Subject),
206    Comments(Comments),
207    Keywords(Keywords),
208    OptionalField(OptionalField),
209}
210impl Parsable for Field {
211    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
212        let mut rem = input;
213        if let Ok(x) = parse!(OrigDate, rem) {
214            return Ok((Field::OrigDate(x), rem));
215        }
216        if let Ok(x) = parse!(From, rem) {
217            return Ok((Field::From(x), rem));
218        }
219        if let Ok(x) = parse!(Sender, rem) {
220            return Ok((Field::Sender(x), rem));
221        }
222        if let Ok(x) = parse!(ReplyTo, rem) {
223            return Ok((Field::ReplyTo(x), rem));
224        }
225        if let Ok(x) = parse!(To, rem) {
226            return Ok((Field::To(x), rem));
227        }
228        if let Ok(x) = parse!(Cc, rem) {
229            return Ok((Field::Cc(x), rem));
230        }
231        if let Ok(x) = parse!(Bcc, rem) {
232            return Ok((Field::Bcc(x), rem));
233        }
234        if let Ok(x) = parse!(MessageId, rem) {
235            return Ok((Field::MessageId(x), rem));
236        }
237        if let Ok(x) = parse!(InReplyTo, rem) {
238            return Ok((Field::InReplyTo(x), rem));
239        }
240        if let Ok(x) = parse!(References, rem) {
241            return Ok((Field::References(x), rem));
242        }
243        if let Ok(x) = parse!(Subject, rem) {
244            return Ok((Field::Subject(x), rem));
245        }
246        if let Ok(x) = parse!(Comments, rem) {
247            return Ok((Field::Comments(x), rem));
248        }
249        if let Ok(x) = parse!(Keywords, rem) {
250            return Ok((Field::Keywords(x), rem));
251        }
252        if let Ok(x) = parse!(OptionalField, rem) {
253            return Ok((Field::OptionalField(x), rem));
254        }
255        Err(ParseError::NotFound("Field"))
256    }
257}
258impl Streamable for Field {
259    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
260        match *self {
261            Field::OrigDate(ref x) => x.stream(w),
262            Field::From(ref x) => x.stream(w),
263            Field::Sender(ref x) => x.stream(w),
264            Field::ReplyTo(ref x) => x.stream(w),
265            Field::To(ref x) => x.stream(w),
266            Field::Cc(ref x) => x.stream(w),
267            Field::Bcc(ref x) => x.stream(w),
268            Field::MessageId(ref x) => x.stream(w),
269            Field::InReplyTo(ref x) => x.stream(w),
270            Field::References(ref x) => x.stream(w),
271            Field::Subject(ref x) => x.stream(w),
272            Field::Comments(ref x) => x.stream(w),
273            Field::Keywords(ref x) => x.stream(w),
274            Field::OptionalField(ref x) => x.stream(w),
275        }
276    }
277}
278impl_display!(Field);
279
280// 3.6
281// a sub part of the Fields definition
282#[derive(Debug, Clone, PartialEq)]
283pub struct ResentTraceBlock {
284    pub trace: Trace,
285    pub resent_fields: Vec<ResentField>,
286}
287impl Parsable for ResentTraceBlock {
288    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
289        let mut rem = input;
290        if let Ok(t) = parse!(Trace, rem) {
291            let mut fields: Vec<ResentField> = Vec::new();
292            while let Ok(f) = parse!(ResentField, rem) {
293                fields.push(f);
294            }
295            if fields.len() == 0 {
296                Err(ParseError::ExpectedType("Resent Field"))
297            } else {
298                Ok((ResentTraceBlock {
299                    trace: t,
300                    resent_fields: fields
301                }, rem))
302            }
303        } else {
304            Err(ParseError::NotFound("Resent Trace Block"))
305        }
306    }
307}
308impl Streamable for ResentTraceBlock {
309    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
310        let mut count: usize = 0;
311        count += self.trace.stream(w)?;
312        for field in &self.resent_fields {
313            count += field.stream(w)?;
314        }
315        Ok(count)
316    }
317}
318impl_display!(ResentTraceBlock);
319
320// 3.6
321// a sub part of the Fields definition
322#[derive(Debug, Clone, PartialEq)]
323pub struct OptTraceBlock {
324    pub trace: Trace,
325    pub opt_fields: Vec<OptionalField>,
326}
327impl Parsable for OptTraceBlock {
328    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
329        let mut rem = input;
330        if let Ok(t) = parse!(Trace, rem) {
331            let mut fields: Vec<OptionalField> = Vec::new();
332            while let Ok(f) = parse!(OptionalField, rem) {
333                fields.push(f);
334            }
335            if fields.len() == 0 {
336                Err(ParseError::ExpectedType("Optional Field"))
337            } else {
338                Ok((OptTraceBlock {
339                    trace: t,
340                    opt_fields: fields
341                }, rem))
342            }
343        } else {
344            Err(ParseError::NotFound("Opt Trace Block"))
345        }
346    }
347}
348impl Streamable for OptTraceBlock {
349    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
350        let mut count: usize = 0;
351        count += self.trace.stream(w)?;
352        for field in &self.opt_fields {
353            count += field.stream(w)?;
354        }
355        Ok(count)
356    }
357}
358impl_display!(OptTraceBlock);
359
360// 3.6
361// a sub part of the Fields definition
362#[derive(Debug, Clone, PartialEq)]
363pub enum TraceBlock {
364    Resent(ResentTraceBlock),
365    Opt(OptTraceBlock),
366}
367impl Parsable for TraceBlock {
368    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
369        let mut rem = input;
370        if let Ok(block) = parse!(ResentTraceBlock, rem) {
371            Ok((TraceBlock::Resent(block), rem))
372        }
373        else if let Ok(block) = parse!(OptTraceBlock, rem) {
374            Ok((TraceBlock::Opt(block), rem))
375        }
376        else {
377            Err(ParseError::NotFound("Trace Block"))
378        }
379    }
380}
381impl Streamable for TraceBlock {
382    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
383        match *self {
384            TraceBlock::Resent(ref block) => block.stream(w),
385            TraceBlock::Opt(ref block) => block.stream(w),
386        }
387    }
388}
389impl_display!(TraceBlock);
390
391// 3.6
392// fields          =   *(trace
393//                       *optional-field /
394//                       *(resent-date /
395//                        resent-from /
396//                        resent-sender /
397//                        resent-to /
398//                        resent-cc /
399//                        resent-bcc /
400//                        resent-msg-id))
401//                     *(orig-date /
402//                     from /
403//                     sender /
404//                     reply-to /
405//                     to /
406//                     cc /
407//                     bcc /
408//                     message-id /
409//                     in-reply-to /
410//                     references /
411//                     subject /
412//                     comments /
413//                     keywords /
414//                     optional-field)
415#[derive(Debug, Clone, PartialEq)]
416pub struct Fields {
417    pub trace_blocks: Vec<TraceBlock>,
418    pub fields: Vec<Field>,
419}
420impl Parsable for Fields {
421    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
422        let mut rem = input;
423        let mut trace_blocks: Vec<TraceBlock> = Vec::new();
424        while let Ok(tb) = parse!(TraceBlock, rem) {
425            trace_blocks.push(tb);
426        }
427        let mut fields: Vec<Field> = Vec::new();
428        while let Ok(f) = parse!(Field, rem) {
429            fields.push(f);
430        }
431        Ok((Fields {
432            trace_blocks: trace_blocks,
433            fields: fields,
434        }, rem))
435    }
436}
437impl Streamable for Fields {
438    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
439        let mut count: usize = 0;
440        for tb in &self.trace_blocks {
441            count += tb.stream(w)?;
442        }
443        for f in &self.fields {
444            count += f.stream(w)?;
445        }
446        Ok(count)
447    }
448}
449impl_display!(Fields);
450
451// 3.5
452// text            =   %d1-9 /            ; Characters excluding CR
453//                     %d11 /             ;  and LF
454//                     %d12 /
455//                     %d14-127
456#[inline]
457pub fn is_text(c: u8) -> bool {
458    (c>=1 && c<=9) || c==11 || c==12 || (c>=14 && c<=127)
459}
460def_cclass!(Text, is_text);
461
462// 3.5
463// body            =   (*(*998text CRLF) *998text) / obs-body
464#[derive(Debug, Clone, PartialEq)]
465// for performance/memory reasons, we store as a Vec<u8>
466// rather than Vec<Line> where Line is Vec<Text>.
467pub struct Body(pub Vec<u8>);
468impl Parsable for Body {
469    fn parse(mut input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
470        let mut body: Vec<u8> = Vec::new();
471        let mut line_number: usize = 0;
472        loop {
473            line_number += 1;
474            let mut line: Vec<u8> = Vec::new();
475            match input.stream_until_token(b"\r\n", &mut line) {
476                Err(e) => return Err(ParseError::Io(e)),
477                Ok((_, found)) => {
478                    let mut rem = &*line;
479                    if let Ok(text) = parse!(Text, rem) {
480                        if rem.len() > 0 {
481                            return Err(ParseError::InvalidBodyChar(rem[0]));
482                        }
483                        if text.0.len() > 998 {
484                            return Err(ParseError::LineTooLong(line_number));
485                        }
486                        body.extend(text.0.clone());
487                    }
488                    if !found { break; } // end of input
489                    else { body.extend_from_slice(b"\r\n"); }
490                }
491            }
492        }
493        Ok((Body(body), input))
494    }
495}
496impl Streamable for Body {
497    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
498        w.write(&self.0)
499    }
500}
501impl<'a> TryFrom<&'a [u8]> for Body {
502    type Error = ParseError;
503    fn try_from(input: &'a [u8]) -> Result<Body, ParseError> {
504        let (out,rem) = Body::parse(input)?;
505        if rem.len() > 0 {
506            Err(ParseError::TrailingInput("Body", input.len() - rem.len()))
507        } else {
508            Ok(out)
509        }
510    }
511}
512impl<'a> TryFrom<&'a str> for Body {
513    type Error = ParseError;
514    fn try_from(input: &'a str) -> Result<Body, ParseError> {
515        TryFrom::try_from(input.as_bytes())
516    }
517}
518impl_display!(Body);
519
520// 3.5
521// message         =   (fields / obs-fields)
522//                     [CRLF body]
523#[derive(Debug, Clone, PartialEq)]
524pub struct Message {
525    pub fields: Fields,
526    pub body: Option<Body>
527}
528impl Parsable for Message {
529    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
530        let mut rem = input;
531        if let Ok(fields) = parse!(Fields, rem) {
532            if &rem[..2] != b"\r\n" {
533                return Ok((Message {
534                    fields: fields,
535                    body: None,
536                }, rem));
537            }
538            rem = &rem[2..];
539            parse!(Body, rem).map(|b| (Message {
540                fields: fields,
541                body: Some(b),
542            }, rem))
543        } else {
544            Err(ParseError::NotFound("Message"))
545        }
546    }
547}
548impl Streamable for Message {
549    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
550        let mut count: usize = 0;
551        count += self.fields.stream(w)?;
552        if let Some(ref body) = self.body {
553            count += w.write(b"\r\n")?;
554            count += body.stream(w)?;
555        }
556        Ok(count)
557    }
558}
559impl_display!(Message);