Files
odoo_source/addons/mass_mailing/models/mail_thread.py
T
Thibault Delavallée 2896aad34e [REF] mass_mailing: rename mail.mail.statistics and reporting model
PURPOSE

Mass mailing is currently a bit messy. As SMS will be added as a way to notify
people in mass through SMS let us take this opportunity to somehow clean this
application: organization, light code cleaning, model renaming.

SPECIFICATIONS

Rename mail.mail.statistics to mailing.trace and mail.statistics.report
to mail.trace.report. Rationale :

  * mail.mail.statistics is linked to mail.mail model. Soon this model will
    hold data related to SMS sending. It makes sense to be broader in the
    naming;
  * mailing.trace is more inlined with marketing.trace model that is the
    marketing automation model using it in marketing automation (enterprise
    application);
  * mailing.trace is shorter to write;
  * mail.statistics.report model should sense to be updated at the same
    time;

MIGRATION

mail.mail.statistics model -> mailing.trace
mail_mail_statistics table -> mailing_trace
mail.statistics.report model -> mail.trace.report

fields updated (w column change)
  * link.tracker.click: mail_stat_id -> mailing_trace_id

fields updated (no column change)
  * mail.mail: statistics_ids -> mailing_trace_ids
  * mail.mass_mailing: statistics_ids -> mailing_trace_ids

LINKS

Task ID 2037906
Preparing task ID 1997464 (SMS addition in mass mailing)
PR #34938
2019-07-17 15:39:06 +00:00

75 lines
3.9 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
import re
import datetime
from odoo import api, models, tools, fields
from odoo.tools import decode_smtp_header, decode_message_header
_logger = logging.getLogger(__name__)
BLACKLIST_MAX_BOUNCED_LIMIT = 5
class MailThread(models.AbstractModel):
""" Update MailThread to add the support of bounce management in mass mailing traces. """
_inherit = 'mail.thread'
@api.model
def message_route(self, message, message_dict, model=None, thread_id=None, custom_values=None):
""" Override to udpate mass mailing traces based on bounce emails """
bounce_alias = self.env['ir.config_parameter'].sudo().get_param("mail.bounce.alias")
email_to = decode_message_header(message, 'To')
email_to_localpart = (tools.email_split(email_to) or [''])[0].split('@', 1)[0].lower()
if bounce_alias and bounce_alias in email_to_localpart:
bounce_re = re.compile("%s\+(\d+)-?([\w.]+)?-?(\d+)?" % re.escape(bounce_alias), re.UNICODE)
bounce_match = bounce_re.search(email_to)
if bounce_match:
bounced_mail_id = bounce_match.group(1)
self.env['mailing.trace'].set_bounced(mail_mail_ids=[bounced_mail_id])
return super(MailThread, self).message_route(message, message_dict, model, thread_id, custom_values)
@api.model
def message_route_process(self, message, message_dict, routes):
""" Override to update the parent mailing traces. The parent is found
by using the References header of the incoming message and looking for
matching message_id in mailing.trace. """
if message.get('References') and routes:
message_ids = [x.strip() for x in decode_smtp_header(message['References']).split()]
self.env['mailing.trace'].set_opened(mail_message_ids=message_ids)
self.env['mailing.trace'].set_replied(mail_message_ids=message_ids)
return super(MailThread, self).message_route_process(message, message_dict, routes)
def message_post_with_template(self, template_id, **kwargs):
# avoid having message send through `message_post*` methods being implicitly considered as
# mass-mailing
no_massmail = self.with_context(
default_mass_mailing_name=False,
default_mass_mailing_id=False,
)
return super(MailThread, no_massmail).message_post_with_template(template_id, **kwargs)
def _message_receive_bounce(self, email, partner, mail_id=None):
"""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,
the email address is added to the blacklist in order to avoid continuing
to send mass_mail to that email address. If it bounced too much times
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)
three_months_ago = fields.Datetime.to_string(datetime.datetime.now() - datetime.timedelta(weeks=13))
traces = self.env['mailing.trace'] \
.search(['&', ('bounced', '>', three_months_ago), ('email', '=ilike', email)]) \
.mapped('bounced')
if len(traces) >= BLACKLIST_MAX_BOUNCED_LIMIT:
if max(traces) > min(traces) + datetime.timedelta(weeks=1):
blacklist_rec = self.env['mail.blacklist'].sudo()._add(email)
blacklist_rec._message_log(
body='This email has been automatically blacklisted because of too much bounced.')