miltr_common/modifications/
quarantine.rs

1//! Carefully put this mail in a box and leave it
2use std::borrow::Cow;
3
4use bytes::{BufMut, BytesMut};
5
6use crate::decoding::Parsable;
7use crate::encoding::Writable;
8use crate::ProtocolError;
9
10/// This quarantines the message into a holding pool defined by the MTA.
11/// (First implemented in Sendmail in version 8.13; offered to the milter by
12/// the `SMFIF_QUARANTINE` flag in "actions" of `SMFIC_OPTNEG`.)
13#[derive(Debug, Clone)]
14pub struct Quarantine {
15    /// Give a reason to the client why this was quarantined
16    reason: BytesMut,
17}
18
19impl Quarantine {
20    const CODE: u8 = b'q';
21
22    /// Quarantine with the given message
23    #[must_use]
24    pub fn new(reason: &[u8]) -> Self {
25        Self {
26            reason: BytesMut::from_iter(reason),
27        }
28    }
29
30    /// Give a reason to the client why this was quarantined
31    #[must_use]
32    pub fn reason(&self) -> Cow<str> {
33        String::from_utf8_lossy(&self.reason)
34    }
35}
36
37impl Parsable for Quarantine {
38    const CODE: u8 = Self::CODE;
39
40    fn parse(buffer: BytesMut) -> Result<Self, ProtocolError> {
41        Ok(Self { reason: buffer })
42    }
43}
44
45impl Writable for Quarantine {
46    fn write(&self, buffer: &mut BytesMut) {
47        buffer.extend_from_slice(&self.reason);
48        buffer.put_u8(0);
49    }
50
51    fn len(&self) -> usize {
52        self.reason.len() + 1
53    }
54
55    fn code(&self) -> u8 {
56        Self::CODE
57    }
58    fn is_empty(&self) -> bool {
59        self.len() == 0
60    }
61}
62
63#[cfg(test)]
64mod test {
65    use super::*;
66    #[test]
67    fn test_quarantine() {
68        let mut buffer = BytesMut::from("");
69        let quan = Quarantine {
70            reason: BytesMut::from("Invalid Input"),
71        };
72        quan.write(&mut buffer);
73
74        assert_eq!(buffer, BytesMut::from("Invalid Input\0"));
75    }
76}