From 974f512f5f5d3b9f80a8c3fcde290e4f55cf1230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Voet?= Date: Mon, 9 Mar 2020 14:03:56 +0000 Subject: [PATCH 1/2] [IMP] tools: add a tool method to find if an html content is empty In odoo empty html is not always completely empty. This tool method allow to consider html holding void tags as empty html. This happens notably when using the editor that may store


even if displayed content is void. Task ID 2126509 PR #41827 --- odoo/addons/base/tests/test_mail.py | 24 +++++++++++++++++++----- odoo/tools/mail.py | 14 ++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/odoo/addons/base/tests/test_mail.py b/odoo/addons/base/tests/test_mail.py index e1b80c52c28..c2e9899fca1 100644 --- a/odoo/addons/base/tests/test_mail.py +++ b/odoo/addons/base/tests/test_mail.py @@ -9,7 +9,8 @@ import threading from odoo.tests.common import BaseCase, SavepointCase, TransactionCase from odoo.tools import ( - html_sanitize, append_content_to_html, plaintext2html, email_split, + is_html_empty, html_sanitize, append_content_to_html, plaintext2html, + email_split, misc, formataddr, ) @@ -103,10 +104,10 @@ class TestSanitizer(BaseCase): not_emails = [ '

cat
', '@github-login'] - for email in not_emails: - sanitized = html_sanitize(email) - left_part = email.split('>')[0] # take only left part, as the sanitizer could add data information on node - self.assertNotIn(misc.html_escape(email), sanitized, 'html_sanitize stripped emails of original html') + for not_email in not_emails: + sanitized = html_sanitize(not_email) + left_part = not_email.split('>')[0] # take only left part, as the sanitizer could add data information on node + self.assertNotIn(misc.html_escape(not_email), sanitized, 'html_sanitize stripped emails of original html') self.assertIn(left_part, sanitized) def test_style_parsing(self): @@ -318,6 +319,19 @@ class TestHtmlTools(BaseCase): for html, content, plaintext_flag, preserve_flag, container_tag, expected in test_samples: self.assertEqual(append_content_to_html(html, content, plaintext_flag, preserve_flag, container_tag), expected, 'append_content_to_html is broken') + def test_is_html_empty(self): + void_strings_samples = ['', False, ' '] + for content in void_strings_samples: + self.assertTrue(is_html_empty(content)) + + void_html_samples = ['


', '


'] + for content in void_html_samples: + self.assertTrue(is_html_empty(content), 'Failed with %s' % content) + + valid_html_samples = ['


1

', '

1

'] + for content in valid_html_samples: + self.assertFalse(is_html_empty(content)) + class TestEmailTools(BaseCase): """ Test some of our generic utility functions for emails """ diff --git a/odoo/tools/mail.py b/odoo/tools/mail.py index 50467df606e..b6640da1240 100644 --- a/odoo/tools/mail.py +++ b/odoo/tools/mail.py @@ -254,6 +254,20 @@ def html_sanitize(src, silent=True, sanitize_tags=True, sanitize_attributes=Fals # HTML/Text management #---------------------------------------------------------- +def is_html_empty(html_content): + """Check if a html content is empty. If there are only formatting tags or + a void content return True. Famous use case if a '


