Skip to content
Permalink
Browse files

[IMP] mail: rewrote a bit bouncy bounce

  • Loading branch information...
tde-banana-odoo committed Jan 4, 2019
1 parent 740b509 commit 3e6ddb04e524ff1b6b6e3bb329006467a856227b
@@ -338,12 +338,12 @@ def _notify_specific_email_values(self, message):
return res

@api.multi
def _message_receive_bounce(self, email, partner, mail_id=None):
def _message_receive_bounce(self, email, partner):
""" Override bounce management to unsubscribe bouncing addresses """
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)
return super(Channel, self)._message_receive_bounce(email, partner)

@api.multi
def _notify_email_recipients(self, message, recipient_ids):
@@ -1170,33 +1170,24 @@ def message_route(self, message, message_dict, model=None, thread_id=None, custo
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)

partners, partner_address = self.env['res.partner'], False
bounced_email = 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:
partners = partners.sudo().search([('email', '=', partner_address)])
for partner in partners:
partner._message_receive_bounce(partner_address, partner, mail_id=bounced_mail_id)
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', 'ilike', bounced_email)])

mail_message = self.env['mail.message']
bounced_msg_id = False
if email_part:
email = email_part.get_payload()[0]
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)])
bounced_msg_id = tools.mail_header_msgid_re.findall(tools.decode_message_header(email, 'Message-Id'))

if partners and mail_message:
notifications = self.env['mail.notification'].sudo().search([
('mail_message_id', '=', mail_message.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(int(bounced_thread_id))._message_receive_bounce(partner_address, partners, mail_id=bounced_mail_id)
bounced_record = False
if bounced_model in self.env and bounced_thread_id:
bounced_record = self.env[bounced_model].browse(int(bounced_thread_id)).exists()

self._gateway_bounce(bounced_email, bounced_partner, bounced_msg_id, bounced_record, 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, partners)
return []
@@ -1469,7 +1460,7 @@ def message_update(self, msg_dict, update_vals=None):
return True

@api.multi
def _message_receive_bounce(self, email, partner, mail_id=None):
def _message_receive_bounce(self, email, partner):
"""Called by ``message_process`` when a bounce email (such as Undelivered
Mail Returned to Sender) is received for an existing thread. The default
behavior is to check is an integer ``message_bounce`` column exists.
@@ -1484,6 +1475,34 @@ def _message_receive_bounce(self, email, partner, mail_id=None):
for record in self:
record.message_bounce = record.message_bounce + 1

@api.model
def _gateway_bounce(self, email, partner, bounced_record, bounced_msg_id, bonced_mail_id):
"""Called by ``message_process`` when a bounce email (such as Undelivered
Mail Returned to Sender) is received for an existing thread. The default
behavior is to check is an integer ``message_bounce`` column exists.
If it is the case, its content is incremented.
:param mail_id: ID of the sent email that bounced. It may not exist anymore
but it could be usefull if the information was kept. This is
used notably in mass mailing.
:param RecordSet partner: partner matching the bounced email address, if any
:param string email: email that caused the bounce """
if bounced_record and hasattr(bounced_record, '_message_receive_bounce'):
bounced_record._message_receive_bounce(email, partner)

bl_models = self.env['ir.model'].sudo().search([('is_mail_blacklist', '=', True)])
for model in bl_models:
self.env[model.model].sudo().search([('email_normalized', 'ilike', email)])._message_receive_bounce(email, partner)

if bounced_msg_id:
mail_message = self.env['mail.message'].sudo().search([('message_id', '=', bounced_msg_id)])

if partner and mail_message:
self.env['mail.notification'].sudo().search([
('mail_message_id', '=', mail_message.id),
('res_partner_id', 'in', partner.ids)]
).write({'email_status': 'bounce'})

def _message_extract_payload_postprocess(self, message, body, attachments):
""" Perform some cleaning / postprocess in the body and attachments
extracted from the email. Note that this processing is specific to the
@@ -53,8 +53,8 @@ def message_post_with_template(self, template_id, **kwargs):
)
return super(MailThread, no_massmail).message_post_with_template(template_id, **kwargs)

@api.multi
def _message_receive_bounce(self, email, partner, mail_id=None):
@api.model
def _gateway_bounce(self, email, partner, bounced_record, bounced_msg_id, bonced_mail_id):
"""In addition, an auto blacklist rule check if the email can be blacklisted
to avoid sending mails indefinitely to this email address.
This rule checks if the email bounced too much. If this is the case,
@@ -63,12 +63,10 @@ def _message_receive_bounce(self, email, partner, mail_id=None):
in the last month and the bounced are at least separated by one week,
to avoid blacklist someone because of a temporary mail server error,
then the email is considered as invalid and is blacklisted."""
super(MailThread, self)._message_receive_bounce(email, partner, mail_id=None)
super(MailThread, self)._gateway_bounce(email, partner, bounced_record bounced_msg_id, bonced_mail_id)

three_months_ago = fields.Datetime.to_string(datetime.datetime.now() - datetime.timedelta(weeks=13))
stats = self.env['mail.mail.statistics'] \
.search(['&', ('bounced', '>', three_months_ago), ('email', '=ilike', email)]) \
.mapped('bounced')
stats = self.env['mail.mail.statistics'].search(['&', ('bounced', '>', three_months_ago), ('email', '=ilike', email)]).mapped('bounced')
if len(stats) >= BLACKLIST_MAX_BOUNCED_LIMIT:
if max(stats) > min(stats) + datetime.timedelta(weeks=1):
blacklist_rec = self.env['mail.blacklist'].sudo()._add(email)
@@ -22,28 +22,28 @@ def test_mail_bounced_auto_blacklist(self):
'bounced': datetime.datetime.now() - datetime.timedelta(weeks=2),
'email': self.mailing_contact_1.email
})
self.mailing_contact_1._message_receive_bounce(self.mailing_contact_1.email, self.mailing_contact_1)
self.env['mail.thread']._message_receive_bounce(self.mailing_contact_1.email, False, self.mailing_contact_1, False, False)
mail_statistics.create({
'model': 'mail.mass_mailing.contact',
'res_id': self.mailing_contact_1.id,
'bounced': datetime.datetime.now() - datetime.timedelta(weeks=3),
'email': self.mailing_contact_1.email
})
self.mailing_contact_1._message_receive_bounce(self.mailing_contact_1.email, self.mailing_contact_1)
self.env['mail.thread']._message_receive_bounce(self.mailing_contact_1.email, False, self.mailing_contact_1, False, False)
mail_statistics.create({
'model': 'mail.mass_mailing.contact',
'res_id': self.mailing_contact_1.id,
'bounced': datetime.datetime.now() - datetime.timedelta(weeks=4),
'email': self.mailing_contact_1.email
})
self.mailing_contact_1._message_receive_bounce(self.mailing_contact_1.email, self.mailing_contact_1)
self.env['mail.thread']._message_receive_bounce(self.mailing_contact_1.email, False, self.mailing_contact_1, False, False)
mail_statistics.create({
'model': 'mail.mass_mailing.contact',
'res_id': self.mailing_contact_1.id,
'bounced': datetime.datetime.now() - datetime.timedelta(weeks=5),
'email': self.mailing_contact_1.email
})
self.mailing_contact_1._message_receive_bounce(self.mailing_contact_1.email, self.mailing_contact_1)
self.env['mail.thread']._message_receive_bounce(self.mailing_contact_1.email, False, self.mailing_contact_1, False, False)


# create mass mailing record

0 comments on commit 3e6ddb0

Please sign in to comment.
You can’t perform that action at this time.