]> git.r.bdr.sh - rbdr/olden-mail/blame - src/middleware/find_mailboxes_compatibility.rs
Adjust middleware to modify responses
[rbdr/olden-mail] / src / middleware / find_mailboxes_compatibility.rs
CommitLineData
573aaf2a
RBR
1use log::debug;
2
8ab8739c
RBR
3use 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.
573aaf2a
RBR
7/// which is not understood by modern servers. It instead replaces it with
8/// a LIST command.
8ab8739c
RBR
9pub struct FindMailboxesCompatibility {
10 tags: Vec<String>,
11}
12
13impl FindMailboxesCompatibility {
14 pub fn new() -> Self {
15 FindMailboxesCompatibility { tags: vec![] }
16 }
17}
18
19impl 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.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!("{} OK Completed", tag)));
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();
a8a71b19 44 }
8ab8739c
RBR
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 {}\r", mailbox_name));
59 }
60 }
61
62 return Some(line.to_string());
63 })
64 .collect();
65
66 return lines.join("\n").into_bytes();
573aaf2a 67 }
573aaf2a 68}