ms_autodiscover/types/
pox.rs

1use std::{io::Read, time::Duration};
2
3use serde::{Deserialize, Serialize};
4
5use super::response::{AutodiscoverResponse, AutodiscoverResult, RedirectType};
6
7use crate::{
8    constants::{DEFAULT_MICROSOFT_REQUEST_SCHEMA, DEFAULT_MICROSOFT_RESPONSE_SCHEMA},
9    error::Result,
10};
11
12#[derive(Serialize, Deserialize, Debug)]
13#[serde(rename_all = "PascalCase")]
14pub struct Error {
15    code: usize,
16    message: String,
17    debug_data: String,
18}
19
20impl Error {
21    pub fn code(&self) -> usize {
22        self.code
23    }
24
25    pub fn message(&self) -> &str {
26        self.message.as_ref()
27    }
28
29    pub fn debug_data(&self) -> &str {
30        self.debug_data.as_ref()
31    }
32}
33
34#[derive(Serialize, Deserialize, Debug)]
35/// Config follows Microsofts spec: https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/autodiscover-pox
36pub struct Autodiscover {
37    #[serde(rename(serialize = "@xmlns"), skip_deserializing)]
38    xmlns: String,
39    #[serde(rename = "$value")]
40    properties: Vec<ConfigProperty>,
41}
42
43impl Autodiscover {
44    pub fn create_request<E: Into<String>>(email_address: E) -> Self {
45        let req = Request::new(email_address.into());
46
47        let properties = vec![ConfigProperty::Request(req)];
48
49        Self {
50            properties,
51            xmlns: DEFAULT_MICROSOFT_REQUEST_SCHEMA.to_string(),
52        }
53    }
54
55    pub fn from_xml<R: Read>(xml: R) -> Result<Self> {
56        let config: Self = serde_xml_rs::from_reader(xml)?;
57
58        // info!("{:?}", config);
59
60        Ok(config)
61    }
62
63    fn into_response(self) -> Option<Response> {
64        for property in self.properties {
65            match property {
66                ConfigProperty::Response(response) => return Some(response),
67                _ => {}
68            }
69        }
70
71        None
72    }
73}
74
75#[derive(Serialize, Deserialize, Debug)]
76#[serde(rename_all = "PascalCase")]
77pub enum ConfigProperty {
78    Response(Response),
79    Request(Request),
80}
81
82#[derive(Serialize, Deserialize, Debug)]
83#[serde(rename_all = "PascalCase")]
84pub struct Request {
85    #[serde(rename = "$value")]
86    properties: Vec<RequestProperty>,
87}
88
89impl Request {
90    pub fn new(email_address: String) -> Self {
91        let properties = vec![
92            RequestProperty::EMailAddress(email_address),
93            RequestProperty::AcceptableResponseSchema(
94                DEFAULT_MICROSOFT_RESPONSE_SCHEMA.to_string(),
95            ),
96        ];
97
98        Self { properties }
99    }
100}
101
102#[derive(Serialize, Deserialize, Debug)]
103#[serde(rename_all = "PascalCase")]
104pub enum RequestProperty {
105    EMailAddress(String),
106    AcceptableResponseSchema(String),
107    LegacyDN(LegacyDN),
108}
109
110#[derive(Serialize, Deserialize, Debug)]
111#[serde(rename_all = "PascalCase")]
112pub struct Response {
113    #[serde(rename = "$value")]
114    properties: Vec<ResponseProperty>,
115}
116
117impl Response {
118    pub fn account(&self) -> Vec<&Account> {
119        let mut accounts = Vec::new();
120
121        for property in &self.properties {
122            match property {
123                ResponseProperty::Account(account) => accounts.push(account),
124                _ => {}
125            }
126        }
127
128        accounts
129    }
130
131    pub fn user(&self) -> Option<&User> {
132        for property in &self.properties {
133            match property {
134                ResponseProperty::User(user) => return Some(user),
135                _ => {}
136            }
137        }
138
139        None
140    }
141
142    pub fn error(&self) -> Option<&Error> {
143        for property in &self.properties {
144            match property {
145                ResponseProperty::Error(error) => return Some(error),
146                _ => {}
147            }
148        }
149
150        None
151    }
152}
153
154#[derive(Serialize, Deserialize, Debug)]
155#[serde(rename_all = "PascalCase")]
156pub enum ResponseProperty {
157    User(User),
158    Account(Account),
159    Error(Error),
160}
161
162#[derive(Serialize, Deserialize, Debug)]
163#[serde(rename_all = "PascalCase")]
164pub struct User {
165    #[serde(rename = "$value")]
166    properties: Vec<UserProperty>,
167}
168
169impl User {
170    /// Represents the user's display name.
171    ///
172    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/displayname-string
173    pub fn display_name(&self) -> Option<&str> {
174        for property in &self.properties {
175            match property {
176                UserProperty::DisplayName(name) => return Some(name),
177                _ => {}
178            }
179        }
180
181        None
182    }
183
184    /// Identifies a user's mailbox by legacy distinguished name.
185    ///
186    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/legacydn-pox
187    pub fn legacy_dn(&self) -> Option<&str> {
188        for property in &self.properties {
189            match property {
190                UserProperty::LegacyDN(name) => return Some(&name.0),
191                _ => {}
192            }
193        }
194
195        None
196    }
197
198    /// Uniquely identifies the Exchange forest.
199    ///
200    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/deploymentid-pox
201    pub fn deployment_id(&self) -> Option<&str> {
202        for property in &self.properties {
203            match property {
204                UserProperty::DeploymentId(id) => return Some(id),
205                _ => {}
206            }
207        }
208
209        None
210    }
211
212    /// Contains the user's SMTP address that is used for the Autodiscover process.
213    ///
214    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/autodiscoversmtpaddress-pox
215    pub fn autodiscover_smtp_address(&self) -> Option<&str> {
216        for property in &self.properties {
217            match property {
218                UserProperty::AutoDiscoverSMTPAddress(addr) => return Some(addr),
219                _ => {}
220            }
221        }
222
223        None
224    }
225}
226
227#[derive(Serialize, Deserialize, Debug)]
228pub enum UserProperty {
229    DisplayName(String),
230    LegacyDN(LegacyDN),
231    DeploymentId(String),
232    AutoDiscoverSMTPAddress(String),
233}
234
235#[derive(Serialize, Deserialize, Debug)]
236pub struct LegacyDN(String);
237
238#[derive(Serialize, Deserialize, Debug)]
239#[serde(rename_all = "PascalCase")]
240pub struct Account {
241    #[serde(rename = "$value")]
242    properties: Vec<AccountProperty>,
243}
244
245impl Account {
246    /// Represents the account type.
247    ///
248    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/accounttype-pox
249    pub fn account_type(&self) -> Option<&AccountType> {
250        for property in &self.properties {
251            match property {
252                AccountProperty::AccountType(r#type) => return Some(r#type),
253                _ => {}
254            }
255        }
256
257        None
258    }
259
260    /// Provides information that is used to determine whether another Autodiscover request is required to return the user configuration information.
261    ///
262    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/action-pox
263    pub fn action_type(&self) -> Option<&Action> {
264        for property in &self.properties {
265            match property {
266                AccountProperty::Action(action) => return Some(action),
267                _ => {}
268            }
269        }
270
271        None
272    }
273
274    /// Indicates whether the user's mailbox is hosted in Exchange Online or Exchange Online as part of Office 365.
275    ///
276    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/microsoftonline-pox
277    pub fn microsoft_online(&self) -> bool {
278        for property in &self.properties {
279            match property {
280                AccountProperty::MicrosoftOnline(online) => return *online,
281                _ => {}
282            }
283        }
284
285        false
286    }
287
288    /// Specifies the email address that should be used for a subsequent Autodiscover request.
289    ///
290    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/redirectaddr-pox
291    pub fn redirect_addr(&self) -> Option<&str> {
292        for property in &self.properties {
293            match property {
294                AccountProperty::RedirectAddr(addr) => return Some(addr),
295                _ => {}
296            }
297        }
298
299        None
300    }
301
302    /// Contains the URL of the computer that is running Exchange Server that has the Client Access server role installed that should be used to obtain Autodiscover settings.
303    ///
304    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/redirecturl-pox
305    pub fn redirect_url(&self) -> Option<&str> {
306        for property in &self.properties {
307            match property {
308                AccountProperty::RedirectUrl(url) => return Some(url),
309                _ => {}
310            }
311        }
312
313        None
314    }
315
316    /// Contains the path of an image that is used to brand the configuration experience.
317    ///
318    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/image-pox
319    pub fn image(&self) -> Option<&str> {
320        for property in &self.properties {
321            match property {
322                AccountProperty::Image(path) => return Some(path),
323                _ => {}
324            }
325        }
326
327        None
328    }
329
330    /// Contains the URL of the home page of the Internet service provider (ISP).
331    ///
332    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/servicehome-pox
333    pub fn service_home(&self) -> Option<&str> {
334        for property in &self.properties {
335            match property {
336                AccountProperty::ServiceHome(url) => return Some(url),
337                _ => {}
338            }
339        }
340
341        None
342    }
343
344    /// Contains the specifications for connecting a client to the Client Access server
345    ///
346    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/protocol-pox
347    pub fn protocol(&self) -> Option<&Protocol> {
348        for property in &self.properties {
349            match property {
350                AccountProperty::Protocol(proto) => return Some(proto),
351                _ => {}
352            }
353        }
354
355        None
356    }
357
358    /// Contains information that clients can use to send an Autodiscover request to discover public folder information for the user.
359    ///
360    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/publicfolderinformation-pox
361    pub fn public_folder_information(&self) -> Option<&PublicFolderInformation> {
362        for property in &self.properties {
363            match property {
364                AccountProperty::PublicFolderInformation(info) => return Some(info),
365                _ => {}
366            }
367        }
368
369        None
370    }
371
372    /// Contains an Autodiscover error response.
373    ///
374    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/error-pox
375    pub fn error(&self) -> Option<&Error> {
376        for property in &self.properties {
377            match property {
378                AccountProperty::Error(error) => return Some(error),
379                _ => {}
380            }
381        }
382
383        None
384    }
385}
386
387#[derive(Serialize, Deserialize, Debug)]
388#[serde(rename_all = "PascalCase")]
389pub enum AccountProperty {
390    AccountType(AccountType),
391    Action(Action),
392    MicrosoftOnline(bool),
393    RedirectUrl(String),
394    RedirectAddr(String),
395    Image(String),
396    ServiceHome(String),
397    Protocol(Protocol),
398    PublicFolderInformation(PublicFolderInformation),
399    Error(Error),
400}
401
402#[derive(Serialize, Deserialize, Debug)]
403#[serde(rename_all = "camelCase")]
404pub enum AccountType {
405    Email,
406}
407
408#[derive(Serialize, Deserialize, Debug)]
409#[serde(rename_all = "camelCase")]
410pub enum Action {
411    RedirectUrl,
412    RedirectAddr,
413    Settings,
414}
415
416#[derive(Serialize, Deserialize, Debug)]
417#[serde(rename_all = "PascalCase")]
418pub struct Protocol {
419    #[serde(rename = "$value")]
420    properties: Vec<ProtocolProperty>,
421}
422
423impl Protocol {
424    /// Identifies the type of the configured mail account.
425    ///
426    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/type-pox
427    pub fn r#type(&self) -> Option<&Type> {
428        for property in &self.properties {
429            match property {
430                ProtocolProperty::Type(r#type) => return Some(r#type),
431                _ => {}
432            }
433        }
434
435        None
436    }
437
438    /// Contains a collection of URLs that a client can use to connect to Exchange from inside the organization's network.
439    ///
440    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/internal-pox
441    pub fn internal(&self) -> Option<&Connectivity> {
442        for property in &self.properties {
443            match property {
444                ProtocolProperty::Internal(internal) => return Some(internal),
445                _ => {}
446            }
447        }
448
449        None
450    }
451
452    /// Contains a collection of URLs that a client can use to connect to Exchange from outside of the organization's network.
453    ///
454    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/external-pox
455    pub fn external(&self) -> Option<&Connectivity> {
456        for property in &self.properties {
457            match property {
458                ProtocolProperty::External(external) => return Some(external),
459                _ => {}
460            }
461        }
462
463        None
464    }
465
466    /// Specifies the Time to Live, during which the settings remain valid.
467    ///
468    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/ttl-pox
469    pub fn ttl(&self) -> Duration {
470        for property in &self.properties {
471            match property {
472                ProtocolProperty::Ttl(ttl) => return Duration::from_secs(ttl * 60 * 60),
473                _ => {}
474            }
475        }
476
477        Duration::from_secs(60 * 60)
478    }
479
480    /// Specifies the name of the mail server.
481    ///
482    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/server-pox
483    pub fn server(&self) -> Option<&str> {
484        for property in &self.properties {
485            match property {
486                ProtocolProperty::Server(server) => return Some(server),
487                _ => {}
488            }
489        }
490
491        None
492    }
493
494    /// Specifies the Exchange Server distinguished name.
495    ///
496    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/serverdn-pox
497    pub fn server_dn(&self) -> Option<&str> {
498        for property in &self.properties {
499            match property {
500                ProtocolProperty::Server(server) => return Some(server),
501                _ => {}
502            }
503        }
504
505        None
506    }
507
508    /// Represents the Exchange Server version number.
509    ///
510    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/serverversion-pox
511    pub fn server_version(&self) -> Option<&str> {
512        for property in &self.properties {
513            match property {
514                ProtocolProperty::ServerVersion(version) => return Some(version),
515                _ => {}
516            }
517        }
518
519        None
520    }
521
522    /// Contains the fully-qualified domain name (FQDN) of the public folder server for the user.
523    ///
524    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/publicfolderserver-pox
525    pub fn public_folder_server(&self) -> Option<&str> {
526        for property in &self.properties {
527            match property {
528                ProtocolProperty::PublicFolderServer(server) => return Some(server),
529                _ => {}
530            }
531        }
532
533        None
534    }
535
536    /// Specifies the port that is used to connect to the store.
537    ///
538    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/port-pox
539    pub fn port(&self) -> Option<&u16> {
540        for property in &self.properties {
541            match property {
542                ProtocolProperty::Port(port) => return Some(port),
543                _ => {}
544            }
545        }
546
547        None
548    }
549
550    /// Specifies the URL of the best endpoint instance for Exchange Web Services (EWS) for a mail-enabled user.
551    ///
552    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/ewsurl-pox
553    pub fn ews_url(&self) -> Option<&str> {
554        for property in &self.properties {
555            match property {
556                ProtocolProperty::EwsUrl(url) => return Some(url),
557                _ => {}
558            }
559        }
560
561        None
562    }
563
564    /// Specifies the user's logon name.
565    ///
566    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/loginname-pox
567    pub fn login_name(&self) -> Option<&str> {
568        for property in &self.properties {
569            match property {
570                ProtocolProperty::LoginName(name) => return Some(name),
571                _ => {}
572            }
573        }
574
575        None
576    }
577
578    /// Indicates whether the domain is required for authentication.
579    ///
580    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/domainrequired-pox
581    pub fn domain_required(&self) -> Option<bool> {
582        for property in &self.properties {
583            match property {
584                ProtocolProperty::DomainRequired(required) => return Some(required.bool()),
585                _ => {}
586            }
587        }
588
589        None
590    }
591
592    /// Specifies the user's domain.
593    ///
594    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/domainname-pox
595    pub fn domain_name(&self) -> Option<&str> {
596        for property in &self.properties {
597            match property {
598                ProtocolProperty::DomainName(name) => return Some(name),
599                _ => {}
600            }
601        }
602
603        None
604    }
605
606    /// Indicates whether secure password authentication is required.
607    ///
608    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/spa-pox
609    pub fn spa(&self) -> bool {
610        for property in &self.properties {
611            match property {
612                ProtocolProperty::Spa(spa) => return spa.bool(),
613                _ => {}
614            }
615        }
616
617        true
618    }
619
620    /// Specifies the authentication scheme that is used when authenticating against the Exchange 2007 computer that has the Mailbox server role installed.
621    ///
622    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/authpackage-pox
623    pub fn auth_package(&self) -> Option<&AuthPackage> {
624        for property in &self.properties {
625            match property {
626                ProtocolProperty::AuthPackage(package) => return Some(package),
627                _ => {}
628            }
629        }
630
631        None
632    }
633
634    /// Specifies the Secure Sockets Layer (SSL) certificate principal name that is required to connect to the Microsoft Exchange organization by using SSL.
635    ///
636    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/certprincipalname-pox
637    pub fn cert_principal_name(&self) -> &str {
638        for property in &self.properties {
639            match property {
640                ProtocolProperty::CertPrincipalName(name) => return name,
641                _ => {}
642            }
643        }
644
645        "msstd:SERVER"
646    }
647
648    /// Specifies whether secure logon is needed.
649    ///
650    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/ssl-pox
651    pub fn ssl(&self) -> bool {
652        for property in &self.properties {
653            match property {
654                ProtocolProperty::Ssl(ssl) => return ssl.bool(),
655                _ => {}
656            }
657        }
658
659        true
660    }
661
662    /// Indicates whether the authentication information that is provided for a POP3 type of account is also used for Simple Mail Transfer Protocol (SMTP).
663    ///
664    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/usepopauth-pox
665    pub fn use_pop_auth(&self) -> Option<bool> {
666        for property in &self.properties {
667            match property {
668                ProtocolProperty::UsePOPAuth(use_pop) => return Some(use_pop.bool()),
669                _ => {}
670            }
671        }
672
673        None
674    }
675
676    /// Specifies whether the SMTP server requires that e-mail be downloaded before it sends e-mail by using the SMTP server.
677    ///
678    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/smtplast-pox
679    pub fn smtp_last(&self) -> bool {
680        for property in &self.properties {
681            match property {
682                ProtocolProperty::SMTPLast(last) => return last.bool(),
683                _ => {}
684            }
685        }
686
687        false
688    }
689
690    /// Contains the criteria that are used to determine whether the client computer is on a network that meets the Internet Service Provider's requirements to connect to the server.
691    ///
692    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/networkrequirements-pox
693    pub fn network_requirements(&self) -> Option<&NetworkRequirements> {
694        for property in &self.properties {
695            match property {
696                ProtocolProperty::NetworkRequirements(requirements) => return Some(requirements),
697                _ => {}
698            }
699        }
700
701        None
702    }
703
704    /// Contains the specifications for connecting a client to the address book server by using the MAPI/HTTP protocol. This element is only present if the Type attribute on the Protocol element is present and set to "mapiHttp". The AddressBook element is applicable to clients that implement the MAPI/HTTP protocol and target Exchange Online and versions of Exchange starting with 15.00.0847.032.
705    ///
706    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/addressbook-pox
707    pub fn address_book(&self) -> Option<&AddressBook> {
708        for property in &self.properties {
709            match property {
710                ProtocolProperty::AddressBook(address_book) => return Some(address_book),
711                _ => {}
712            }
713        }
714
715        None
716    }
717
718    /// Contains the specifications for connecting a client to the user's mailbox by using the MAPI/HTTP protocol. This element is only present if the Type attribute on the Protocol element is present and set to "mapiHttp". The MailStore element is applicable to clients that implement the MAPI/HTTP protocol and target Exchange Online and versions of Exchange starting with 15.00.0847.032.
719    ///
720    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/mailstore-pox
721    pub fn mail_store(&self) -> Option<&MailStore> {
722        for property in &self.properties {
723            match property {
724                ProtocolProperty::MailStore(store) => return Some(store),
725                _ => {}
726            }
727        }
728
729        None
730    }
731}
732
733#[derive(Serialize, Deserialize, Debug)]
734#[serde(rename_all = "PascalCase")]
735pub enum ProtocolProperty {
736    Type(Type),
737    Internal(Connectivity),
738    External(Connectivity),
739    #[serde(rename = "TTL")]
740    Ttl(u64),
741    Server(String),
742    ServerDN(String),
743    ServerVersion(String),
744    MdbDN(String),
745    PublicFolderServer(String),
746    Port(u16),
747    DirectoryPort(u16),
748    ReferralPort(u16),
749    ASUrl(String),
750    EwsUrl(String),
751    SharingUrl(String),
752    EmwsUrl(String),
753    OOFUrl(String),
754    OABUrl(String),
755    UMUrl(String),
756    EwsPartnerUrl(String),
757    LoginName(String),
758    DomainRequired(OnOff),
759    DomainName(String),
760    #[serde(rename = "SPA")]
761    Spa(OnOff),
762    AuthPackage(AuthPackage),
763    CertPrincipalName(String),
764    #[serde(rename = "SSL")]
765    Ssl(OnOff),
766    AuthRequired(OnOff),
767    UsePOPAuth(OnOff),
768    SMTPLast(OnOff),
769    NetworkRequirements(NetworkRequirements),
770    AddressBook(AddressBook),
771    MailStore(MailStore),
772    Encryption(Encryption),
773}
774
775#[derive(Serialize, Deserialize, Debug)]
776#[serde(rename_all = "UPPERCASE")]
777pub enum Type {
778    Smtp,
779    Imap,
780    Exch,
781    ExHttp,
782    Expr,
783    Web,
784}
785
786#[derive(Serialize, Deserialize, Debug)]
787#[serde(rename_all = "lowercase")]
788pub enum OnOff {
789    On,
790    Off,
791}
792
793impl OnOff {
794    pub fn bool(&self) -> bool {
795        match self {
796            OnOff::On => true,
797            OnOff::Off => false,
798        }
799    }
800}
801
802#[derive(Serialize, Deserialize, Debug)]
803#[serde(rename_all = "PascalCase")]
804pub struct Connectivity {
805    #[serde(rename = "OWAUrl")]
806    owa_url: String,
807    protocol: Protocol,
808}
809
810impl Connectivity {
811    /// Describes the URL and authentication schema that is used to access a particular computer that is running Microsoft Exchange Server that has the Client Access server role installed that hosts Outlook Web Access.
812    ///
813    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/owaurl-pox
814    pub fn owa_url(&self) -> &str {
815        self.owa_url.as_ref()
816    }
817
818    /// Contains the specifications for connecting a client to the computer that is running Microsoft Exchange Server that has the Client Access server role installed. This Protocol element has only two child elements: a Type (POX) element specifying the connection protocol, and an ASUrl (POX) element, specifying the EWS endpoint for the Availability web service.
819    ///
820    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/protocol-pox
821    pub fn protocol(&self) -> &Protocol {
822        &self.protocol
823    }
824}
825
826#[derive(Serialize, Deserialize, Debug)]
827pub enum Encryption {
828    #[serde(rename = "TLS")]
829    Tls,
830    #[serde(rename = "SSL")]
831    Ssl,
832}
833
834#[derive(Serialize, Deserialize, Debug)]
835#[serde(rename_all = "lowercase")]
836pub enum AuthPackage {
837    Basic,
838    Kerb,
839    KerbNtlm,
840    Ntlm,
841    Certificate,
842    Negotiate,
843    Nego2,
844}
845
846#[derive(Serialize, Deserialize, Debug)]
847#[serde(rename_all = "PascalCase")]
848pub struct PublicFolderInformation {
849    smtp_address: String,
850}
851
852impl PublicFolderInformation {
853    /// Contains the SMTP address assigned to the public folder message store configured for the user. This SMTP address can be used in the EMailAddress (POX) element of an Autodiscover request to discover public folder settings.
854    ///
855    /// https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/smtpaddress-pox
856    pub fn smtp_address(&self) -> &str {
857        self.smtp_address.as_ref()
858    }
859}
860
861#[derive(Serialize, Deserialize, Debug)]
862#[serde(rename_all = "PascalCase")]
863pub struct AddressBook {
864    external_url: String,
865    interal_url: String,
866}
867
868#[derive(Serialize, Deserialize, Debug)]
869#[serde(rename_all = "PascalCase")]
870pub struct MailStore {
871    external_url: String,
872    interal_url: String,
873}
874
875#[derive(Serialize, Deserialize, Debug)]
876pub struct NetworkRequirements {
877    #[serde(rename = "Ipv4Start")]
878    pub ipv4_start: String,
879    #[serde(rename = "Ipv4End")]
880    pub ipv4_end: String,
881    #[serde(rename = "Ipv6Start")]
882    pub ipv6_start: String,
883    #[serde(rename = "Ipv6end")]
884    pub ipv6_end: String,
885}
886
887impl Into<AutodiscoverResult> for Autodiscover {
888    fn into(self) -> AutodiscoverResult {
889        if let Some(response) = self.into_response() {
890            for account in response.account() {
891                if let Some(action_type) = account.action_type() {
892                    let redirect_type = match action_type {
893                        Action::RedirectAddr => match account.redirect_addr() {
894                            Some(addr) => Some(RedirectType::Email(addr.to_string())),
895                            None => {
896                                return AutodiscoverResult::error(
897                                    "Missing redirect address when it should be available",
898                                )
899                            }
900                        },
901                        Action::RedirectUrl => match account.redirect_url() {
902                            Some(url) => Some(RedirectType::Url(url.to_string())),
903                            None => {
904                                return AutodiscoverResult::error(
905                                    "Missing redirect url when it should be available",
906                                )
907                            }
908                        },
909                        _ => None,
910                    };
911
912                    if let Some(redirect) = redirect_type {
913                        return AutodiscoverResult::Redirect(redirect);
914                    }
915                }
916
917                if let Some(error) = account.error() {
918                    return AutodiscoverResult::Error(error.into());
919                }
920            }
921
922            if let Some(error) = response.error() {
923                return AutodiscoverResult::Error(error.into());
924            }
925
926            return AutodiscoverResult::Ok(AutodiscoverResponse::Pox(response));
927        }
928
929        AutodiscoverResult::error("Config did not contain a response value")
930    }
931}