miltr_common/modifications/
body.rs

1//! Replace body parts
2
3use std::borrow::Cow;
4
5use bytes::BytesMut;
6
7use crate::decoding::Parsable;
8use crate::encoding::Writable;
9use crate::ProtocolError;
10
11/// Replace the body of the incoming mail.
12///
13/// If this modification action is used, the **whole** body has to be sent back.
14/// It can be split across multiple `ReplaceBody` actions, but in the end,
15/// the complete intended response has to be sent.
16#[derive(Debug, Clone)]
17pub struct ReplaceBody {
18    body: BytesMut,
19}
20
21impl<'a> FromIterator<&'a u8> for ReplaceBody {
22    fn from_iter<T: IntoIterator<Item = &'a u8>>(into_iter: T) -> Self {
23        Self {
24            body: into_iter.into_iter().copied().collect(), // body: BytesMut::from_iter(into_iter.into_iter().copied())
25        }
26    }
27}
28
29impl ReplaceBody {
30    const CODE: u8 = b'b';
31
32    /// A body part to replace the original
33    #[must_use]
34    pub fn new(body: &[u8]) -> Self {
35        Self {
36            body: BytesMut::from_iter(body),
37        }
38    }
39
40    /// The body to send back.
41    ///
42    /// Will be interpreted by the client as a valid mail.
43    #[must_use]
44    pub fn body(&self) -> Cow<str> {
45        String::from_utf8_lossy(&self.body)
46    }
47}
48
49impl Parsable for ReplaceBody {
50    const CODE: u8 = Self::CODE;
51
52    fn parse(buffer: BytesMut) -> Result<Self, ProtocolError> {
53        Ok(Self { body: buffer })
54    }
55}
56
57impl Writable for ReplaceBody {
58    /// A milter that uses `SMFIR_REPLBODY` must replace the entire body
59    fn write(&self, buffer: &mut BytesMut) {
60        buffer.extend_from_slice(&self.body);
61    }
62
63    fn len(&self) -> usize {
64        self.body.len()
65    }
66
67    fn code(&self) -> u8 {
68        Self::CODE
69    }
70
71    fn is_empty(&self) -> bool {
72        self.len() == 0
73    }
74}
75
76#[cfg(test)]
77mod test {
78    use super::*;
79    #[test]
80    fn test_replace_body() {
81        let mut buffer = BytesMut::from("b");
82        let replace_body = ReplaceBody {
83            body: BytesMut::from("new body"),
84        };
85        replace_body.write(&mut buffer);
86
87        assert_eq!(buffer, BytesMut::from("bnew body"));
88    }
89}