diff --git a/addons/mail/tests/test_mail_composer.py b/addons/mail/tests/test_mail_composer.py
index 9b573efb5be..846c98f8f84 100644
--- a/addons/mail/tests/test_mail_composer.py
+++ b/addons/mail/tests/test_mail_composer.py
@@ -2,7 +2,9 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.mail.tests.common import MailCommon
-from odoo.tests import tagged, users
+from odoo.exceptions import AccessError
+from odoo.tests import Form, tagged, users
+from odoo.tools import mute_logger
@tagged('mail_composer')
@@ -30,14 +32,199 @@ class TestMailComposer(MailCommon):
"""
cls.mail_template = cls.env['mail.template'].create({
- 'name': 'Test template with mso conditionals',
- 'subject': 'MSO FTW',
+ 'auto_delete': True,
'body_html': cls.body_html,
'lang': '{{ object.lang }}',
- 'auto_delete': True,
- 'model_id': cls.env.ref('base.model_res_partner').id,
+ 'model_id': cls.env['ir.model']._get_id('res.partner'),
+ 'subject': 'MSO FTW',
+ 'name': 'Test template with mso conditionals',
})
+
+@tagged('mail_composer')
+class TestMailComposerForm(TestMailComposer):
+ """ Test mail composer form view usage. """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestMailComposerForm, cls).setUpClass()
+
+ cls.user_employee.write({'groups_id': [
+ (4, cls.env.ref('base.group_private_addresses').id),
+ (4, cls.env.ref('base.group_partner_manager').id),
+ ]})
+ cls.partner_private, cls.partner_private_2, cls.partner_classic = cls.env['res.partner'].create([
+ {
+ 'email': 'private.customer@text.example.com',
+ 'phone': '0032455112233',
+ 'name': 'Private Customer',
+ 'type': 'private',
+ },
+ {
+ 'email': 'private.customer.2@test.example.com',
+ 'phone': '0032455445566',
+ 'name': 'Private Customer 2',
+ 'type': 'private',
+ },
+ {
+ 'email': 'not.private@test.example.com',
+ 'phone': '0032455778899',
+ 'name': 'Classic Customer',
+ 'type': 'contact',
+ }
+ ])
+
+ @mute_logger('odoo.addons.mail.models.mail_mail')
+ @users('employee')
+ def test_composer_default_recipients(self):
+ """ Test usage of a private partner in composer, as default value """
+ partner_classic = self.partner_classic.with_env(self.env)
+ test_record = self.test_record.with_env(self.env)
+
+ form = Form(self.env['mail.compose.message'].with_context({
+ 'default_partner_ids': partner_classic.ids,
+ 'default_model': test_record._name,
+ 'default_res_id': test_record.id,
+ }))
+ form.body = '
Hello
'
+ self.assertEqual(
+ form.partner_ids._get_ids(), partner_classic.ids,
+ 'Default populates the field'
+ )
+ saved_form = form.save()
+ self.assertEqual(
+ saved_form.partner_ids, partner_classic,
+ 'Default value is kept at save'
+ )
+
+ with self.mock_mail_gateway():
+ saved_form._action_send_mail()
+
+ message = self.test_record.message_ids[0]
+ self.assertEqual(message.body, 'Hello
')
+ self.assertEqual(message.partner_ids, partner_classic)
+ self.assertEqual(message.subject, f'{test_record.name}')
+
+ @mute_logger('odoo.addons.mail.models.mail_mail')
+ @users('employee')
+ def test_composer_default_recipients_private(self):
+ """ Test usage of a private partner in composer, as default value """
+ partner_private = self.partner_private.with_env(self.env)
+ partner_classic = self.partner_classic.with_env(self.env)
+ test_record = self.test_record.with_env(self.env)
+
+ form = Form(self.env['mail.compose.message'].with_context({
+ 'default_partner_ids': (partner_private + partner_classic).ids,
+ 'default_model': test_record._name,
+ 'default_res_id': test_record.id,
+ }))
+ form.body = 'Hello
'
+ self.assertEqual(
+ sorted(form.partner_ids._get_ids()),
+ sorted((partner_private + partner_classic).ids),
+ 'Default populates the field'
+ )
+ saved_form = form.save()
+ self.assertEqual(
+ # saved_form.partner_ids, partner_private + partner_classic,
+ saved_form.partner_ids, partner_classic,
+ 'Default value is kept at save (FIXME: loosing private partner)'
+ )
+
+ with self.mock_mail_gateway():
+ saved_form._action_send_mail()
+
+ message = self.test_record.message_ids[0]
+ self.assertEqual(message.body, 'Hello
')
+ # self.assertEqual(message.partner_ids, partner_private + partner_classic)
+ self.assertEqual(
+ message.partner_ids, partner_classic,
+ 'FIXME: loosing private partner'
+ )
+ self.assertEqual(message.subject, f'{test_record.name}')
+
+ @mute_logger('odoo.addons.base.models.ir_rule', 'odoo.addons.mail.models.mail_mail')
+ @users('employee')
+ def test_composer_default_recipients_private_norights(self):
+ """ Test usage of a private partner in composer when not having the
+ rights to see them, as default value """
+ self.user_employee.write({'groups_id': [
+ (3, self.env.ref('base.group_private_addresses').id),
+ ]})
+ with self.assertRaises(AccessError):
+ _name = self.partner_private.with_env(self.env).name
+
+ partner_classic = self.partner_classic.with_env(self.env)
+ test_record = self.test_record.with_env(self.env)
+
+ with self.assertRaises(AccessError):
+ _form = Form(self.env['mail.compose.message'].with_context({
+ 'default_partner_ids': (self.partner_private + partner_classic).ids,
+ 'default_model': test_record._name,
+ 'default_res_id': test_record.id,
+ }))
+
+ @mute_logger('odoo.addons.mail.models.mail_mail')
+ @users('employee')
+ def test_composer_template_recipients_private(self):
+ """ Test usage of a private partner in composer, comint from template
+ value """
+ email_to_new = 'new.customer@test.example.com'
+ self.mail_template.write({
+ 'email_to': f'{self.partner_private_2.email_formatted}, {email_to_new}',
+ 'partner_to': f'{self.partner_private.id},{self.partner_classic.id}',
+ })
+ template = self.mail_template.with_env(self.env)
+ partner_private = self.partner_private.with_env(self.env)
+ partner_private_2 = self.partner_private_2.with_env(self.env)
+ partner_classic = self.partner_classic.with_env(self.env)
+ test_record = self.test_record.with_env(self.env)
+
+ form = Form(self.env['mail.compose.message'].with_context({
+ 'default_model': test_record._name,
+ 'default_res_id': test_record.id,
+ 'default_template_id': template.id,
+ }))
+
+ # transformation from email_to into partner_ids: find or create
+ existing_partner = self.env['res.partner'].search(
+ [('email_normalized', '=', self.partner_private_2.email_normalized)]
+ )
+ self.assertEqual(existing_partner, partner_private_2, 'Should find existing private contact')
+ new_partner = self.env['res.partner'].search(
+ [('email_normalized', '=', email_to_new)]
+ )
+ self.assertEqual(new_partner.type, 'contact', 'Should create a new contact')
+
+ self.assertEqual(
+ sorted(form.partner_ids._get_ids()),
+ sorted((partner_private + partner_classic + partner_private_2 + new_partner).ids),
+ 'Template populates the field with both email_to and partner_to'
+ )
+ saved_form = form.save()
+ self.assertEqual(
+ # saved_form.partner_ids, partner_private + partner_classic + partner_private_2 + new_partner,
+ saved_form.partner_ids, partner_classic + new_partner,
+ 'Template value is kept at save (FIXME: loosing private partner)'
+ )
+
+ with self.mock_mail_gateway():
+ saved_form._action_send_mail()
+
+ message = self.test_record.message_ids[0]
+ self.assertIn('Hello sir!
', message.body)
+ # self.assertEqual(message.partner_ids, partner_private + partner_classic + partner_private_2 + new_partner)
+ self.assertEqual(
+ message.partner_ids, partner_classic + new_partner,
+ 'FIXME: loosing private partner'
+ )
+ self.assertEqual(message.subject, 'MSO FTW')
+
+
+@tagged('mail_composer')
+class TestMailComposerRendering(TestMailComposer):
+ """ Test rendering and support of various html tweaks in composer """
+
@users('employee')
def test_mail_mass_mode_template_with_mso(self):
mail_compose_message = self.env['mail.compose.message'].create({
@@ -55,6 +242,7 @@ class TestMailComposer(MailCommon):
'We must preserve (mso) comments in email html'
)
+ @mute_logger('odoo.addons.mail.models.mail_mail')
@users('employee')
def test_mail_mass_mode_compose_with_mso(self):
composer = self.env['mail.compose.message'].with_context({
diff --git a/addons/test_mail/tests/test_mail_gateway.py b/addons/test_mail/tests/test_mail_gateway.py
index 1a79c8cdeb6..9bec4123ac4 100644
--- a/addons/test_mail/tests/test_mail_gateway.py
+++ b/addons/test_mail/tests/test_mail_gateway.py
@@ -118,6 +118,7 @@ class TestEmailParsing(TestMailCommon):
class TestMailAlias(TestMailCommon):
@users('employee')
+ @mute_logger('odoo.addons.base.models.ir_model')
def test_alias_creation(self):
record = self.env['mail.test.container'].create({
'name': 'Test Record',
@@ -309,7 +310,24 @@ class TestMailgateway(TestMailCommon):
@mute_logger('odoo.addons.mail.models.mail_thread')
def test_message_process_followers(self):
- """ Incoming email: recognized author not archived and not odoobot: added as follower """
+ """ Incoming email: recognized author not archived and not odoobot:
+ added as follower. Also test corner cases: archived, private. """
+ partner_archived, partner_private = self.env['res.partner'].create([
+ {
+ 'active': False,
+ 'email': 'archived.customer@text.example.com',
+ 'phone': '0032455112233',
+ 'name': 'Archived Customer',
+ 'type': 'contact',
+ },
+ {
+ 'email': 'private.customer@text.example.com',
+ 'phone': '0032455112233',
+ 'name': 'Private Customer',
+ 'type': 'private',
+ },
+ ])
+
with self.mock_mail_gateway():
record = self.format_and_process(MAIL_TEMPLATE, self.partner_1.email_formatted, 'groups@test.com')
@@ -335,20 +353,17 @@ class TestMailgateway(TestMailCommon):
'message_process: unrecognized email -> no follower')
# archived partner -> no follower
- self.partner_1.active = False
- self.partner_1.flush_recordset()
with self.mock_mail_gateway():
record3 = self.format_and_process(
- MAIL_TEMPLATE, self.partner_1.email_formatted, 'groups@test.com',
- subject='Yet Another Email')
+ MAIL_TEMPLATE, partner_archived.email_formatted, 'groups@test.com',
+ subject='Archived Partner')
self.assertEqual(record3.message_ids[0].author_id, self.env['res.partner'])
- self.assertEqual(record3.message_ids[0].email_from, self.partner_1.email_formatted)
+ self.assertEqual(record3.message_ids[0].email_from, partner_archived.email_formatted)
self.assertEqual(record3.message_follower_ids.partner_id, self.env['res.partner'],
- 'message_process: unrecognized email -> no follower')
+ 'message_process: archived partner -> no follower')
self.assertEqual(record3.message_partner_ids, self.env['res.partner'],
- 'message_process: unrecognized email -> no follower')
-
+ 'message_process: archived partner -> no follower')
# partner_root -> never again
odoobot = self.env.ref('base.partner_root')
@@ -362,9 +377,22 @@ class TestMailgateway(TestMailCommon):
self.assertEqual(record4.message_ids[0].author_id, odoobot)
self.assertEqual(record4.message_ids[0].email_from, odoobot.email_formatted)
self.assertEqual(record4.message_follower_ids.partner_id, self.env['res.partner'],
- 'message_process: unrecognized email -> no follower')
+ 'message_process: odoobot -> no follower')
self.assertEqual(record4.message_partner_ids, self.env['res.partner'],
- 'message_process: unrecognized email -> no follower')
+ 'message_process: odoobot -> no follower')
+
+ # private partner
+ with self.mock_mail_gateway():
+ record5 = self.format_and_process(
+ MAIL_TEMPLATE, partner_private.email_formatted, 'groups@test.com',
+ subject='Private Partner')
+
+ self.assertEqual(record5.message_ids[0].author_id, partner_private)
+ self.assertEqual(record5.message_ids[0].email_from, partner_private.email_formatted)
+ self.assertEqual(record5.message_follower_ids.partner_id, partner_private,
+ 'message_process: private partner is recognized')
+ self.assertEqual(record5.message_partner_ids, partner_private,
+ 'message_process: private partner is recognized')
# --------------------------------------------------
# Author recognition
@@ -399,7 +427,7 @@ class TestMailgateway(TestMailCommon):
self.assertEqual(record.message_ids[0].email_from, self.partner_1.email)
self.assertNotSentEmail() # No notification / bounce should be sent
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
+ @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink')
def test_message_process_email_partner_find(self):
""" Finding the partner based on email, based on partner / user / follower """
self.alias.write({'alias_force_thread_id': self.test_record.id})
@@ -720,7 +748,7 @@ class TestMailgateway(TestMailCommon):
self.assertEqual(record.message_ids[0].create_uid, self.user_employee)
self.assertEqual(record.message_ids[0].author_id, self.user_employee.partner_id)
- @mute_logger('odoo.addons.mail.models.mail_thread')
+ @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink')
def test_message_process_create_uid_email_follower(self):
self.alias.write({
'alias_parent_model_id': self.test_model.id,
@@ -1017,7 +1045,7 @@ class TestMailgateway(TestMailCommon):
self.assertEqual(self.partner_1.message_bounce, 0)
self.assertEqual(self.test_record.message_bounce, 1)
- @mute_logger('odoo.addons.mail.models.mail_thread')
+ @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink')
def test_message_process_bounce_records_channel(self):
""" Test blacklist allow to multi-bounce and auto update of mail.channel """
other_record = self.env['mail.test.gateway'].create({
@@ -1090,7 +1118,7 @@ class TestMailgateway(TestMailCommon):
self.assertEqual(len(self.test_record.message_ids), init_msg_count + 1)
self.assertEqual(self.fake_email.child_ids, self.test_record.message_ids[0])
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
+ @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink', 'odoo.addons.mail.models.mail_mail', 'odoo.tests')
def test_message_process_references_multi_parent(self):
""" Incoming email with multiple references """
reply1 = self._create_gateway_message(
@@ -1149,7 +1177,7 @@ class TestMailgateway(TestMailCommon):
self.assertEqual(new_msg.parent_id, self.fake_email, 'Mail: flattening attach to original message')
self.assertEqual(new_msg.subtype_id, self.env.ref('mail.mt_comment'), 'Mail: parent should be a comment (before flattening)')
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
+ @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink', 'odoo.addons.mail.models.mail_mail', 'odoo.tests')
def test_message_process_references_multi_parent_notflat(self):
""" Incoming email with multiple references with ``_mail_flat_thread``
being False (mail.group/mail.channel behavior like). """