email/autoconfig/
config.rs1use std::time::Duration;
9
10use serde::Deserialize;
11
12#[derive(Debug, Deserialize)]
13#[serde(rename_all = "camelCase")]
14pub struct AutoConfig {
16 pub version: String,
17 pub email_provider: EmailProvider,
18 #[serde(rename = "oAuth2")]
19 pub oauth2: Option<OAuth2Config>,
20}
21
22impl AutoConfig {
23 pub fn is_gmail(&self) -> bool {
24 self.email_provider.id == "googlemail.com"
25 }
26
27 pub fn version(&self) -> &str {
29 &self.version
30 }
31
32 pub fn email_provider(&self) -> &EmailProvider {
35 &self.email_provider
36 }
37
38 pub fn oauth2(&self) -> Option<&OAuth2Config> {
41 self.oauth2.as_ref()
42 }
43}
44
45#[derive(Debug, Deserialize)]
46#[serde(rename_all = "camelCase")]
47pub struct OAuth2Config {
48 issuer: String,
49 scope: String,
50 #[serde(rename = "authURL")]
51 auth_url: String,
52 #[serde(rename = "tokenURL")]
53 token_url: String,
54}
55
56impl OAuth2Config {
57 pub fn issuer(&self) -> &str {
60 &self.issuer
61 }
62
63 pub fn scope(&self) -> Vec<&str> {
66 self.scope.split(' ').collect()
67 }
68
69 pub fn auth_url(&self) -> &str {
71 &self.auth_url
72 }
73
74 pub fn token_url(&self) -> &str {
76 &self.token_url
77 }
78}
79
80#[derive(Debug, Deserialize)]
81pub struct EmailProvider {
82 pub id: String,
83 #[serde(rename = "$value")]
84 pub properties: Vec<EmailProviderProperty>,
85}
86
87impl EmailProvider {
88 pub fn properties(&self) -> &Vec<EmailProviderProperty> {
92 &self.properties
93 }
94
95 pub fn id(&self) -> &str {
97 &self.id
98 }
99
100 pub fn domain(&self) -> Vec<&str> {
103 let mut domains: Vec<&str> = Vec::new();
104
105 for property in &self.properties {
106 if let EmailProviderProperty::Domain(domain) = property {
107 domains.push(domain)
108 }
109 }
110
111 domains
112 }
113
114 pub fn display_name(&self) -> Option<&str> {
116 for property in &self.properties {
117 if let EmailProviderProperty::DisplayName(display_name) = property {
118 return Some(display_name);
119 }
120 }
121
122 None
123 }
124
125 pub fn display_short_name(&self) -> Option<&str> {
127 for property in &self.properties {
128 if let EmailProviderProperty::DisplayShortName(short_name) = property {
129 return Some(short_name);
130 }
131 }
132
133 None
134 }
135
136 pub fn incoming_servers(&self) -> Vec<&Server> {
139 let mut servers: Vec<&Server> = Vec::new();
140
141 for property in &self.properties {
142 if let EmailProviderProperty::IncomingServer(server) = property {
143 servers.push(server)
144 }
145 }
146
147 servers
148 }
149
150 pub fn outgoing_servers(&self) -> Vec<&Server> {
153 let mut servers: Vec<&Server> = Vec::new();
154
155 for property in &self.properties {
156 if let EmailProviderProperty::OutgoingServer(server) = property {
157 servers.push(server)
158 }
159 }
160
161 servers
162 }
163
164 pub fn servers(&self) -> Vec<&Server> {
167 let mut servers: Vec<&Server> = Vec::new();
168
169 for property in &self.properties {
170 match property {
171 EmailProviderProperty::IncomingServer(server) => servers.push(server),
172 EmailProviderProperty::OutgoingServer(server) => servers.push(server),
173 _ => {}
174 }
175 }
176
177 servers
178 }
179
180 pub fn documentation(&self) -> Option<&Documentation> {
183 for property in &self.properties {
184 if let EmailProviderProperty::Documentation(documentation) = property {
185 return Some(documentation);
186 }
187 }
188
189 None
190 }
191}
192
193#[derive(Debug, Deserialize)]
194#[serde(rename_all = "camelCase")]
195pub enum EmailProviderProperty {
196 Domain(String),
197 DisplayName(String),
198 DisplayShortName(String),
199 IncomingServer(Server),
200 OutgoingServer(Server),
201 Documentation(Documentation),
202}
203
204#[derive(Debug, Deserialize)]
205pub struct Server {
206 pub r#type: ServerType,
207 #[serde(rename = "$value")]
208 pub properties: Vec<ServerProperty>,
209}
210
211impl Server {
212 pub fn properties(&self) -> &Vec<ServerProperty> {
215 &self.properties
216 }
217
218 pub fn server_type(&self) -> &ServerType {
220 &self.r#type
221 }
222
223 pub fn hostname(&self) -> Option<&str> {
225 for property in &self.properties {
226 if let ServerProperty::Hostname(hostname) = property {
227 return Some(hostname);
228 }
229 }
230
231 None
232 }
233
234 pub fn port(&self) -> Option<&u16> {
236 for property in &self.properties {
237 if let ServerProperty::Port(port) = property {
238 return Some(port);
239 }
240 }
241
242 None
243 }
244
245 pub fn security_type(&self) -> Option<&SecurityType> {
247 for property in &self.properties {
248 if let ServerProperty::SocketType(socket_type) = property {
249 return Some(socket_type);
250 }
251 }
252
253 None
254 }
255
256 pub fn authentication_type(&self) -> Vec<&AuthenticationType> {
259 let mut types: Vec<&AuthenticationType> = Vec::new();
260
261 for property in &self.properties {
262 if let ServerProperty::Authentication(authentication_type) = property {
263 types.push(authentication_type)
264 }
265 }
266
267 types
268 }
269
270 pub fn username(&self) -> Option<&str> {
272 for property in &self.properties {
273 if let ServerProperty::Username(username) = property {
274 return Some(username);
275 }
276 }
277
278 None
279 }
280
281 pub fn password(&self) -> Option<&str> {
283 for property in &self.properties {
284 if let ServerProperty::Password(password) = property {
285 return Some(password);
286 }
287 }
288
289 None
290 }
291}
292
293#[derive(Debug, Deserialize)]
294#[serde(rename_all = "camelCase")]
295pub enum ServerProperty {
296 Hostname(String),
297 Port(u16),
298 SocketType(SecurityType),
299 Authentication(AuthenticationType),
300 OwaURL(String),
301 EwsURL(String),
302 UseGlobalPreferredServer(bool),
303 Pop3(Pop3Config),
304 Username(String),
305 Password(String),
306}
307
308#[derive(Debug, Deserialize)]
309pub enum SecurityType {
310 #[serde(rename = "plain")]
311 Plain,
312 #[serde(rename = "STARTTLS")]
313 Starttls,
314 #[serde(rename = "SSL")]
315 Tls,
316}
317
318#[derive(Debug, Deserialize)]
319#[serde(rename_all = "camelCase")]
320pub enum ServerType {
321 Exchange,
322 #[cfg(feature = "imap")]
323 Imap,
324 #[cfg(feature = "smtp")]
325 Smtp,
326 #[serde(other)]
327 Unknown,
328}
329
330#[derive(Debug, Deserialize)]
331pub enum AuthenticationType {
332 #[serde(rename = "password-cleartext")]
333 PasswordCleartext,
334 #[serde(rename = "password-encrypted")]
335 PasswordEncrypted,
336 #[serde(rename = "NTLM")]
337 Ntlm,
338 #[serde(rename = "GSAPI")]
339 GsApi,
340 #[serde(rename = "client-IP-address")]
341 ClientIPAddress,
342 #[serde(rename = "TLS-client-cert")]
343 TlsClientCert,
344 OAuth2,
345 #[serde(rename = "None")]
346 None,
347}
348
349#[derive(Debug, Deserialize)]
350#[serde(rename_all = "camelCase")]
351pub struct Pop3Config {
352 leave_messages_on_server: bool,
353 download_on_biff: Option<bool>,
354 days_to_leave_messages_on_server: Option<u64>,
355 check_interval: Option<CheckInterval>,
356}
357
358impl Pop3Config {
359 pub fn leave_messages_on_server(&self) -> &bool {
362 &self.leave_messages_on_server
363 }
364
365 pub fn download_on_biff(&self) -> Option<&bool> {
366 self.download_on_biff.as_ref()
367 }
368
369 pub fn time_to_leave_messages_on_server(&self) -> Option<Duration> {
371 self.days_to_leave_messages_on_server
372 .as_ref()
373 .map(|days| Duration::from_secs(days * 24 * 60 * 60))
374 }
375
376 pub fn check_interval(&self) -> Option<Duration> {
379 match self.check_interval.as_ref() {
380 Some(interval) => {
381 if let Some(minutes) = interval.minutes {
382 return Some(Duration::from_secs(minutes * 60));
383 };
384
385 None
386 }
387 None => None,
388 }
389 }
390}
391
392#[derive(Debug, Deserialize)]
393struct CheckInterval {
394 minutes: Option<u64>,
395}
396
397#[derive(Debug, Deserialize)]
398pub struct Documentation {
399 url: String,
400 #[serde(rename = "$value")]
401 properties: Vec<DocumentationDescription>,
402}
403
404impl Documentation {
405 pub fn url(&self) -> &str {
407 &self.url
408 }
409
410 pub fn properties(&self) -> &Vec<DocumentationDescription> {
412 &self.properties
413 }
414}
415
416#[derive(Debug, Deserialize)]
417pub struct DocumentationDescription {
418 lang: Option<String>,
419 #[serde(rename = "$value")]
420 description: String,
421}
422
423impl DocumentationDescription {
424 pub fn language(&self) -> Option<&str> {
426 self.lang.as_deref()
427 }
428
429 pub fn description(&self) -> &str {
431 &self.description
432 }
433}