def _show_message_cleartext(self, message_id: str, ciphertext: str, address_id: str) -> None: key_id, private_key = self._db.get_own_address_nacl_key(address_id) cleartext = self._crypto_provider.decrypt(ciphertext, private_key) # Cleartext is supposed to be a MIME formatted message msg = BytesParser(policy=policy.default).parsebytes(cleartext) ## DEBUG self._logger.debug("Message id: {0} - Content: {1}".format(message_id, msg.as_string())) content = [] address_pad = None address_pad_req = None for part in msg.walk(): # Account for stuff we know will turn up - Specifically wrappers and protocol # control messages if part.get_content_type() == 'application/json': if part['Content-Description'] == NodeIntercom.address_pad_request_description: address_pad_req = NodeIntercom.AddressPadRequest.deserialize(part.get_content()) if part['Content-Description'] == NodeIntercom.address_pad_description: address_pad = NodeIntercom.AddressPad.deserialize(part.get_content()) elif part.get_content_maintype() == 'multipart' or \ part.get_content_maintype() == 'application': continue else: content.append(part.get_content()) msg_string = "From: {0}\nTo: {1}\n\n{2}".format(msg['from'], msg['to'], "\n".join(content)) def _delete_message(message_id): self._logger.debug("Attempting to clean out message: {0}".format(message_id)) self._db.clean_out_received_message(message_id) self.received_messages() # Reload the messages menu return True def _no_action(): return True # If the mail contained a address pad request or a message pad, show the alternatives if address_pad: import_prompt = "This message includes a block of addresses to {0}. " \ "Import these?".format(address_pad.from_alias) should_import = self._show_confirmation_dialog(import_prompt) self._redraw() if should_import: self._import_address_pad(address_pad, msg['to']) if address_pad_req: request_prompt = "This message includes a request by {0} to send {1} additional " \ "addresses. Enqueue addresses to {0}?".format(msg['from'], address_pad_req.pad_size) should_respond = self._show_confirmation_dialog(request_prompt) self._redraw() if should_respond: # Takes the "from" field and finds a contact from it, which is not ideal - # A "real" version of this would offer some kind of contact selection interaction # instead of trusting the from-header. destination = self._db.read_contact_from_nickname(msg['from']) # If the destination is not a known nickname, we'll just drop it - Again not ideal. if not destination: return address_data = self._db.get_address_pad_nacl(destination.contact_id)[0] return_msg = self._generate_own_address_pad_mime_message(destination, 10) self._enqueue_generic_message(address_data, return_msg) # With the system messages done and dusted, let's show the defaul choices menu_items = [] menu_items.append(_MenuItem("q", "Return", lambda: _no_action)) menu_items.append(_MenuItem("d", "Delete", lambda: _delete_message(message_id))) action_menu = _Menu("Choice", menu_items) self._show_selection_dialog(action_menu, vertical=False, text=msg_string)