Module exchangelib.autodiscover.properties
Expand source code
from ..errors import AutoDiscoverFailed, ErrorNonExistentMailbox
from ..fields import (
BooleanField,
BuildField,
Choice,
ChoiceField,
EmailAddressField,
EWSElementField,
IntegerField,
OnOffField,
ProtocolListField,
TextField,
)
from ..properties import EWSElement
from ..transport import BASIC, CBA, DEFAULT_ENCODING, GSSAPI, NOAUTH, NTLM, SSPI
from ..util import AUTODISCOVER_BASE_NS, AUTODISCOVER_REQUEST_NS
from ..util import AUTODISCOVER_RESPONSE_NS as RNS
from ..util import ParseError, add_xml_child, create_element, is_xml, to_xml, xml_to_str
from ..version import Version
class AutodiscoverBase(EWSElement):
NAMESPACE = RNS
class User(AutodiscoverBase):
"""MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/user-pox"""
ELEMENT_NAME = "User"
display_name = TextField(field_uri="DisplayName", namespace=RNS)
legacy_dn = TextField(field_uri="LegacyDN", namespace=RNS)
deployment_id = TextField(field_uri="DeploymentId", namespace=RNS) # GUID format
autodiscover_smtp_address = EmailAddressField(field_uri="AutoDiscoverSMTPAddress", namespace=RNS)
class IntExtUrlBase(AutodiscoverBase):
external_url = TextField(field_uri="ExternalUrl", namespace=RNS)
internal_url = TextField(field_uri="InternalUrl", namespace=RNS)
class AddressBook(IntExtUrlBase):
"""MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/addressbook-pox"""
ELEMENT_NAME = "AddressBook"
class MailStore(IntExtUrlBase):
"""MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/mailstore-pox"""
ELEMENT_NAME = "MailStore"
class NetworkRequirements(AutodiscoverBase):
"""MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/networkrequirements-pox"""
ELEMENT_NAME = "NetworkRequirements"
ipv4_start = TextField(field_uri="IPv4Start", namespace=RNS)
ipv4_end = TextField(field_uri="IPv4End", namespace=RNS)
ipv6_start = TextField(field_uri="IPv6Start", namespace=RNS)
ipv6_end = TextField(field_uri="IPv6End", namespace=RNS)
class SimpleProtocol(AutodiscoverBase):
"""MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/protocol-pox
Used for the 'Internal' and 'External' elements that may contain a stripped-down version of the Protocol element.
"""
ELEMENT_NAME = "Protocol"
WEB = "WEB"
EXCH = "EXCH"
EXPR = "EXPR"
EXHTTP = "EXHTTP"
TYPES = (WEB, EXCH, EXPR, EXHTTP)
type = ChoiceField(field_uri="Type", choices={Choice(c) for c in TYPES}, namespace=RNS)
as_url = TextField(field_uri="ASUrl", namespace=RNS)
class IntExtBase(AutodiscoverBase):
# TODO: 'OWAUrl' also has an AuthenticationMethod enum-style XML attribute with values:
# WindowsIntegrated, FBA, NTLM, Digest, Basic, LiveIdFba, OAuth
owa_url = TextField(field_uri="OWAUrl", namespace=RNS)
protocol = EWSElementField(value_cls=SimpleProtocol)
class Internal(IntExtBase):
"""MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/internal-pox"""
ELEMENT_NAME = "Internal"
class External(IntExtBase):
"""MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/external-pox"""
ELEMENT_NAME = "External"
class Protocol(SimpleProtocol):
"""MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/protocol-pox"""
# Attribute 'Type' is ignored here. Has a name conflict with the child element and does not seem useful.
version = TextField(field_uri="Version", is_attribute=True, namespace=RNS)
internal = EWSElementField(value_cls=Internal)
external = EWSElementField(value_cls=External)
ttl = IntegerField(field_uri="TTL", namespace=RNS, default=1) # TTL for this autodiscover response, in hours
server = TextField(field_uri="Server", namespace=RNS)
server_dn = TextField(field_uri="ServerDN", namespace=RNS)
server_version = BuildField(field_uri="ServerVersion", namespace=RNS)
mdb_dn = TextField(field_uri="MdbDN", namespace=RNS)
public_folder_server = TextField(field_uri="PublicFolderServer", namespace=RNS)
port = IntegerField(field_uri="Port", namespace=RNS, min=1, max=65535)
directory_port = IntegerField(field_uri="DirectoryPort", namespace=RNS, min=1, max=65535)
referral_port = IntegerField(field_uri="ReferralPort", namespace=RNS, min=1, max=65535)
ews_url = TextField(field_uri="EwsUrl", namespace=RNS)
emws_url = TextField(field_uri="EmwsUrl", namespace=RNS)
sharing_url = TextField(field_uri="SharingUrl", namespace=RNS)
ecp_url = TextField(field_uri="EcpUrl", namespace=RNS)
ecp_url_um = TextField(field_uri="EcpUrl-um", namespace=RNS)
ecp_url_aggr = TextField(field_uri="EcpUrl-aggr", namespace=RNS)
ecp_url_mt = TextField(field_uri="EcpUrl-mt", namespace=RNS)
ecp_url_ret = TextField(field_uri="EcpUrl-ret", namespace=RNS)
ecp_url_sms = TextField(field_uri="EcpUrl-sms", namespace=RNS)
ecp_url_publish = TextField(field_uri="EcpUrl-publish", namespace=RNS)
ecp_url_photo = TextField(field_uri="EcpUrl-photo", namespace=RNS)
ecp_url_tm = TextField(field_uri="EcpUrl-tm", namespace=RNS)
ecp_url_tm_creating = TextField(field_uri="EcpUrl-tmCreating", namespace=RNS)
ecp_url_tm_hiding = TextField(field_uri="EcpUrl-tmHiding", namespace=RNS)
ecp_url_tm_editing = TextField(field_uri="EcpUrl-tmEditing", namespace=RNS)
ecp_url_extinstall = TextField(field_uri="EcpUrl-extinstall", namespace=RNS)
oof_url = TextField(field_uri="OOFUrl", namespace=RNS)
oab_url = TextField(field_uri="OABUrl", namespace=RNS)
um_url = TextField(field_uri="UMUrl", namespace=RNS)
ews_partner_url = TextField(field_uri="EwsPartnerUrl", namespace=RNS)
login_name = TextField(field_uri="LoginName", namespace=RNS)
domain_required = OnOffField(field_uri="DomainRequired", namespace=RNS)
domain_name = TextField(field_uri="DomainName", namespace=RNS)
spa = OnOffField(field_uri="SPA", namespace=RNS, default=True)
auth_package = ChoiceField(
field_uri="AuthPackage",
namespace=RNS,
choices={Choice(c) for c in ("basic", "kerb", "kerbntlm", "ntlm", "certificate", "negotiate", "nego2")},
)
cert_principal_name = TextField(field_uri="CertPrincipalName", namespace=RNS)
ssl = OnOffField(field_uri="SSL", namespace=RNS, default=True)
auth_required = OnOffField(field_uri="AuthRequired", namespace=RNS, default=True)
use_pop_path = OnOffField(field_uri="UsePOPAuth", namespace=RNS)
smtp_last = OnOffField(field_uri="SMTPLast", namespace=RNS, default=False)
network_requirements = EWSElementField(value_cls=NetworkRequirements)
address_book = EWSElementField(value_cls=AddressBook)
mail_store = EWSElementField(value_cls=MailStore)
@property
def auth_type(self):
# Translates 'auth_package' value to our own 'auth_type' enum vals
if not self.auth_required:
return NOAUTH
if not self.auth_package:
return None
return {
# Missing in list are DIGEST and OAUTH2
"basic": BASIC,
"kerb": GSSAPI,
"kerbntlm": NTLM, # Means client can choose between NTLM and GSSAPI
"ntlm": NTLM,
"certificate": CBA,
"negotiate": SSPI, # Unsure about this one
"nego2": GSSAPI,
"anonymous": NOAUTH, # Seen in some docs even though it's not mentioned in MSDN
}.get(self.auth_package.lower())
class Error(EWSElement):
"""MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/error-pox"""
ELEMENT_NAME = "Error"
NAMESPACE = AUTODISCOVER_BASE_NS
id = TextField(field_uri="Id", namespace=AUTODISCOVER_BASE_NS, is_attribute=True)
time = TextField(field_uri="Time", namespace=AUTODISCOVER_BASE_NS, is_attribute=True)
code = TextField(field_uri="ErrorCode", namespace=AUTODISCOVER_BASE_NS)
message = TextField(field_uri="Message", namespace=AUTODISCOVER_BASE_NS)
debug_data = TextField(field_uri="DebugData", namespace=AUTODISCOVER_BASE_NS)
class Account(AutodiscoverBase):
"""MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/account-pox"""
ELEMENT_NAME = "Account"
REDIRECT_URL = "redirectUrl"
REDIRECT_ADDR = "redirectAddr"
SETTINGS = "settings"
ACTIONS = (REDIRECT_URL, REDIRECT_ADDR, SETTINGS)
type = ChoiceField(field_uri="AccountType", namespace=RNS, choices={Choice("email")})
action = ChoiceField(field_uri="Action", namespace=RNS, choices={Choice(p) for p in ACTIONS})
microsoft_online = BooleanField(field_uri="MicrosoftOnline", namespace=RNS)
redirect_url = TextField(field_uri="RedirectURL", namespace=RNS)
redirect_address = EmailAddressField(field_uri="RedirectAddr", namespace=RNS)
image = TextField(field_uri="Image", namespace=RNS) # Path to image used for branding
service_home = TextField(field_uri="ServiceHome", namespace=RNS) # URL to website of ISP
protocols = ProtocolListField()
# 'SmtpAddress' is inside the 'PublicFolderInformation' element
public_folder_smtp_address = TextField(field_uri="SmtpAddress", namespace=RNS)
@classmethod
def from_xml(cls, elem, account):
kwargs = {}
public_folder_information = elem.find(f"{{{cls.NAMESPACE}}}PublicFolderInformation")
for f in cls.FIELDS:
if f.name == "public_folder_smtp_address":
if public_folder_information is None:
continue
kwargs[f.name] = f.from_xml(elem=public_folder_information, account=account)
continue
kwargs[f.name] = f.from_xml(elem=elem, account=account)
cls._clear(elem)
return cls(**kwargs)
class Response(AutodiscoverBase):
"""MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/response-pox"""
ELEMENT_NAME = "Response"
user = EWSElementField(value_cls=User)
account = EWSElementField(value_cls=Account)
@property
def redirect_address(self):
try:
if self.account.action != Account.REDIRECT_ADDR:
return None
return self.account.redirect_address
except AttributeError:
return None
@property
def redirect_url(self):
try:
if self.account.action != Account.REDIRECT_URL:
return None
return self.account.redirect_url
except AttributeError:
return None
@property
def autodiscover_smtp_address(self):
# AutoDiscoverSMTPAddress might not be present in the XML. In this case, use the original email address.
try:
if self.account.action != Account.SETTINGS:
return None
return self.user.autodiscover_smtp_address
except AttributeError:
return None
@property
def version(self):
# Get the server version. Not all protocol entries have a server version, so we cheat a bit and also look at the
# other ones that point to the same endpoint.
ews_url = self.protocol.ews_url
for protocol in self.account.protocols:
if not protocol.ews_url or not protocol.server_version:
continue
if protocol.ews_url.lower() == ews_url.lower():
return Version(build=protocol.server_version)
return None
@property
def protocol(self):
"""Return the protocol containing an EWS URL.
A response may contain a number of possible protocol types. EXPR is meant for EWS. See
https://techcommunity.microsoft.com/t5/blogs/blogarticleprintpage/blog-id/Exchange/article-id/16
We allow fallback to EXCH if EXPR is not available, to support installations where EXPR is not available.
Additionally, some responses may contain an EXPR with no EWS URL. In that case, return EXCH, if available.
"""
protocols = {p.type: p for p in self.account.protocols if p.ews_url}
if Protocol.EXPR in protocols:
return protocols[Protocol.EXPR]
if Protocol.EXCH in protocols:
return protocols[Protocol.EXCH]
raise ValueError(
f"No EWS URL found in any of the available protocols: {[str(p) for p in self.account.protocols]}"
)
class ErrorResponse(EWSElement):
"""MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/response-pox
Like 'Response', but with a different namespace.
"""
ELEMENT_NAME = "Response"
NAMESPACE = AUTODISCOVER_BASE_NS
error = EWSElementField(value_cls=Error)
class Autodiscover(EWSElement):
ELEMENT_NAME = "Autodiscover"
NAMESPACE = AUTODISCOVER_BASE_NS
response = EWSElementField(value_cls=Response)
error_response = EWSElementField(value_cls=ErrorResponse)
@staticmethod
def _clear(elem):
# Parent implementation also clears the parent, but this element doesn't have one.
elem.clear()
@classmethod
def from_bytes(cls, bytes_content):
"""Create an instance from response bytes. An Autodiscover request and response example is available at:
https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/pox-autodiscover-response-for-exchange
:param bytes_content:
:return:
"""
if not is_xml(bytes_content):
raise ParseError(f"Response is not XML: {bytes_content}", "<not from file>", -1, 0)
root = to_xml(bytes_content).getroot() # May raise ParseError
if root.tag != cls.response_tag():
raise ParseError(f"Unknown root element in XML: {bytes_content}", "<not from file>", -1, 0)
return cls.from_xml(elem=root, account=None)
def raise_errors(self):
if self.response is not None:
return
# Find an error message in the response and raise the relevant exception
try:
error_code = self.error_response.error.code
message = self.error_response.error.message
if message in ("The e-mail address cannot be found.", "The email address can't be found."):
raise ErrorNonExistentMailbox("The SMTP address has no mailbox associated with it")
raise AutoDiscoverFailed(f"Unknown error {error_code}: {message}")
except AttributeError:
raise AutoDiscoverFailed(f"Unknown autodiscover error response: {self.error_response}")
@staticmethod
def payload(email):
# Builds a full Autodiscover XML request
payload = create_element("Autodiscover", attrs=dict(xmlns=AUTODISCOVER_REQUEST_NS))
request = create_element("Request")
add_xml_child(request, "EMailAddress", email)
add_xml_child(request, "AcceptableResponseSchema", RNS)
payload.append(request)
return xml_to_str(payload, encoding=DEFAULT_ENCODING, xml_declaration=True)
Classes
class Account (**kwargs)
-
Expand source code
class Account(AutodiscoverBase): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/account-pox""" ELEMENT_NAME = "Account" REDIRECT_URL = "redirectUrl" REDIRECT_ADDR = "redirectAddr" SETTINGS = "settings" ACTIONS = (REDIRECT_URL, REDIRECT_ADDR, SETTINGS) type = ChoiceField(field_uri="AccountType", namespace=RNS, choices={Choice("email")}) action = ChoiceField(field_uri="Action", namespace=RNS, choices={Choice(p) for p in ACTIONS}) microsoft_online = BooleanField(field_uri="MicrosoftOnline", namespace=RNS) redirect_url = TextField(field_uri="RedirectURL", namespace=RNS) redirect_address = EmailAddressField(field_uri="RedirectAddr", namespace=RNS) image = TextField(field_uri="Image", namespace=RNS) # Path to image used for branding service_home = TextField(field_uri="ServiceHome", namespace=RNS) # URL to website of ISP protocols = ProtocolListField() # 'SmtpAddress' is inside the 'PublicFolderInformation' element public_folder_smtp_address = TextField(field_uri="SmtpAddress", namespace=RNS) @classmethod def from_xml(cls, elem, account): kwargs = {} public_folder_information = elem.find(f"{{{cls.NAMESPACE}}}PublicFolderInformation") for f in cls.FIELDS: if f.name == "public_folder_smtp_address": if public_folder_information is None: continue kwargs[f.name] = f.from_xml(elem=public_folder_information, account=account) continue kwargs[f.name] = f.from_xml(elem=elem, account=account) cls._clear(elem) return cls(**kwargs)
Ancestors
Class variables
var ACTIONS
var ELEMENT_NAME
var FIELDS
var REDIRECT_ADDR
var REDIRECT_URL
var SETTINGS
Static methods
def from_xml(elem, account)
-
Expand source code
@classmethod def from_xml(cls, elem, account): kwargs = {} public_folder_information = elem.find(f"{{{cls.NAMESPACE}}}PublicFolderInformation") for f in cls.FIELDS: if f.name == "public_folder_smtp_address": if public_folder_information is None: continue kwargs[f.name] = f.from_xml(elem=public_folder_information, account=account) continue kwargs[f.name] = f.from_xml(elem=elem, account=account) cls._clear(elem) return cls(**kwargs)
Instance variables
var action
var image
var microsoft_online
var protocols
var public_folder_smtp_address
var redirect_address
var redirect_url
var service_home
var type
Inherited members
class AddressBook (**kwargs)
-
MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/addressbook-pox
Expand source code
class AddressBook(IntExtUrlBase): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/addressbook-pox""" ELEMENT_NAME = "AddressBook"
Ancestors
Class variables
var ELEMENT_NAME
Inherited members
class Autodiscover (**kwargs)
-
Base class for all XML element implementations.
Expand source code
class Autodiscover(EWSElement): ELEMENT_NAME = "Autodiscover" NAMESPACE = AUTODISCOVER_BASE_NS response = EWSElementField(value_cls=Response) error_response = EWSElementField(value_cls=ErrorResponse) @staticmethod def _clear(elem): # Parent implementation also clears the parent, but this element doesn't have one. elem.clear() @classmethod def from_bytes(cls, bytes_content): """Create an instance from response bytes. An Autodiscover request and response example is available at: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/pox-autodiscover-response-for-exchange :param bytes_content: :return: """ if not is_xml(bytes_content): raise ParseError(f"Response is not XML: {bytes_content}", "<not from file>", -1, 0) root = to_xml(bytes_content).getroot() # May raise ParseError if root.tag != cls.response_tag(): raise ParseError(f"Unknown root element in XML: {bytes_content}", "<not from file>", -1, 0) return cls.from_xml(elem=root, account=None) def raise_errors(self): if self.response is not None: return # Find an error message in the response and raise the relevant exception try: error_code = self.error_response.error.code message = self.error_response.error.message if message in ("The e-mail address cannot be found.", "The email address can't be found."): raise ErrorNonExistentMailbox("The SMTP address has no mailbox associated with it") raise AutoDiscoverFailed(f"Unknown error {error_code}: {message}") except AttributeError: raise AutoDiscoverFailed(f"Unknown autodiscover error response: {self.error_response}") @staticmethod def payload(email): # Builds a full Autodiscover XML request payload = create_element("Autodiscover", attrs=dict(xmlns=AUTODISCOVER_REQUEST_NS)) request = create_element("Request") add_xml_child(request, "EMailAddress", email) add_xml_child(request, "AcceptableResponseSchema", RNS) payload.append(request) return xml_to_str(payload, encoding=DEFAULT_ENCODING, xml_declaration=True)
Ancestors
Class variables
var ELEMENT_NAME
var FIELDS
var NAMESPACE
Static methods
def from_bytes(bytes_content)
-
Create an instance from response bytes. An Autodiscover request and response example is available at: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/pox-autodiscover-response-for-exchange
:param bytes_content: :return:
Expand source code
@classmethod def from_bytes(cls, bytes_content): """Create an instance from response bytes. An Autodiscover request and response example is available at: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/pox-autodiscover-response-for-exchange :param bytes_content: :return: """ if not is_xml(bytes_content): raise ParseError(f"Response is not XML: {bytes_content}", "<not from file>", -1, 0) root = to_xml(bytes_content).getroot() # May raise ParseError if root.tag != cls.response_tag(): raise ParseError(f"Unknown root element in XML: {bytes_content}", "<not from file>", -1, 0) return cls.from_xml(elem=root, account=None)
def payload(email)
-
Expand source code
@staticmethod def payload(email): # Builds a full Autodiscover XML request payload = create_element("Autodiscover", attrs=dict(xmlns=AUTODISCOVER_REQUEST_NS)) request = create_element("Request") add_xml_child(request, "EMailAddress", email) add_xml_child(request, "AcceptableResponseSchema", RNS) payload.append(request) return xml_to_str(payload, encoding=DEFAULT_ENCODING, xml_declaration=True)
Instance variables
var error_response
var response
Methods
def raise_errors(self)
-
Expand source code
def raise_errors(self): if self.response is not None: return # Find an error message in the response and raise the relevant exception try: error_code = self.error_response.error.code message = self.error_response.error.message if message in ("The e-mail address cannot be found.", "The email address can't be found."): raise ErrorNonExistentMailbox("The SMTP address has no mailbox associated with it") raise AutoDiscoverFailed(f"Unknown error {error_code}: {message}") except AttributeError: raise AutoDiscoverFailed(f"Unknown autodiscover error response: {self.error_response}")
Inherited members
class AutodiscoverBase (**kwargs)
-
Base class for all XML element implementations.
Expand source code
class AutodiscoverBase(EWSElement): NAMESPACE = RNS
Ancestors
Subclasses
Class variables
var NAMESPACE
Inherited members
class Error (**kwargs)
-
Expand source code
class Error(EWSElement): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/error-pox""" ELEMENT_NAME = "Error" NAMESPACE = AUTODISCOVER_BASE_NS id = TextField(field_uri="Id", namespace=AUTODISCOVER_BASE_NS, is_attribute=True) time = TextField(field_uri="Time", namespace=AUTODISCOVER_BASE_NS, is_attribute=True) code = TextField(field_uri="ErrorCode", namespace=AUTODISCOVER_BASE_NS) message = TextField(field_uri="Message", namespace=AUTODISCOVER_BASE_NS) debug_data = TextField(field_uri="DebugData", namespace=AUTODISCOVER_BASE_NS)
Ancestors
Class variables
var ELEMENT_NAME
var FIELDS
var NAMESPACE
Instance variables
var code
var debug_data
var id
var message
var time
Inherited members
class ErrorResponse (**kwargs)
-
MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/response-pox
Like 'Response', but with a different namespace.
Expand source code
class ErrorResponse(EWSElement): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/response-pox Like 'Response', but with a different namespace. """ ELEMENT_NAME = "Response" NAMESPACE = AUTODISCOVER_BASE_NS error = EWSElementField(value_cls=Error)
Ancestors
Class variables
var ELEMENT_NAME
var FIELDS
var NAMESPACE
Instance variables
var error
Inherited members
class External (**kwargs)
-
Expand source code
class External(IntExtBase): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/external-pox""" ELEMENT_NAME = "External"
Ancestors
Class variables
var ELEMENT_NAME
Inherited members
class IntExtBase (**kwargs)
-
Base class for all XML element implementations.
Expand source code
class IntExtBase(AutodiscoverBase): # TODO: 'OWAUrl' also has an AuthenticationMethod enum-style XML attribute with values: # WindowsIntegrated, FBA, NTLM, Digest, Basic, LiveIdFba, OAuth owa_url = TextField(field_uri="OWAUrl", namespace=RNS) protocol = EWSElementField(value_cls=SimpleProtocol)
Ancestors
Subclasses
Class variables
var FIELDS
Instance variables
var owa_url
var protocol
Inherited members
class IntExtUrlBase (**kwargs)
-
Base class for all XML element implementations.
Expand source code
class IntExtUrlBase(AutodiscoverBase): external_url = TextField(field_uri="ExternalUrl", namespace=RNS) internal_url = TextField(field_uri="InternalUrl", namespace=RNS)
Ancestors
Subclasses
Class variables
var FIELDS
Instance variables
var external_url
var internal_url
Inherited members
class Internal (**kwargs)
-
Expand source code
class Internal(IntExtBase): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/internal-pox""" ELEMENT_NAME = "Internal"
Ancestors
Class variables
var ELEMENT_NAME
Inherited members
class MailStore (**kwargs)
-
MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/mailstore-pox
Expand source code
class MailStore(IntExtUrlBase): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/mailstore-pox""" ELEMENT_NAME = "MailStore"
Ancestors
Class variables
var ELEMENT_NAME
Inherited members
class NetworkRequirements (**kwargs)
-
Expand source code
class NetworkRequirements(AutodiscoverBase): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/networkrequirements-pox""" ELEMENT_NAME = "NetworkRequirements" ipv4_start = TextField(field_uri="IPv4Start", namespace=RNS) ipv4_end = TextField(field_uri="IPv4End", namespace=RNS) ipv6_start = TextField(field_uri="IPv6Start", namespace=RNS) ipv6_end = TextField(field_uri="IPv6End", namespace=RNS)
Ancestors
Class variables
var ELEMENT_NAME
var FIELDS
Instance variables
var ipv4_end
var ipv4_start
var ipv6_end
var ipv6_start
Inherited members
class Protocol (**kwargs)
-
Expand source code
class Protocol(SimpleProtocol): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/protocol-pox""" # Attribute 'Type' is ignored here. Has a name conflict with the child element and does not seem useful. version = TextField(field_uri="Version", is_attribute=True, namespace=RNS) internal = EWSElementField(value_cls=Internal) external = EWSElementField(value_cls=External) ttl = IntegerField(field_uri="TTL", namespace=RNS, default=1) # TTL for this autodiscover response, in hours server = TextField(field_uri="Server", namespace=RNS) server_dn = TextField(field_uri="ServerDN", namespace=RNS) server_version = BuildField(field_uri="ServerVersion", namespace=RNS) mdb_dn = TextField(field_uri="MdbDN", namespace=RNS) public_folder_server = TextField(field_uri="PublicFolderServer", namespace=RNS) port = IntegerField(field_uri="Port", namespace=RNS, min=1, max=65535) directory_port = IntegerField(field_uri="DirectoryPort", namespace=RNS, min=1, max=65535) referral_port = IntegerField(field_uri="ReferralPort", namespace=RNS, min=1, max=65535) ews_url = TextField(field_uri="EwsUrl", namespace=RNS) emws_url = TextField(field_uri="EmwsUrl", namespace=RNS) sharing_url = TextField(field_uri="SharingUrl", namespace=RNS) ecp_url = TextField(field_uri="EcpUrl", namespace=RNS) ecp_url_um = TextField(field_uri="EcpUrl-um", namespace=RNS) ecp_url_aggr = TextField(field_uri="EcpUrl-aggr", namespace=RNS) ecp_url_mt = TextField(field_uri="EcpUrl-mt", namespace=RNS) ecp_url_ret = TextField(field_uri="EcpUrl-ret", namespace=RNS) ecp_url_sms = TextField(field_uri="EcpUrl-sms", namespace=RNS) ecp_url_publish = TextField(field_uri="EcpUrl-publish", namespace=RNS) ecp_url_photo = TextField(field_uri="EcpUrl-photo", namespace=RNS) ecp_url_tm = TextField(field_uri="EcpUrl-tm", namespace=RNS) ecp_url_tm_creating = TextField(field_uri="EcpUrl-tmCreating", namespace=RNS) ecp_url_tm_hiding = TextField(field_uri="EcpUrl-tmHiding", namespace=RNS) ecp_url_tm_editing = TextField(field_uri="EcpUrl-tmEditing", namespace=RNS) ecp_url_extinstall = TextField(field_uri="EcpUrl-extinstall", namespace=RNS) oof_url = TextField(field_uri="OOFUrl", namespace=RNS) oab_url = TextField(field_uri="OABUrl", namespace=RNS) um_url = TextField(field_uri="UMUrl", namespace=RNS) ews_partner_url = TextField(field_uri="EwsPartnerUrl", namespace=RNS) login_name = TextField(field_uri="LoginName", namespace=RNS) domain_required = OnOffField(field_uri="DomainRequired", namespace=RNS) domain_name = TextField(field_uri="DomainName", namespace=RNS) spa = OnOffField(field_uri="SPA", namespace=RNS, default=True) auth_package = ChoiceField( field_uri="AuthPackage", namespace=RNS, choices={Choice(c) for c in ("basic", "kerb", "kerbntlm", "ntlm", "certificate", "negotiate", "nego2")}, ) cert_principal_name = TextField(field_uri="CertPrincipalName", namespace=RNS) ssl = OnOffField(field_uri="SSL", namespace=RNS, default=True) auth_required = OnOffField(field_uri="AuthRequired", namespace=RNS, default=True) use_pop_path = OnOffField(field_uri="UsePOPAuth", namespace=RNS) smtp_last = OnOffField(field_uri="SMTPLast", namespace=RNS, default=False) network_requirements = EWSElementField(value_cls=NetworkRequirements) address_book = EWSElementField(value_cls=AddressBook) mail_store = EWSElementField(value_cls=MailStore) @property def auth_type(self): # Translates 'auth_package' value to our own 'auth_type' enum vals if not self.auth_required: return NOAUTH if not self.auth_package: return None return { # Missing in list are DIGEST and OAUTH2 "basic": BASIC, "kerb": GSSAPI, "kerbntlm": NTLM, # Means client can choose between NTLM and GSSAPI "ntlm": NTLM, "certificate": CBA, "negotiate": SSPI, # Unsure about this one "nego2": GSSAPI, "anonymous": NOAUTH, # Seen in some docs even though it's not mentioned in MSDN }.get(self.auth_package.lower())
Ancestors
Class variables
var FIELDS
Instance variables
var address_book
var auth_package
var auth_required
var auth_type
-
Expand source code
@property def auth_type(self): # Translates 'auth_package' value to our own 'auth_type' enum vals if not self.auth_required: return NOAUTH if not self.auth_package: return None return { # Missing in list are DIGEST and OAUTH2 "basic": BASIC, "kerb": GSSAPI, "kerbntlm": NTLM, # Means client can choose between NTLM and GSSAPI "ntlm": NTLM, "certificate": CBA, "negotiate": SSPI, # Unsure about this one "nego2": GSSAPI, "anonymous": NOAUTH, # Seen in some docs even though it's not mentioned in MSDN }.get(self.auth_package.lower())
var cert_principal_name
var directory_port
var domain_name
var domain_required
var ecp_url
var ecp_url_aggr
var ecp_url_extinstall
var ecp_url_mt
var ecp_url_photo
var ecp_url_publish
var ecp_url_ret
var ecp_url_sms
var ecp_url_tm
var ecp_url_tm_creating
var ecp_url_tm_editing
var ecp_url_tm_hiding
var ecp_url_um
var emws_url
var ews_partner_url
var ews_url
var external
var internal
var login_name
var mail_store
var mdb_dn
var network_requirements
var oab_url
var oof_url
var port
var public_folder_server
var referral_port
var server
var server_dn
var server_version
var sharing_url
var smtp_last
var spa
var ssl
var ttl
var um_url
var use_pop_path
var version
Inherited members
class Response (**kwargs)
-
Expand source code
class Response(AutodiscoverBase): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/response-pox""" ELEMENT_NAME = "Response" user = EWSElementField(value_cls=User) account = EWSElementField(value_cls=Account) @property def redirect_address(self): try: if self.account.action != Account.REDIRECT_ADDR: return None return self.account.redirect_address except AttributeError: return None @property def redirect_url(self): try: if self.account.action != Account.REDIRECT_URL: return None return self.account.redirect_url except AttributeError: return None @property def autodiscover_smtp_address(self): # AutoDiscoverSMTPAddress might not be present in the XML. In this case, use the original email address. try: if self.account.action != Account.SETTINGS: return None return self.user.autodiscover_smtp_address except AttributeError: return None @property def version(self): # Get the server version. Not all protocol entries have a server version, so we cheat a bit and also look at the # other ones that point to the same endpoint. ews_url = self.protocol.ews_url for protocol in self.account.protocols: if not protocol.ews_url or not protocol.server_version: continue if protocol.ews_url.lower() == ews_url.lower(): return Version(build=protocol.server_version) return None @property def protocol(self): """Return the protocol containing an EWS URL. A response may contain a number of possible protocol types. EXPR is meant for EWS. See https://techcommunity.microsoft.com/t5/blogs/blogarticleprintpage/blog-id/Exchange/article-id/16 We allow fallback to EXCH if EXPR is not available, to support installations where EXPR is not available. Additionally, some responses may contain an EXPR with no EWS URL. In that case, return EXCH, if available. """ protocols = {p.type: p for p in self.account.protocols if p.ews_url} if Protocol.EXPR in protocols: return protocols[Protocol.EXPR] if Protocol.EXCH in protocols: return protocols[Protocol.EXCH] raise ValueError( f"No EWS URL found in any of the available protocols: {[str(p) for p in self.account.protocols]}" )
Ancestors
Class variables
var ELEMENT_NAME
var FIELDS
Instance variables
var account
var autodiscover_smtp_address
-
Expand source code
@property def autodiscover_smtp_address(self): # AutoDiscoverSMTPAddress might not be present in the XML. In this case, use the original email address. try: if self.account.action != Account.SETTINGS: return None return self.user.autodiscover_smtp_address except AttributeError: return None
var protocol
-
Return the protocol containing an EWS URL.
A response may contain a number of possible protocol types. EXPR is meant for EWS. See https://techcommunity.microsoft.com/t5/blogs/blogarticleprintpage/blog-id/Exchange/article-id/16
We allow fallback to EXCH if EXPR is not available, to support installations where EXPR is not available.
Additionally, some responses may contain an EXPR with no EWS URL. In that case, return EXCH, if available.
Expand source code
@property def protocol(self): """Return the protocol containing an EWS URL. A response may contain a number of possible protocol types. EXPR is meant for EWS. See https://techcommunity.microsoft.com/t5/blogs/blogarticleprintpage/blog-id/Exchange/article-id/16 We allow fallback to EXCH if EXPR is not available, to support installations where EXPR is not available. Additionally, some responses may contain an EXPR with no EWS URL. In that case, return EXCH, if available. """ protocols = {p.type: p for p in self.account.protocols if p.ews_url} if Protocol.EXPR in protocols: return protocols[Protocol.EXPR] if Protocol.EXCH in protocols: return protocols[Protocol.EXCH] raise ValueError( f"No EWS URL found in any of the available protocols: {[str(p) for p in self.account.protocols]}" )
var redirect_address
-
Expand source code
@property def redirect_address(self): try: if self.account.action != Account.REDIRECT_ADDR: return None return self.account.redirect_address except AttributeError: return None
var redirect_url
-
Expand source code
@property def redirect_url(self): try: if self.account.action != Account.REDIRECT_URL: return None return self.account.redirect_url except AttributeError: return None
var user
var version
-
Expand source code
@property def version(self): # Get the server version. Not all protocol entries have a server version, so we cheat a bit and also look at the # other ones that point to the same endpoint. ews_url = self.protocol.ews_url for protocol in self.account.protocols: if not protocol.ews_url or not protocol.server_version: continue if protocol.ews_url.lower() == ews_url.lower(): return Version(build=protocol.server_version) return None
Inherited members
class SimpleProtocol (**kwargs)
-
MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/protocol-pox
Used for the 'Internal' and 'External' elements that may contain a stripped-down version of the Protocol element.
Expand source code
class SimpleProtocol(AutodiscoverBase): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/protocol-pox Used for the 'Internal' and 'External' elements that may contain a stripped-down version of the Protocol element. """ ELEMENT_NAME = "Protocol" WEB = "WEB" EXCH = "EXCH" EXPR = "EXPR" EXHTTP = "EXHTTP" TYPES = (WEB, EXCH, EXPR, EXHTTP) type = ChoiceField(field_uri="Type", choices={Choice(c) for c in TYPES}, namespace=RNS) as_url = TextField(field_uri="ASUrl", namespace=RNS)
Ancestors
Subclasses
Class variables
var ELEMENT_NAME
var EXCH
var EXHTTP
var EXPR
var FIELDS
var TYPES
var WEB
Instance variables
var as_url
var type
Inherited members
class User (**kwargs)
-
Expand source code
class User(AutodiscoverBase): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/user-pox""" ELEMENT_NAME = "User" display_name = TextField(field_uri="DisplayName", namespace=RNS) legacy_dn = TextField(field_uri="LegacyDN", namespace=RNS) deployment_id = TextField(field_uri="DeploymentId", namespace=RNS) # GUID format autodiscover_smtp_address = EmailAddressField(field_uri="AutoDiscoverSMTPAddress", namespace=RNS)
Ancestors
Class variables
var ELEMENT_NAME
var FIELDS
Instance variables
var autodiscover_smtp_address
var deployment_id
var display_name
var legacy_dn
Inherited members