mail_builder/headers/
content_type.rs1use std::borrow::Cow;
8
9use crate::encoders::encode::rfc2047_encode;
10
11use super::Header;
12
13#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
15pub struct ContentType<'x> {
16 pub c_type: Cow<'x, str>,
17 pub attributes: Vec<(Cow<'x, str>, Cow<'x, str>)>,
18}
19
20impl<'x> ContentType<'x> {
21 pub fn new(c_type: impl Into<Cow<'x, str>>) -> Self {
23 Self {
24 c_type: c_type.into(),
25 attributes: Vec::new(),
26 }
27 }
28
29 pub fn attribute(
31 mut self,
32 key: impl Into<Cow<'x, str>>,
33 value: impl Into<Cow<'x, str>>,
34 ) -> Self {
35 self.attributes.push((key.into(), value.into()));
36 self
37 }
38
39 pub fn is_text(&self) -> bool {
41 self.c_type.starts_with("text/")
42 }
43
44 pub fn is_attachment(&self) -> bool {
46 self.c_type == "attachment"
47 }
48}
49
50impl Header for ContentType<'_> {
51 fn write_header(
52 &self,
53 mut output: impl std::io::Write,
54 mut bytes_written: usize,
55 ) -> std::io::Result<usize> {
56 output.write_all(self.c_type.as_bytes())?;
57 bytes_written += self.c_type.len();
58 if !self.attributes.is_empty() {
59 output.write_all(b"; ")?;
60 bytes_written += 2;
61 for (pos, (key, value)) in self.attributes.iter().enumerate() {
62 if bytes_written + key.len() + value.len() + 3 >= 76 {
63 output.write_all(b"\r\n\t")?;
64 bytes_written = 1;
65 }
66
67 output.write_all(key.as_bytes())?;
68 output.write_all(b"=")?;
69 bytes_written += rfc2047_encode(value, &mut output)? + key.len() + 1;
70 if pos < self.attributes.len() - 1 {
71 output.write_all(b"; ")?;
72 bytes_written += 2;
73 }
74 }
75 }
76 output.write_all(b"\r\n")?;
77 Ok(0)
78 }
79}