From aca34baba8041461bfc63ad8521f91c39f122c64 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 15 Dec 2016 14:44:52 +0100 Subject: [PATCH] [FIX] mail: fix cardinality issues in bounce processing A couple of places in the processing of bounces only accepted a single matching partner. But there could be multiple partners matching an email address, and we should handle them all. There might also be no matching `bounced_thread_id` matched by the regex, so we should guard against a bounced_thread_id == None. --- addons/mail/models/mail_channel.py | 5 +++-- addons/mail/models/mail_thread.py | 17 +++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py index f0fe2784447..1491039e860 100644 --- a/addons/mail/models/mail_channel.py +++ b/addons/mail/models/mail_channel.py @@ -209,8 +209,9 @@ class Channel(models.Model): @api.multi def message_receive_bounce(self, email, partner, mail_id=None): """ Override bounce management to unsubscribe bouncing addresses """ - if partner.message_bounce >= self.MAX_BOUNCE_LIMIT: - self._action_unfollow(partner) + for p in partner: + if p.message_bounce >= self.MAX_BOUNCE_LIMIT: + self._action_unfollow(p) return super(Channel, self).message_receive_bounce(email, partner, mail_id=mail_id) @api.multi diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index c360dfbd6fd..1edbd7f6275 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -1053,19 +1053,20 @@ class MailThread(models.AbstractModel): bounce_match = bounce_re.search(email_to) if bounce_match: - bounced_mail_id, bounced_model, bounced_thread_id = bounce_match.group(1), bounce_match.group(2), int(bounce_match.group(3)) + bounced_mail_id, bounced_model, bounced_thread_id = bounce_match.group(1), bounce_match.group(2), bounce_match.group(3) email_part = next((part for part in message.walk() if part.get_content_type() == 'message/rfc822'), None) dsn_part = next((part for part in message.walk() if part.get_content_type() == 'message/delivery-status'), None) - partner, partner_address = self.env['res.partner'], False + partners, partner_address = self.env['res.partner'], False 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') partner_address = final_recipient_data.split(';', 1)[1].strip() if partner_address: - partner = partner.sudo().search([('email', 'like', partner_address)]) - partner.message_receive_bounce(partner_address, partner, mail_id=bounced_mail_id) + partners = partners.sudo().search([('email', 'like', partner_address)]) + for partner in partners: + partner.message_receive_bounce(partner_address, partner, mail_id=bounced_mail_id) mail_message = self.env['mail.message'] if email_part: @@ -1073,19 +1074,19 @@ class MailThread(models.AbstractModel): bounced_message_id = tools.mail_header_msgid_re.findall(tools.decode_message_header(email, 'Message-Id')) mail_message = MailMessage.sudo().search([('message_id', 'in', bounced_message_id)]) - if partner and mail_message: + if partners and mail_message: notifications = self.env['mail.notification'].sudo().search([ ('mail_message_id', '=', mail_message.id), - ('res_partner_id', '=', partner.id)]) + ('res_partner_id', 'in', partners.ids)]) notifications.write({ 'email_status': 'bounce' }) if bounced_model in self.env and hasattr(self.env[bounced_model], 'message_receive_bounce') and bounced_thread_id: - self.env[bounced_model].browse(bounced_thread_id).message_receive_bounce(partner_address, partner, mail_id=bounced_mail_id) + self.env[bounced_model].browse(int(bounced_thread_id)).message_receive_bounce(partner_address, partners, mail_id=bounced_mail_id) _logger.info('Routing mail from %s to %s with Message-Id %s: bounced mail from mail %s, model: %s, thread_id: %s: dest %s (partner %s)', - email_from, email_to, message_id, bounced_mail_id, bounced_model, bounced_thread_id, partner_address, partner.id) + email_from, email_to, message_id, bounced_mail_id, bounced_model, bounced_thread_id, partner_address, partners) return [] # 0. First check if this is a bounce message or not.