(self, email_message, message_dict)
return {
            'bounced_email': bounced_email,
            'bounced_partner': bounced_partner,
            'bounced_msg_id': bounced_msg_id,
            'bounced_message': bounced_message,
        }
Parse email and extract bounce information to be used in future
        processing.

        :param email_message: an email.message instance;
        :param message_dict: dictionary holding already-parsed values;

        :return dict: bounce-related values will be added, containing

          * bounced_email: email that bounced (normalized);
          * bounce_partner: res.partner recordset whose email_normalized =
            bounced_email;
          * bounced_msg_id: list of message_ID references (<...@myserver>) linked
            to the email that bounced;
          * bounced_message: if found, mail.message recordset matching bounced_msg_id;
Parse email and extract bounce information to be used in future
        processing.
Parse email and extract bounce information to be used in future processing .
def _message_parse_extract_bounce(self, email_message, message_dict):
        """ Parse email and extract bounce information to be used in future
        processing.

        :param email_message: an email.message instance;
        :param message_dict: dictionary holding already-parsed values;

        :return dict: bounce-related values will be added, containing

          * bounced_email: email that bounced (normalized);
          * bounce_partner: res.partner recordset whose email_normalized =
            bounced_email;
          * bounced_msg_id: list of message_ID references (<...@myserver>) linked
            to the email that bounced;
          * bounced_message: if found, mail.message recordset matching bounced_msg_id;
        """
        if not isinstance(email_message, EmailMessage):
            raise TypeError('message must be an email.message.EmailMessage at this point')

        email_part = next((part for part in email_message.walk() if part.get_content_type() in {'message/rfc822', 'text/rfc822-headers'}), None)
        dsn_part = next((part for part in email_message.walk() if part.get_content_type() == 'message/delivery-status'), None)

        bounced_email = False
        bounced_partner = self.env['res.partner'].sudo()
        if dsn_part and len(dsn_part.get_payload()) > 1:
            dsn = dsn_part.get_payload()[1]
            final_recipient_data = tools.decode_message_header(dsn, 'Final-Recipient')
            # old servers may hold void or invalid Final-Recipient header
            if final_recipient_data and ";" in final_recipient_data:
                bounced_email = tools.email_normalize(final_recipient_data.split(';', 1)[1].strip())
            if bounced_email:
                bounced_partner = self.env['res.partner'].sudo().search([('email_normalized', '=', bounced_email)])

        bounced_msg_id = False
        bounced_message = self.env['mail.message'].sudo()
        if email_part:
            if email_part.get_content_type() == 'text/rfc822-headers':
                # Convert the message body into a message itself
                email_payload = message_from_string(email_part.get_payload(), policy=policy.SMTP)
            else:
                email_payload = email_part.get_payload()[0]
            bounced_msg_id = tools.mail_header_msgid_re.findall(tools.decode_message_header(email_payload, 'Message-Id'))
            if bounced_msg_id:
                bounced_message = self.env['mail.message'].sudo().search([('message_id', 'in', bounced_msg_id)])

        return {
            'bounced_email': bounced_email,
            'bounced_partner': bounced_partner,
            'bounced_msg_id': bounced_msg_id,
            'bounced_message': bounced_message,
        }
def _message_parse_extract_bounce ( self , email_message , message_dict ) : if not isinstance ( email_message , EmailMessage ) : raise TypeError ( 'message must be an email.message.EmailMessage at this point' ) email_part = next ( ( part for part in email_message . walk ( ) if part . get_content_type ( ) in { 'message/rfc822' , 'text/rfc822-headers' } ) , None ) dsn_part = next ( ( part for part in email_message . walk ( ) if part . get_content_type ( ) == 'message/delivery-status' ) , None ) bounced_email = False bounced_partner = self . env [ 'res.partner' ] . sudo ( ) if dsn_part and len ( dsn_part . get_payload ( ) ) > 1 : dsn = dsn_part . get_payload ( ) [ 1 ] final_recipient_data = tools . decode_message_header ( dsn , 'Final-Recipient' ) # old servers may hold void or invalid Final-Recipient header if final_recipient_data and ";" in final_recipient_data : bounced_email = tools . email_normalize ( final_recipient_data . split ( ';' , 1 ) [ 1 ] . strip ( ) ) if bounced_email : bounced_partner = self . env [ 'res.partner' ] . sudo ( ) . search ( [ ( 'email_normalized' , '=' , bounced_email ) ] ) bounced_msg_id = False bounced_message = self . env [ 'mail.message' ] . sudo ( ) if email_part : if email_part . get_content_type ( ) == 'text/rfc822-headers' : # Convert the message body into a message itself email_payload = message_from_string ( email_part . get_payload ( ) , policy = policy . SMTP ) else : email_payload = email_part . get_payload ( ) [ 0 ] bounced_msg_id = tools . mail_header_msgid_re . findall ( tools . decode_message_header ( email_payload , 'Message-Id' ) ) if bounced_msg_id : bounced_message = self . env [ 'mail.message' ] . sudo ( ) . search ( [ ( 'message_id' , 'in' , bounced_msg_id ) ] ) return { 'bounced_email' : bounced_email , 'bounced_partner' : bounced_partner , 'bounced_msg_id' : bounced_msg_id , 'bounced_message' : bounced_message , }