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