1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#![doc = include_str!("../README.md")]

/// Parse and represent full emails as "parts" as defined by MIME (RFC 2046)
pub mod part;

/// Parse and represent IMF (Internet Message Format) headers (RFC 822, RFC 5322)
pub mod imf;

/// Parse and represent MIME headers (RFC 2045, RFC 2047)
pub mod mime;

/// MIME and IMF represent headers the same way: module contains their commong logic
pub mod header;

/// Low-level email-specific text-based representation for data
pub mod text;

/// Manipulate buffer of bytes
mod pointers;

use nom::{combinator::into, IResult};

/// Parse a whole email including its (MIME) body
///
/// Returns the parsed content, but also the remaining bytes
/// if the parser stopped before arriving to the end (for example
/// due to a multipart delimiter).
///
/// # Arguments
///
/// * `input` - A buffer of bytes containing your full email
///
/// # Returns
///
/// * `rest` - The rest of the buffer, the part that is not parsed as the email ended before the
/// end of the data
/// * `msg` - The parsed message
///
/// # Examples
///
/// ```
/// let input = br#"Date: 7 Mar 2023 08:00:00 +0200
/// From: deuxfleurs@example.com
/// To: someone_else@example.com
/// Subject: An RFC 822 formatted message
/// MIME-Version: 1.0
/// Content-Type: text/plain; charset=us-ascii
///
/// This is the plain text body of the message. Note the blank line
/// between the header information and the body of the message."#;
///
/// let (_, email) = eml_codec::parse_message(input).unwrap();
/// println!(
///     "{} raw message is:\n{}",
///     email.imf.from[0].to_string(),
///     String::from_utf8_lossy(email.child.as_text().unwrap().body),
/// );
/// ```
pub fn parse_message(input: &[u8]) -> IResult<&[u8], part::composite::Message> {
    into(part::composite::message(mime::MIME::<
        mime::r#type::DeductibleMessage,
    >::default()))(input)
}

/// Only extract the headers of the email that are part of the Internet Message Format spec
///
/// Emails headers contain MIME and IMF (Internet Message Format) headers.
/// Sometimes you only need to know the recipient or the sender of an email,
/// and are not interested in its content. In this case, you only need to parse the IMF
/// fields and can ignore the MIME headers + the body. This is what this function does.
///
/// # Arguments
///
/// * `input` - A buffer of bytes containing either only the headers of your email or your full
/// email (in both cases, the body will be ignored)
///
/// # Returns
///
/// * `rest` - The rest of the buffer, ie. the body of your email as raw bytes
/// * `imf` - The parsed IMF headers of your email
///
/// # Examples
///
/// ```
/// let input = br#"Date: 7 Mar 2023 08:00:00 +0200
/// From: deuxfleurs@example.com
/// To: someone_else@example.com
/// Subject: An RFC 822 formatted message
/// MIME-Version: 1.0
/// Content-Type: text/plain; charset=us-ascii
///
/// This is the plain text body of the message. Note the blank line
/// between the header information and the body of the message."#;
///
/// let (_, imf) = eml_codec::parse_imf(input).unwrap();
/// println!(
///     "{} just sent you an email with subject \"{}\"",
///     imf.from[0].to_string(),
///     imf.subject.unwrap().to_string(),
/// );
/// ```
pub fn parse_imf(input: &[u8]) -> IResult<&[u8], imf::Imf> {
    imf::imf(input)
}