Skip to main content

mail_builder/headers/
message_id.rs

1use std::borrow::Cow;
2
3use super::{
4    Header,
5    fold::{FoldWriter, write_control_free},
6};
7use crate::{mime::write_boundary, writer::Writer};
8
9/// RFC5322 Message ID header
10#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
11pub struct MessageId<'x> {
12    pub id: Vec<Cow<'x, str>>,
13}
14
15impl<'x> MessageId<'x> {
16    /// Create a new Message ID header
17    pub fn new(id: impl Into<Cow<'x, str>>) -> Self {
18        Self {
19            id: vec![id.into()],
20        }
21    }
22
23    /// Create a new multi-value Message ID header
24    pub fn new_list<T, U>(ids: T) -> Self
25    where
26        T: Iterator<Item = U>,
27        U: Into<Cow<'x, str>>,
28    {
29        Self {
30            id: ids.map(|s| s.into()).collect(),
31        }
32    }
33}
34
35impl<'x> From<&'x str> for MessageId<'x> {
36    fn from(value: &'x str) -> Self {
37        Self::new(value)
38    }
39}
40
41impl From<String> for MessageId<'_> {
42    fn from(value: String) -> Self {
43        Self::new(value)
44    }
45}
46
47impl<'x> From<&[&'x str]> for MessageId<'x> {
48    fn from(value: &[&'x str]) -> Self {
49        MessageId {
50            id: value.iter().map(|&s| s.into()).collect(),
51        }
52    }
53}
54
55impl<'x> From<&'x [String]> for MessageId<'x> {
56    fn from(value: &'x [String]) -> Self {
57        MessageId {
58            id: value.iter().map(|s| s.into()).collect(),
59        }
60    }
61}
62
63impl<'x, T> From<Vec<T>> for MessageId<'x>
64where
65    T: Into<Cow<'x, str>>,
66{
67    fn from(value: Vec<T>) -> Self {
68        MessageId {
69            id: value.into_iter().map(|s| s.into()).collect(),
70        }
71    }
72}
73
74pub fn generate_message_id_header(output: &mut impl Writer, hostname: &str) {
75    output.write_byte(b'<');
76    write_boundary(output, ".");
77    output.write_byte(b'@');
78    output.write(hostname.as_bytes());
79    output.write_byte(b'>');
80}
81
82impl Header for MessageId<'_> {
83    fn write_header(&self, output: &mut impl Writer, column: usize) {
84        let Some((last, head)) = self.id.split_last() else {
85            output.write(b"\r\n");
86            return;
87        };
88
89        let mut folder = FoldWriter::new(output, column);
90
91        for id in head {
92            folder.begin_atom(id.len() + 2);
93            folder.write_byte(b'<');
94            write_control_free(&mut folder, id.as_bytes());
95            folder.write_byte(b'>');
96            folder.space();
97        }
98
99        folder.begin_atom(last.len() + 2);
100        folder.write_byte(b'<');
101        write_control_free(&mut folder, last.as_bytes());
102        folder.write(b">\r\n");
103    }
104}