dust_mail/client/
protocol.rs

1use async_trait::async_trait;
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use crate::{error::Result, tree::Node};
7
8use super::{
9    connection::ConnectionSecurity,
10    incoming::types::{
11        mailbox::Mailbox,
12        message::{Message, Preview},
13    },
14    outgoing::types::sendable::SendableMessage,
15};
16
17#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
18pub struct RemoteServer {
19    server: String,
20    port: u16,
21    security: ConnectionSecurity,
22}
23
24impl RemoteServer {
25    pub fn new<Server: Into<String>>(
26        server: Server,
27        port: u16,
28        security: ConnectionSecurity,
29    ) -> Self {
30        Self {
31            server: server.into(),
32            port,
33            security,
34        }
35    }
36
37    pub fn security(&self) -> &ConnectionSecurity {
38        &self.security
39    }
40
41    pub fn domain(&self) -> &str {
42        self.server.as_ref()
43    }
44
45    pub fn port(&self) -> u16 {
46        self.port
47    }
48}
49
50#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
51pub enum Credentials {
52    Password { username: String, password: String },
53    OAuth { username: String, token: String },
54}
55
56impl Credentials {
57    pub fn username(&self) -> &str {
58        match &self {
59            Credentials::OAuth { username, .. } => username,
60            Credentials::Password { username, .. } => username,
61        }
62    }
63}
64
65impl Credentials {
66    pub fn password<U: Into<String>, P: Into<String>>(username: U, password: P) -> Self {
67        Credentials::Password {
68            username: username.into(),
69            password: password.into(),
70        }
71    }
72
73    pub fn oauth<U: Into<String>, T: Into<String>>(username: U, token: T) -> Self {
74        Credentials::OAuth {
75            username: username.into(),
76            token: token.into(),
77        }
78    }
79}
80
81pub trait ServerCredentials {
82    fn credentials(&self) -> &Credentials;
83}
84
85#[cfg(feature = "smtp")]
86#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
87pub struct SmtpCredentials {
88    server: RemoteServer,
89    credentials: Credentials,
90}
91
92#[cfg(feature = "smtp")]
93impl SmtpCredentials {
94    pub fn new(server: RemoteServer, credentials: Credentials) -> Self {
95        Self {
96            server,
97            credentials,
98        }
99    }
100
101    pub fn server(&self) -> &RemoteServer {
102        &self.server
103    }
104}
105
106#[cfg(feature = "smtp")]
107impl ServerCredentials for SmtpCredentials {
108    fn credentials(&self) -> &Credentials {
109        &self.credentials
110    }
111}
112
113#[cfg(feature = "imap")]
114#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
115pub struct ImapCredentials {
116    server: RemoteServer,
117    credentials: Credentials,
118}
119
120#[cfg(feature = "imap")]
121impl ImapCredentials {
122    pub fn new(server: RemoteServer, credentials: Credentials) -> Self {
123        Self {
124            server,
125            credentials,
126        }
127    }
128
129    pub fn server(&self) -> &RemoteServer {
130        &self.server
131    }
132}
133
134#[cfg(feature = "imap")]
135impl ServerCredentials for ImapCredentials {
136    fn credentials(&self) -> &Credentials {
137        &self.credentials
138    }
139}
140
141#[cfg(feature = "pop")]
142#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
143pub struct PopCredentials {
144    server: RemoteServer,
145    credentials: Credentials,
146}
147
148#[cfg(feature = "pop")]
149impl PopCredentials {
150    pub fn new(server: RemoteServer, credentials: Credentials) -> Self {
151        Self {
152            server,
153            credentials,
154        }
155    }
156
157    pub fn server(&self) -> &RemoteServer {
158        &self.server
159    }
160}
161
162#[cfg(feature = "pop")]
163impl ServerCredentials for PopCredentials {
164    fn credentials(&self) -> &Credentials {
165        &self.credentials
166    }
167}
168
169#[async_trait]
170pub trait IncomingProtocol {
171    async fn send_keep_alive(&mut self) -> Result<()>;
172
173    fn should_keep_alive(&self) -> bool;
174
175    async fn get_mailbox_list(&mut self) -> Result<Node<Mailbox>>;
176
177    async fn get_mailbox(&mut self, mailbox_id: &str) -> Result<Node<Mailbox>>;
178
179    async fn rename_mailbox(&mut self, old_name: &str, new_name: &str) -> Result<()>;
180
181    async fn create_mailbox(&mut self, name: &str) -> Result<()>;
182
183    async fn delete_mailbox(&mut self, box_id: &str) -> Result<()>;
184
185    async fn get_messages(
186        &mut self,
187        box_id: &str,
188        start: usize,
189        end: usize,
190    ) -> Result<Vec<Preview>>;
191
192    async fn get_message(&mut self, box_id: &str, message_id: &str) -> Result<Message>;
193
194    async fn logout(&mut self) -> Result<()>;
195}
196
197#[async_trait]
198pub trait OutgoingProtocol {
199    async fn send_message(&mut self, message: SendableMessage) -> Result<()>;
200}
201
202#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
203pub enum IncomingEmailProtocol {
204    #[cfg(feature = "imap")]
205    Imap(ImapCredentials),
206
207    #[cfg(feature = "pop")]
208    Pop(PopCredentials),
209
210    #[cfg(feature = "maildir")]
211    Maildir(std::path::PathBuf),
212}
213
214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
215pub enum OutgoingEmailProtocol {
216    #[cfg(feature = "smtp")]
217    Smtp(SmtpCredentials),
218}
219
220pub struct IncomingConfig {}
221
222impl Default for IncomingConfig {
223    fn default() -> Self {
224        let config = Self::new();
225
226        config
227    }
228}
229
230impl IncomingConfig {
231    pub fn new() -> Self {
232        Self {}
233    }
234}