'Parses a string or email.message.Message representing an
RFC-2822 email, and returns a generic dict holding the
message details.
:param message: the message to parse
:type message: email.message.Message | string | unicode
:param bool save_original: whether the returned dict
should include an ``original`` attachment containing
the source of the message
:rtype: dict
:return: A dict with the following structure, where each
field may not be present if missing in original
message::
{ \'message_id\': msg_id,
\'subject\': subject,
\'from\': from,
\'to\': to,
\'cc\': cc,
\'body\': unified_body,
\'attachments\': [(\'file1\', \'bytes\'),
(\'file2\', \'bytes\')}'

@api.model
def message_parse(self, message, save_original=False):

    msg_dict = {'message_type': 'email'}
    if (not isinstance(message, Message)):
        if isinstance(message, unicode):
            message = message.encode('utf-8')
        message = email.message_from_string(message)
    message_id = message['message-id']
    if (not message_id):
        message_id = ('<%s@localhost>' % time.time())
        _logger.debug('Parsing    Message    without    message-id,    generating    a    random    one:    %s', message_id)
    msg_dict['message_id'] = message_id
    if message.get('Subject'):
        msg_dict['subject'] = tools.decode_smtp_header(message.get('Subject'))
    msg_dict['from'] = tools.decode_smtp_header(message.get('from'))
    msg_dict['to'] = tools.decode_smtp_header(message.get('to'))
    msg_dict['cc'] = tools.decode_smtp_header(message.get('cc'))
    msg_dict['email_from'] = tools.decode_smtp_header(message.get('from'))
    partner_ids = self._message_find_partners(message, ['To', 'Cc'])
    msg_dict['partner_ids'] = [(4, partner_id) for partner_id in partner_ids]
    if message.get('Date'):
        try:
            date_hdr = tools.decode_smtp_header(message.get('Date'))
            parsed_date = dateutil.parser.parse(date_hdr, fuzzy=True)
            if (parsed_date.utcoffset() is None):
                stored_date = parsed_date.replace(tzinfo=pytz.utc)
            else:
                stored_date = parsed_date.astimezone(tz=pytz.utc)
        except Exception:
            _logger.info('Failed    to    parse    Date    header    %r    in    incoming    mail    with    message-id    %r,    assuming    current    date/time.', message.get('Date'), message_id)
            stored_date = datetime.datetime.now()
        msg_dict['date'] = stored_date.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
    if message.get('In-Reply-To'):
        parent_ids = self.env['mail.message'].search([('message_id', '=', tools.decode_smtp_header(message['In-Reply-To'].strip()))], limit=1)
        if parent_ids:
            msg_dict['parent_id'] = parent_ids.id
            msg_dict['internal'] = ((parent_ids.subtype_id and parent_ids.subtype_id.internal) or False)
    if (message.get('References') and ('parent_id' not in msg_dict)):
        msg_list = tools.mail_header_msgid_re.findall(tools.decode_smtp_header(message['References']))
        parent_ids = self.env['mail.message'].search([('message_id', 'in', [x.strip() for x in msg_list])], limit=1)
        if parent_ids:
            msg_dict['parent_id'] = parent_ids.id
            msg_dict['internal'] = ((parent_ids.subtype_id and parent_ids.subtype_id.internal) or False)
    (msg_dict['body'], msg_dict['attachments']) = self._message_extract_payload(message, save_original=save_original)
    return msg_dict
