asimov_imap_module/
message.rs

1// This is free and unencumbered software released into the public domain.
2
3use super::ImapError;
4use imap::types::Fetch;
5use know::classes::EmailMessage;
6use mail_parser::MessageParser;
7
8#[derive(Clone, Debug, Eq, Hash, PartialEq)]
9pub struct ImapMessage {
10    pub pos: usize,
11    pub uid: Option<u32>,
12    pub size: Option<u32>,
13    pub headers: EmailMessage,
14    pub body: Option<String>,
15}
16
17impl TryFrom<&Fetch<'_>> for ImapMessage {
18    type Error = ImapError;
19
20    fn try_from(input: &Fetch) -> Result<Self, Self::Error> {
21        Ok(match input.body() {
22            Some(bytes) => {
23                let message = MessageParser::default()
24                    .parse(bytes)
25                    .ok_or(ImapError::InvalidMessage)?;
26                let headers: EmailMessage = (&message)
27                    .try_into()
28                    .map_err(|_| ImapError::InvalidHeaders)?;
29                let body = headers.body.clone();
30                Self {
31                    pos: input.message as _,
32                    uid: input.uid,
33                    size: input.size,
34                    headers,
35                    body,
36                }
37            },
38            None => {
39                let envelope = input.envelope().unwrap();
40                let mut headers: EmailMessage =
41                    envelope.try_into().map_err(|_| ImapError::InvalidHeaders)?;
42                if let Some(subject_bytes) = envelope.subject.as_ref() {
43                    headers.subject = rfc2047_decoder::decode(subject_bytes).ok();
44                }
45                Self {
46                    pos: input.message as _,
47                    uid: input.uid,
48                    size: input.size,
49                    headers,
50                    body: None,
51                }
52            },
53        })
54    }
55}