def _convert_message_part_to_str(message_part: email.message.EmailMessage) -> Tuple[str, bool]: content: Union[str, bytes] = message_part.get_content() content_type = message_part.get_content_type() content_transfer_encoding = message_part['Content-Transfer-Encoding'] logger_dict = {'ContentType': content_type, 'ContentTransferEncoding': content_transfer_encoding} if isinstance(content, str): logger.info('Successfully decoded message part with {ContentType} {ContentTransferEncoding} as string', fparams=logger_dict) return content, False try: if content_type == 'application/xml': decoded_content = content.decode() logger.info('Successfully decoded message part with {ContentType} {ContentTransferEncoding} ' 'as a string', fparams=logger_dict) return decoded_content, False decoded_content = base64.b64encode(content).decode() logger.info('Successfully encoded binary message part with {ContentType} {ContentTransferEncoding} as ' 'a base64 string', fparams=logger_dict) return decoded_content, True except UnicodeDecodeError as e: logger.error('Failed to decode ebXML message part with {ContentType} {ContentTransferEncoding}.', fparams=logger_dict) raise ebxml_envelope.EbXmlParsingError(f'Failed to decode ebXML message part with ' f'Content-Type: {content_type} and ' f'Content-Transfer-Encoding: {content_transfer_encoding}') from e
def _extract_message_parts(msg: email.message.EmailMessage) -> Tuple[str, str, List[Dict[str, Union[str, bool]]]]: """Extract the ebXML and payload parts of the message and return them as a tuple. :param msg: The message to extract parts from. :return: A tuple containing the ebXML and payload (if present, otherwise None) parts of the message provided. """ # EIS section 2.5.4 defines that the first MIME part must contain the ebML SOAP message and the message payload # (if present) must be the first additional attachment. if not msg.is_multipart(): logger.error('Non-multipart message received') raise ebxml_envelope.EbXmlParsingError("Non-multipart message received") message_parts: Sequence[email.message.EmailMessage] = tuple(msg.iter_parts()) EbxmlRequestEnvelope._report_any_defects_in_message_parts(message_parts) # ebXML part is the first part of the message ebxml_part = EbxmlRequestEnvelope._extract_ebxml_part(message_parts[0]) payload_part = None attachments = [] if len(message_parts) > 1: # HL7 payload part is the second part of the message payload_part = EbxmlRequestEnvelope._extract_hl7_payload_part(message_parts[1]) # Any additional attachments are from the third part of the message onwards attachments.extend(EbxmlRequestEnvelope._extract_additional_attachments_parts(message_parts[2:])) return ebxml_part, payload_part, attachments
def _extract_hl7_payload_part( message_part: email.message.EmailMessage) -> str: payload_part, is_base64_payload = EbxmlRequestEnvelope._convert_message_part_to_str( message_part) if is_base64_payload: logger.error( '0008', 'Failed to decode HL7 payload part of message as text') raise ebxml_envelope.EbXmlParsingError( "Failed to decode HL7 payload part of message as text") return payload_part
def _extract_ebxml_part(message_part: email.message.EmailMessage) -> str: ebxml_part, is_base64_ebxml_part = EbxmlRequestEnvelope._convert_message_part_to_str( message_part) if is_base64_ebxml_part: logger.error( '0007', 'Failed to decode ebXML header part of message as text') raise ebxml_envelope.EbXmlParsingError( "Failed to decode ebXML header part of message as text") return ebxml_part