imsg_map/folders.rs
1//! Folder listing and SETPATH navigation for MAP folder hierarchy.
2
3use tokio::io::{AsyncRead, AsyncWrite};
4
5use crate::client::MapClient;
6use crate::{FolderListing, MapError};
7
8/// iOS telecom/msg folder hierarchy. Validated on SETPATH.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum Folder {
11 /// SETPATH segment `"inbox"`.
12 Inbox,
13 /// SETPATH segment `"sent"`.
14 Sent,
15 /// Queued outbound messages awaiting delivery.
16 Outbox,
17 /// Messages moved to the trash.
18 Deleted,
19}
20
21impl Folder {
22 /// SETPATH segment name for this folder as required by the MAP specification.
23 #[must_use]
24 pub const fn as_str(self) -> &'static str {
25 match self {
26 Self::Inbox => "inbox",
27 Self::Sent => "sent",
28 Self::Outbox => "outbox",
29 Self::Deleted => "deleted",
30 }
31 }
32}
33
34impl<T: AsyncRead + AsyncWrite + Unpin> MapClient<T> {
35 /// Backs up to root if already inside a subfolder, then navigates `telecom` → `msg` and
36 /// lists that level. Use this instead of a bare [`MapClient::get_folder_listing`], which
37 /// lists only the current OBEX directory — on iOS that is the root unless the
38 /// `telecom/msg` SETPATHs are issued first.
39 ///
40 /// # Errors
41 ///
42 /// Returns [`MapError`] if a backup or forward SETPATH fails, the server returns a
43 /// non-OK response, or the listing XML is malformed.
44 pub async fn list_message_folders(&mut self) -> Result<FolderListing, MapError> {
45 self.reset_to_root().await?;
46 self.setpath("telecom").await?;
47 self.setpath("msg").await?;
48 self.get_folder_listing().await
49 }
50}