rust_rcs_core/imdn/
mod.rs1use crate::cpim::cpim_message::{CPIMHeaders, CPIMMessage};
16
17use crate::internet::body::message_body::MessageBody;
18use crate::internet::header;
19use crate::internet::header_field::AsHeaderField;
20use crate::internet::headers::content_type::AsContentType;
21
22use crate::util::raw_string::StrEq;
23
24pub struct IMDNInfo<'a> {
25 pub imdn_id: &'a [u8],
26 pub disposition_notification: Option<&'a [u8]>,
27}
28
29pub trait GetIMDNInfo<'a> {
30 fn get_imdn_info_from_inflated_headers(
31 &'a self,
32 headers: Vec<(Vec<u8>, &'a [u8])>,
33 ) -> Result<IMDNInfo, &'static str>;
34 fn get_imdn_info(&self) -> Result<IMDNInfo, &'static str>;
35}
36
37impl<'a> GetIMDNInfo<'a> for CPIMMessage {
38 fn get_imdn_info_from_inflated_headers(
39 &'a self,
40 headers: Vec<(Vec<u8>, &'a [u8])>,
41 ) -> Result<IMDNInfo, &'static str> {
42 let mut imdn_id: Option<&[u8]> = None;
43 let mut disposition_notification: Option<&[u8]> = None;
44
45 for (n, v) in headers {
46 if &n == b"<urn:ietf:params:imdn>.Message-ID" {
47 imdn_id = Some(v);
48 } else if &n == b"<urn:ietf:params:imdn>.Disposition-Notification" {
49 disposition_notification = Some(v);
50 }
51 }
52
53 if let Some(imdn_id) = imdn_id {
54 return Ok(IMDNInfo {
55 imdn_id,
56 disposition_notification,
57 });
58 }
59
60 Err("cannot find Message-ID")
61 }
62
63 fn get_imdn_info(&self) -> Result<IMDNInfo, &'static str> {
64 match &self.headers {
65 CPIMHeaders::Deflated(headers) => {
66 let mut inflated_headers: Vec<(Vec<u8>, &[u8])> = Vec::with_capacity(headers.len());
67
68 let inflator = self.ns.as_inflator();
69 for header in headers {
70 inflated_headers.push(inflator(&header));
71 }
72
73 self.get_imdn_info_from_inflated_headers(inflated_headers)
74 }
75
76 CPIMHeaders::Inflated(headers) => {
77 let mut inflated_headers: Vec<(Vec<u8>, &[u8])> = Vec::with_capacity(headers.len());
78
79 for header in headers {
80 inflated_headers.push((header.get_name().to_vec(), header.get_value()));
81 }
82
83 self.get_imdn_info_from_inflated_headers(inflated_headers)
84 }
85 }
86 }
87}
88
89pub fn message_contains_imdn(message: &MessageBody, notification_checked: bool) -> bool {
90 let mut notification_checked = notification_checked;
91
92 if !notification_checked {
93 if let Some(content_disposition_header) =
94 header::search(&message.headers, b"Content-Disposition", false)
95 {
96 if content_disposition_header.get_value() == b"notification" {
97 notification_checked = true;
98 }
99 }
100 }
101
102 if notification_checked {
103 if let Some(content_type_header) = header::search(&message.headers, b"Content-Type", false)
104 {
105 let content_type_header_field = content_type_header.get_value().as_header_field();
106 if let Some(content_type) = content_type_header_field.as_content_type() {
107 if content_type.major_type.equals_bytes(b"message", true)
108 && content_type.sub_type.equals_bytes(b"imdn+xml", true)
109 {
110 return true;
111 }
112 }
113 }
114 }
115
116 false
117}