Module exchangelib.services.get_attachment
Classes
class GetAttachment (*args, **kwargs)-
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 = f"{{{MNS}}}Attachments" cls_map = {cls.response_tag(): cls for cls in (FileAttachment, ItemAttachment)} 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 InvalidEnumValue("body_type", 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 _elem_to_obj(self, elem): return self.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(f"m:{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) payload.append(attachment_ids_element(items=items, version=self.account.version)) return payload def _update_api_version(self, api_version, header): if not self.streaming: super()._update_api_version(api_version, header) # TODO: We're skipping this part in streaming mode because StreamingBase64Parser cannot parse the SOAP header def _get_soap_parts(self, response): if not self.streaming: return super()._get_soap_parts(response) # Pass the response unaltered. We want to use our custom streaming parser return None, response def _get_soap_messages(self, body): if not self.streaming: return super()._get_soap_messages(body) # '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) 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(content=enf.data) _, body = super()._get_soap_parts(response=response) # TODO: We're skipping ._update_api_version() here because we don't have access to the 'api_version' used. 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.stop_streaming() self.streaming = FalseAncestors
Class variables
var cls_map-
The type of the None singleton.
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 InvalidEnumValue("body_type", 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(f"m:{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) payload.append(attachment_ids_element(items=items, version=self.account.version)) 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) 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(content=enf.data) _, body = super()._get_soap_parts(response=response) # TODO: We're skipping ._update_api_version() here because we don't have access to the 'api_version' used. 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.stop_streaming() self.streaming = False
Inherited members