' added by + some web editor. + + :param str html_content: html content, coming from example from an HTML field + :returns: bool, True if no content found or if containing only void formatting tags + """ + if not html_content: + return True + tag_re = re.compile(r'\<\s*\/?(?:p|div|span|br|b|i)\s*\>') + return not bool(re.sub(tag_re, '', html_content).strip()) + + def html_keep_url(text): """ Transform the url into clickable link with tag """ idx = 0 From c5e6511e8d35a206e966658325ac8dce6a097a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Voet=20=28ryv=29?= Date: Wed, 18 Dec 2019 12:01:37 +0000 Subject: [PATCH 2/2] [IMP] mail: ease bounce email content update based on alias security PURPOSE When incoming emails bounce due to alias security bounce email is quite generic. Purpose of this task is to ease its customization and update. SPECIFICATIONS In order to improve the flexibility of alias, add a customizable html field on the alias model. This html content will be send as bounce email core content in case of bounced/unauthorized mail received for this alias, Obviously it has no effect on 'everyone' security setting as no email will bounce due to that issue. If it is not set a default generic mail will be send depending on security setting. It allows to keep void html fields when no specific bounce content is required In HR, an old template allowing some light customization for employee based security option is removed as it is completely replaced by the new feature. Also add references message-id of the mail received to the answer so that threads are correctly set. LINKS Task ID 2126509 --- addons/hr/data/hr_data.xml | 38 --------------- addons/hr/models/mail_alias.py | 19 +++++--- addons/mail/data/mail_data.xml | 6 +++ addons/mail/models/mail_alias.py | 51 +++++++++++++++------ addons/mail/models/mail_channel.py | 4 +- addons/mail/models/mail_thread.py | 24 ++++------ addons/mail/views/mail_alias_views.xml | 1 + addons/test_mail/tests/test_mail_gateway.py | 26 +++++++++++ odoo/tools/mail.py | 1 + 9 files changed, 94 insertions(+), 76 deletions(-) diff --git a/addons/hr/data/hr_data.xml b/addons/hr/data/hr_data.xml index 60601583cd1..2e7fca012b7 100644 --- a/addons/hr/data/hr_data.xml +++ b/addons/hr/data/hr_data.xml @@ -60,44 +60,6 @@ ])]"/> - - HR: mailgateway unknown employee bounce - - Your document has not been created - ${user.email_formatted | safe} - ${ctx['email_to']|safe} - - - - -
- - - - - -
- - -
-
- Hi,
- Your document has not been created because your email address is not recognized. Please send emails with the email address recorded on your employee information, or contact your HR manager. -
-
-
-
- - -
- Powered by Odoo -
-
-
- ${user.lang} - -
- hr.hr_presence_control_login True diff --git a/addons/hr/models/mail_alias.py b/addons/hr/models/mail_alias.py index c224d21df07..6a363221943 100644 --- a/addons/hr/models/mail_alias.py +++ b/addons/hr/models/mail_alias.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import fields, models, tools +from odoo import fields, models, tools, _ class Alias(models.Model): @@ -9,8 +9,16 @@ class Alias(models.Model): alias_contact = fields.Selection(selection_add=[('employees', 'Authenticated Employees')]) + def _get_alias_bounced_body_fallback(self, message_dict): + if self.alias_contact == 'employees': + return _("""Hi,
+Your document has not been created because your email address is not recognized.
+Please send emails with the email address recorded on your employee information, or contact your HR manager.""") + else: + return super(Alias, self)._get_alias_bounced_body_fallback(message_dict) -class MailAlias(models.AbstractModel): + +class AliasMixin(models.AbstractModel): _inherit = 'mail.alias.mixin' def _alias_check_contact_on_record(self, record, message, message_dict, alias): @@ -21,9 +29,6 @@ class MailAlias(models.AbstractModel): if not employee: employee = self.env['hr.employee'].search([('user_id.email', 'ilike', email_address)], limit=1) if not employee: - return { - 'error_message': 'restricted to employees', - 'error_template': self.env.ref('hr.mail_template_data_unknown_employee_email_address').body_html, - } + return _('restricted to employees') return True - return super(MailAlias, self)._alias_check_contact_on_record(record, message, message_dict, alias) + return super(AliasMixin, self)._alias_check_contact_on_record(record, message, message_dict, alias) diff --git a/addons/mail/data/mail_data.xml b/addons/mail/data/mail_data.xml index a83cafbbc8d..3e0c6ca6b37 100644 --- a/addons/mail/data/mail_data.xml +++ b/addons/mail/data/mail_data.xml @@ -363,6 +363,12 @@
+ + +