exchangelib.services API documentation
Description: Implement a selection of EWS services (operations) …

# Module `exchangelib.services`

Implement a selection of EWS services (operations).

Exchange is very picky about things like the order of XML elements in SOAP requests, so we need to generate XML automatically instead of taking advantage of Python SOAP libraries and the WSDL file.

Exchange EWS operations overview: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/ews-operations-in-exchange

Expand source code

    """Implement a selection of EWS services (operations).

    Exchange is very picky about things like the order of XML elements in SOAP requests, so we need to generate XML
    automatically instead of taking advantage of Python SOAP libraries and the WSDL file.

    Exchange EWS operations overview:
        https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/ews-operations-in-exchange
    """

    from .archive_item import ArchiveItem
    from .common import CHUNK_SIZE
    from .convert_id import ConvertId
    from .copy_item import CopyItem
    from .create_attachment import CreateAttachment
    from .create_folder import CreateFolder
    from .create_item import CreateItem
    from .create_user_configuration import CreateUserConfiguration
    from .delete_attachment import DeleteAttachment
    from .delete_folder import DeleteFolder
    from .delete_item import DeleteItem
    from .delete_user_configuration import DeleteUserConfiguration
    from .empty_folder import EmptyFolder
    from .expand_dl import ExpandDL
    from .export_items import ExportItems
    from .find_folder import FindFolder
    from .find_item import FindItem
    from .find_people import FindPeople
    from .get_attachment import GetAttachment
    from .get_delegate import GetDelegate
    from .get_events import GetEvents
    from .get_folder import GetFolder
    from .get_item import GetItem
    from .get_mail_tips import GetMailTips
    from .get_persona import GetPersona
    from .get_room_lists import GetRoomLists
    from .get_rooms import GetRooms
    from .get_searchable_mailboxes import GetSearchableMailboxes
    from .get_server_time_zones import GetServerTimeZones
    from .get_streaming_events import GetStreamingEvents
    from .get_user_availability import GetUserAvailability
    from .get_user_configuration import GetUserConfiguration
    from .get_user_oof_settings import GetUserOofSettings
    from .mark_as_junk import MarkAsJunk
    from .move_folder import MoveFolder
    from .move_item import MoveItem
    from .resolve_names import ResolveNames
    from .send_item import SendItem
    from .send_notification import SendNotification
    from .set_user_oof_settings import SetUserOofSettings
    from .subscribe import SubscribeToStreaming, SubscribeToPull, SubscribeToPush
    from .sync_folder_hierarchy import SyncFolderHierarchy
    from .sync_folder_items import SyncFolderItems
    from .unsubscribe import Unsubscribe
    from .update_folder import UpdateFolder
    from .update_item import UpdateItem
    from .update_user_configuration import UpdateUserConfiguration
    from .upload_items import UploadItems

    __all__ = [
        'CHUNK_SIZE',
        'ArchiveItem',
        'ConvertId',
        'CopyItem',
        'CreateAttachment',
        'CreateFolder',
        'CreateItem',
        'CreateUserConfiguration',
        'DeleteAttachment',
        'DeleteFolder',
        'DeleteUserConfiguration',
        'DeleteItem',
        'EmptyFolder',
        'ExpandDL',
        'ExportItems',
        'FindFolder',
        'FindItem',
        'FindPeople',
        'GetAttachment',
        'GetDelegate',
        'GetEvents',
        'GetFolder',
        'GetItem',
        'GetMailTips',
        'GetPersona',
        'GetRoomLists',
        'GetRooms',
        'GetSearchableMailboxes',
        'GetServerTimeZones',
        'GetStreamingEvents',
        'GetUserAvailability',
        'GetUserConfiguration',
        'GetUserOofSettings',
        'MarkAsJunk',
        'MoveFolder',
        'MoveItem',
        'ResolveNames',
        'SendItem',
        'SendNotification',
        'SetUserOofSettings',
        'SubscribeToPull',
        'SubscribeToPush',
        'SubscribeToStreaming',
        'SyncFolderHierarchy',
        'SyncFolderItems',
        'Unsubscribe',
        'UpdateFolder',
        'UpdateItem',
        'UpdateUserConfiguration',
        'UploadItems',
    ]

## Sub-modules

`exchangelib.services.archive_item`
`exchangelib.services.common`
`exchangelib.services.convert_id`
`exchangelib.services.copy_item`
`exchangelib.services.create_attachment`
`exchangelib.services.create_folder`
`exchangelib.services.create_item`
`exchangelib.services.create_user_configuration`
`exchangelib.services.delete_attachment`
`exchangelib.services.delete_folder`
`exchangelib.services.delete_item`
`exchangelib.services.delete_user_configuration`
`exchangelib.services.empty_folder`
`exchangelib.services.expand_dl`
`exchangelib.services.export_items`
`exchangelib.services.find_folder`
`exchangelib.services.find_item`
`exchangelib.services.find_people`
`exchangelib.services.get_attachment`
`exchangelib.services.get_delegate`
`exchangelib.services.get_events`
`exchangelib.services.get_folder`
`exchangelib.services.get_item`
`exchangelib.services.get_mail_tips`
`exchangelib.services.get_persona`
`exchangelib.services.get_room_lists`
`exchangelib.services.get_rooms`
`exchangelib.services.get_searchable_mailboxes`
`exchangelib.services.get_server_time_zones`
`exchangelib.services.get_streaming_events`
`exchangelib.services.get_user_availability`
`exchangelib.services.get_user_configuration`
`exchangelib.services.get_user_oof_settings`
`exchangelib.services.mark_as_junk`
`exchangelib.services.move_folder`
`exchangelib.services.move_item`
`exchangelib.services.resolve_names`
`exchangelib.services.send_item`
`exchangelib.services.send_notification`
`exchangelib.services.set_user_oof_settings`
`exchangelib.services.subscribe`

  The 'Subscribe' service has two different modes, pull and push, with different signatures. Implement as two distinct classes.

`exchangelib.services.sync_folder_hierarchy`
`exchangelib.services.sync_folder_items`
`exchangelib.services.unsubscribe`
`exchangelib.services.update_folder`
`exchangelib.services.update_item`
`exchangelib.services.update_user_configuration`
`exchangelib.services.upload_items`

## Classes

