Skip to content

Commit

Permalink
Merge PR #1475 into 17.0
Browse files Browse the repository at this point in the history
Signed-off-by hbrunn
  • Loading branch information
OCA-git-bot committed Nov 22, 2024
2 parents ce46528 + 82e6646 commit c52083d
Show file tree
Hide file tree
Showing 13 changed files with 244 additions and 9 deletions.
6 changes: 6 additions & 0 deletions .oca/oca-port/blacklist/mail_tracking.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"pull_requests": {
"792": "(auto) Nothing to port from PR #792",
"1244": "(auto) Nothing to port from PR #1244"
}
}
1 change: 1 addition & 0 deletions mail_tracking/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"views/mail_tracking_event_view.xml",
"views/mail_message_view.xml",
"views/res_partner_view.xml",
"views/res_config_settings.xml",
],
"assets": {
"web.assets_backend": [
Expand Down
2 changes: 2 additions & 0 deletions mail_tracking/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from . import res_company
from . import res_config_settings
from . import ir_mail_server
from . import mail_bounced_mixin
from . import mail_guest
Expand Down
6 changes: 6 additions & 0 deletions mail_tracking/models/mail_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ def tracking_status(self):
@api.model
def _drop_aliases(self, mail_list):
aliases = self.env["mail.alias"].get_aliases()
if self.env.company.mail_tracking_show_aliases:
IrConfigParamObj = self.env["ir.config_parameter"].sudo()
aliases = "{}@{}".format(
IrConfigParamObj.get_param("mail.catchall.alias"),
IrConfigParamObj.get_param("mail.catchall.domain"),
)

def _filter_alias(email):
email_wn = getaddresses([email])[0][1]
Expand Down
7 changes: 4 additions & 3 deletions mail_tracking/models/mail_thread.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,10 @@ def _add_extra_recipients_suggestions(self, suggestions, field_mail, reason):
)
else:
partner = ResPartnerObj.browse(partner_id)
self._message_add_suggested_recipient(
suggestions, partner=partner, reason=reason
)
if partner.email not in aliases:
self._message_add_suggested_recipient(
suggestions, partner=partner, reason=reason
)

@api.model
def get_view(self, view_id=None, view_type="form", **options):
Expand Down
40 changes: 38 additions & 2 deletions mail_tracking/models/mail_tracking_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,7 @@ class MailTrackingEmail(models.Model):
@api.depends("mail_message_id")
def _compute_message_id(self):
"""This helper field will allow us to map the message_id from either the linked
mail.message or a mass.mailing mail.trace.
"""
mail.message or a mass.mailing mail.trace."""
self.message_id = False
for tracking in self.filtered("mail_message_id"):
tracking.message_id = tracking.mail_message_id.message_id
Expand Down Expand Up @@ -462,3 +461,40 @@ def event_process(self, request, post, metadata, event_type=None):
# - return 'NONE' if this request is not for you
# - return 'ERROR' if any error
return "NONE" # pragma: no cover

def _get_old_mail_tracking_email_domain(self, max_age_days):
target_write_date = fields.Datetime.subtract(
fields.Datetime.now(), days=max_age_days
)
return [("write_date", "<", target_write_date)]

@api.autovacuum
def _gc_mail_tracking_email(self, limit=5000):
config_max_age_days = (
self.env["ir.config_parameter"]
.sudo()
.get_param("mail_tracking.mail_tracking_email_max_age_days")
)
try:
max_age_days = int(config_max_age_days)
except ValueError:
max_age_days = 0

if not max_age_days > 0:
return False

domain = self._get_old_mail_tracking_email_domain(max_age_days)
records_to_delete = self.search(domain, limit=limit).exists()
if records_to_delete:
_logger.info(
"Deleting %s mail.tracking.email records", len(records_to_delete)
)
records_to_delete.flush_recordset()
# Using a direct query to avoid ORM as it causes an issue with
# a related field mass_mailing_id in customer DB when deleting
# the records. This might be 14.0 specific, so changing to
# .unlink() should be tested when forward porting.
query = "DELETE FROM mail_tracking_email WHERE id IN %s"
args = (tuple(records_to_delete.ids),)
self.env.cr.execute(query, args)
self.invalidate_model()
10 changes: 10 additions & 0 deletions mail_tracking/models/res_company.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from odoo import fields, models


class ResCompany(models.Model):
_inherit = "res.company"

mail_tracking_show_aliases = fields.Boolean(
string="Show Aliases in Mail Tracking",
default=False,
)
16 changes: 16 additions & 0 deletions mail_tracking/models/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from odoo import fields, models


class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"

mail_tracking_show_aliases = fields.Boolean(
related="company_id.mail_tracking_show_aliases",
readonly=False,
)
mail_tracking_email_max_age_days = fields.Integer(
"Max age in days of mail tracking email records",
config_parameter="mail_tracking.mail_tracking_email_max_age_days",
help="If set as positive integer enables the deletion of "
"old mail tracking records to reduce the database size.",
)
11 changes: 7 additions & 4 deletions mail_tracking/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.

See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
Expand Down Expand Up @@ -274,7 +275,7 @@
margin-left: 2em ;
margin-right: 2em }

pre.code .ln { color: grey; } /* line numbers */
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
Expand All @@ -300,7 +301,7 @@
span.pre {
white-space: pre }

span.problematic {
span.problematic, pre.problematic {
color: red }

span.section-subtitle {
Expand Down Expand Up @@ -495,7 +496,9 @@ <h2><a class="toc-backref" href="#toc-entry-8">Contributors</a></h2>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-9">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
Expand Down
1 change: 1 addition & 0 deletions mail_tracking/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from . import test_mail_tracking
from . import test_gc_mail_tracking_email
88 changes: 88 additions & 0 deletions mail_tracking/tests/test_gc_mail_tracking_email.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from odoo import fields

from odoo.addons.base.tests.common import SavepointCaseWithUserDemo


class TestMailTrackingEmailCleanUp(SavepointCaseWithUserDemo):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
cls.settings = cls.env["res.config.settings"].create(
{"mail_tracking_email_max_age_days": 365}
)
cls.settings.set_values()
cls.partner = cls.env.ref("base.res_partner_address_28")
cls.message = cls.env["mail.message"].create(
{
"model": "res.partner",
"res_id": cls.partner.id,
"body": "TEST",
"message_type": "email",
"subtype_id": cls.env.ref("mail.mt_comment").id,
"author_id": cls.partner.id,
"date": "2024-03-26",
}
)
cls.recent_mail_tracking_email = cls.env["mail.tracking.email"].create(
{"mail_message_id": cls.message.id}
)
# Can't set the write_date directly as it gets overwritten by the ORM
cls.old_mail_tracking_email = cls.env["mail.tracking.email"].create(
{"mail_message_id": cls.message.id}
)
cls.total_count = 2
cls.recent_count = 1
cls.domain = [
("mail_message_id", "=", cls.message.id),
]

def _set_write_date(self):
# Set the write_date of the old record to be older than the max_age_days
# Update DB directly to avoid ORM overwriting the write_date
old_write_date = fields.Datetime.subtract(fields.Datetime.now(), days=400)
self.env.cr.execute(
"UPDATE mail_tracking_email SET write_date = %s WHERE id = %s",
(old_write_date, self.old_mail_tracking_email.id),
)

def test_deletion_of_mail_tracking_email(self):
self._set_write_date()
self.assertEqual(
len(self.env["mail.tracking.email"].search(self.domain)), self.total_count
)
self.env["mail.tracking.email"]._gc_mail_tracking_email()
self.assertEqual(
len(self.env["mail.tracking.email"].search(self.domain)), self.recent_count
)
self.assertTrue(self.recent_mail_tracking_email.exists())

def test_deletion_follows_configuration_variable(self):
self._set_write_date()
self.assertEqual(
len(self.env["mail.tracking.email"].search(self.domain)), self.total_count
)
# when disabled, no deletions should happen
self.settings.mail_tracking_email_max_age_days = 0
self.settings.set_values()
self.env["mail.tracking.email"]._gc_mail_tracking_email()
self.assertEqual(
len(self.env["mail.tracking.email"].search(self.domain)), self.total_count
)
# when disabled, no deletions should happen
self.settings.mail_tracking_email_max_age_days = -1
self.settings.set_values()
self.env["mail.tracking.email"]._gc_mail_tracking_email()
self.assertEqual(
len(self.env["mail.tracking.email"].search(self.domain)), self.total_count
)
# when enabled, deletions should happen
self.settings.mail_tracking_email_max_age_days = 365
self.settings.set_values()
self.env["mail.tracking.email"]._gc_mail_tracking_email()
self.assertEqual(
len(self.env["mail.tracking.email"].search(self.domain)), self.recent_count
)
30 changes: 30 additions & 0 deletions mail_tracking/tests/test_mail_tracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,36 @@ def test_message_post_partner_no_email(self):
self.assertEqual(tracking_email.error_type, "no_recipient")
self.assertFalse(self.recipient.email_bounced)

def test_message_post_show_aliases(self):
# Create message with show aliases setup
self.env.company.mail_tracking_show_aliases = True
# Setup catchall domain
IrConfigParamObj = self.env["ir.config_parameter"].sudo()
IrConfigParamObj.set_param("mail.catchall.domain", "test.com")
# pylint: disable=C8107
message = self.env["mail.message"].create(
{
"subject": "Message test",
"author_id": self.sender.id,
"email_from": self.sender.email,
"message_type": "comment",
"model": "res.partner",
"res_id": self.recipient.id,
"partner_ids": [(4, self.recipient.id)],
"email_cc": "Dominique Pinon <unnamed@test.com>, customer-invoices@test.com", # noqa E501
"body": "<p>This is another test message</p>",
}
)
message_dict, *_ = message.message_format()
self.assertTrue(
any(
[
tracking["recipient"] == "customer-invoices@test.com"
for tracking in message_dict["partner_trackings"]
]
)
)

def _check_partner_trackings_cc(self, message):
message_dict = message.message_format()[0]
self.assertEqual(len(message_dict["partner_trackings"]), 3)
Expand Down
35 changes: 35 additions & 0 deletions mail_tracking/views/res_config_settings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.mail.tracking</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="mail.res_config_settings_view_form" />
<field name="arch" type="xml">
<xpath expr="//block[@id='emails']" position="inside">
<setting>
<field name="mail_tracking_show_aliases" />
<div class="content-group">
<label for="mail_tracking_show_aliases" />
<div
class="text-muted"
id="mail_tracking_show_aliases"
>Show Aliases in Mail Tracking</div>
</div>
</setting>
<setting>
<field name="mail_tracking_email_max_age_days" />
<div class="content-group">
<label
for="mail_tracking_email_max_age_days"
string="Max age in days of mail tracking email records"
/>
<div
class="text-muted"
id="mail_tracking_email_max_age_days"
>If set as positive integer enables the deletion of old mail tracking records to reduce the database size.</div>
</div>
</setting>
</xpath>
</field>
</record>
</odoo>

0 comments on commit c52083d

Please sign in to comment.