]> git.r.bdr.sh - rbdr/olden-mail/blob - src/middleware/find_mailboxes_compatibility.rs
Trim the tag
[rbdr/olden-mail] / src / middleware / find_mailboxes_compatibility.rs
1 use log::debug;
2
3 use super::Middleware;
4
5 /// `MailDrop` can't find folders to sync because it implements `IMAPv3` and
6 /// sends FIND MAILBOXES /*, which does not exist in `IMAPv4`.
7 /// which is not understood by modern servers. It instead replaces it with
8 /// a LIST command.
9 pub struct FindMailboxesCompatibility {
10 tags: Vec<String>,
11 }
12
13 impl FindMailboxesCompatibility {
14 pub fn new() -> Self {
15 FindMailboxesCompatibility { tags: vec![] }
16 }
17 }
18
19 impl Middleware for FindMailboxesCompatibility {
20 fn client_message(&mut self, input: &[u8]) -> Vec<u8> {
21 let command = String::from_utf8_lossy(input);
22 if command.contains("FIND MAILBOXES /*") {
23 if let Some(tag) = command.split("FIND MAILBOXES /*").next() {
24 // We'll need to convert the LIST to a FIND
25 self.tags.push(tag.trim().to_string());
26 let replacement = format!("{} LIST \"\" \"*\"\r\n", tag.trim());
27 debug!("### {replacement}");
28 return replacement.into_bytes();
29 }
30 }
31 input.to_vec()
32 }
33
34 fn server_message(&mut self, input: &[u8]) -> Vec<u8> {
35 let command = String::from_utf8_lossy(input);
36 let contains_ok_completed = self
37 .tags
38 .iter()
39 .any(|tag| command.contains(&format!("{tag} OK Completed")));
40
41 // We want to only modify responses that were a result of a MAILBOX call.
42 if !contains_ok_completed {
43 return input.to_vec();
44 }
45
46 let lines: Vec<String> = command
47 .lines()
48 .filter_map(|line| {
49 // The IMAPv3 spec specifically says INBOX is excluded from MAILBOX
50 if line.starts_with("* LIST") && line.trim_end().ends_with("\"/\" INBOX") {
51 return None;
52 }
53
54 // Transform IMAPv4 "* LIST" lines to IMAPv3 "* MAILBOX"
55 if line.starts_with("* LIST") {
56 if let Some(last_slash_pos) = line.rfind('/') {
57 let mailbox_name = line[(last_slash_pos + 1)..].trim();
58 return Some(format!("* MAILBOX {mailbox_name}\r"));
59 }
60 }
61
62 Some(line.to_string())
63 })
64 .collect();
65
66 lines.join("\n").into_bytes()
67 }
68 }