`class ArchiveItem (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/archiveitem-operation

  Expand source code

      class ArchiveItem(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/archiveitem-operation"""

          SERVICE_NAME = 'ArchiveItem'
          element_container_name = '{%s}Items' % MNS
          supported_from = EXCHANGE_2013

          def call(self, items, to_folder):
              """Move a list of items to a specific folder in the archive mailbox.

              :param items: a list of (id, changekey) tuples or Item objects
              :param to_folder:

              :return: None
              """
              return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=items, to_folder=to_folder))

          def _elems_to_objs(self, elems):
              from ..items import Item
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield Item.id_from_xml(elem)

          def get_payload(self, items, to_folder):
              archiveitem = create_element('m:%s' % self.SERVICE_NAME)
              folder_id = create_folder_ids_element(tag='m:ArchiveSourceFolderId', folders=[to_folder],
                                                    version=self.account.version)
              item_ids = create_item_ids_element(items=items, version=self.account.version)
              archiveitem.append(folder_id)
              archiveitem.append(item_ids)
              return archiveitem

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`
  `var supported_from`

  ### Methods

  `def call(self, items, to_folder)`

    Move a list of items to a specific folder in the archive mailbox.

    :param items: a list of (id, changekey) tuples or Item objects :param to_folder:

    :return: None

    Expand source code

        def call(self, items, to_folder):
            """Move a list of items to a specific folder in the archive mailbox.

            :param items: a list of (id, changekey) tuples or Item objects
            :param to_folder:

            :return: None
            """
            return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=items, to_folder=to_folder))

  `def get_payload(self, items, to_folder)`
    Expand source code

        def get_payload(self, items, to_folder):
            archiveitem = create_element('m:%s' % self.SERVICE_NAME)
            folder_id = create_folder_ids_element(tag='m:ArchiveSourceFolderId', folders=[to_folder],
                                                  version=self.account.version)
            item_ids = create_item_ids_element(items=items, version=self.account.version)
            archiveitem.append(folder_id)
            archiveitem.append(item_ids)
            return archiveitem

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class ConvertId (protocol, chunk_size=None, timeout=None)`

  Take a list of IDs to convert. Returns a list of converted IDs or exception instances, in the same order as the input list.

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/convertid-operation

  Expand source code

      class ConvertId(EWSService):
          """Take a list of IDs to convert. Returns a list of converted IDs or exception instances, in the same order as the
          input list.

          MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/convertid-operation
          """

          SERVICE_NAME = 'ConvertId'
          supported_from = EXCHANGE_2007_SP1

          def call(self, items, destination_format):
              if destination_format not in ID_FORMATS:
                  raise ValueError("'destination_format' %r must be one of %s" % (destination_format, ID_FORMATS))
              return self._elems_to_objs(
                  self._chunked_get_elements(self.get_payload, items=items, destination_format=destination_format)
              )

          def _elems_to_objs(self, elems):
              cls_map = {cls.response_tag(): cls for cls in (
                  AlternateId, AlternatePublicFolderId, AlternatePublicFolderItemId
              )}
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield cls_map[elem.tag].from_xml(elem, account=None)

          def get_payload(self, items, destination_format):
              supported_item_classes = AlternateId, AlternatePublicFolderId, AlternatePublicFolderItemId
              convertid = create_element('m:%s' % self.SERVICE_NAME, attrs=dict(DestinationFormat=destination_format))
              item_ids = create_element('m:SourceIds')
              for item in items:
                  if not isinstance(item, supported_item_classes):
                      raise ValueError("'item' value %r must be an instance of %r" % (item, supported_item_classes))
                  set_xml_value(item_ids, item, version=self.protocol.version)
              if not len(item_ids):
                  raise ValueError('"items" must not be empty')
              convertid.append(item_ids)
              return convertid

          @classmethod
          def _get_elements_in_container(cls, container):
              # We may have other elements in here, e.g. 'ResponseCode'. Filter away those.
              return container.findall(AlternateId.response_tag()) \
                  + container.findall(AlternatePublicFolderId.response_tag()) \
                  + container.findall(AlternatePublicFolderItemId.response_tag())

  ### Ancestors

  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var supported_from`

  ### Methods

  `def call(self, items, destination_format)`
    Expand source code

        def call(self, items, destination_format):
            if destination_format not in ID_FORMATS:
                raise ValueError("'destination_format' %r must be one of %s" % (destination_format, ID_FORMATS))
            return self._elems_to_objs(
                self._chunked_get_elements(self.get_payload, items=items, destination_format=destination_format)
            )

  `def get_payload(self, items, destination_format)`
    Expand source code

        def get_payload(self, items, destination_format):
            supported_item_classes = AlternateId, AlternatePublicFolderId, AlternatePublicFolderItemId
            convertid = create_element('m:%s' % self.SERVICE_NAME, attrs=dict(DestinationFormat=destination_format))
            item_ids = create_element('m:SourceIds')
            for item in items:
                if not isinstance(item, supported_item_classes):
                    raise ValueError("'item' value %r must be an instance of %r" % (item, supported_item_classes))
                set_xml_value(item_ids, item, version=self.protocol.version)
            if not len(item_ids):
                raise ValueError('"items" must not be empty')
            convertid.append(item_ids)
            return convertid

  ### Inherited members

  - `EWSService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class CopyItem (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/copyitem-operation

  Expand source code

      class CopyItem(move_item.MoveItem):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/copyitem-operation"""

          SERVICE_NAME = 'CopyItem'

  ### Ancestors

  - MoveItem
  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`

  ### Inherited members

  - `MoveItem`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class CreateAttachment (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createattachment-operation

  Expand source code

      class CreateAttachment(EWSAccountService):
          """MSDN:
          https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createattachment-operation
          """

          SERVICE_NAME = 'CreateAttachment'
          element_container_name = '{%s}Attachments' % MNS

          def call(self, parent_item, items):
              return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=items, parent_item=parent_item))

          def _elems_to_objs(self, elems):
              from ..attachments import FileAttachment, ItemAttachment
              cls_map = {cls.response_tag(): cls for cls in (FileAttachment, ItemAttachment)}
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield cls_map[elem.tag].from_xml(elem=elem, account=self.account)

          def get_payload(self, items, parent_item):
              from ..items import BaseItem
              payload = create_element('m:%s' % self.SERVICE_NAME)
              version = self.account.version
              if isinstance(parent_item, BaseItem):
                  # to_item_id() would convert this to a normal ItemId, but the service wants a ParentItemId
                  parent_item = ParentItemId(parent_item.id, parent_item.changekey)
              set_xml_value(payload, to_item_id(parent_item, ParentItemId, version=version), version=version)
              attachments = create_element('m:Attachments')
              for item in items:
                  set_xml_value(attachments, item, version=self.account.version)
              if not len(attachments):
                  raise ValueError('"items" must not be empty')
              payload.append(attachments)
              return payload

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`

  ### Methods

  `def call(self, parent_item, items)`
    Expand source code

        def call(self, parent_item, items):
            return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=items, parent_item=parent_item))

  `def get_payload(self, items, parent_item)`
    Expand source code

        def get_payload(self, items, parent_item):
            from ..items import BaseItem
            payload = create_element('m:%s' % self.SERVICE_NAME)
            version = self.account.version
            if isinstance(parent_item, BaseItem):
                # to_item_id() would convert this to a normal ItemId, but the service wants a ParentItemId
                parent_item = ParentItemId(parent_item.id, parent_item.changekey)
            set_xml_value(payload, to_item_id(parent_item, ParentItemId, version=version), version=version)
            attachments = create_element('m:Attachments')
            for item in items:
                set_xml_value(attachments, item, version=self.account.version)
            if not len(attachments):
                raise ValueError('"items" must not be empty')
            payload.append(attachments)
            return payload

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class CreateFolder (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createfolder-operation

  Expand source code

      class CreateFolder(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createfolder-operation"""

          SERVICE_NAME = 'CreateFolder'
          element_container_name = '{%s}Folders' % MNS

          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              self.folders = []  # A hack to communicate parsing args to _elems_to_objs()

          def call(self, parent_folder, folders):
              # We can't easily find the correct folder class from the returned XML. Instead, return objects with the same
              # class as the folder instance it was requested with.
              self.folders = list(folders)  # Convert to a list, in case 'folders' is a generator. We're iterating twice.
              return self._elems_to_objs(self._chunked_get_elements(
                      self.get_payload, items=self.folders, parent_folder=parent_folder,
              ))

          def _elems_to_objs(self, elems):
              for folder, elem in zip(self.folders, elems):
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield parse_folder_elem(elem=elem, folder=folder, account=self.account)

          def get_payload(self, folders, parent_folder):
              create_folder = create_element('m:%s' % self.SERVICE_NAME)
              parentfolderid = create_element('m:ParentFolderId')
              set_xml_value(parentfolderid, parent_folder, version=self.account.version)
              set_xml_value(create_folder, parentfolderid, version=self.account.version)
              folder_ids = create_folder_ids_element(tag='m:Folders', folders=folders, version=self.account.version)
              create_folder.append(folder_ids)
              return create_folder

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`

  ### Methods

  `def call(self, parent_folder, folders)`
    Expand source code

        def call(self, parent_folder, folders):
            # We can't easily find the correct folder class from the returned XML. Instead, return objects with the same
            # class as the folder instance it was requested with.
            self.folders = list(folders)  # Convert to a list, in case 'folders' is a generator. We're iterating twice.
            return self._elems_to_objs(self._chunked_get_elements(
                    self.get_payload, items=self.folders, parent_folder=parent_folder,
            ))

  `def get_payload(self, folders, parent_folder)`
    Expand source code

        def get_payload(self, folders, parent_folder):
            create_folder = create_element('m:%s' % self.SERVICE_NAME)
            parentfolderid = create_element('m:ParentFolderId')
            set_xml_value(parentfolderid, parent_folder, version=self.account.version)
            set_xml_value(create_folder, parentfolderid, version=self.account.version)
            folder_ids = create_folder_ids_element(tag='m:Folders', folders=folders, version=self.account.version)
            create_folder.append(folder_ids)
            return create_folder

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class CreateItem (*args, **kwargs)`

  Take a folder and a list of items. Return the result of creation as a list of tuples (success[True|False], errormessage), in the same order as the input list.

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createitem-operation

  Expand source code

      class CreateItem(EWSAccountService):
          """Take a folder and a list of items. Return the result of creation as a list of tuples (success[True|False],
          errormessage), in the same order as the input list.

          MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createitem-operation
          """

          SERVICE_NAME = 'CreateItem'
          element_container_name = '{%s}Items' % MNS

          def call(self, items, folder, message_disposition, send_meeting_invitations):
              from ..folders import BaseFolder, FolderId
              from ..items import SAVE_ONLY, SEND_AND_SAVE_COPY, SEND_ONLY, \
                  SEND_MEETING_INVITATIONS_CHOICES, MESSAGE_DISPOSITION_CHOICES
              if message_disposition not in MESSAGE_DISPOSITION_CHOICES:
                  raise ValueError("'message_disposition' %s must be one of %s" % (
                      message_disposition, MESSAGE_DISPOSITION_CHOICES
                  ))
              if send_meeting_invitations not in SEND_MEETING_INVITATIONS_CHOICES:
                  raise ValueError("'send_meeting_invitations' %s must be one of %s" % (
                      send_meeting_invitations, SEND_MEETING_INVITATIONS_CHOICES
                  ))
              if folder is not None:
                  if not isinstance(folder, (BaseFolder, FolderId)):
                      raise ValueError("'folder' %r must be a Folder or FolderId instance" % folder)
                  if folder.account != self.account:
                      raise ValueError('"Folder must belong to this account')
              if message_disposition == SAVE_ONLY and folder is None:
                  raise AttributeError("Folder must be supplied when in save-only mode")
              if message_disposition == SEND_AND_SAVE_COPY and folder is None:
                  folder = self.account.sent  # 'Sent' is default EWS behaviour
              if message_disposition == SEND_ONLY and folder is not None:
                  raise AttributeError("Folder must be None in send-ony mode")
              return self._elems_to_objs(self._chunked_get_elements(
                  self.get_payload,
                  items=items,
                  folder=folder,
                  message_disposition=message_disposition,
                  send_meeting_invitations=send_meeting_invitations,
              ))

          def _elems_to_objs(self, elems):
              from ..items import BulkCreateResult
              for elem in elems:
                  if isinstance(elem, (Exception, type(None))):
                      yield elem
                      continue
                  if isinstance(elem, bool):
                      yield elem
                      continue
                  yield BulkCreateResult.from_xml(elem=elem, account=self.account)

          @classmethod
          def _get_elements_in_container(cls, container):
              res = super()._get_elements_in_container(container)
              return res or [True]

          def get_payload(self, items, folder, message_disposition, send_meeting_invitations):
              """Take a list of Item objects (CalendarItem, Message etc) and return the XML for a CreateItem request.
              convert items to XML Elements.

              MessageDisposition is only applicable to email messages, where it is required.

              SendMeetingInvitations is required for calendar items. It is also applicable to tasks, meeting request
              responses (see
              https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createitem-operation-meeting-request
              ) and sharing
              invitation accepts (see
              https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createitem-acceptsharinginvitation
              ). The last two are not supported yet.

              :param items:
              :param folder:
              :param message_disposition:
              :param send_meeting_invitations:
              """
              createitem = create_element(
                  'm:%s' % self.SERVICE_NAME,
                  attrs=OrderedDict([
                      ('MessageDisposition', message_disposition),
                      ('SendMeetingInvitations', send_meeting_invitations),
                  ])
              )
              if folder:
                  saveditemfolderid = create_element('m:SavedItemFolderId')
                  set_xml_value(saveditemfolderid, folder, version=self.account.version)
                  createitem.append(saveditemfolderid)
              item_elems = create_element('m:Items')
              for item in items:
                  if not item.account:
                      item.account = self.account
                  set_xml_value(item_elems, item, version=self.account.version)
              if not len(item_elems):
                  raise ValueError('"items" must not be empty')
              createitem.append(item_elems)
              return createitem

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`

  ### Methods

  `def call(self, items, folder, message_disposition, send_meeting_invitations)`
    Expand source code

        def call(self, items, folder, message_disposition, send_meeting_invitations):
            from ..folders import BaseFolder, FolderId
            from ..items import SAVE_ONLY, SEND_AND_SAVE_COPY, SEND_ONLY, \
                SEND_MEETING_INVITATIONS_CHOICES, MESSAGE_DISPOSITION_CHOICES
            if message_disposition not in MESSAGE_DISPOSITION_CHOICES:
                raise ValueError("'message_disposition' %s must be one of %s" % (
                    message_disposition, MESSAGE_DISPOSITION_CHOICES
                ))
            if send_meeting_invitations not in SEND_MEETING_INVITATIONS_CHOICES:
                raise ValueError("'send_meeting_invitations' %s must be one of %s" % (
                    send_meeting_invitations, SEND_MEETING_INVITATIONS_CHOICES
                ))
            if folder is not None:
                if not isinstance(folder, (BaseFolder, FolderId)):
                    raise ValueError("'folder' %r must be a Folder or FolderId instance" % folder)
                if folder.account != self.account:
                    raise ValueError('"Folder must belong to this account')
            if message_disposition == SAVE_ONLY and folder is None:
                raise AttributeError("Folder must be supplied when in save-only mode")
            if message_disposition == SEND_AND_SAVE_COPY and folder is None:
                folder = self.account.sent  # 'Sent' is default EWS behaviour
            if message_disposition == SEND_ONLY and folder is not None:
                raise AttributeError("Folder must be None in send-ony mode")
            return self._elems_to_objs(self._chunked_get_elements(
                self.get_payload,
                items=items,
                folder=folder,
                message_disposition=message_disposition,
                send_meeting_invitations=send_meeting_invitations,
            ))

  `def get_payload(self, items, folder, message_disposition, send_meeting_invitations)`

    Take a list of Item objects (CalendarItem, Message etc) and return the XML for a CreateItem request. convert items to XML Elements.

    MessageDisposition is only applicable to email messages, where it is required.

    SendMeetingInvitations is required for calendar items. It is also applicable to tasks, meeting request responses (see https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createitem-operation-meeting-request ) and sharing invitation accepts (see https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createitem-acceptsharinginvitation ). The last two are not supported yet.

    :param items: :param folder: :param message_disposition: :param send_meeting_invitations:

    Expand source code

        def get_payload(self, items, folder, message_disposition, send_meeting_invitations):
            """Take a list of Item objects (CalendarItem, Message etc) and return the XML for a CreateItem request.
            convert items to XML Elements.

            MessageDisposition is only applicable to email messages, where it is required.

            SendMeetingInvitations is required for calendar items. It is also applicable to tasks, meeting request
            responses (see
            https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createitem-operation-meeting-request
            ) and sharing
            invitation accepts (see
            https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createitem-acceptsharinginvitation
            ). The last two are not supported yet.

            :param items:
            :param folder:
            :param message_disposition:
            :param send_meeting_invitations:
            """
            createitem = create_element(
                'm:%s' % self.SERVICE_NAME,
                attrs=OrderedDict([
                    ('MessageDisposition', message_disposition),
                    ('SendMeetingInvitations', send_meeting_invitations),
                ])
            )
            if folder:
                saveditemfolderid = create_element('m:SavedItemFolderId')
                set_xml_value(saveditemfolderid, folder, version=self.account.version)
                createitem.append(saveditemfolderid)
            item_elems = create_element('m:Items')
            for item in items:
                if not item.account:
                    item.account = self.account
                set_xml_value(item_elems, item, version=self.account.version)
            if not len(item_elems):
                raise ValueError('"items" must not be empty')
            createitem.append(item_elems)
            return createitem

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class CreateUserConfiguration (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createuserconfiguration-operation

  Expand source code

      class CreateUserConfiguration(EWSAccountService):
          """MSDN:
          https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/createuserconfiguration-operation
          """

          SERVICE_NAME = 'CreateUserConfiguration'
          returns_elements = False

          def call(self, user_configuration):
              return self._get_elements(payload=self.get_payload(user_configuration=user_configuration))

          def get_payload(self, user_configuration):
              createuserconfiguration = create_element('m:%s' % self.SERVICE_NAME)
              set_xml_value(createuserconfiguration, user_configuration, version=self.protocol.version)
              return createuserconfiguration

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var returns_elements`

  ### Methods

  `def call(self, user_configuration)`
    Expand source code

        def call(self, user_configuration):
            return self._get_elements(payload=self.get_payload(user_configuration=user_configuration))

  `def get_payload(self, user_configuration)`
    Expand source code

        def get_payload(self, user_configuration):
            createuserconfiguration = create_element('m:%s' % self.SERVICE_NAME)
            set_xml_value(createuserconfiguration, user_configuration, version=self.protocol.version)
            return createuserconfiguration

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class DeleteAttachment (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/deleteattachment-operation

  Expand source code

      class DeleteAttachment(EWSAccountService):
          """MSDN:
          https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/deleteattachment-operation
          """

          SERVICE_NAME = 'DeleteAttachment'

          def call(self, items):
              return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=items))

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield RootItemId.from_xml(elem=elem, account=self.account)

          @classmethod
          def _get_elements_in_container(cls, container):
              return container.findall(RootItemId.response_tag())

          def get_payload(self, items):
              payload = create_element('m:%s' % self.SERVICE_NAME)
              attachment_ids = create_attachment_ids_element(items=items, version=self.account.version)
              payload.append(attachment_ids)
              return payload

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`

  ### Methods

  `def call(self, items)`
    Expand source code

        def call(self, items):
            return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=items))

  `def get_payload(self, items)`
    Expand source code

        def get_payload(self, items):
            payload = create_element('m:%s' % self.SERVICE_NAME)
            attachment_ids = create_attachment_ids_element(items=items, version=self.account.version)
            payload.append(attachment_ids)
            return payload

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class DeleteFolder (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/deletefolder-operation

  Expand source code

      class DeleteFolder(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/deletefolder-operation"""

          SERVICE_NAME = 'DeleteFolder'
          returns_elements = False

          def call(self, folders, delete_type):
              return self._chunked_get_elements(self.get_payload, items=folders, delete_type=delete_type)

          def get_payload(self, folders, delete_type):
              deletefolder = create_element('m:%s' % self.SERVICE_NAME, attrs=dict(DeleteType=delete_type))
              folder_ids = create_folder_ids_element(tag='m:FolderIds', folders=folders, version=self.account.version)
              deletefolder.append(folder_ids)
              return deletefolder

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var returns_elements`

  ### Methods

  `def call(self, folders, delete_type)`
    Expand source code

        def call(self, folders, delete_type):
            return self._chunked_get_elements(self.get_payload, items=folders, delete_type=delete_type)

  `def get_payload(self, folders, delete_type)`
    Expand source code

        def get_payload(self, folders, delete_type):
            deletefolder = create_element('m:%s' % self.SERVICE_NAME, attrs=dict(DeleteType=delete_type))
            folder_ids = create_folder_ids_element(tag='m:FolderIds', folders=folders, version=self.account.version)
            deletefolder.append(folder_ids)
            return deletefolder

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class DeleteItem (*args, **kwargs)`

  Take a folder and a list of (id, changekey) tuples. Return result of deletion as a list of tuples (success[True|False], errormessage), in the same order as the input list.

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/deleteitem-operation

  Expand source code

      class DeleteItem(EWSAccountService):
          """Take a folder and a list of (id, changekey) tuples. Return result of deletion as a list of tuples
          (success[True|False], errormessage), in the same order as the input list.

          MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/deleteitem-operation
          """

          SERVICE_NAME = 'DeleteItem'
          returns_elements = False

          def call(self, items, delete_type, send_meeting_cancellations, affected_task_occurrences, suppress_read_receipts):
              from ..items import DELETE_TYPE_CHOICES, SEND_MEETING_CANCELLATIONS_CHOICES, AFFECTED_TASK_OCCURRENCES_CHOICES
              if delete_type not in DELETE_TYPE_CHOICES:
                  raise ValueError("'delete_type' %s must be one of %s" % (
                      delete_type, DELETE_TYPE_CHOICES
                  ))
              if send_meeting_cancellations not in SEND_MEETING_CANCELLATIONS_CHOICES:
                  raise ValueError("'send_meeting_cancellations' %s must be one of %s" % (
                      send_meeting_cancellations, SEND_MEETING_CANCELLATIONS_CHOICES
                  ))
              if affected_task_occurrences not in AFFECTED_TASK_OCCURRENCES_CHOICES:
                  raise ValueError("'affected_task_occurrences' %s must be one of %s" % (
                      affected_task_occurrences, AFFECTED_TASK_OCCURRENCES_CHOICES
                  ))
              if suppress_read_receipts not in (True, False):
                  raise ValueError("'suppress_read_receipts' %s must be True or False" % suppress_read_receipts)
              return self._chunked_get_elements(
                  self.get_payload,
                  items=items,
                  delete_type=delete_type,
                  send_meeting_cancellations=send_meeting_cancellations,
                  affected_task_occurrences=affected_task_occurrences,
                  suppress_read_receipts=suppress_read_receipts,
              )

          def get_payload(self, items, delete_type, send_meeting_cancellations, affected_task_occurrences,
                          suppress_read_receipts):
              # Takes a list of (id, changekey) tuples or Item objects and returns the XML for a DeleteItem request.
              if self.account.version.build >= EXCHANGE_2013_SP1:
                  deleteitem = create_element(
                      'm:%s' % self.SERVICE_NAME,
                      attrs=OrderedDict([
                          ('DeleteType', delete_type),
                          ('SendMeetingCancellations', send_meeting_cancellations),
                          ('AffectedTaskOccurrences', affected_task_occurrences),
                          ('SuppressReadReceipts', 'true' if suppress_read_receipts else 'false'),
                      ])
                  )
              else:
                  deleteitem = create_element(
                      'm:%s' % self.SERVICE_NAME,
                      attrs=OrderedDict([
                          ('DeleteType', delete_type),
                          ('SendMeetingCancellations', send_meeting_cancellations),
                          ('AffectedTaskOccurrences', affected_task_occurrences),
                       ])
                  )

              item_ids = create_item_ids_element(items=items, version=self.account.version)
              deleteitem.append(item_ids)
              return deleteitem

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var returns_elements`

  ### Methods

  `def call(self, items, delete_type, send_meeting_cancellations, affected_task_occurrences, suppress_read_receipts)`
    Expand source code

        def call(self, items, delete_type, send_meeting_cancellations, affected_task_occurrences, suppress_read_receipts):
            from ..items import DELETE_TYPE_CHOICES, SEND_MEETING_CANCELLATIONS_CHOICES, AFFECTED_TASK_OCCURRENCES_CHOICES
            if delete_type not in DELETE_TYPE_CHOICES:
                raise ValueError("'delete_type' %s must be one of %s" % (
                    delete_type, DELETE_TYPE_CHOICES
                ))
            if send_meeting_cancellations not in SEND_MEETING_CANCELLATIONS_CHOICES:
                raise ValueError("'send_meeting_cancellations' %s must be one of %s" % (
                    send_meeting_cancellations, SEND_MEETING_CANCELLATIONS_CHOICES
                ))
            if affected_task_occurrences not in AFFECTED_TASK_OCCURRENCES_CHOICES:
                raise ValueError("'affected_task_occurrences' %s must be one of %s" % (
                    affected_task_occurrences, AFFECTED_TASK_OCCURRENCES_CHOICES
                ))
            if suppress_read_receipts not in (True, False):
                raise ValueError("'suppress_read_receipts' %s must be True or False" % suppress_read_receipts)
            return self._chunked_get_elements(
                self.get_payload,
                items=items,
                delete_type=delete_type,
                send_meeting_cancellations=send_meeting_cancellations,
                affected_task_occurrences=affected_task_occurrences,
                suppress_read_receipts=suppress_read_receipts,
            )

  `def get_payload(self, items, delete_type, send_meeting_cancellations, affected_task_occurrences, suppress_read_receipts)`
    Expand source code

        def get_payload(self, items, delete_type, send_meeting_cancellations, affected_task_occurrences,
                        suppress_read_receipts):
            # Takes a list of (id, changekey) tuples or Item objects and returns the XML for a DeleteItem request.
            if self.account.version.build >= EXCHANGE_2013_SP1:
                deleteitem = create_element(
                    'm:%s' % self.SERVICE_NAME,
                    attrs=OrderedDict([
                        ('DeleteType', delete_type),
                        ('SendMeetingCancellations', send_meeting_cancellations),
                        ('AffectedTaskOccurrences', affected_task_occurrences),
                        ('SuppressReadReceipts', 'true' if suppress_read_receipts else 'false'),
                    ])
                )
            else:
                deleteitem = create_element(
                    'm:%s' % self.SERVICE_NAME,
                    attrs=OrderedDict([
                        ('DeleteType', delete_type),
                        ('SendMeetingCancellations', send_meeting_cancellations),
                        ('AffectedTaskOccurrences', affected_task_occurrences),
                     ])
                )

            item_ids = create_item_ids_element(items=items, version=self.account.version)
            deleteitem.append(item_ids)
            return deleteitem

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class DeleteUserConfiguration (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/deleteuserconfiguration-operation

  Expand source code

      class DeleteUserConfiguration(EWSAccountService):
          """MSDN:
          https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/deleteuserconfiguration-operation
          """

          SERVICE_NAME = 'DeleteUserConfiguration'
          returns_elements = False

          def call(self, user_configuration_name):
              return self._get_elements(payload=self.get_payload(user_configuration_name=user_configuration_name))

          def get_payload(self, user_configuration_name):
              deleteuserconfiguration = create_element('m:%s' % self.SERVICE_NAME)
              set_xml_value(deleteuserconfiguration, user_configuration_name, version=self.account.version)
              return deleteuserconfiguration

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var returns_elements`

  ### Methods

  `def call(self, user_configuration_name)`
    Expand source code

        def call(self, user_configuration_name):
            return self._get_elements(payload=self.get_payload(user_configuration_name=user_configuration_name))

  `def get_payload(self, user_configuration_name)`
    Expand source code

        def get_payload(self, user_configuration_name):
            deleteuserconfiguration = create_element('m:%s' % self.SERVICE_NAME)
            set_xml_value(deleteuserconfiguration, user_configuration_name, version=self.account.version)
            return deleteuserconfiguration

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class EmptyFolder (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/emptyfolder-operation

  Expand source code

      class EmptyFolder(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/emptyfolder-operation"""

          SERVICE_NAME = 'EmptyFolder'
          returns_elements = False

          def call(self, folders, delete_type, delete_sub_folders):
              return self._chunked_get_elements(
                  self.get_payload, items=folders, delete_type=delete_type, delete_sub_folders=delete_sub_folders
              )

          def get_payload(self, folders, delete_type, delete_sub_folders):
              emptyfolder = create_element(
                  'm:%s' % self.SERVICE_NAME,
                  attrs=OrderedDict([
                      ('DeleteType', delete_type),
                      ('DeleteSubFolders', 'true' if delete_sub_folders else 'false'),
                  ])
              )
              folder_ids = create_folder_ids_element(tag='m:FolderIds', folders=folders, version=self.account.version)
              emptyfolder.append(folder_ids)
              return emptyfolder

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var returns_elements`

  ### Methods

  `def call(self, folders, delete_type, delete_sub_folders)`
    Expand source code

        def call(self, folders, delete_type, delete_sub_folders):
            return self._chunked_get_elements(
                self.get_payload, items=folders, delete_type=delete_type, delete_sub_folders=delete_sub_folders
            )

  `def get_payload(self, folders, delete_type, delete_sub_folders)`
    Expand source code

        def get_payload(self, folders, delete_type, delete_sub_folders):
            emptyfolder = create_element(
                'm:%s' % self.SERVICE_NAME,
                attrs=OrderedDict([
                    ('DeleteType', delete_type),
                    ('DeleteSubFolders', 'true' if delete_sub_folders else 'false'),
                ])
            )
            folder_ids = create_folder_ids_element(tag='m:FolderIds', folders=folders, version=self.account.version)
            emptyfolder.append(folder_ids)
            return emptyfolder

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class ExpandDL (protocol, chunk_size=None, timeout=None)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/expanddl-operation

  Expand source code

      class ExpandDL(EWSService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/expanddl-operation"""

          SERVICE_NAME = 'ExpandDL'
          element_container_name = '{%s}DLExpansion' % MNS
          WARNINGS_TO_IGNORE_IN_RESPONSE = ErrorNameResolutionMultipleResults

          def call(self, distribution_list):
              return self._elems_to_objs(self._get_elements(payload=self.get_payload(distribution_list=distribution_list)))

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield Mailbox.from_xml(elem, account=None)

          def get_payload(self, distribution_list):
              payload = create_element('m:%s' % self.SERVICE_NAME)
              set_xml_value(payload, distribution_list, version=self.protocol.version)
              return payload

  ### Ancestors

  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var WARNINGS_TO_IGNORE_IN_RESPONSE`

    Global error type within this module.

  `var element_container_name`

  ### Methods

  `def call(self, distribution_list)`
    Expand source code

        def call(self, distribution_list):
            return self._elems_to_objs(self._get_elements(payload=self.get_payload(distribution_list=distribution_list)))

  `def get_payload(self, distribution_list)`
    Expand source code

        def get_payload(self, distribution_list):
            payload = create_element('m:%s' % self.SERVICE_NAME)
            set_xml_value(payload, distribution_list, version=self.protocol.version)
            return payload

  ### Inherited members

  - `EWSService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class ExportItems (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/exportitems-operation

  Expand source code

      class ExportItems(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/exportitems-operation"""

          ERRORS_TO_CATCH_IN_RESPONSE = ResponseMessageError
          SERVICE_NAME = 'ExportItems'
          element_container_name = '{%s}Data' % MNS

          def call(self, items):
              return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=items))

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield elem.text  # All we want is the 64bit string in the 'Data' tag

          def get_payload(self, items):
              exportitems = create_element('m:%s' % self.SERVICE_NAME)
              item_ids = create_item_ids_element(items=items, version=self.account.version)
              exportitems.append(item_ids)
              return exportitems

          # We need to override this since ExportItemsResponseMessage is formatted a
          # little bit differently. .
          @classmethod
          def _get_elements_in_container(cls, container):
              return [container]

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var ERRORS_TO_CATCH_IN_RESPONSE`

    Global error type within this module.

  `var SERVICE_NAME`
  `var element_container_name`

  ### Methods

  `def call(self, items)`
    Expand source code

        def call(self, items):
            return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=items))

  `def get_payload(self, items)`
    Expand source code

        def get_payload(self, items):
            exportitems = create_element('m:%s' % self.SERVICE_NAME)
            item_ids = create_item_ids_element(items=items, version=self.account.version)
            exportitems.append(item_ids)
            return exportitems

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class FindFolder (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/findfolder-operation

  Expand source code

      class FindFolder(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/findfolder-operation"""

          SERVICE_NAME = 'FindFolder'
          element_container_name = '{%s}Folders' % TNS
          paging_container_name = '{%s}RootFolder' % MNS
          supports_paging = True

          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              self.root = None  # A hack to communicate parsing args to _elems_to_objs()

          def call(self, folders, additional_fields, restriction, shape, depth, max_items, offset):
              """Find subfolders of a folder.

              :param folders: the folders to act on
              :param additional_fields: the extra fields that should be returned with the folder, as FieldPath objects
              :param restriction: Restriction object that defines the filters for the query
              :param shape: The set of attributes to return
              :param depth: How deep in the folder structure to search for folders
              :param max_items: The maximum number of items to return
              :param offset: the offset relative to the first item in the item collection. Usually 0.

              :return: XML elements for the matching folders
              """
              roots = {f.root for f in folders}
              if len(roots) != 1:
                  raise ValueError('FindFolder must be called with folders in the same root hierarchy (%r)' % roots)
              self.root = roots.pop()
              return self._elems_to_objs(self._paged_call(
                      payload_func=self.get_payload,
                      max_items=max_items,
                      folders=folders,
                      **dict(
                          additional_fields=additional_fields,
                          restriction=restriction,
                          shape=shape,
                          depth=depth,
                          page_size=self.chunk_size,
                          offset=offset,
                      )
              ))

          def _elems_to_objs(self, elems):
              from ..folders import Folder
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield Folder.from_xml_with_root(elem=elem, root=self.root)

          def get_payload(self, folders, additional_fields, restriction, shape, depth, page_size, offset=0):
              findfolder = create_element('m:%s' % self.SERVICE_NAME, attrs=dict(Traversal=depth))
              foldershape = create_shape_element(
                  tag='m:FolderShape', shape=shape, additional_fields=additional_fields, version=self.account.version
              )
              findfolder.append(foldershape)
              if self.account.version.build >= EXCHANGE_2010:
                  indexedpageviewitem = create_element(
                      'm:IndexedPageFolderView',
                      attrs=OrderedDict([
                          ('MaxEntriesReturned', str(page_size)),
                          ('Offset', str(offset)),
                          ('BasePoint', 'Beginning'),
                      ])
                  )
                  findfolder.append(indexedpageviewitem)
              else:
                  if offset != 0:
                      raise ValueError('Offsets are only supported from Exchange 2010')
              if restriction:
                  findfolder.append(restriction.to_xml(version=self.account.version))
              parentfolderids = create_element('m:ParentFolderIds')
              set_xml_value(parentfolderids, folders, version=self.account.version)
              findfolder.append(parentfolderids)
              return findfolder

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`
  `var paging_container_name`
  `var supports_paging`

  ### Methods

  `def call(self, folders, additional_fields, restriction, shape, depth, max_items, offset)`

    Find subfolders of a folder.

    :param folders: the folders to act on :param additional_fields: the extra fields that should be returned with the folder, as FieldPath objects :param restriction: Restriction object that defines the filters for the query :param shape: The set of attributes to return :param depth: How deep in the folder structure to search for folders :param max_items: The maximum number of items to return :param offset: the offset relative to the first item in the item collection. Usually 0.

    :return: XML elements for the matching folders

    Expand source code

        def call(self, folders, additional_fields, restriction, shape, depth, max_items, offset):
            """Find subfolders of a folder.

            :param folders: the folders to act on
            :param additional_fields: the extra fields that should be returned with the folder, as FieldPath objects
            :param restriction: Restriction object that defines the filters for the query
            :param shape: The set of attributes to return
            :param depth: How deep in the folder structure to search for folders
            :param max_items: The maximum number of items to return
            :param offset: the offset relative to the first item in the item collection. Usually 0.

            :return: XML elements for the matching folders
            """
            roots = {f.root for f in folders}
            if len(roots) != 1:
                raise ValueError('FindFolder must be called with folders in the same root hierarchy (%r)' % roots)
            self.root = roots.pop()
            return self._elems_to_objs(self._paged_call(
                    payload_func=self.get_payload,
                    max_items=max_items,
                    folders=folders,
                    **dict(
                        additional_fields=additional_fields,
                        restriction=restriction,
                        shape=shape,
                        depth=depth,
                        page_size=self.chunk_size,
                        offset=offset,
                    )
            ))

  `def get_payload(self, folders, additional_fields, restriction, shape, depth, page_size, offset=0)`
    Expand source code

        def get_payload(self, folders, additional_fields, restriction, shape, depth, page_size, offset=0):
            findfolder = create_element('m:%s' % self.SERVICE_NAME, attrs=dict(Traversal=depth))
            foldershape = create_shape_element(
                tag='m:FolderShape', shape=shape, additional_fields=additional_fields, version=self.account.version
            )
            findfolder.append(foldershape)
            if self.account.version.build >= EXCHANGE_2010:
                indexedpageviewitem = create_element(
                    'm:IndexedPageFolderView',
                    attrs=OrderedDict([
                        ('MaxEntriesReturned', str(page_size)),
                        ('Offset', str(offset)),
                        ('BasePoint', 'Beginning'),
                    ])
                )
                findfolder.append(indexedpageviewitem)
            else:
                if offset != 0:
                    raise ValueError('Offsets are only supported from Exchange 2010')
            if restriction:
                findfolder.append(restriction.to_xml(version=self.account.version))
            parentfolderids = create_element('m:ParentFolderIds')
            set_xml_value(parentfolderids, folders, version=self.account.version)
            findfolder.append(parentfolderids)
            return findfolder

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class FindItem (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/finditem-operation

  Expand source code

      class FindItem(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/finditem-operation"""

          SERVICE_NAME = 'FindItem'
          element_container_name = '{%s}Items' % TNS
          paging_container_name = '{%s}RootFolder' % MNS
          supports_paging = True

          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              # A hack to communicate parsing args to _elems_to_objs()
              self.additional_fields = None
              self.shape = None

          def call(self, folders, additional_fields, restriction, order_fields, shape, query_string, depth, calendar_view,
                   max_items, offset):
              """Find items in an account.

              :param folders: the folders to act on
              :param additional_fields: the extra fields that should be returned with the item, as FieldPath objects
              :param restriction: a Restriction object for
              :param order_fields: the fields to sort the results by
              :param shape: The set of attributes to return
              :param query_string: a QueryString object
              :param depth: How deep in the folder structure to search for items
              :param calendar_view: If set, returns recurring calendar items unfolded
              :param max_items: the max number of items to return
              :param offset: the offset relative to the first item in the item collection. Usually 0.

              :return: XML elements for the matching items
              """
              self.additional_fields = additional_fields
              self.shape = shape
              return self._elems_to_objs(self._paged_call(
                  payload_func=self.get_payload,
                  max_items=max_items,
                  folders=folders,
                  **dict(
                      additional_fields=additional_fields,
                      restriction=restriction,
                      order_fields=order_fields,
                      query_string=query_string,
                      shape=shape,
                      depth=depth,
                      calendar_view=calendar_view,
                      page_size=self.chunk_size,
                      offset=offset,
                  )
              ))

          def _elems_to_objs(self, elems):
              from ..folders.base import BaseFolder
              from ..items import Item, ID_ONLY
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  if self.shape == ID_ONLY and self.additional_fields is None:
                      yield Item.id_from_xml(elem)
                      continue
                  yield BaseFolder.item_model_from_tag(elem.tag).from_xml(elem=elem, account=self.account)

          def get_payload(self, folders, additional_fields, restriction, order_fields, query_string, shape, depth,
                          calendar_view, page_size, offset=0):
              finditem = create_element('m:%s' % self.SERVICE_NAME, attrs=dict(Traversal=depth))
              itemshape = create_shape_element(
                  tag='m:ItemShape', shape=shape, additional_fields=additional_fields, version=self.account.version
              )
              finditem.append(itemshape)
              if calendar_view is None:
                  view_type = create_element(
                      'm:IndexedPageItemView',
                      attrs=OrderedDict([
                          ('MaxEntriesReturned', str(page_size)),
                          ('Offset', str(offset)),
                          ('BasePoint', 'Beginning'),
                      ])
                  )
              else:
                  view_type = calendar_view.to_xml(version=self.account.version)
              finditem.append(view_type)
              if restriction:
                  finditem.append(restriction.to_xml(version=self.account.version))
              if order_fields:
                  finditem.append(set_xml_value(
                      create_element('m:SortOrder'),
                      order_fields,
                      version=self.account.version
                  ))
              finditem.append(set_xml_value(
                  create_element('m:ParentFolderIds'),
                  folders,
                  version=self.account.version
              ))
              if query_string:
                  finditem.append(query_string.to_xml(version=self.account.version))
              return finditem

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`
  `var paging_container_name`
  `var supports_paging`

  ### Methods

  `def call(self, folders, additional_fields, restriction, order_fields, shape, query_string, depth, calendar_view, max_items, offset)`

    Find items in an account.

    :param folders: the folders to act on :param additional_fields: the extra fields that should be returned with the item, as FieldPath objects :param restriction: a Restriction object for :param order_fields: the fields to sort the results by :param shape: The set of attributes to return :param query_string: a QueryString object :param depth: How deep in the folder structure to search for items :param calendar_view: If set, returns recurring calendar items unfolded :param max_items: the max number of items to return :param offset: the offset relative to the first item in the item collection. Usually 0.

    :return: XML elements for the matching items

    Expand source code

        def call(self, folders, additional_fields, restriction, order_fields, shape, query_string, depth, calendar_view,
                 max_items, offset):
            """Find items in an account.

            :param folders: the folders to act on
            :param additional_fields: the extra fields that should be returned with the item, as FieldPath objects
            :param restriction: a Restriction object for
            :param order_fields: the fields to sort the results by
            :param shape: The set of attributes to return
            :param query_string: a QueryString object
            :param depth: How deep in the folder structure to search for items
            :param calendar_view: If set, returns recurring calendar items unfolded
            :param max_items: the max number of items to return
            :param offset: the offset relative to the first item in the item collection. Usually 0.

            :return: XML elements for the matching items
            """
            self.additional_fields = additional_fields
            self.shape = shape
            return self._elems_to_objs(self._paged_call(
                payload_func=self.get_payload,
                max_items=max_items,
                folders=folders,
                **dict(
                    additional_fields=additional_fields,
                    restriction=restriction,
                    order_fields=order_fields,
                    query_string=query_string,
                    shape=shape,
                    depth=depth,
                    calendar_view=calendar_view,
                    page_size=self.chunk_size,
                    offset=offset,
                )
            ))

  `def get_payload(self, folders, additional_fields, restriction, order_fields, query_string, shape, depth, calendar_view, page_size, offset=0)`
    Expand source code

        def get_payload(self, folders, additional_fields, restriction, order_fields, query_string, shape, depth,
                        calendar_view, page_size, offset=0):
            finditem = create_element('m:%s' % self.SERVICE_NAME, attrs=dict(Traversal=depth))
            itemshape = create_shape_element(
                tag='m:ItemShape', shape=shape, additional_fields=additional_fields, version=self.account.version
            )
            finditem.append(itemshape)
            if calendar_view is None:
                view_type = create_element(
                    'm:IndexedPageItemView',
                    attrs=OrderedDict([
                        ('MaxEntriesReturned', str(page_size)),
                        ('Offset', str(offset)),
                        ('BasePoint', 'Beginning'),
                    ])
                )
            else:
                view_type = calendar_view.to_xml(version=self.account.version)
            finditem.append(view_type)
            if restriction:
                finditem.append(restriction.to_xml(version=self.account.version))
            if order_fields:
                finditem.append(set_xml_value(
                    create_element('m:SortOrder'),
                    order_fields,
                    version=self.account.version
                ))
            finditem.append(set_xml_value(
                create_element('m:ParentFolderIds'),
                folders,
                version=self.account.version
            ))
            if query_string:
                finditem.append(query_string.to_xml(version=self.account.version))
            return finditem

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class FindPeople (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/findpeople-operation

  Expand source code

      class FindPeople(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/findpeople-operation"""

          SERVICE_NAME = 'FindPeople'
          element_container_name = '{%s}People' % MNS
          supported_from = EXCHANGE_2013
          supports_paging = True

          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              # A hack to communicate parsing args to _elems_to_objs()
              self.additional_fields = None
              self.shape = None

          def call(self, folder, additional_fields, restriction, order_fields, shape, query_string, depth, max_items, offset):
              """Find items in an account.

              :param folder: the Folder object to query
              :param additional_fields: the extra fields that should be returned with the item, as FieldPath objects
              :param restriction: a Restriction object for
              :param order_fields: the fields to sort the results by
              :param shape: The set of attributes to return
              :param query_string: a QueryString object
              :param depth: How deep in the folder structure to search for items
              :param max_items: the max number of items to return
              :param offset: the offset relative to the first item in the item collection. Usually 0.

              :return: XML elements for the matching items
              """
              self.additional_fields = additional_fields
              self.shape = shape
              return self._elems_to_objs(self._paged_call(
                  payload_func=self.get_payload,
                  max_items=max_items,
                  folders=[folder],  # We can only query one folder, so there will only be one element in response
                  **dict(
                      additional_fields=additional_fields,
                      restriction=restriction,
                      order_fields=order_fields,
                      query_string=query_string,
                      shape=shape,
                      depth=depth,
                      page_size=self.chunk_size,
                      offset=offset,
                  )
              ))

          def _elems_to_objs(self, elems):
              from ..items import Persona, ID_ONLY
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  if self.shape == ID_ONLY and self.additional_fields is None:
                      yield Persona.id_from_xml(elem)
                      continue
                  yield Persona.from_xml(elem, account=self.account)

          def get_payload(self, folders, additional_fields, restriction, order_fields, query_string, shape, depth, page_size,
                          offset=0):
              folders = list(folders)
              if len(folders) != 1:
                  raise ValueError('%r can only query one folder' % self.SERVICE_NAME)
              folder = folders[0]
              findpeople = create_element('m:%s' % self.SERVICE_NAME, attrs=dict(Traversal=depth))
              personashape = create_shape_element(
                  tag='m:PersonaShape', shape=shape, additional_fields=additional_fields, version=self.account.version
              )
              findpeople.append(personashape)
              view_type = create_element(
                  'm:IndexedPageItemView',
                  attrs=OrderedDict([
                      ('MaxEntriesReturned', str(page_size)),
                      ('Offset', str(offset)),
                      ('BasePoint', 'Beginning'),
                  ])
              )
              findpeople.append(view_type)
              if restriction:
                  findpeople.append(restriction.to_xml(version=self.account.version))
              if order_fields:
                  findpeople.append(set_xml_value(
                      create_element('m:SortOrder'),
                      order_fields,
                      version=self.account.version
                  ))
              findpeople.append(set_xml_value(
                  create_element('m:ParentFolderId'),
                  folder,
                  version=self.account.version
              ))
              if query_string:
                  findpeople.append(query_string.to_xml(version=self.account.version))
              return findpeople

          @staticmethod
          def _get_paging_values(elem):
              """Find paging values. The paging element from FindPeople is different from other paging containers."""
              item_count = int(elem.find('{%s}TotalNumberOfPeopleInView' % MNS).text)
              first_matching = int(elem.find('{%s}FirstMatchingRowIndex' % MNS).text)
              first_loaded = int(elem.find('{%s}FirstLoadedRowIndex' % MNS).text)
              log.debug('Got page with total items %s, first matching %s, first loaded %s ', item_count, first_matching,
                        first_loaded)
              next_offset = None  # GetPersona does not support fetching more pages
              return item_count, next_offset

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`
  `var supported_from`
  `var supports_paging`

  ### Methods

  `def call(self, folder, additional_fields, restriction, order_fields, shape, query_string, depth, max_items, offset)`

    Find items in an account.

    :param folder: the Folder object to query :param additional_fields: the extra fields that should be returned with the item, as FieldPath objects :param restriction: a Restriction object for :param order_fields: the fields to sort the results by :param shape: The set of attributes to return :param query_string: a QueryString object :param depth: How deep in the folder structure to search for items :param max_items: the max number of items to return :param offset: the offset relative to the first item in the item collection. Usually 0.

    :return: XML elements for the matching items

    Expand source code

        def call(self, folder, additional_fields, restriction, order_fields, shape, query_string, depth, max_items, offset):
            """Find items in an account.

            :param folder: the Folder object to query
            :param additional_fields: the extra fields that should be returned with the item, as FieldPath objects
            :param restriction: a Restriction object for
            :param order_fields: the fields to sort the results by
            :param shape: The set of attributes to return
            :param query_string: a QueryString object
            :param depth: How deep in the folder structure to search for items
            :param max_items: the max number of items to return
            :param offset: the offset relative to the first item in the item collection. Usually 0.

            :return: XML elements for the matching items
            """
            self.additional_fields = additional_fields
            self.shape = shape
            return self._elems_to_objs(self._paged_call(
                payload_func=self.get_payload,
                max_items=max_items,
                folders=[folder],  # We can only query one folder, so there will only be one element in response
                **dict(
                    additional_fields=additional_fields,
                    restriction=restriction,
                    order_fields=order_fields,
                    query_string=query_string,
                    shape=shape,
                    depth=depth,
                    page_size=self.chunk_size,
                    offset=offset,
                )
            ))

  `def get_payload(self, folders, additional_fields, restriction, order_fields, query_string, shape, depth, page_size, offset=0)`
    Expand source code

        def get_payload(self, folders, additional_fields, restriction, order_fields, query_string, shape, depth, page_size,
                        offset=0):
            folders = list(folders)
            if len(folders) != 1:
                raise ValueError('%r can only query one folder' % self.SERVICE_NAME)
            folder = folders[0]
            findpeople = create_element('m:%s' % self.SERVICE_NAME, attrs=dict(Traversal=depth))
            personashape = create_shape_element(
                tag='m:PersonaShape', shape=shape, additional_fields=additional_fields, version=self.account.version
            )
            findpeople.append(personashape)
            view_type = create_element(
                'm:IndexedPageItemView',
                attrs=OrderedDict([
                    ('MaxEntriesReturned', str(page_size)),
                    ('Offset', str(offset)),
                    ('BasePoint', 'Beginning'),
                ])
            )
            findpeople.append(view_type)
            if restriction:
                findpeople.append(restriction.to_xml(version=self.account.version))
            if order_fields:
                findpeople.append(set_xml_value(
                    create_element('m:SortOrder'),
                    order_fields,
                    version=self.account.version
                ))
            findpeople.append(set_xml_value(
                create_element('m:ParentFolderId'),
                folder,
                version=self.account.version
            ))
            if query_string:
                findpeople.append(query_string.to_xml(version=self.account.version))
            return findpeople

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetAttachment (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getattachment-operation

  Expand source code

      class GetAttachment(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getattachment-operation"""

          SERVICE_NAME = 'GetAttachment'
          element_container_name = '{%s}Attachments' % MNS

          def call(self, items, include_mime_content, body_type, filter_html_content, additional_fields):
              if body_type and body_type not in BODY_TYPE_CHOICES:
                  raise ValueError("'body_type' %s must be one of %s" % (body_type, BODY_TYPE_CHOICES))
              return self._elems_to_objs(self._chunked_get_elements(
                  self.get_payload, items=items, include_mime_content=include_mime_content,
                  body_type=body_type, filter_html_content=filter_html_content, additional_fields=additional_fields,
              ))

          def _elems_to_objs(self, elems):
              from ..attachments import FileAttachment, ItemAttachment
              cls_map = {cls.response_tag(): cls for cls in (FileAttachment, ItemAttachment)}
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield cls_map[elem.tag].from_xml(elem=elem, account=self.account)

          def get_payload(self, items, include_mime_content, body_type, filter_html_content, additional_fields):
              payload = create_element('m:%s' % self.SERVICE_NAME)
              shape_elem = create_element('m:AttachmentShape')
              if include_mime_content:
                  add_xml_child(shape_elem, 't:IncludeMimeContent', 'true')
              if body_type:
                  add_xml_child(shape_elem, 't:BodyType', body_type)
              if filter_html_content is not None:
                  add_xml_child(shape_elem, 't:FilterHtmlContent', 'true' if filter_html_content else 'false')
              if additional_fields:
                  additional_properties = create_element('t:AdditionalProperties')
                  expanded_fields = chain(*(f.expand(version=self.account.version) for f in additional_fields))
                  set_xml_value(additional_properties, sorted(
                      expanded_fields,
                      key=lambda f: (getattr(f.field, 'field_uri', ''), f.path)
                  ), version=self.account.version)
                  shape_elem.append(additional_properties)
              if len(shape_elem):
                  payload.append(shape_elem)
              attachment_ids = create_attachment_ids_element(items=items, version=self.account.version)
              payload.append(attachment_ids)
              return payload

          def _update_api_version(self, api_version, header, **parse_opts):
              if not parse_opts.get('stream_file_content', False):
                  super()._update_api_version(api_version, header, **parse_opts)
              # TODO: We're skipping this part in streaming mode because StreamingBase64Parser cannot parse the SOAP header

          @classmethod
          def _get_soap_parts(cls, response, **parse_opts):
              if not parse_opts.get('stream_file_content', False):
                  return super()._get_soap_parts(response, **parse_opts)

              # Pass the response unaltered. We want to use our custom streaming parser
              return None, response

          def _get_soap_messages(self, body, **parse_opts):
              if not parse_opts.get('stream_file_content', False):
                  return super()._get_soap_messages(body, **parse_opts)

              from ..attachments import FileAttachment
              # 'body' is actually the raw response passed on by '_get_soap_parts'
              r = body
              parser = StreamingBase64Parser()
              field = FileAttachment.get_field_by_fieldname('_content')
              handler = StreamingContentHandler(parser=parser, ns=field.namespace, element_name=field.field_uri)
              parser.setContentHandler(handler)
              return parser.parse(r)

          def stream_file_content(self, attachment_id):
              # The streaming XML parser can only stream content of one attachment
              payload = self.get_payload(
                  items=[attachment_id], include_mime_content=False, body_type=None, filter_html_content=None,
                  additional_fields=None,
              )
              self.streaming = True
              try:
                  yield from self._get_response_xml(payload=payload, stream_file_content=True)
              except ElementNotFound as enf:
                  # When the returned XML does not contain a Content element, ElementNotFound is thrown by parser.parse().
                  # Let the non-streaming SOAP parser parse the response and hook into the normal exception handling.
                  # Wrap in DummyResponse because _get_soap_parts() expects an iter_content() method.
                  response = DummyResponse(url=None, headers=None, request_headers=None, content=enf.data)
                  _, body = super()._get_soap_parts(response=response)
                  res = super()._get_soap_messages(body=body)
                  for e in self._get_elements_in_response(response=res):
                      if isinstance(e, Exception):
                          raise e
                  # The returned content did not contain any EWS exceptions. Give up and re-raise the original exception.
                  raise enf
              finally:
                  self.streaming = False
                  self.stop_streaming()

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`

  ### Methods

  `def call(self, items, include_mime_content, body_type, filter_html_content, additional_fields)`
    Expand source code

        def call(self, items, include_mime_content, body_type, filter_html_content, additional_fields):
            if body_type and body_type not in BODY_TYPE_CHOICES:
                raise ValueError("'body_type' %s must be one of %s" % (body_type, BODY_TYPE_CHOICES))
            return self._elems_to_objs(self._chunked_get_elements(
                self.get_payload, items=items, include_mime_content=include_mime_content,
                body_type=body_type, filter_html_content=filter_html_content, additional_fields=additional_fields,
            ))

  `def get_payload(self, items, include_mime_content, body_type, filter_html_content, additional_fields)`
    Expand source code

        def get_payload(self, items, include_mime_content, body_type, filter_html_content, additional_fields):
            payload = create_element('m:%s' % self.SERVICE_NAME)
            shape_elem = create_element('m:AttachmentShape')
            if include_mime_content:
                add_xml_child(shape_elem, 't:IncludeMimeContent', 'true')
            if body_type:
                add_xml_child(shape_elem, 't:BodyType', body_type)
            if filter_html_content is not None:
                add_xml_child(shape_elem, 't:FilterHtmlContent', 'true' if filter_html_content else 'false')
            if additional_fields:
                additional_properties = create_element('t:AdditionalProperties')
                expanded_fields = chain(*(f.expand(version=self.account.version) for f in additional_fields))
                set_xml_value(additional_properties, sorted(
                    expanded_fields,
                    key=lambda f: (getattr(f.field, 'field_uri', ''), f.path)
                ), version=self.account.version)
                shape_elem.append(additional_properties)
            if len(shape_elem):
                payload.append(shape_elem)
            attachment_ids = create_attachment_ids_element(items=items, version=self.account.version)
            payload.append(attachment_ids)
            return payload

  `def stream_file_content(self, attachment_id)`
    Expand source code

        def stream_file_content(self, attachment_id):
            # The streaming XML parser can only stream content of one attachment
            payload = self.get_payload(
                items=[attachment_id], include_mime_content=False, body_type=None, filter_html_content=None,
                additional_fields=None,
            )
            self.streaming = True
            try:
                yield from self._get_response_xml(payload=payload, stream_file_content=True)
            except ElementNotFound as enf:
                # When the returned XML does not contain a Content element, ElementNotFound is thrown by parser.parse().
                # Let the non-streaming SOAP parser parse the response and hook into the normal exception handling.
                # Wrap in DummyResponse because _get_soap_parts() expects an iter_content() method.
                response = DummyResponse(url=None, headers=None, request_headers=None, content=enf.data)
                _, body = super()._get_soap_parts(response=response)
                res = super()._get_soap_messages(body=body)
                for e in self._get_elements_in_response(response=res):
                    if isinstance(e, Exception):
                        raise e
                # The returned content did not contain any EWS exceptions. Give up and re-raise the original exception.
                raise enf
            finally:
                self.streaming = False
                self.stop_streaming()

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetDelegate (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getdelegate-operation

  Expand source code

      class GetDelegate(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getdelegate-operation"""

          SERVICE_NAME = 'GetDelegate'
          supported_from = EXCHANGE_2007_SP1

          def call(self, user_ids, include_permissions):
              return self._elems_to_objs(self._chunked_get_elements(
                  self.get_payload,
                  items=user_ids or [None],
                  mailbox=DLMailbox(email_address=self.account.primary_smtp_address),
                  include_permissions=include_permissions,
              ))

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield DelegateUser.from_xml(elem=elem, account=self.account)

          def get_payload(self, user_ids, mailbox, include_permissions):
              payload = create_element(
                  'm:%s' % self.SERVICE_NAME,
                  attrs=dict(IncludePermissions='true' if include_permissions else 'false'),
              )
              set_xml_value(payload, mailbox, version=self.protocol.version)
              if user_ids != [None]:
                  set_xml_value(payload, user_ids, version=self.protocol.version)
              return payload

          @classmethod
          def _get_elements_in_container(cls, container):
              return container.findall(DelegateUser.response_tag())

          @classmethod
          def _response_message_tag(cls):
              return '{%s}DelegateUserResponseMessageType' % MNS

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var supported_from`

  ### Methods

  `def call(self, user_ids, include_permissions)`
    Expand source code

        def call(self, user_ids, include_permissions):
            return self._elems_to_objs(self._chunked_get_elements(
                self.get_payload,
                items=user_ids or [None],
                mailbox=DLMailbox(email_address=self.account.primary_smtp_address),
                include_permissions=include_permissions,
            ))

  `def get_payload(self, user_ids, mailbox, include_permissions)`
    Expand source code

        def get_payload(self, user_ids, mailbox, include_permissions):
            payload = create_element(
                'm:%s' % self.SERVICE_NAME,
                attrs=dict(IncludePermissions='true' if include_permissions else 'false'),
            )
            set_xml_value(payload, mailbox, version=self.protocol.version)
            if user_ids != [None]:
                set_xml_value(payload, user_ids, version=self.protocol.version)
            return payload

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetEvents (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getevents-operation

  Expand source code

      class GetEvents(EWSAccountService):
          """MSDN:
          https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getevents-operation
          """

          SERVICE_NAME = 'GetEvents'
          prefer_affinity = True

          def call(self, subscription_id, watermark):
              return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                      subscription_id=subscription_id, watermark=watermark,
              )))

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield Notification.from_xml(elem=elem, account=None)

          @classmethod
          def _get_elements_in_container(cls, container):
              return container.findall(Notification.response_tag())

          def get_payload(self, subscription_id, watermark):
              getstreamingevents = create_element('m:%s' % self.SERVICE_NAME)
              add_xml_child(getstreamingevents, 'm:SubscriptionId', subscription_id)
              add_xml_child(getstreamingevents, 'm:Watermark', watermark)
              return getstreamingevents

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var prefer_affinity`

  ### Methods

  `def call(self, subscription_id, watermark)`
    Expand source code

        def call(self, subscription_id, watermark):
            return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                    subscription_id=subscription_id, watermark=watermark,
            )))

  `def get_payload(self, subscription_id, watermark)`
    Expand source code

        def get_payload(self, subscription_id, watermark):
            getstreamingevents = create_element('m:%s' % self.SERVICE_NAME)
            add_xml_child(getstreamingevents, 'm:SubscriptionId', subscription_id)
            add_xml_child(getstreamingevents, 'm:Watermark', watermark)
            return getstreamingevents

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetFolder (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getfolder-operation

  Expand source code

      class GetFolder(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getfolder-operation"""

          SERVICE_NAME = 'GetFolder'
          element_container_name = '{%s}Folders' % MNS
          ERRORS_TO_CATCH_IN_RESPONSE = EWSAccountService.ERRORS_TO_CATCH_IN_RESPONSE + (
              ErrorFolderNotFound, ErrorNoPublicFolderReplicaAvailable, ErrorInvalidOperation,
          )

          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              self.folders = []  # A hack to communicate parsing args to _elems_to_objs()

          def call(self, folders, additional_fields, shape):
              """Take a folder ID and returns the full information for that folder.

              :param folders: a list of Folder objects
              :param additional_fields: the extra fields that should be returned with the folder, as FieldPath objects
              :param shape: The set of attributes to return

              :return: XML elements for the folders, in stable order
              """
              # We can't easily find the correct folder class from the returned XML. Instead, return objects with the same
              # class as the folder instance it was requested with.
              self.folders = list(folders)  # Convert to a list, in case 'folders' is a generator. We're iterating twice.
              return self._elems_to_objs(self._chunked_get_elements(
                  self.get_payload,
                  items=self.folders,
                  additional_fields=additional_fields,
                  shape=shape,
              ))

          def _elems_to_objs(self, elems):
              for folder, elem in zip(self.folders, elems):
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield parse_folder_elem(elem=elem, folder=folder, account=self.account)

          def get_payload(self, folders, additional_fields, shape):
              getfolder = create_element('m:%s' % self.SERVICE_NAME)
              foldershape = create_shape_element(
                  tag='m:FolderShape', shape=shape, additional_fields=additional_fields, version=self.account.version
              )
              getfolder.append(foldershape)
              folder_ids = create_folder_ids_element(tag='m:FolderIds', folders=folders, version=self.account.version)
              getfolder.append(folder_ids)
              return getfolder

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var ERRORS_TO_CATCH_IN_RESPONSE`
  `var SERVICE_NAME`
  `var element_container_name`

  ### Methods

  `def call(self, folders, additional_fields, shape)`

    Take a folder ID and returns the full information for that folder.

    :param folders: a list of Folder objects :param additional_fields: the extra fields that should be returned with the folder, as FieldPath objects :param shape: The set of attributes to return

    :return: XML elements for the folders, in stable order

    Expand source code

        def call(self, folders, additional_fields, shape):
            """Take a folder ID and returns the full information for that folder.

            :param folders: a list of Folder objects
            :param additional_fields: the extra fields that should be returned with the folder, as FieldPath objects
            :param shape: The set of attributes to return

            :return: XML elements for the folders, in stable order
            """
            # We can't easily find the correct folder class from the returned XML. Instead, return objects with the same
            # class as the folder instance it was requested with.
            self.folders = list(folders)  # Convert to a list, in case 'folders' is a generator. We're iterating twice.
            return self._elems_to_objs(self._chunked_get_elements(
                self.get_payload,
                items=self.folders,
                additional_fields=additional_fields,
                shape=shape,
            ))

  `def get_payload(self, folders, additional_fields, shape)`
    Expand source code

        def get_payload(self, folders, additional_fields, shape):
            getfolder = create_element('m:%s' % self.SERVICE_NAME)
            foldershape = create_shape_element(
                tag='m:FolderShape', shape=shape, additional_fields=additional_fields, version=self.account.version
            )
            getfolder.append(foldershape)
            folder_ids = create_folder_ids_element(tag='m:FolderIds', folders=folders, version=self.account.version)
            getfolder.append(folder_ids)
            return getfolder

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetItem (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getitem-operation

  Expand source code

      class GetItem(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getitem-operation"""

          SERVICE_NAME = 'GetItem'
          element_container_name = '{%s}Items' % MNS

          def call(self, items, additional_fields, shape):
              """Return all items in an account that correspond to a list of ID's, in stable order.

              :param items: a list of (id, changekey) tuples or Item objects
              :param additional_fields: the extra fields that should be returned with the item, as FieldPath objects
              :param shape: The shape of returned objects

              :return: XML elements for the items, in stable order
              """
              return self._elems_to_objs(self._chunked_get_elements(
                  self.get_payload, items=items, additional_fields=additional_fields, shape=shape,
              ))

          def _elems_to_objs(self, elems):
              from ..folders.base import BaseFolder
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield BaseFolder.item_model_from_tag(elem.tag).from_xml(elem=elem, account=self.account)

          def get_payload(self, items, additional_fields, shape):
              getitem = create_element('m:%s' % self.SERVICE_NAME)
              itemshape = create_shape_element(
                  tag='m:ItemShape', shape=shape, additional_fields=additional_fields, version=self.account.version
              )
              getitem.append(itemshape)
              item_ids = create_item_ids_element(items=items, version=self.account.version)
              getitem.append(item_ids)
              return getitem

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`

  ### Methods

  `def call(self, items, additional_fields, shape)`

    Return all items in an account that correspond to a list of ID's, in stable order.

    :param items: a list of (id, changekey) tuples or Item objects :param additional_fields: the extra fields that should be returned with the item, as FieldPath objects :param shape: The shape of returned objects

    :return: XML elements for the items, in stable order

    Expand source code

        def call(self, items, additional_fields, shape):
            """Return all items in an account that correspond to a list of ID's, in stable order.

            :param items: a list of (id, changekey) tuples or Item objects
            :param additional_fields: the extra fields that should be returned with the item, as FieldPath objects
            :param shape: The shape of returned objects

            :return: XML elements for the items, in stable order
            """
            return self._elems_to_objs(self._chunked_get_elements(
                self.get_payload, items=items, additional_fields=additional_fields, shape=shape,
            ))

  `def get_payload(self, items, additional_fields, shape)`
    Expand source code

        def get_payload(self, items, additional_fields, shape):
            getitem = create_element('m:%s' % self.SERVICE_NAME)
            itemshape = create_shape_element(
                tag='m:ItemShape', shape=shape, additional_fields=additional_fields, version=self.account.version
            )
            getitem.append(itemshape)
            item_ids = create_item_ids_element(items=items, version=self.account.version)
            getitem.append(item_ids)
            return getitem

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetMailTips (protocol, chunk_size=None, timeout=None)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getmailtips-operation

  Expand source code

      class GetMailTips(EWSService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getmailtips-operation"""

          SERVICE_NAME = 'GetMailTips'

          def call(self, sending_as, recipients, mail_tips_requested):
              return self._elems_to_objs(self._chunked_get_elements(
                  self.get_payload,
                  items=recipients,
                  sending_as=sending_as,
                  mail_tips_requested=mail_tips_requested,
              ))

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield MailTips.from_xml(elem=elem, account=None)

          def get_payload(self, recipients, sending_as,  mail_tips_requested):
              payload = create_element('m:%s' % self.SERVICE_NAME)
              set_xml_value(payload, sending_as, version=self.protocol.version)

              recipients_elem = create_element('m:Recipients')
              for recipient in recipients:
                  set_xml_value(recipients_elem, recipient, version=self.protocol.version)
              if not len(recipients_elem):
                  raise ValueError('"recipients" must not be empty')
              payload.append(recipients_elem)

              if mail_tips_requested:
                  set_xml_value(payload, mail_tips_requested, version=self.protocol.version)
              return payload

          def _get_elements_in_response(self, response):
              for msg in response:
                  yield self._get_element_container(message=msg, name=MailTips.response_tag())

          @classmethod
          def _response_message_tag(cls):
              return '{%s}MailTipsResponseMessageType' % MNS

  ### Ancestors

  - EWSService

  ### Class variables

  `var SERVICE_NAME`

  ### Methods

  `def call(self, sending_as, recipients, mail_tips_requested)`
    Expand source code

        def call(self, sending_as, recipients, mail_tips_requested):
            return self._elems_to_objs(self._chunked_get_elements(
                self.get_payload,
                items=recipients,
                sending_as=sending_as,
                mail_tips_requested=mail_tips_requested,
            ))

  `def get_payload(self, recipients, sending_as, mail_tips_requested)`
    Expand source code

        def get_payload(self, recipients, sending_as,  mail_tips_requested):
            payload = create_element('m:%s' % self.SERVICE_NAME)
            set_xml_value(payload, sending_as, version=self.protocol.version)

            recipients_elem = create_element('m:Recipients')
            for recipient in recipients:
                set_xml_value(recipients_elem, recipient, version=self.protocol.version)
            if not len(recipients_elem):
                raise ValueError('"recipients" must not be empty')
            payload.append(recipients_elem)

            if mail_tips_requested:
                set_xml_value(payload, mail_tips_requested, version=self.protocol.version)
            return payload

  ### Inherited members

  - `EWSService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetPersona (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getpersona-operation

  Expand source code

      class GetPersona(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getpersona-operation"""

          SERVICE_NAME = 'GetPersona'

          def call(self, persona):
              return self._elems_to_objs(self._get_elements(payload=self.get_payload(persona=persona)))

          def _elems_to_objs(self, elems):
              from ..items import Persona
              elements = list(elems)
              if len(elements) != 1:
                  raise ValueError('Expected exactly one element in response')
              elem = elements[0]
              if isinstance(elem, Exception):
                  raise elem
              return Persona.from_xml(elem=elem, account=None)

          def get_payload(self, persona):
              version = self.protocol.version
              payload = create_element('m:%s' % self.SERVICE_NAME)
              set_xml_value(payload, to_item_id(persona, PersonaId, version=version), version=version)
              return payload

          @classmethod
          def _get_elements_in_container(cls, container):
              from ..items import Persona
              return container.findall('{%s}%s' % (MNS, Persona.ELEMENT_NAME))

          @classmethod
          def _response_tag(cls):
              return '{%s}%sResponseMessage' % (MNS, cls.SERVICE_NAME)

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`

  ### Methods

  `def call(self, persona)`
    Expand source code

        def call(self, persona):
            return self._elems_to_objs(self._get_elements(payload=self.get_payload(persona=persona)))

  `def get_payload(self, persona)`
    Expand source code

        def get_payload(self, persona):
            version = self.protocol.version
            payload = create_element('m:%s' % self.SERVICE_NAME)
            set_xml_value(payload, to_item_id(persona, PersonaId, version=version), version=version)
            return payload

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetRoomLists (protocol, chunk_size=None, timeout=None)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getroomlists-operation

  Expand source code

      class GetRoomLists(EWSService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getroomlists-operation"""

          SERVICE_NAME = 'GetRoomLists'
          element_container_name = '{%s}RoomLists' % MNS
          supported_from = EXCHANGE_2010

          def call(self):
              return self._elems_to_objs(self._get_elements(payload=self.get_payload()))

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield RoomList.from_xml(elem=elem, account=None)

          def get_payload(self):
              return create_element('m:%s' % self.SERVICE_NAME)

  ### Ancestors

  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`
  `var supported_from`

  ### Methods

  `def call(self)`
    Expand source code

        def call(self):
            return self._elems_to_objs(self._get_elements(payload=self.get_payload()))

  `def get_payload(self)`
    Expand source code

        def get_payload(self):
            return create_element('m:%s' % self.SERVICE_NAME)

  ### Inherited members

  - `EWSService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetRooms (protocol, chunk_size=None, timeout=None)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getrooms-operation

  Expand source code

      class GetRooms(EWSService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getrooms-operation"""

          SERVICE_NAME = 'GetRooms'
          element_container_name = '{%s}Rooms' % MNS
          supported_from = EXCHANGE_2010

          def call(self, roomlist):
              return self._elems_to_objs(self._get_elements(payload=self.get_payload(roomlist=roomlist)))

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield Room.from_xml(elem=elem, account=None)

          def get_payload(self, roomlist):
              getrooms = create_element('m:%s' % self.SERVICE_NAME)
              set_xml_value(getrooms, roomlist, version=self.protocol.version)
              return getrooms

  ### Ancestors

  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`
  `var supported_from`

  ### Methods

  `def call(self, roomlist)`
    Expand source code

        def call(self, roomlist):
            return self._elems_to_objs(self._get_elements(payload=self.get_payload(roomlist=roomlist)))

  `def get_payload(self, roomlist)`
    Expand source code

        def get_payload(self, roomlist):
            getrooms = create_element('m:%s' % self.SERVICE_NAME)
            set_xml_value(getrooms, roomlist, version=self.protocol.version)
            return getrooms

  ### Inherited members

  - `EWSService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetSearchableMailboxes (protocol, chunk_size=None, timeout=None)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getsearchablemailboxes-operation

  Expand source code

      class GetSearchableMailboxes(EWSService):
          """MSDN:
          https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getsearchablemailboxes-operation
          """

          SERVICE_NAME = 'GetSearchableMailboxes'
          element_container_name = '{%s}SearchableMailboxes' % MNS
          failed_mailboxes_container_name = '{%s}FailedMailboxes' % MNS
          supported_from = EXCHANGE_2013

          def call(self, search_filter, expand_group_membership):
              return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                      search_filter=search_filter,
                      expand_group_membership=expand_group_membership,
              )))

          def _elems_to_objs(self, elems):
              cls_map = {cls.response_tag(): cls for cls in (SearchableMailbox, FailedMailbox)}
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield cls_map[elem.tag].from_xml(elem=elem, account=None)

          def get_payload(self, search_filter, expand_group_membership):
              payload = create_element('m:%s' % self.SERVICE_NAME)
              if search_filter:
                  add_xml_child(payload, 'm:SearchFilter', search_filter)
              if expand_group_membership is not None:
                  add_xml_child(payload, 'm:ExpandGroupMembership', 'true' if expand_group_membership else 'false')
              return payload

          def _get_elements_in_response(self, response):
              for msg in response:
                  for container_name in (self.element_container_name, self.failed_mailboxes_container_name):
                      try:
                          container_or_exc = self._get_element_container(message=msg, name=container_name)
                      except MalformedResponseError:
                          # Responses may contain no failed mailboxes. _get_element_container() does not accept this.
                          if container_name == self.failed_mailboxes_container_name:
                              continue
                          raise
                      if isinstance(container_or_exc, (bool, Exception)):
                          yield container_or_exc
                          continue
                      yield from self._get_elements_in_container(container=container_or_exc)

  ### Ancestors

  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`
  `var failed_mailboxes_container_name`
  `var supported_from`

  ### Methods

  `def call(self, search_filter, expand_group_membership)`
    Expand source code

        def call(self, search_filter, expand_group_membership):
            return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                    search_filter=search_filter,
                    expand_group_membership=expand_group_membership,
            )))

  `def get_payload(self, search_filter, expand_group_membership)`
    Expand source code

        def get_payload(self, search_filter, expand_group_membership):
            payload = create_element('m:%s' % self.SERVICE_NAME)
            if search_filter:
                add_xml_child(payload, 'm:SearchFilter', search_filter)
            if expand_group_membership is not None:
                add_xml_child(payload, 'm:ExpandGroupMembership', 'true' if expand_group_membership else 'false')
            return payload

  ### Inherited members

  - `EWSService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetServerTimeZones (protocol, chunk_size=None, timeout=None)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getservertimezones-operation

  Expand source code

      class GetServerTimeZones(EWSService):
          """MSDN:
          https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getservertimezones-operation
          """

          SERVICE_NAME = 'GetServerTimeZones'
          element_container_name = '{%s}TimeZoneDefinitions' % MNS
          supported_from = EXCHANGE_2010

          def call(self, timezones=None, return_full_timezone_data=False):
              return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                  timezones=timezones,
                  return_full_timezone_data=return_full_timezone_data
              )))

          def get_payload(self, timezones, return_full_timezone_data):
              payload = create_element(
                  'm:%s' % self.SERVICE_NAME,
                  attrs=dict(ReturnFullTimeZoneData='true' if return_full_timezone_data else 'false'),
              )
              if timezones is not None:
                  is_empty, timezones = peek(timezones)
                  if not is_empty:
                      tz_ids = create_element('m:Ids')
                      for timezone in timezones:
                          tz_id = set_xml_value(create_element('t:Id'), timezone.ms_id, version=self.protocol.version)
                          tz_ids.append(tz_id)
                      payload.append(tz_ids)
              return payload

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  tz_id = elem.get('Id')
                  tz_name = elem.get('Name')
                  tz_periods = self._get_periods(elem)
                  tz_transitions_groups = self._get_transitions_groups(elem)
                  tz_transitions = self._get_transitions(elem)
                  yield tz_id, tz_name, tz_periods, tz_transitions, tz_transitions_groups

          @staticmethod
          def _get_periods(timezonedef):
              tz_periods = {}
              periods = timezonedef.find('{%s}Periods' % TNS)
              for period in periods.findall('{%s}Period' % TNS):
                  # Convert e.g. "trule:Microsoft/Registry/W. Europe Standard Time/2006-Daylight" to (2006, 'Daylight')
                  p_year, p_type = period.get('Id').rsplit('/', 1)[1].split('-')
                  tz_periods[(int(p_year), p_type)] = dict(
                      name=period.get('Name'),
                      bias=xml_text_to_value(period.get('Bias'), datetime.timedelta)
                  )
              return tz_periods

          @staticmethod
          def _get_transitions_groups(timezonedef):
              tz_transitions_groups = {}
              transitiongroups = timezonedef.find('{%s}TransitionsGroups' % TNS)
              if transitiongroups is not None:
                  for transitiongroup in transitiongroups.findall('{%s}TransitionsGroup' % TNS):
                      tg_id = int(transitiongroup.get('Id'))
                      tz_transitions_groups[tg_id] = []
                      for transition in transitiongroup.findall('{%s}Transition' % TNS):
                          # Apply same conversion to To as for period IDs
                          to_year, to_type = transition.find('{%s}To' % TNS).text.rsplit('/', 1)[1].split('-')
                          tz_transitions_groups[tg_id].append(dict(
                              to=(int(to_year), to_type),
                          ))
                      for transition in transitiongroup.findall('{%s}RecurringDayTransition' % TNS):
                          # Apply same conversion to To as for period IDs
                          to_year, to_type = transition.find('{%s}To' % TNS).text.rsplit('/', 1)[1].split('-')
                          occurrence = xml_text_to_value(transition.find('{%s}Occurrence' % TNS).text, int)
                          if occurrence == -1:
                              # See TimeZoneTransition.from_xml()
                              occurrence = 5
                          tz_transitions_groups[tg_id].append(dict(
                              to=(int(to_year), to_type),
                              offset=xml_text_to_value(transition.find('{%s}TimeOffset' % TNS).text, datetime.timedelta),
                              iso_month=xml_text_to_value(transition.find('{%s}Month' % TNS).text, int),
                              iso_weekday=WEEKDAY_NAMES.index(transition.find('{%s}DayOfWeek' % TNS).text) + 1,
                              occurrence=occurrence,
                          ))
              return tz_transitions_groups

          @staticmethod
          def _get_transitions(timezonedef):
              tz_transitions = {}
              transitions = timezonedef.find('{%s}Transitions' % TNS)
              if transitions is not None:
                  for transition in transitions.findall('{%s}Transition' % TNS):
                      to = transition.find('{%s}To' % TNS)
                      if to.get('Kind') != 'Group':
                          raise ValueError('Unexpected "Kind" XML attr: %s' % to.get('Kind'))
                      tg_id = xml_text_to_value(to.text, int)
                      tz_transitions[tg_id] = None
                  for transition in transitions.findall('{%s}AbsoluteDateTransition' % TNS):
                      to = transition.find('{%s}To' % TNS)
                      if to.get('Kind') != 'Group':
                          raise ValueError('Unexpected "Kind" XML attr: %s' % to.get('Kind'))
                      tg_id = xml_text_to_value(to.text, int)
                      try:
                          t_date = xml_text_to_value(transition.find('{%s}DateTime' % TNS).text, EWSDateTime).date()
                      except NaiveDateTimeNotAllowed as e:
                          # We encountered a naive datetime. Don't worry. we just need the date
                          t_date = e.local_dt.date()
                      tz_transitions[tg_id] = t_date
              return tz_transitions

  ### Ancestors

  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`
  `var supported_from`

  ### Methods

  `def call(self, timezones=None, return_full_timezone_data=False)`
    Expand source code

        def call(self, timezones=None, return_full_timezone_data=False):
            return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                timezones=timezones,
                return_full_timezone_data=return_full_timezone_data
            )))

  `def get_payload(self, timezones, return_full_timezone_data)`
    Expand source code

        def get_payload(self, timezones, return_full_timezone_data):
            payload = create_element(
                'm:%s' % self.SERVICE_NAME,
                attrs=dict(ReturnFullTimeZoneData='true' if return_full_timezone_data else 'false'),
            )
            if timezones is not None:
                is_empty, timezones = peek(timezones)
                if not is_empty:
                    tz_ids = create_element('m:Ids')
                    for timezone in timezones:
                        tz_id = set_xml_value(create_element('t:Id'), timezone.ms_id, version=self.protocol.version)
                        tz_ids.append(tz_id)
                    payload.append(tz_ids)
            return payload

  ### Inherited members

  - `EWSService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetStreamingEvents (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getstreamingevents-operation

  Expand source code

      class GetStreamingEvents(EWSAccountService):
          """MSDN:
          https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getstreamingevents-operation
          """

          SERVICE_NAME = 'GetStreamingEvents'
          element_container_name = '{%s}Notifications' % MNS
          streaming = True
          prefer_affinity = True

          # Connection status values
          OK = 'OK'
          CLOSED = 'Closed'

          def __init__(self, *args, **kwargs):
              # These values are set each time call() is consumed
              self.connection_status = None
              self.error_subscription_ids = []
              super().__init__(*args, **kwargs)

          def call(self, subscription_ids, connection_timeout):
              if connection_timeout < 1:
                  raise ValueError("'connection_timeout' must be a positive integer")
              return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                      subscription_ids=subscription_ids, connection_timeout=connection_timeout,
              )))

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield Notification.from_xml(elem=elem, account=None)

          @classmethod
          def _get_soap_parts(cls, response, **parse_opts):
              # Pass the response unaltered. We want to use our custom document yielder
              return None, response

          def _get_soap_messages(self, body, **parse_opts):
              # 'body' is actually the raw response passed on by '_get_soap_parts'. We want to continuously read the content,
              # looking for complete XML documents. When we have a full document, we want to parse it as if it was a normal
              # XML response.
              r = body
              for i, doc in enumerate(DocumentYielder(r.iter_content()), start=1):
                  xml_log.debug('''Response XML (docs received: %(i)s): %(xml_response)s''', dict(i=i, xml_response=doc))
                  response = DummyResponse(url=None, headers=None, request_headers=None, content=doc)
                  try:
                      _, body = super()._get_soap_parts(response=response, **parse_opts)
                  except Exception:
                      r.close()  # Release memory
                      raise
                  # TODO: We're skipping ._update_api_version() here because we don't have access to the 'api_version' used.
                  # TODO: We should be doing a lot of error handling for ._get_soap_messages().
                  yield from super()._get_soap_messages(body=body, **parse_opts)
                  if self.connection_status == self.CLOSED:
                      # Don't wait for the TCP connection to timeout
                      break

          def _get_element_container(self, message, name=None):
              error_ids_elem = message.find('{%s}ErrorSubscriptionIds' % MNS)
              if error_ids_elem is not None:
                  self.error_subscription_ids = get_xml_attrs(error_ids_elem, '{%s}ErrorSubscriptionId' % MNS)
                  log.debug('These subscription IDs are invalid: %s', self.error_subscription_ids)
              self.connection_status = get_xml_attr(message, '{%s}ConnectionStatus' % MNS)  # Either 'OK' or 'Closed'
              log.debug('Connection status is: %s', self.connection_status)
              # Upstream expects to find a 'name' tag but our response does not always have it. Return an empty element.
              if message.find(name) is None:
                  return []
              return super()._get_element_container(message=message, name=name)

          def get_payload(self, subscription_ids, connection_timeout):
              getstreamingevents = create_element('m:%s' % self.SERVICE_NAME)
              subscriptions_elem = create_element('m:SubscriptionIds')
              for subscription_id in subscription_ids:
                  add_xml_child(subscriptions_elem, 't:SubscriptionId', subscription_id)
              if not len(subscriptions_elem):
                  raise ValueError('"subscription_ids" must not be empty')

              getstreamingevents.append(subscriptions_elem)
              add_xml_child(getstreamingevents, 'm:ConnectionTimeout', connection_timeout)
              return getstreamingevents

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var CLOSED`
  `var OK`
  `var SERVICE_NAME`
  `var element_container_name`
  `var prefer_affinity`
  `var streaming`

  ### Methods

  `def call(self, subscription_ids, connection_timeout)`
    Expand source code

        def call(self, subscription_ids, connection_timeout):
            if connection_timeout < 1:
                raise ValueError("'connection_timeout' must be a positive integer")
            return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                    subscription_ids=subscription_ids, connection_timeout=connection_timeout,
            )))

  `def get_payload(self, subscription_ids, connection_timeout)`
    Expand source code

        def get_payload(self, subscription_ids, connection_timeout):
            getstreamingevents = create_element('m:%s' % self.SERVICE_NAME)
            subscriptions_elem = create_element('m:SubscriptionIds')
            for subscription_id in subscription_ids:
                add_xml_child(subscriptions_elem, 't:SubscriptionId', subscription_id)
            if not len(subscriptions_elem):
                raise ValueError('"subscription_ids" must not be empty')

            getstreamingevents.append(subscriptions_elem)
            add_xml_child(getstreamingevents, 'm:ConnectionTimeout', connection_timeout)
            return getstreamingevents

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetUserAvailability (protocol, chunk_size=None, timeout=None)`

  Get detailed availability information for a list of users. MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getuseravailability-operation

  Expand source code

      class GetUserAvailability(EWSService):
          """Get detailed availability information for a list of users.
          MSDN:
          https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getuseravailability-operation
          """

          SERVICE_NAME = 'GetUserAvailability'

          def call(self, timezone, mailbox_data, free_busy_view_options):
              # TODO: Also supports SuggestionsViewOptions, see
              #  https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/suggestionsviewoptions
              return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                  timezone=timezone,
                  mailbox_data=mailbox_data,
                  free_busy_view_options=free_busy_view_options
              )))

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield FreeBusyView.from_xml(elem=elem, account=None)

          def get_payload(self, timezone, mailbox_data, free_busy_view_options):
              payload = create_element('m:%sRequest' % self.SERVICE_NAME)
              set_xml_value(payload, timezone, version=self.protocol.version)
              mailbox_data_array = create_element('m:MailboxDataArray')
              set_xml_value(mailbox_data_array, mailbox_data, version=self.protocol.version)
              payload.append(mailbox_data_array)
              set_xml_value(payload, free_busy_view_options, version=self.protocol.version)
              return payload

          @staticmethod
          def _response_messages_tag():
              return '{%s}FreeBusyResponseArray' % MNS

          @classmethod
          def _response_message_tag(cls):
              return '{%s}FreeBusyResponse' % MNS

          def _get_elements_in_response(self, response):
              for msg in response:
                  # Just check the response code and raise errors
                  self._get_element_container(message=msg.find('{%s}ResponseMessage' % MNS))
                  yield from self._get_elements_in_container(container=msg)

          @classmethod
          def _get_elements_in_container(cls, container):
              return [container.find('{%s}FreeBusyView' % MNS)]

  ### Ancestors

  - EWSService

  ### Class variables

  `var SERVICE_NAME`

  ### Methods

  `def call(self, timezone, mailbox_data, free_busy_view_options)`
    Expand source code

        def call(self, timezone, mailbox_data, free_busy_view_options):
            # TODO: Also supports SuggestionsViewOptions, see
            #  https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/suggestionsviewoptions
            return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                timezone=timezone,
                mailbox_data=mailbox_data,
                free_busy_view_options=free_busy_view_options
            )))

  `def get_payload(self, timezone, mailbox_data, free_busy_view_options)`
    Expand source code

        def get_payload(self, timezone, mailbox_data, free_busy_view_options):
            payload = create_element('m:%sRequest' % self.SERVICE_NAME)
            set_xml_value(payload, timezone, version=self.protocol.version)
            mailbox_data_array = create_element('m:MailboxDataArray')
            set_xml_value(mailbox_data_array, mailbox_data, version=self.protocol.version)
            payload.append(mailbox_data_array)
            set_xml_value(payload, free_busy_view_options, version=self.protocol.version)
            return payload

  ### Inherited members

  - `EWSService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetUserConfiguration (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getuserconfiguration-operation

  Expand source code

      class GetUserConfiguration(EWSAccountService):
          """MSDN:
          https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getuserconfiguration-operation
          """

          SERVICE_NAME = 'GetUserConfiguration'

          def call(self, user_configuration_name, properties):
              if properties not in PROPERTIES_CHOICES:
                  raise ValueError("'properties' %r must be one of %s" % (properties, PROPERTIES_CHOICES))
              return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                      user_configuration_name=user_configuration_name, properties=properties
              )))

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield UserConfiguration.from_xml(elem=elem, account=self.account)

          @classmethod
          def _get_elements_in_container(cls, container):
              return container.findall(UserConfiguration.response_tag())

          def get_payload(self, user_configuration_name, properties):
              getuserconfiguration = create_element('m:%s' % self.SERVICE_NAME)
              set_xml_value(getuserconfiguration, user_configuration_name, version=self.account.version)
              user_configuration_properties = create_element('m:UserConfigurationProperties')
              set_xml_value(user_configuration_properties, properties, version=self.account.version)
              getuserconfiguration.append(user_configuration_properties)
              return getuserconfiguration

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`

  ### Methods

  `def call(self, user_configuration_name, properties)`
    Expand source code

        def call(self, user_configuration_name, properties):
            if properties not in PROPERTIES_CHOICES:
                raise ValueError("'properties' %r must be one of %s" % (properties, PROPERTIES_CHOICES))
            return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                    user_configuration_name=user_configuration_name, properties=properties
            )))

  `def get_payload(self, user_configuration_name, properties)`
    Expand source code

        def get_payload(self, user_configuration_name, properties):
            getuserconfiguration = create_element('m:%s' % self.SERVICE_NAME)
            set_xml_value(getuserconfiguration, user_configuration_name, version=self.account.version)
            user_configuration_properties = create_element('m:UserConfigurationProperties')
            set_xml_value(user_configuration_properties, properties, version=self.account.version)
            getuserconfiguration.append(user_configuration_properties)
            return getuserconfiguration

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class GetUserOofSettings (*args, **kwargs)`

  Get automatic reply settings for the specified mailbox. MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getuseroofsettings-operation

  Expand source code

      class GetUserOofSettings(EWSAccountService):
          """Get automatic reply settings for the specified mailbox.
          MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/getuseroofsettings-operation
          """

          SERVICE_NAME = 'GetUserOofSettings'
          element_container_name = '{%s}OofSettings' % TNS

          def call(self, mailbox):
              return self._elems_to_objs(self._get_elements(payload=self.get_payload(mailbox=mailbox)))

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield OofSettings.from_xml(elem=elem, account=self.account)

          def get_payload(self, mailbox):
              payload = create_element('m:%sRequest' % self.SERVICE_NAME)
              return set_xml_value(payload, AvailabilityMailbox.from_mailbox(mailbox), version=self.account.version)

          @classmethod
          def _get_elements_in_container(cls, container):
              # This service only returns one result, directly in 'container'
              return [container]

          def _get_element_container(self, message, name=None):
              # This service returns the result container outside the response message
              super()._get_element_container(message=message.find(self._response_message_tag()), name=None)
              return message.find(name)

          @classmethod
          def _response_message_tag(cls):
              return '{%s}ResponseMessage' % MNS

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`

  ### Methods

  `def call(self, mailbox)`
    Expand source code

        def call(self, mailbox):
            return self._elems_to_objs(self._get_elements(payload=self.get_payload(mailbox=mailbox)))

  `def get_payload(self, mailbox)`
    Expand source code

        def get_payload(self, mailbox):
            payload = create_element('m:%sRequest' % self.SERVICE_NAME)
            return set_xml_value(payload, AvailabilityMailbox.from_mailbox(mailbox), version=self.account.version)

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class MarkAsJunk (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/markasjunk-operation

  Expand source code

      class MarkAsJunk(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/markasjunk-operation"""

          SERVICE_NAME = 'MarkAsJunk'

          def call(self, items, is_junk, move_item):
              return self._elems_to_objs(
                  self._chunked_get_elements(self.get_payload, items=items, is_junk=is_junk, move_item=move_item)
              )

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, (Exception, type(None))):
                      yield elem
                      continue
                  yield MovedItemId.id_from_xml(elem)

          @classmethod
          def _get_elements_in_container(cls, container):
              return container.findall(MovedItemId.response_tag())

          def get_payload(self, items, is_junk, move_item):
              # Takes a list of items and returns either success or raises an error message
              mark_as_junk = create_element(
                  'm:%s' % self.SERVICE_NAME,
                  attrs=dict(IsJunk='true' if is_junk else 'false', MoveItem='true' if move_item else 'false')
              )
              item_ids = create_item_ids_element(items=items, version=self.account.version)
              mark_as_junk.append(item_ids)
              return mark_as_junk

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`

  ### Methods

  `def call(self, items, is_junk, move_item)`
    Expand source code

        def call(self, items, is_junk, move_item):
            return self._elems_to_objs(
                self._chunked_get_elements(self.get_payload, items=items, is_junk=is_junk, move_item=move_item)
            )

  `def get_payload(self, items, is_junk, move_item)`
    Expand source code

        def get_payload(self, items, is_junk, move_item):
            # Takes a list of items and returns either success or raises an error message
            mark_as_junk = create_element(
                'm:%s' % self.SERVICE_NAME,
                attrs=dict(IsJunk='true' if is_junk else 'false', MoveItem='true' if move_item else 'false')
            )
            item_ids = create_item_ids_element(items=items, version=self.account.version)
            mark_as_junk.append(item_ids)
            return mark_as_junk

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class MoveFolder (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/movefolder-operation

  Expand source code

      class MoveFolder(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/movefolder-operation"""

          SERVICE_NAME = "MoveFolder"
          element_container_name = '{%s}Folders' % MNS

          def call(self, folders, to_folder):
              from ..folders import BaseFolder, FolderId
              if not isinstance(to_folder, (BaseFolder, FolderId)):
                  raise ValueError("'to_folder' %r must be a Folder or FolderId instance" % to_folder)
              return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=folders, to_folder=to_folder))

          def _elems_to_objs(self, elems):
              from ..folders import FolderId
              for elem in elems:
                  if isinstance(elem, (Exception, type(None))):
                      yield elem
                      continue
                  yield FolderId.from_xml(elem=elem.find(FolderId.response_tag()), account=self.account)

          def get_payload(self, folders, to_folder):
              # Takes a list of folders and returns their new folder IDs
              movefolder = create_element('m:%s' % self.SERVICE_NAME)
              tofolderid = create_element('m:ToFolderId')
              set_xml_value(tofolderid, to_folder, version=self.account.version)
              movefolder.append(tofolderid)
              folder_ids = create_folder_ids_element(tag='m:FolderIds', folders=folders, version=self.account.version)
              movefolder.append(folder_ids)
              return movefolder

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`

  ### Methods

  `def call(self, folders, to_folder)`
    Expand source code

        def call(self, folders, to_folder):
            from ..folders import BaseFolder, FolderId
            if not isinstance(to_folder, (BaseFolder, FolderId)):
                raise ValueError("'to_folder' %r must be a Folder or FolderId instance" % to_folder)
            return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=folders, to_folder=to_folder))

  `def get_payload(self, folders, to_folder)`
    Expand source code

        def get_payload(self, folders, to_folder):
            # Takes a list of folders and returns their new folder IDs
            movefolder = create_element('m:%s' % self.SERVICE_NAME)
            tofolderid = create_element('m:ToFolderId')
            set_xml_value(tofolderid, to_folder, version=self.account.version)
            movefolder.append(tofolderid)
            folder_ids = create_folder_ids_element(tag='m:FolderIds', folders=folders, version=self.account.version)
            movefolder.append(folder_ids)
            return movefolder

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class MoveItem (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/moveitem-operation

  Expand source code

      class MoveItem(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/moveitem-operation"""

          SERVICE_NAME = 'MoveItem'
          element_container_name = '{%s}Items' % MNS

          def call(self, items, to_folder):
              from ..folders import BaseFolder, FolderId
              if not isinstance(to_folder, (BaseFolder, FolderId)):
                  raise ValueError("'to_folder' %r must be a Folder or FolderId instance" % to_folder)
              return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=items, to_folder=to_folder))

          def _elems_to_objs(self, elems):
              from ..items import Item
              for elem in elems:
                  if isinstance(elem, (Exception, type(None))):
                      yield elem
                      continue
                  yield Item.id_from_xml(elem)

          def get_payload(self, items, to_folder):
              # Takes a list of items and returns their new item IDs
              moveitem = create_element('m:%s' % self.SERVICE_NAME)
              tofolderid = create_element('m:ToFolderId')
              set_xml_value(tofolderid, to_folder, version=self.account.version)
              moveitem.append(tofolderid)
              item_ids = create_item_ids_element(items=items, version=self.account.version)
              moveitem.append(item_ids)
              return moveitem

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Subclasses

  - CopyItem

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`

  ### Methods

  `def call(self, items, to_folder)`
    Expand source code

        def call(self, items, to_folder):
            from ..folders import BaseFolder, FolderId
            if not isinstance(to_folder, (BaseFolder, FolderId)):
                raise ValueError("'to_folder' %r must be a Folder or FolderId instance" % to_folder)
            return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=items, to_folder=to_folder))

  `def get_payload(self, items, to_folder)`
    Expand source code

        def get_payload(self, items, to_folder):
            # Takes a list of items and returns their new item IDs
            moveitem = create_element('m:%s' % self.SERVICE_NAME)
            tofolderid = create_element('m:ToFolderId')
            set_xml_value(tofolderid, to_folder, version=self.account.version)
            moveitem.append(tofolderid)
            item_ids = create_item_ids_element(items=items, version=self.account.version)
            moveitem.append(item_ids)
            return moveitem

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class ResolveNames (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/resolvenames-operation

  Expand source code

      class ResolveNames(EWSService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/resolvenames-operation"""

          SERVICE_NAME = 'ResolveNames'
          element_container_name = '{%s}ResolutionSet' % MNS
          ERRORS_TO_CATCH_IN_RESPONSE = ErrorNameResolutionNoResults
          WARNINGS_TO_IGNORE_IN_RESPONSE = ErrorNameResolutionMultipleResults
          # Note: paging information is returned as attrs on the 'ResolutionSet' element, but this service does not
          # support the 'IndexedPageItemView' element, so it's not really a paging service. According to docs, at most
          # 100 candidates are returned for a lookup.
          supports_paging = False

          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              self.return_full_contact_data = False  # A hack to communicate parsing args to _elems_to_objs()

          def call(self, unresolved_entries, parent_folders=None, return_full_contact_data=False, search_scope=None,
                   contact_data_shape=None):
              from ..items import SHAPE_CHOICES, SEARCH_SCOPE_CHOICES
              if self.chunk_size > 100:
                  log.warning(
                      'Chunk size %s is dangerously high. %s supports returning at most 100 candidates for a lookup',
                      self.chunk_size, self.SERVICE_NAME
                  )
              if search_scope and search_scope not in SEARCH_SCOPE_CHOICES:
                  raise ValueError("'search_scope' %s must be one if %s" % (search_scope, SEARCH_SCOPE_CHOICES))
              if contact_data_shape and contact_data_shape not in SHAPE_CHOICES:
                  raise ValueError("'shape' %s must be one if %s" % (contact_data_shape, SHAPE_CHOICES))
              self.return_full_contact_data = return_full_contact_data
              return self._elems_to_objs(self._chunked_get_elements(
                  self.get_payload,
                  items=unresolved_entries,
                  parent_folders=parent_folders,
                  return_full_contact_data=return_full_contact_data,
                  search_scope=search_scope,
                  contact_data_shape=contact_data_shape,
              ))

          def _elems_to_objs(self, elems):
              from ..items import Contact
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  if self.return_full_contact_data:
                      mailbox_elem = elem.find(Mailbox.response_tag())
                      contact_elem = elem.find(Contact.response_tag())
                      yield (
                          None if mailbox_elem is None else Mailbox.from_xml(elem=mailbox_elem, account=None),
                          None if contact_elem is None else Contact.from_xml(elem=contact_elem, account=None),
                      )
                  else:
                      yield Mailbox.from_xml(elem=elem.find(Mailbox.response_tag()), account=None)

          def get_payload(self, unresolved_entries, parent_folders, return_full_contact_data, search_scope,
                          contact_data_shape):
              payload = create_element(
                  'm:%s' % self.SERVICE_NAME,
                  attrs=dict(ReturnFullContactData='true' if return_full_contact_data else 'false'),
              )
              if search_scope:
                  payload.set('SearchScope', search_scope)
              if contact_data_shape:
                  if self.protocol.version.build < EXCHANGE_2010_SP2:
                      raise NotImplementedError(
                          "'contact_data_shape' is only supported for Exchange 2010 SP2 servers and later")
                  payload.set('ContactDataShape', contact_data_shape)
              if parent_folders:
                  parentfolderids = create_element('m:ParentFolderIds')
                  set_xml_value(parentfolderids, parent_folders, version=self.protocol.version)
              for entry in unresolved_entries:
                  add_xml_child(payload, 'm:UnresolvedEntry', entry)
              if not len(payload):
                  raise ValueError('"unresolved_entries" must not be empty')
              return payload

  ### Ancestors

  - EWSService

  ### Class variables

  `var ERRORS_TO_CATCH_IN_RESPONSE`

    Global error type within this module.

  `var SERVICE_NAME`
  `var WARNINGS_TO_IGNORE_IN_RESPONSE`

    Global error type within this module.

  `var element_container_name`
  `var supports_paging`

  ### Methods

  `def call(self, unresolved_entries, parent_folders=None, return_full_contact_data=False, search_scope=None, contact_data_shape=None)`
    Expand source code

        def call(self, unresolved_entries, parent_folders=None, return_full_contact_data=False, search_scope=None,
                 contact_data_shape=None):
            from ..items import SHAPE_CHOICES, SEARCH_SCOPE_CHOICES
            if self.chunk_size > 100:
                log.warning(
                    'Chunk size %s is dangerously high. %s supports returning at most 100 candidates for a lookup',
                    self.chunk_size, self.SERVICE_NAME
                )
            if search_scope and search_scope not in SEARCH_SCOPE_CHOICES:
                raise ValueError("'search_scope' %s must be one if %s" % (search_scope, SEARCH_SCOPE_CHOICES))
            if contact_data_shape and contact_data_shape not in SHAPE_CHOICES:
                raise ValueError("'shape' %s must be one if %s" % (contact_data_shape, SHAPE_CHOICES))
            self.return_full_contact_data = return_full_contact_data
            return self._elems_to_objs(self._chunked_get_elements(
                self.get_payload,
                items=unresolved_entries,
                parent_folders=parent_folders,
                return_full_contact_data=return_full_contact_data,
                search_scope=search_scope,
                contact_data_shape=contact_data_shape,
            ))

  `def get_payload(self, unresolved_entries, parent_folders, return_full_contact_data, search_scope, contact_data_shape)`
    Expand source code

        def get_payload(self, unresolved_entries, parent_folders, return_full_contact_data, search_scope,
                        contact_data_shape):
            payload = create_element(
                'm:%s' % self.SERVICE_NAME,
                attrs=dict(ReturnFullContactData='true' if return_full_contact_data else 'false'),
            )
            if search_scope:
                payload.set('SearchScope', search_scope)
            if contact_data_shape:
                if self.protocol.version.build < EXCHANGE_2010_SP2:
                    raise NotImplementedError(
                        "'contact_data_shape' is only supported for Exchange 2010 SP2 servers and later")
                payload.set('ContactDataShape', contact_data_shape)
            if parent_folders:
                parentfolderids = create_element('m:ParentFolderIds')
                set_xml_value(parentfolderids, parent_folders, version=self.protocol.version)
            for entry in unresolved_entries:
                add_xml_child(payload, 'm:UnresolvedEntry', entry)
            if not len(payload):
                raise ValueError('"unresolved_entries" must not be empty')
            return payload

  ### Inherited members

  - `EWSService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class SendItem (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/senditem-operation

  Expand source code

      class SendItem(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/senditem-operation"""

          SERVICE_NAME = 'SendItem'
          returns_elements = False

          def call(self, items, saved_item_folder):
              from ..folders import BaseFolder, FolderId
              if saved_item_folder and not isinstance(saved_item_folder, (BaseFolder, FolderId)):
                  raise ValueError("'saved_item_folder' %r must be a Folder or FolderId instance" % saved_item_folder)
              return self._chunked_get_elements(self.get_payload, items=items, saved_item_folder=saved_item_folder)

          def get_payload(self, items, saved_item_folder):
              senditem = create_element(
                  'm:%s' % self.SERVICE_NAME,
                  attrs=dict(SaveItemToFolder='true' if saved_item_folder else 'false'),
              )
              item_ids = create_item_ids_element(items=items, version=self.account.version)
              senditem.append(item_ids)
              if saved_item_folder:
                  saveditemfolderid = create_element('m:SavedItemFolderId')
                  set_xml_value(saveditemfolderid, saved_item_folder, version=self.account.version)
                  senditem.append(saveditemfolderid)
              return senditem

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var returns_elements`

  ### Methods

  `def call(self, items, saved_item_folder)`
    Expand source code

        def call(self, items, saved_item_folder):
            from ..folders import BaseFolder, FolderId
            if saved_item_folder and not isinstance(saved_item_folder, (BaseFolder, FolderId)):
                raise ValueError("'saved_item_folder' %r must be a Folder or FolderId instance" % saved_item_folder)
            return self._chunked_get_elements(self.get_payload, items=items, saved_item_folder=saved_item_folder)

  `def get_payload(self, items, saved_item_folder)`
    Expand source code

        def get_payload(self, items, saved_item_folder):
            senditem = create_element(
                'm:%s' % self.SERVICE_NAME,
                attrs=dict(SaveItemToFolder='true' if saved_item_folder else 'false'),
            )
            item_ids = create_item_ids_element(items=items, version=self.account.version)
            senditem.append(item_ids)
            if saved_item_folder:
                saveditemfolderid = create_element('m:SavedItemFolderId')
                set_xml_value(saveditemfolderid, saved_item_folder, version=self.account.version)
                senditem.append(saveditemfolderid)
            return senditem

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class SendNotification (protocol, chunk_size=None, timeout=None)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/sendnotification

  This is not an actual EWS service you can call. We only use it to parse the XML body of push notifications.

  Expand source code

      class SendNotification(EWSService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/sendnotification

          This is not an actual EWS service you can call. We only use it to parse the XML body of push notifications.
          """

          SERVICE_NAME = 'SendNotification'

          def call(self):
              raise NotImplementedError()

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield Notification.from_xml(elem=elem, account=None)

          @classmethod
          def _response_tag(cls):
              """Return the name of the element containing the service response."""
              return '{%s}%s' % (MNS, cls.SERVICE_NAME)

          @classmethod
          def _get_elements_in_container(cls, container):
              return container.findall(Notification.response_tag())

  ### Ancestors

  - EWSService

  ### Class variables

  `var SERVICE_NAME`

  ### Methods

  `def call(self)`
    Expand source code

        def call(self):
            raise NotImplementedError()

  ### Inherited members

  - `EWSService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class SetUserOofSettings (*args, **kwargs)`

  Set automatic replies for the specified mailbox. MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/setuseroofsettings-operation

  Expand source code

      class SetUserOofSettings(EWSAccountService):
          """Set automatic replies for the specified mailbox.
          MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/setuseroofsettings-operation
          """

          SERVICE_NAME = 'SetUserOofSettings'
          returns_elements = False

          def call(self, oof_settings, mailbox):
              if not isinstance(oof_settings, OofSettings):
                  raise ValueError("'oof_settings' %r must be an OofSettings instance" % oof_settings)
              if not isinstance(mailbox, Mailbox):
                  raise ValueError("'mailbox' %r must be an Mailbox instance" % mailbox)
              return self._get_elements(payload=self.get_payload(oof_settings=oof_settings, mailbox=mailbox))

          def get_payload(self, oof_settings, mailbox):
              payload = create_element('m:%sRequest' % self.SERVICE_NAME)
              set_xml_value(payload, AvailabilityMailbox.from_mailbox(mailbox), version=self.account.version)
              set_xml_value(payload, oof_settings, version=self.account.version)
              return payload

          def _get_element_container(self, message, name=None):
              message = message.find(self._response_message_tag())
              return super()._get_element_container(message=message, name=name)

          @classmethod
          def _response_message_tag(cls):
              return '{%s}ResponseMessage' % MNS

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var returns_elements`

  ### Methods

  `def call(self, oof_settings, mailbox)`
    Expand source code

        def call(self, oof_settings, mailbox):
            if not isinstance(oof_settings, OofSettings):
                raise ValueError("'oof_settings' %r must be an OofSettings instance" % oof_settings)
            if not isinstance(mailbox, Mailbox):
                raise ValueError("'mailbox' %r must be an Mailbox instance" % mailbox)
            return self._get_elements(payload=self.get_payload(oof_settings=oof_settings, mailbox=mailbox))

  `def get_payload(self, oof_settings, mailbox)`
    Expand source code

        def get_payload(self, oof_settings, mailbox):
            payload = create_element('m:%sRequest' % self.SERVICE_NAME)
            set_xml_value(payload, AvailabilityMailbox.from_mailbox(mailbox), version=self.account.version)
            set_xml_value(payload, oof_settings, version=self.account.version)
            return payload

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class SubscribeToPull (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/subscribe-operation

  Expand source code

      class SubscribeToPull(Subscribe):
          subscription_request_elem_tag = 'm:PullSubscriptionRequest'

          def call(self, folders, event_types, watermark, timeout):
              yield from self._partial_call(
                  payload_func=self.get_payload, folders=folders, event_types=event_types, timeout=timeout,
                  watermark=watermark,
              )

          def get_payload(self, folders, event_types, watermark, timeout):
              subscribe = create_element('m:%s' % self.SERVICE_NAME)
              request_elem = self._partial_payload(folders=folders, event_types=event_types)
              if watermark:
                  add_xml_child(request_elem, 'm:Watermark', watermark)
              add_xml_child(request_elem, 't:Timeout', timeout)  # In minutes
              subscribe.append(request_elem)
              return subscribe

  ### Ancestors

  - Subscribe
  - EWSAccountService
  - EWSService

  ### Class variables

  `var subscription_request_elem_tag`

  ### Methods

  `def call(self, folders, event_types, watermark, timeout)`
    Expand source code

        def call(self, folders, event_types, watermark, timeout):
            yield from self._partial_call(
                payload_func=self.get_payload, folders=folders, event_types=event_types, timeout=timeout,
                watermark=watermark,
            )

  `def get_payload(self, folders, event_types, watermark, timeout)`
    Expand source code

        def get_payload(self, folders, event_types, watermark, timeout):
            subscribe = create_element('m:%s' % self.SERVICE_NAME)
            request_elem = self._partial_payload(folders=folders, event_types=event_types)
            if watermark:
                add_xml_child(request_elem, 'm:Watermark', watermark)
            add_xml_child(request_elem, 't:Timeout', timeout)  # In minutes
            subscribe.append(request_elem)
            return subscribe

  ### Inherited members

  - `Subscribe`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class SubscribeToPush (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/subscribe-operation

  Expand source code

      class SubscribeToPush(Subscribe):
          subscription_request_elem_tag = 'm:PushSubscriptionRequest'

          def call(self, folders, event_types, watermark, status_frequency, url):
              yield from self._partial_call(
                  payload_func=self.get_payload, folders=folders, event_types=event_types,
                  status_frequency=status_frequency, url=url, watermark=watermark,
              )

          def get_payload(self, folders, event_types, watermark, status_frequency, url):
              subscribe = create_element('m:%s' % self.SERVICE_NAME)
              request_elem = self._partial_payload(folders=folders, event_types=event_types)
              if watermark:
                  add_xml_child(request_elem, 'm:Watermark', watermark)
              add_xml_child(request_elem, 't:StatusFrequency', status_frequency)  # In minutes
              add_xml_child(request_elem, 't:URL', url)
              subscribe.append(request_elem)
              return subscribe

  ### Ancestors

  - Subscribe
  - EWSAccountService
  - EWSService

  ### Class variables

  `var subscription_request_elem_tag`

  ### Methods

  `def call(self, folders, event_types, watermark, status_frequency, url)`
    Expand source code

        def call(self, folders, event_types, watermark, status_frequency, url):
            yield from self._partial_call(
                payload_func=self.get_payload, folders=folders, event_types=event_types,
                status_frequency=status_frequency, url=url, watermark=watermark,
            )

  `def get_payload(self, folders, event_types, watermark, status_frequency, url)`
    Expand source code

        def get_payload(self, folders, event_types, watermark, status_frequency, url):
            subscribe = create_element('m:%s' % self.SERVICE_NAME)
            request_elem = self._partial_payload(folders=folders, event_types=event_types)
            if watermark:
                add_xml_child(request_elem, 'm:Watermark', watermark)
            add_xml_child(request_elem, 't:StatusFrequency', status_frequency)  # In minutes
            add_xml_child(request_elem, 't:URL', url)
            subscribe.append(request_elem)
            return subscribe

  ### Inherited members

  - `Subscribe`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class SubscribeToStreaming (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/subscribe-operation

  Expand source code

      class SubscribeToStreaming(Subscribe):
          subscription_request_elem_tag = 'm:StreamingSubscriptionRequest'

          def call(self, folders, event_types):
              yield from self._partial_call(payload_func=self.get_payload, folders=folders, event_types=event_types)

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield elem.text

          @classmethod
          def _get_elements_in_container(cls, container):
              return [container.find('{%s}SubscriptionId' % MNS)]

          def get_payload(self, folders, event_types):
              subscribe = create_element('m:%s' % self.SERVICE_NAME)
              request_elem = self._partial_payload(folders=folders, event_types=event_types)
              subscribe.append(request_elem)
              return subscribe

  ### Ancestors

  - Subscribe
  - EWSAccountService
  - EWSService

  ### Class variables

  `var subscription_request_elem_tag`

  ### Methods

  `def call(self, folders, event_types)`
    Expand source code

        def call(self, folders, event_types):
            yield from self._partial_call(payload_func=self.get_payload, folders=folders, event_types=event_types)

  `def get_payload(self, folders, event_types)`
    Expand source code

        def get_payload(self, folders, event_types):
            subscribe = create_element('m:%s' % self.SERVICE_NAME)
            request_elem = self._partial_payload(folders=folders, event_types=event_types)
            subscribe.append(request_elem)
            return subscribe

  ### Inherited members

  - `Subscribe`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class SyncFolderHierarchy (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/syncfolderhierarchy-operation

  Expand source code

      class SyncFolderHierarchy(SyncFolder):
          """MSDN:
          https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/syncfolderhierarchy-operation
          """

          SERVICE_NAME = 'SyncFolderHierarchy'
          shape_tag = 'm:FolderShape'
          last_in_range_name = '{%s}IncludesLastFolderInRange' % MNS

          def call(self, folder, shape, additional_fields, sync_state):
              self.sync_state = sync_state
              change_types = self._change_types_map()
              for elem in self._get_elements(payload=self.get_payload(
                      folder=folder,
                      shape=shape,
                      additional_fields=additional_fields,
                      sync_state=sync_state,
              )):
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  change_type = change_types[elem.tag]
                  if change_type == self.DELETE:
                      folder = FolderId.from_xml(elem=elem.find(FolderId.response_tag()), account=self.account)
                  else:
                      # We can't find() the element because we don't know which tag to look for. The change element can
                      # contain multiple folder types, each with their own tag.
                      folder_elem = elem[0]
                      folder = parse_folder_elem(elem=folder_elem, folder=folder, account=self.account)
                  yield change_type, folder

          def get_payload(self, folder, shape, additional_fields, sync_state):
              return self._partial_get_payload(
                  folder=folder, shape=shape, additional_fields=additional_fields, sync_state=sync_state
              )

  ### Ancestors

  - SyncFolder
  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var last_in_range_name`
  `var shape_tag`

  ### Methods

  `def call(self, folder, shape, additional_fields, sync_state)`
    Expand source code

        def call(self, folder, shape, additional_fields, sync_state):
            self.sync_state = sync_state
            change_types = self._change_types_map()
            for elem in self._get_elements(payload=self.get_payload(
                    folder=folder,
                    shape=shape,
                    additional_fields=additional_fields,
                    sync_state=sync_state,
            )):
                if isinstance(elem, Exception):
                    yield elem
                    continue
                change_type = change_types[elem.tag]
                if change_type == self.DELETE:
                    folder = FolderId.from_xml(elem=elem.find(FolderId.response_tag()), account=self.account)
                else:
                    # We can't find() the element because we don't know which tag to look for. The change element can
                    # contain multiple folder types, each with their own tag.
                    folder_elem = elem[0]
                    folder = parse_folder_elem(elem=folder_elem, folder=folder, account=self.account)
                yield change_type, folder

  `def get_payload(self, folder, shape, additional_fields, sync_state)`
    Expand source code

        def get_payload(self, folder, shape, additional_fields, sync_state):
            return self._partial_get_payload(
                folder=folder, shape=shape, additional_fields=additional_fields, sync_state=sync_state
            )

  ### Inherited members

  - `SyncFolder`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class SyncFolderItems (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/syncfolderitems-operation

  Expand source code

      class SyncFolderItems(SyncFolder):
          """MSDN:
          https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/syncfolderitems-operation
          """

          SERVICE_NAME = 'SyncFolderItems'
          SYNC_SCOPES = {
              'NormalItems',
              'NormalAndAssociatedItems',
          }
          # Extra change type
          READ_FLAG_CHANGE = 'read_flag_change'
          CHANGE_TYPES = SyncFolder.CHANGE_TYPES + (READ_FLAG_CHANGE,)
          shape_tag = 'm:ItemShape'
          last_in_range_name = '{%s}IncludesLastItemInRange' % MNS

          def _change_types_map(self):
              res = super()._change_types_map()
              res['{%s}ReadFlagChange' % TNS] = self.READ_FLAG_CHANGE
              return res

          def call(self, folder, shape, additional_fields, sync_state, ignore, max_changes_returned, sync_scope):
              self.sync_state = sync_state
              if max_changes_returned is None:
                  max_changes_returned = self.chunk_size
              if max_changes_returned <= 0:
                  raise ValueError("'max_changes_returned' %s must be a positive integer" % max_changes_returned)
              if sync_scope is not None and sync_scope not in self.SYNC_SCOPES:
                  raise ValueError("'sync_scope' %s must be one of %r" % (sync_scope, self.SYNC_SCOPES))
              return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                      folder=folder,
                      shape=shape,
                      additional_fields=additional_fields,
                      sync_state=sync_state,
                      ignore=ignore,
                      max_changes_returned=max_changes_returned,
                      sync_scope=sync_scope,
              )))

          def _elems_to_objs(self, elems):
              from ..folders.base import BaseFolder
              change_types = self._change_types_map()
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  change_type = change_types[elem.tag]
                  if change_type == self.READ_FLAG_CHANGE:
                      item = (
                          ItemId.from_xml(elem=elem.find(ItemId.response_tag()), account=self.account),
                          xml_text_to_value(elem.find('{%s}IsRead' % TNS).text, bool)
                      )
                  elif change_type == self.DELETE:
                      item = ItemId.from_xml(elem=elem.find(ItemId.response_tag()), account=self.account)
                  else:
                      # We can't find() the element because we don't know which tag to look for. The change element can
                      # contain multiple item types, each with their own tag.
                      item_elem = elem[0]
                      item = BaseFolder.item_model_from_tag(item_elem.tag).from_xml(elem=item_elem, account=self.account)
                  yield change_type, item

          def get_payload(self, folder, shape, additional_fields, sync_state, ignore, max_changes_returned, sync_scope):
              syncfolderitems = self._partial_get_payload(
                  folder=folder, shape=shape, additional_fields=additional_fields, sync_state=sync_state
              )
              is_empty, ignore = (True, None) if ignore is None else peek(ignore)
              if not is_empty:
                  item_ids = create_item_ids_element(items=ignore, version=self.account.version, tag='m:Ignore')
                  syncfolderitems.append(item_ids)
              add_xml_child(syncfolderitems, 'm:MaxChangesReturned', max_changes_returned)
              if sync_scope:
                  add_xml_child(syncfolderitems, 'm:SyncScope', sync_scope)
              return syncfolderitems

  ### Ancestors

  - SyncFolder
  - EWSAccountService
  - EWSService

  ### Class variables

  `var CHANGE_TYPES`
  `var READ_FLAG_CHANGE`
  `var SERVICE_NAME`
  `var SYNC_SCOPES`
  `var last_in_range_name`
  `var shape_tag`

  ### Methods

  `def call(self, folder, shape, additional_fields, sync_state, ignore, max_changes_returned, sync_scope)`
    Expand source code

        def call(self, folder, shape, additional_fields, sync_state, ignore, max_changes_returned, sync_scope):
            self.sync_state = sync_state
            if max_changes_returned is None:
                max_changes_returned = self.chunk_size
            if max_changes_returned <= 0:
                raise ValueError("'max_changes_returned' %s must be a positive integer" % max_changes_returned)
            if sync_scope is not None and sync_scope not in self.SYNC_SCOPES:
                raise ValueError("'sync_scope' %s must be one of %r" % (sync_scope, self.SYNC_SCOPES))
            return self._elems_to_objs(self._get_elements(payload=self.get_payload(
                    folder=folder,
                    shape=shape,
                    additional_fields=additional_fields,
                    sync_state=sync_state,
                    ignore=ignore,
                    max_changes_returned=max_changes_returned,
                    sync_scope=sync_scope,
            )))

  `def get_payload(self, folder, shape, additional_fields, sync_state, ignore, max_changes_returned, sync_scope)`
    Expand source code

        def get_payload(self, folder, shape, additional_fields, sync_state, ignore, max_changes_returned, sync_scope):
            syncfolderitems = self._partial_get_payload(
                folder=folder, shape=shape, additional_fields=additional_fields, sync_state=sync_state
            )
            is_empty, ignore = (True, None) if ignore is None else peek(ignore)
            if not is_empty:
                item_ids = create_item_ids_element(items=ignore, version=self.account.version, tag='m:Ignore')
                syncfolderitems.append(item_ids)
            add_xml_child(syncfolderitems, 'm:MaxChangesReturned', max_changes_returned)
            if sync_scope:
                add_xml_child(syncfolderitems, 'm:SyncScope', sync_scope)
            return syncfolderitems

  ### Inherited members

  - `SyncFolder`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class Unsubscribe (*args, **kwargs)`

  Unsubscribing is only valid for pull and streaming notifications.

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/unsubscribe-operation

  Expand source code

      class Unsubscribe(EWSAccountService):
          """Unsubscribing is only valid for pull and streaming notifications.

          MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/unsubscribe-operation
          """

          SERVICE_NAME = 'Unsubscribe'
          returns_elements = False

          def call(self, subscription_id):
              return self._get_elements(payload=self.get_payload(subscription_id=subscription_id))

          def get_payload(self, subscription_id):
              unsubscribe = create_element('m:%s' % self.SERVICE_NAME)
              add_xml_child(unsubscribe, 'm:SubscriptionId', subscription_id)
              return unsubscribe

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var returns_elements`

  ### Methods

  `def call(self, subscription_id)`
    Expand source code

        def call(self, subscription_id):
            return self._get_elements(payload=self.get_payload(subscription_id=subscription_id))

  `def get_payload(self, subscription_id)`
    Expand source code

        def get_payload(self, subscription_id):
            unsubscribe = create_element('m:%s' % self.SERVICE_NAME)
            add_xml_child(unsubscribe, 'm:SubscriptionId', subscription_id)
            return unsubscribe

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class UpdateFolder (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/updatefolder-operation

  Expand source code

      class UpdateFolder(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/updatefolder-operation"""

          SERVICE_NAME = 'UpdateFolder'
          element_container_name = '{%s}Folders' % MNS

          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              self.folders = []  # A hack to communicate parsing args to _elems_to_objs()

          def call(self, folders):
              # We can't easily find the correct folder class from the returned XML. Instead, return objects with the same
              # class as the folder instance it was requested with.
              self.folders = list(folders)  # Convert to a list, in case 'folders' is a generator. We're iterating twice.
              return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=self.folders))

          def _elems_to_objs(self, elems):
              for (folder, _), elem in zip(self.folders, elems):
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield parse_folder_elem(elem=elem, folder=folder, account=self.account)

          @staticmethod
          def _sort_fieldnames(folder_model, fieldnames):
              # Take a list of fieldnames and return the fields in the order they are mentioned in folder_model.FIELDS.
              # Loop over FIELDS and not supported_fields(). Upstream should make sure not to update a non-supported field.
              for f in folder_model.FIELDS:
                  if f.name in fieldnames:
                      yield f.name

          def _set_folder_elem(self, folder_model, field_path, value):
              setfolderfield = create_element('t:SetFolderField')
              set_xml_value(setfolderfield, field_path, version=self.account.version)
              folder = create_element(folder_model.request_tag())
              field_elem = field_path.field.to_xml(value, version=self.account.version)
              set_xml_value(folder, field_elem, version=self.account.version)
              setfolderfield.append(folder)
              return setfolderfield

          def _delete_folder_elem(self, field_path):
              deletefolderfield = create_element('t:DeleteFolderField')
              return set_xml_value(deletefolderfield, field_path, version=self.account.version)

          def _get_folder_update_elems(self, folder, fieldnames):
              folder_model = folder.__class__
              fieldnames_set = set(fieldnames)

              for fieldname in self._sort_fieldnames(folder_model=folder_model, fieldnames=fieldnames_set):
                  field = folder_model.get_field_by_fieldname(fieldname)
                  if field.is_read_only:
                      raise ValueError('%s is a read-only field' % field.name)
                  value = field.clean(getattr(folder, field.name), version=self.account.version)  # Make sure the value is OK

                  if value is None or (field.is_list and not value):
                      # A value of None or [] means we want to remove this field from the item
                      if field.is_required or field.is_required_after_save:
                          raise ValueError('%s is a required field and may not be deleted' % field.name)
                      for field_path in FieldPath(field=field).expand(version=self.account.version):
                          yield self._delete_folder_elem(field_path=field_path)
                      continue

                  yield self._set_folder_elem(folder_model=folder_model, field_path=FieldPath(field=field), value=value)

          def get_payload(self, folders):
              from ..folders import BaseFolder, FolderId
              updatefolder = create_element('m:%s' % self.SERVICE_NAME)
              folderchanges = create_element('m:FolderChanges')
              version = self.account.version
              for folder, fieldnames in folders:
                  folderchange = create_element('t:FolderChange')
                  if not isinstance(folder, (BaseFolder, FolderId)):
                      folder = to_item_id(folder, FolderId, version=version)
                  set_xml_value(folderchange, folder, version=version)
                  updates = create_element('t:Updates')
                  for elem in self._get_folder_update_elems(folder=folder, fieldnames=fieldnames):
                      updates.append(elem)
                  folderchange.append(updates)
                  folderchanges.append(folderchange)
              if not len(folderchanges):
                  raise ValueError('"folders" must not be empty')
              updatefolder.append(folderchanges)
              return updatefolder

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`

  ### Methods

  `def call(self, folders)`
    Expand source code

        def call(self, folders):
            # We can't easily find the correct folder class from the returned XML. Instead, return objects with the same
            # class as the folder instance it was requested with.
            self.folders = list(folders)  # Convert to a list, in case 'folders' is a generator. We're iterating twice.
            return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=self.folders))

  `def get_payload(self, folders)`
    Expand source code

        def get_payload(self, folders):
            from ..folders import BaseFolder, FolderId
            updatefolder = create_element('m:%s' % self.SERVICE_NAME)
            folderchanges = create_element('m:FolderChanges')
            version = self.account.version
            for folder, fieldnames in folders:
                folderchange = create_element('t:FolderChange')
                if not isinstance(folder, (BaseFolder, FolderId)):
                    folder = to_item_id(folder, FolderId, version=version)
                set_xml_value(folderchange, folder, version=version)
                updates = create_element('t:Updates')
                for elem in self._get_folder_update_elems(folder=folder, fieldnames=fieldnames):
                    updates.append(elem)
                folderchange.append(updates)
                folderchanges.append(folderchange)
            if not len(folderchanges):
                raise ValueError('"folders" must not be empty')
            updatefolder.append(folderchanges)
            return updatefolder

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class UpdateItem (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateitem-operation

  Expand source code

      class UpdateItem(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateitem-operation"""

          SERVICE_NAME = 'UpdateItem'
          element_container_name = '{%s}Items' % MNS

          def call(self, items, conflict_resolution, message_disposition, send_meeting_invitations_or_cancellations,
                   suppress_read_receipts):
              from ..items import CONFLICT_RESOLUTION_CHOICES, MESSAGE_DISPOSITION_CHOICES, \
                  SEND_MEETING_INVITATIONS_AND_CANCELLATIONS_CHOICES, SEND_ONLY
              if conflict_resolution not in CONFLICT_RESOLUTION_CHOICES:
                  raise ValueError("'conflict_resolution' %s must be one of %s" % (
                      conflict_resolution, CONFLICT_RESOLUTION_CHOICES
                  ))
              if message_disposition not in MESSAGE_DISPOSITION_CHOICES:
                  raise ValueError("'message_disposition' %s must be one of %s" % (
                      message_disposition, MESSAGE_DISPOSITION_CHOICES
                  ))
              if send_meeting_invitations_or_cancellations not in SEND_MEETING_INVITATIONS_AND_CANCELLATIONS_CHOICES:
                  raise ValueError("'send_meeting_invitations_or_cancellations' %s must be one of %s" % (
                      send_meeting_invitations_or_cancellations, SEND_MEETING_INVITATIONS_AND_CANCELLATIONS_CHOICES
                  ))
              if suppress_read_receipts not in (True, False):
                  raise ValueError("'suppress_read_receipts' %s must be True or False" % suppress_read_receipts)
              if message_disposition == SEND_ONLY:
                  raise ValueError('Cannot send-only existing objects. Use SendItem service instead')
              return self._elems_to_objs(self._chunked_get_elements(
                  self.get_payload,
                  items=items,
                  conflict_resolution=conflict_resolution,
                  message_disposition=message_disposition,
                  send_meeting_invitations_or_cancellations=send_meeting_invitations_or_cancellations,
                  suppress_read_receipts=suppress_read_receipts,
              ))

          def _elems_to_objs(self, elems):
              from ..items import Item
              for elem in elems:
                  if isinstance(elem, (Exception, type(None))):
                      yield elem
                      continue
                  yield Item.id_from_xml(elem)

          def _delete_item_elem(self, field_path):
              deleteitemfield = create_element('t:DeleteItemField')
              return set_xml_value(deleteitemfield, field_path, version=self.account.version)

          def _set_item_elem(self, item_model, field_path, value):
              setitemfield = create_element('t:SetItemField')
              set_xml_value(setitemfield, field_path, version=self.account.version)
              item_elem = create_element(item_model.request_tag())
              field_elem = field_path.field.to_xml(value, version=self.account.version)
              set_xml_value(item_elem, field_elem, version=self.account.version)
              setitemfield.append(item_elem)
              return setitemfield

          @staticmethod
          def _sorted_fields(item_model, fieldnames):
              # Take a list of fieldnames and return the (unique) fields in the order they are mentioned in item_class.FIELDS.
              # Checks that all fieldnames are valid.
              unique_fieldnames = list(OrderedDict.fromkeys(fieldnames))  # Make field names unique ,but keep ordering
              # Loop over FIELDS and not supported_fields(). Upstream should make sure not to update a non-supported field.
              for f in item_model.FIELDS:
                  if f.name in unique_fieldnames:
                      unique_fieldnames.remove(f.name)
                      yield f
              if unique_fieldnames:
                  raise ValueError("Field name(s) %s are not valid for a '%s' item" % (
                      ', '.join("'%s'" % f for f in unique_fieldnames), item_model.__name__))

          def _get_item_update_elems(self, item, fieldnames):
              from ..items import CalendarItem
              fieldnames_copy = list(fieldnames)

              if item.__class__ == CalendarItem:
                  # For CalendarItem items where we update 'start' or 'end', we want to update internal timezone fields
                  item.clean_timezone_fields(version=self.account.version)  # Possibly also sets timezone values
                  for field_name in ('start', 'end'):
                      if field_name in fieldnames_copy:
                          tz_field_name = item.tz_field_for_field_name(field_name).name
                          if tz_field_name not in fieldnames_copy:
                              fieldnames_copy.append(tz_field_name)

              for field in self._sorted_fields(item_model=item.__class__, fieldnames=fieldnames_copy):
                  if field.is_read_only:
                      raise ValueError('%s is a read-only field' % field.name)
                  value = self._get_item_value(item, field)
                  if value is None or (field.is_list and not value):
                      # A value of None or [] means we want to remove this field from the item
                      yield from self._get_delete_item_elems(field=field)
                  else:
                      yield from self._get_set_item_elems(item_model=item.__class__, field=field, value=value)

          def _get_item_value(self, item, field):
              from ..items import CalendarItem
              value = field.clean(getattr(item, field.name), version=self.account.version)  # Make sure the value is OK
              if item.__class__ == CalendarItem:
                  # For CalendarItem items where we update 'start' or 'end', we want to send values in the local timezone
                  if field.name in ('start', 'end'):
                      if type(value) is EWSDate:
                          # EWS always expects a datetime
                          return item.date_to_datetime(field_name=field.name)
                      tz_field_name = item.tz_field_for_field_name(field.name).name
                      return value.astimezone(getattr(item, tz_field_name))
              return value

          def _get_delete_item_elems(self, field):
              if field.is_required or field.is_required_after_save:
                  raise ValueError('%s is a required field and may not be deleted' % field.name)
              for field_path in FieldPath(field=field).expand(version=self.account.version):
                  yield self._delete_item_elem(field_path=field_path)

          def _get_set_item_elems(self, item_model, field, value):
              if isinstance(field, IndexedField):
                  # Generate either set or delete elements for all combinations of labels and subfields
                  supported_labels = field.value_cls.get_field_by_fieldname('label')\
                      .supported_choices(version=self.account.version)
                  seen_labels = set()
                  subfields = field.value_cls.supported_fields(version=self.account.version)
                  for v in value:
                      seen_labels.add(v.label)
                      for subfield in subfields:
                          field_path = FieldPath(field=field, label=v.label, subfield=subfield)
                          subfield_value = getattr(v, subfield.name)
                          if not subfield_value:
                              # Generate delete elements for blank subfield values
                              yield self._delete_item_elem(field_path=field_path)
                          else:
                              # Generate set elements for non-null subfield values
                              yield self._set_item_elem(
                                  item_model=item_model,
                                  field_path=field_path,
                                  value=field.value_cls(**{'label': v.label, subfield.name: subfield_value}),
                              )
                      # Generate delete elements for all subfields of all labels not mentioned in the list of values
                      for label in (label for label in supported_labels if label not in seen_labels):
                          for subfield in subfields:
                              yield self._delete_item_elem(field_path=FieldPath(field=field, label=label, subfield=subfield))
              else:
                  yield self._set_item_elem(item_model=item_model, field_path=FieldPath(field=field), value=value)

          def get_payload(self, items, conflict_resolution, message_disposition, send_meeting_invitations_or_cancellations,
                          suppress_read_receipts):
              # Takes a list of (Item, fieldnames) tuples where 'Item' is a instance of a subclass of Item and 'fieldnames'
              # are the attribute names that were updated. Returns the XML for an UpdateItem call.
              # an UpdateItem request.
              if self.account.version.build >= EXCHANGE_2013_SP1:
                  updateitem = create_element(
                      'm:%s' % self.SERVICE_NAME,
                      attrs=OrderedDict([
                          ('ConflictResolution', conflict_resolution),
                          ('MessageDisposition', message_disposition),
                          ('SendMeetingInvitationsOrCancellations', send_meeting_invitations_or_cancellations),
                          ('SuppressReadReceipts', 'true' if suppress_read_receipts else 'false'),
                      ])
                  )
              else:
                  updateitem = create_element(
                      'm:%s' % self.SERVICE_NAME,
                      attrs=OrderedDict([
                          ('ConflictResolution', conflict_resolution),
                          ('MessageDisposition', message_disposition),
                          ('SendMeetingInvitationsOrCancellations', send_meeting_invitations_or_cancellations),
                      ])
                  )
              itemchanges = create_element('m:ItemChanges')
              version = self.account.version
              for item, fieldnames in items:
                  if not item.account:
                      item.account = self.account
                  if not fieldnames:
                      raise ValueError('"fieldnames" must not be empty')
                  itemchange = create_element('t:ItemChange')
                  set_xml_value(itemchange, to_item_id(item, ItemId, version=version), version=version)
                  updates = create_element('t:Updates')
                  for elem in self._get_item_update_elems(item=item, fieldnames=fieldnames):
                      updates.append(elem)
                  itemchange.append(updates)
                  itemchanges.append(itemchange)
              if not len(itemchanges):
                  raise ValueError('"items" must not be empty')
              updateitem.append(itemchanges)
              return updateitem

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`

  ### Methods

  `def call(self, items, conflict_resolution, message_disposition, send_meeting_invitations_or_cancellations, suppress_read_receipts)`
    Expand source code

        def call(self, items, conflict_resolution, message_disposition, send_meeting_invitations_or_cancellations,
                 suppress_read_receipts):
            from ..items import CONFLICT_RESOLUTION_CHOICES, MESSAGE_DISPOSITION_CHOICES, \
                SEND_MEETING_INVITATIONS_AND_CANCELLATIONS_CHOICES, SEND_ONLY
            if conflict_resolution not in CONFLICT_RESOLUTION_CHOICES:
                raise ValueError("'conflict_resolution' %s must be one of %s" % (
                    conflict_resolution, CONFLICT_RESOLUTION_CHOICES
                ))
            if message_disposition not in MESSAGE_DISPOSITION_CHOICES:
                raise ValueError("'message_disposition' %s must be one of %s" % (
                    message_disposition, MESSAGE_DISPOSITION_CHOICES
                ))
            if send_meeting_invitations_or_cancellations not in SEND_MEETING_INVITATIONS_AND_CANCELLATIONS_CHOICES:
                raise ValueError("'send_meeting_invitations_or_cancellations' %s must be one of %s" % (
                    send_meeting_invitations_or_cancellations, SEND_MEETING_INVITATIONS_AND_CANCELLATIONS_CHOICES
                ))
            if suppress_read_receipts not in (True, False):
                raise ValueError("'suppress_read_receipts' %s must be True or False" % suppress_read_receipts)
            if message_disposition == SEND_ONLY:
                raise ValueError('Cannot send-only existing objects. Use SendItem service instead')
            return self._elems_to_objs(self._chunked_get_elements(
                self.get_payload,
                items=items,
                conflict_resolution=conflict_resolution,
                message_disposition=message_disposition,
                send_meeting_invitations_or_cancellations=send_meeting_invitations_or_cancellations,
                suppress_read_receipts=suppress_read_receipts,
            ))

  `def get_payload(self, items, conflict_resolution, message_disposition, send_meeting_invitations_or_cancellations, suppress_read_receipts)`
    Expand source code

        def get_payload(self, items, conflict_resolution, message_disposition, send_meeting_invitations_or_cancellations,
                        suppress_read_receipts):
            # Takes a list of (Item, fieldnames) tuples where 'Item' is a instance of a subclass of Item and 'fieldnames'
            # are the attribute names that were updated. Returns the XML for an UpdateItem call.
            # an UpdateItem request.
            if self.account.version.build >= EXCHANGE_2013_SP1:
                updateitem = create_element(
                    'm:%s' % self.SERVICE_NAME,
                    attrs=OrderedDict([
                        ('ConflictResolution', conflict_resolution),
                        ('MessageDisposition', message_disposition),
                        ('SendMeetingInvitationsOrCancellations', send_meeting_invitations_or_cancellations),
                        ('SuppressReadReceipts', 'true' if suppress_read_receipts else 'false'),
                    ])
                )
            else:
                updateitem = create_element(
                    'm:%s' % self.SERVICE_NAME,
                    attrs=OrderedDict([
                        ('ConflictResolution', conflict_resolution),
                        ('MessageDisposition', message_disposition),
                        ('SendMeetingInvitationsOrCancellations', send_meeting_invitations_or_cancellations),
                    ])
                )
            itemchanges = create_element('m:ItemChanges')
            version = self.account.version
            for item, fieldnames in items:
                if not item.account:
                    item.account = self.account
                if not fieldnames:
                    raise ValueError('"fieldnames" must not be empty')
                itemchange = create_element('t:ItemChange')
                set_xml_value(itemchange, to_item_id(item, ItemId, version=version), version=version)
                updates = create_element('t:Updates')
                for elem in self._get_item_update_elems(item=item, fieldnames=fieldnames):
                    updates.append(elem)
                itemchange.append(updates)
                itemchanges.append(itemchange)
            if not len(itemchanges):
                raise ValueError('"items" must not be empty')
            updateitem.append(itemchanges)
            return updateitem

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class UpdateUserConfiguration (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateuserconfiguration-operation

  Expand source code

      class UpdateUserConfiguration(EWSAccountService):
          """MSDN:
          https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateuserconfiguration-operation
          """

          SERVICE_NAME = 'UpdateUserConfiguration'
          returns_elements = False

          def call(self, user_configuration):
              return self._get_elements(payload=self.get_payload(user_configuration=user_configuration))

          def get_payload(self, user_configuration):
              updateuserconfiguration = create_element('m:%s' % self.SERVICE_NAME)
              set_xml_value(updateuserconfiguration, user_configuration, version=self.account.version)
              return updateuserconfiguration

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var returns_elements`

  ### Methods

  `def call(self, user_configuration)`
    Expand source code

        def call(self, user_configuration):
            return self._get_elements(payload=self.get_payload(user_configuration=user_configuration))

  `def get_payload(self, user_configuration)`
    Expand source code

        def get_payload(self, user_configuration):
            updateuserconfiguration = create_element('m:%s' % self.SERVICE_NAME)
            set_xml_value(updateuserconfiguration, user_configuration, version=self.account.version)
            return updateuserconfiguration

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`
`class UploadItems (*args, **kwargs)`

  MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/uploaditems-operation

  Expand source code

      class UploadItems(EWSAccountService):
          """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/uploaditems-operation
          """

          SERVICE_NAME = 'UploadItems'
          element_container_name = '{%s}ItemId' % MNS

          def call(self, items):
              # _pool_requests expects 'items', not 'data'
              return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=items))

          def get_payload(self, items):
              """Upload given items to given account.

              'items' is an iterable of tuples where the first element is a Folder instance representing the ParentFolder
              that the item will be placed in and the second element is a tuple containing an optional ItemId, an optional
              Item.is_associated boolean, and a Data string returned from an ExportItems.
              call.

              :param items:
              """
              uploaditems = create_element('m:%s' % self.SERVICE_NAME)
              itemselement = create_element('m:Items')
              uploaditems.append(itemselement)
              for parent_folder, (item_id, is_associated, data_str) in items:
                  # TODO: The full spec also allows the "UpdateOrCreate" create action.
                  item = create_element('t:Item', attrs=dict(CreateAction='Update' if item_id else 'CreateNew'))
                  if is_associated is not None:
                      item.set('IsAssociated', 'true' if is_associated else 'false')
                  parentfolderid = ParentFolderId(parent_folder.id, parent_folder.changekey)
                  set_xml_value(item, parentfolderid, version=self.account.version)
                  if item_id:
                      itemid = to_item_id(item_id, ItemId, version=self.account.version)
                      set_xml_value(item, itemid, version=self.account.version)
                  add_xml_child(item, 't:Data', data_str)
                  itemselement.append(item)
              return uploaditems

          def _elems_to_objs(self, elems):
              for elem in elems:
                  if isinstance(elem, Exception):
                      yield elem
                      continue
                  yield elem.get(ItemId.ID_ATTR), elem.get(ItemId.CHANGEKEY_ATTR)

          @classmethod
          def _get_elements_in_container(cls, container):
              return [container]

  ### Ancestors

  - EWSAccountService
  - EWSService

  ### Class variables

  `var SERVICE_NAME`
  `var element_container_name`

  ### Methods

  `def call(self, items)`
    Expand source code

        def call(self, items):
            # _pool_requests expects 'items', not 'data'
            return self._elems_to_objs(self._chunked_get_elements(self.get_payload, items=items))

  `def get_payload(self, items)`

    Upload given items to given account.

    'items' is an iterable of tuples where the first element is a Folder instance representing the ParentFolder that the item will be placed in and the second element is a tuple containing an optional ItemId, an optional Item.is_associated boolean, and a Data string returned from an ExportItems. call.

    :param items:

    Expand source code

        def get_payload(self, items):
            """Upload given items to given account.

            'items' is an iterable of tuples where the first element is a Folder instance representing the ParentFolder
            that the item will be placed in and the second element is a tuple containing an optional ItemId, an optional
            Item.is_associated boolean, and a Data string returned from an ExportItems.
            call.

            :param items:
            """
            uploaditems = create_element('m:%s' % self.SERVICE_NAME)
            itemselement = create_element('m:Items')
            uploaditems.append(itemselement)
            for parent_folder, (item_id, is_associated, data_str) in items:
                # TODO: The full spec also allows the "UpdateOrCreate" create action.
                item = create_element('t:Item', attrs=dict(CreateAction='Update' if item_id else 'CreateNew'))
                if is_associated is not None:
                    item.set('IsAssociated', 'true' if is_associated else 'false')
                parentfolderid = ParentFolderId(parent_folder.id, parent_folder.changekey)
                set_xml_value(item, parentfolderid, version=self.account.version)
                if item_id:
                    itemid = to_item_id(item_id, ItemId, version=self.account.version)
                    set_xml_value(item, itemid, version=self.account.version)
                add_xml_child(item, 't:Data', data_str)
                itemselement.append(item)
            return uploaditems

  ### Inherited members

  - `EWSAccountService`:
    - `NO_VALID_SERVER_VERSIONS`
    - `WARNINGS_TO_CATCH_IN_RESPONSE`
    - `get`
    - `parse`