mirror of https://github.com/OCA/social.git
commit
ebe778fa59
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"pull_requests": {
|
||||
"792": "(auto) Nothing to port from PR #792",
|
||||
"1244": "(auto) Nothing to port from PR #1244"
|
||||
}
|
||||
}
|
|
@ -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": [
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -226,6 +226,12 @@ class MailMessage(models.Model):
|
|||
@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]
|
||||
|
|
|
@ -94,9 +94,10 @@ class MailThread(models.AbstractModel):
|
|||
)
|
||||
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):
|
||||
|
|
|
@ -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
|
||||
|
@ -462,3 +461,40 @@ class MailTrackingEmail(models.Model):
|
|||
# - 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()
|
||||
|
|
|
@ -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,
|
||||
)
|
|
@ -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.",
|
||||
)
|
|
@ -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.
|
||||
|
@ -274,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
|
|||
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 }
|
||||
|
@ -300,7 +301,7 @@ span.option {
|
|||
span.pre {
|
||||
white-space: pre }
|
||||
|
||||
span.problematic {
|
||||
span.problematic, pre.problematic {
|
||||
color: red }
|
||||
|
||||
span.section-subtitle {
|
||||
|
@ -495,7 +496,9 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
|
|||
<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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
)
|
|
@ -158,6 +158,36 @@ class TestMailTracking(TransactionCase):
|
|||
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)
|
||||
|
|
|
@ -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>
|
Loading…
Reference in New Issue