deltachat/imap/
session.rs1use std::collections::BTreeMap;
2use std::ops::{Deref, DerefMut};
3
4use anyhow::{Context as _, Result};
5use async_imap::types::Mailbox;
6use async_imap::Session as ImapSession;
7use futures::TryStreamExt;
8
9use crate::imap::capabilities::Capabilities;
10use crate::net::session::SessionStream;
11
12const PREFETCH_FLAGS: &str = "(UID INTERNALDATE RFC822.SIZE BODY.PEEK[HEADER.FIELDS (\
19 MESSAGE-ID \
20 DATE \
21 X-MICROSOFT-ORIGINAL-MESSAGE-ID \
22 FROM \
23 IN-REPLY-TO REFERENCES \
24 CHAT-VERSION \
25 AUTO-SUBMITTED \
26 AUTOCRYPT-SETUP-MESSAGE\
27 )])";
28
29#[derive(Debug)]
30pub(crate) struct Session {
31 pub(super) inner: ImapSession<Box<dyn SessionStream>>,
32
33 pub capabilities: Capabilities,
34
35 pub selected_folder: Option<String>,
37
38 pub selected_mailbox: Option<Mailbox>,
40
41 pub selected_folder_needs_expunge: bool,
42
43 pub new_mail: bool,
47}
48
49impl Deref for Session {
50 type Target = ImapSession<Box<dyn SessionStream>>;
51
52 fn deref(&self) -> &Self::Target {
53 &self.inner
54 }
55}
56
57impl DerefMut for Session {
58 fn deref_mut(&mut self) -> &mut Self::Target {
59 &mut self.inner
60 }
61}
62
63impl Session {
64 pub(crate) fn new(
65 inner: ImapSession<Box<dyn SessionStream>>,
66 capabilities: Capabilities,
67 ) -> Self {
68 Self {
69 inner,
70 capabilities,
71 selected_folder: None,
72 selected_mailbox: None,
73 selected_folder_needs_expunge: false,
74 new_mail: false,
75 }
76 }
77
78 pub fn can_idle(&self) -> bool {
79 self.capabilities.can_idle
80 }
81
82 pub fn can_move(&self) -> bool {
83 self.capabilities.can_move
84 }
85
86 pub fn can_check_quota(&self) -> bool {
87 self.capabilities.can_check_quota
88 }
89
90 pub fn can_condstore(&self) -> bool {
91 self.capabilities.can_condstore
92 }
93
94 pub fn can_metadata(&self) -> bool {
95 self.capabilities.can_metadata
96 }
97
98 pub fn can_push(&self) -> bool {
99 self.capabilities.can_push
100 }
101
102 pub fn is_chatmail(&self) -> bool {
104 self.capabilities.is_chatmail
105 }
106
107 pub async fn list_folders(&mut self) -> Result<Vec<async_imap::types::Name>> {
109 let list = self.list(Some(""), Some("*")).await?.try_collect().await?;
110 Ok(list)
111 }
112
113 pub(crate) async fn prefetch(
116 &mut self,
117 uid_next: u32,
118 ) -> Result<Vec<(u32, async_imap::types::Fetch)>> {
119 let set = format!("{uid_next}:*");
121 let mut list = self
122 .uid_fetch(set, PREFETCH_FLAGS)
123 .await
124 .context("IMAP could not fetch")?;
125
126 let mut msgs = BTreeMap::new();
127 while let Some(msg) = list.try_next().await? {
128 if let Some(msg_uid) = msg.uid {
129 if msg_uid >= uid_next {
137 msgs.insert((msg.internal_date(), msg_uid), msg);
138 }
139 }
140 }
141
142 Ok(msgs.into_iter().map(|((_, uid), msg)| (uid, msg)).collect())
143 }
144}