mail_builder/headers/
content_type.rs1use std::borrow::Cow;
13
14use super::Header;
15use crate::encoders::encode::rfc2047_encode;
16
17#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
19pub struct ContentType<'x> {
20 pub c_type: Cow<'x, str>,
21 pub attributes: Vec<(Cow<'x, str>, Cow<'x, str>)>,
22}
23
24impl<'x> ContentType<'x> {
25 pub fn new(c_type: impl Into<Cow<'x, str>>) -> Self {
27 Self {
28 c_type: c_type.into(),
29 attributes: Vec::new(),
30 }
31 }
32
33 pub fn attribute(mut self, key: impl Into<Cow<'x, str>>, value: impl Into<Cow<'x, str>>) -> 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<'x> Header for ContentType<'x> {
51 fn write_header(&self, mut output: impl std::io::Write, mut bytes_written: usize) -> std::io::Result<usize> {
52 output.write_all(self.c_type.as_bytes())?;
53 bytes_written += self.c_type.len();
54 if !self.attributes.is_empty() {
55 output.write_all(b"; ")?;
56 bytes_written += 2;
57 for (pos, (key, value)) in self.attributes.iter().enumerate() {
58 if bytes_written + key.len() + value.len() + 3 >= 76 {
59 output.write_all(b"\r\n\t")?;
60 bytes_written = 1;
61 }
62
63 output.write_all(key.as_bytes())?;
64 output.write_all(b"=")?;
65 bytes_written += rfc2047_encode(value, &mut output)? + key.len() + 1;
66 if pos < self.attributes.len() - 1 {
67 output.write_all(b"; ")?;
68 bytes_written += 2;
69 }
70 }
71 }
72 output.write_all(b"\r\n")?;
73 Ok(0)
74 }
75}