[FIX] test_mail: prepare and fixup tests for alias domains
Some tests are updated to lessen diff in future tests, especially about aliases. Some tests are fixed as they are somehow incorrect (notably in gateway testing) but currently passing as mail gateway is quite permissive. Add some tests preparing MC / alias domains configuration notably about company / alias synchronization, which is currently only based on config parameters. Also update some tests by using fstrings which are generally more readable. Finally move some tests to their right file / main testing class to keep them ordered by main topic. Prepares Task-36879 (Mail: Support MultiCompany Aliases) closes odoo/odoo#136318 X-original-commit: odoo/odoo@c18300e225 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
@@ -1250,6 +1250,10 @@ class MailCommon(common.TransactionCase, MailCase):
|
||||
'name': 'ELIT',
|
||||
})
|
||||
cls.user_admin.write({'company_ids': [(4, cls.company_2.id)]})
|
||||
cls.company_3 = cls.env['res.company'].create({
|
||||
'email': 'company_3@test.example.com',
|
||||
'name': 'Company 3',
|
||||
})
|
||||
|
||||
# employee specific to second company
|
||||
cls.user_employee_c2 = mail_new_test_user(
|
||||
|
||||
@@ -9,7 +9,7 @@ from odoo import exceptions
|
||||
from odoo.addons.mail.tests.common import MailCommon
|
||||
from odoo.tests import tagged
|
||||
from odoo.tests.common import users
|
||||
from odoo.tools import mute_logger
|
||||
from odoo.tools import formataddr, mute_logger
|
||||
|
||||
|
||||
class TestMailAliasCommon(MailCommon):
|
||||
@@ -91,24 +91,30 @@ class TestMailAlias(TestMailAliasCommon):
|
||||
|
||||
@users('admin')
|
||||
def test_alias_name_unique(self):
|
||||
""" Check uniqueness constraint on alias names, at create and update.
|
||||
Also check conflict management with bounce / catchall aliases. """
|
||||
alias_model_id = self.env['ir.model']._get('mail.test.gateway').id
|
||||
catchall_alias = self.env['ir.config_parameter'].sudo().get_param('mail.catchall.alias')
|
||||
bounce_alias = self.env['ir.config_parameter'].sudo().get_param('mail.bounce.alias')
|
||||
|
||||
# test you cannot create aliases matching bounce / catchall
|
||||
new_mail_alias = self.env['mail.alias'].create({
|
||||
'alias_model_id': alias_model_id,
|
||||
'alias_name': 'unused.test.alias',
|
||||
})
|
||||
other_alias = self.env['mail.alias'].create({
|
||||
'alias_model_id': alias_model_id,
|
||||
'alias_name': 'other.test.alias',
|
||||
})
|
||||
|
||||
# test you cannot create or update aliases matching bounce / catchall
|
||||
with self.assertRaises(exceptions.UserError), self.cr.savepoint():
|
||||
self.env['mail.alias'].create({'alias_model_id': alias_model_id, 'alias_name': catchall_alias})
|
||||
with self.assertRaises(exceptions.UserError), self.cr.savepoint():
|
||||
self.env['mail.alias'].create({'alias_model_id': alias_model_id, 'alias_name': bounce_alias})
|
||||
|
||||
new_mail_alias = self.env['mail.alias'].create({
|
||||
'alias_model_id': alias_model_id,
|
||||
'alias_name': 'unused.test.alias'
|
||||
})
|
||||
other_alias = self.env['mail.alias'].create({
|
||||
'alias_model_id': alias_model_id,
|
||||
'alias_name': 'other.test.alias'
|
||||
})
|
||||
with self.assertRaises(exceptions.UserError), self.cr.savepoint():
|
||||
new_mail_alias.write({'alias_name': catchall_alias})
|
||||
with self.assertRaises(exceptions.UserError), self.cr.savepoint():
|
||||
new_mail_alias.write({'alias_name': bounce_alias})
|
||||
|
||||
# test that alias names should be unique
|
||||
with self.assertRaises(exceptions.UserError), self.cr.savepoint():
|
||||
@@ -124,18 +130,26 @@ class TestMailAlias(TestMailAliasCommon):
|
||||
}
|
||||
for alias_name in ('new.alias.1', 'new.alias.2', 'new.alias.1')
|
||||
])
|
||||
with self.assertRaises(psycopg2.errors.UniqueViolation), self.cr.savepoint(), mute_logger('odoo.sql_db'):
|
||||
new_mail_alias.copy({'alias_name': 'unused.test.alias'})
|
||||
with self.assertRaises(exceptions.UserError), self.cr.savepoint():
|
||||
other_alias.write({'alias_name': 'unused.test.alias'})
|
||||
|
||||
# test that re-using catchall and bounce alias raises UserError
|
||||
# cannot set catchall / bounce to used alias
|
||||
with self.assertRaises(exceptions.UserError), self.cr.savepoint():
|
||||
new_mail_alias.write({'alias_name': catchall_alias})
|
||||
self.env['ir.config_parameter'].sudo().set_param('mail.catchall.alias', new_mail_alias.alias_name)
|
||||
with self.assertRaises(exceptions.UserError), self.cr.savepoint():
|
||||
new_mail_alias.write({'alias_name': bounce_alias})
|
||||
self.env['ir.config_parameter'].sudo().set_param('mail.bounce.alias', new_mail_alias.alias_name)
|
||||
|
||||
new_mail_alias.write({'alias_name': 'another.unused.test.alias'})
|
||||
@users('admin')
|
||||
def test_alias_name_unique_copy(self):
|
||||
""" Check uniqueness constraint check when copying aliases """
|
||||
alias_model_id = self.env['ir.model']._get('mail.test.gateway').id
|
||||
new_mail_alias = self.env['mail.alias'].create({
|
||||
'alias_model_id': alias_model_id,
|
||||
'alias_name': 'unused.test.alias'
|
||||
})
|
||||
|
||||
with mute_logger('odoo.sql_db'), self.assertRaises(psycopg2.errors.UniqueViolation), self.cr.savepoint():
|
||||
new_mail_alias.copy({'alias_name': 'unused.test.alias'})
|
||||
|
||||
# test that duplicating an alias should have blank name
|
||||
copy_1 = new_mail_alias.copy()
|
||||
@@ -148,12 +162,6 @@ class TestMailAlias(TestMailAliasCommon):
|
||||
with self.assertRaises(exceptions.UserError):
|
||||
(copy_1 + copy_2).write({'alias_name': 'test.alias.other'})
|
||||
|
||||
# cannot set catchall / bounce to used alias
|
||||
with self.assertRaises(exceptions.UserError), self.cr.savepoint():
|
||||
self.env['ir.config_parameter'].sudo().set_param('mail.catchall.alias', new_mail_alias.alias_name)
|
||||
with self.assertRaises(exceptions.UserError), self.cr.savepoint():
|
||||
self.env['ir.config_parameter'].sudo().set_param('mail.bounce.alias', new_mail_alias.alias_name)
|
||||
|
||||
@users('admin')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_alias_name_sanitize(self):
|
||||
@@ -238,6 +246,45 @@ class TestMailAlias(TestMailAliasCommon):
|
||||
alias.write({'alias_defaults': "{'custom_field': 'validdict'}"})
|
||||
|
||||
|
||||
@tagged('mail_alias', 'multi_company')
|
||||
class TestAliasCompany(TestMailAliasCommon):
|
||||
""" Test company / alias domain and configuration synchronization """
|
||||
|
||||
def test_assert_initial_values(self):
|
||||
""" Test initial setup values: currently all companies share the same
|
||||
alias configuration as it is unique. """
|
||||
self.assertEqual(self.company_admin.catchall_email, f'{self.alias_catchall}@{self.alias_domain}')
|
||||
self.assertEqual(
|
||||
self.company_admin.catchall_formatted,
|
||||
formataddr((self.company_admin.name, f'{self.alias_catchall}@{self.alias_domain}'))
|
||||
)
|
||||
|
||||
self.assertEqual(self.company_2.catchall_email, f'{self.alias_catchall}@{self.alias_domain}')
|
||||
self.assertEqual(
|
||||
self.company_2.catchall_formatted,
|
||||
formataddr((self.company_2.name, f'{self.alias_catchall}@{self.alias_domain}'))
|
||||
)
|
||||
|
||||
self.assertEqual(self.company_3.catchall_email, f'{self.alias_catchall}@{self.alias_domain}')
|
||||
self.assertEqual(
|
||||
self.company_3.catchall_formatted,
|
||||
formataddr((self.company_3.name, f'{self.alias_catchall}@{self.alias_domain}'))
|
||||
)
|
||||
|
||||
@users('erp_manager')
|
||||
def test_res_company_creation_alias_domain(self):
|
||||
""" Test alias domain configuration when creating new companies """
|
||||
company = self.env['res.company'].create({
|
||||
'email': '"Super Company" <super.company@test3.mycompany.com>',
|
||||
'name': 'Super Company',
|
||||
})
|
||||
company.flush_recordset()
|
||||
self.assertEqual(
|
||||
company.catchall_formatted,
|
||||
formataddr((company.name, f'{self.alias_catchall}@{self.alias_domain}'))
|
||||
)
|
||||
|
||||
|
||||
@tagged('mail_gateway', 'mail_alias', 'multi_company')
|
||||
class TestMailAliasMixin(TestMailAliasCommon):
|
||||
""" Test alias mixin implementation, synchornization of alias records
|
||||
|
||||
@@ -29,6 +29,8 @@ class TestMailComposer(MailCommon, TestRecipients):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestMailComposer, cls).setUpClass()
|
||||
|
||||
# force 'now' to ease test about schedulers
|
||||
cls.reference_now = FieldDatetime.from_string('2022-12-24 12:00:00')
|
||||
cls.env.cr._now = cls.reference_now # force create_date to check schedulers
|
||||
|
||||
@@ -1184,6 +1186,72 @@ class TestComposerInternals(TestMailComposer):
|
||||
self.assertEqual(template.name, "%s: %s" % (self.env['ir.model']._get(self.test_record._name).name, 'Template Subject'))
|
||||
self.assertEqual(template.body_html, '<p>Template Body</p>', 'email_template incorrect body_html')
|
||||
|
||||
@users('erp_manager')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
def test_mail_composer_wtpl_populate_new_recipients_mc(self):
|
||||
""" Test auto-populate of auto created partner with related record
|
||||
values when sending a mail with a template, in multi-company environment.
|
||||
"""
|
||||
companies = self.company_admin + self.company_2
|
||||
test_records = self.env['mail.test.ticket.mc'].create([
|
||||
{
|
||||
'email_from': f'newpartner{idx}@example.com',
|
||||
'company_id': companies[idx].id,
|
||||
'customer_id': False,
|
||||
'mobile_number': f'+3319900{idx:02d}{idx:02d}',
|
||||
'name': f'TestRecord{idx}',
|
||||
'phone_number': False,
|
||||
'user_id': False,
|
||||
} for idx in range(2)
|
||||
])
|
||||
manual_recipients = test_records.mapped('email_from')
|
||||
template = self.env['mail.template'].create({
|
||||
'email_to': '{{ object.email_from }}',
|
||||
'model_id': self.env['ir.model']._get_id(test_records._name),
|
||||
'partner_to': False,
|
||||
})
|
||||
|
||||
for composition_mode, batch_mode in product(
|
||||
('comment', 'mass_mail'),
|
||||
(True, False)
|
||||
):
|
||||
with self.subTest(composition_mode=composition_mode, batch_mode=batch_mode):
|
||||
test_records = test_records if batch_mode else test_records[0]
|
||||
|
||||
self.assertFalse(
|
||||
self.env['res.partner'].search(
|
||||
[('email_normalized', 'in', manual_recipients)]
|
||||
)
|
||||
)
|
||||
ctx = {
|
||||
'default_composition_mode': composition_mode,
|
||||
'default_model': test_records._name,
|
||||
'default_res_ids': test_records.ids,
|
||||
}
|
||||
composer = self.env['mail.compose.message'].with_context(ctx).create({
|
||||
'template_id': template.id,
|
||||
})
|
||||
|
||||
with self.mock_mail_gateway():
|
||||
composer._action_send_mail()
|
||||
|
||||
new_partners = self.env['res.partner'].search([('email_normalized', 'in', manual_recipients)],
|
||||
order='email')
|
||||
try:
|
||||
self.assertEqual(
|
||||
len(new_partners), len(test_records)
|
||||
)
|
||||
self.assertEqual(
|
||||
new_partners.mapped('company_id'),
|
||||
test_records.mapped('company_id')
|
||||
)
|
||||
self.assertEqual(
|
||||
new_partners.mapped('mobile'),
|
||||
test_records.mapped('mobile_number')
|
||||
)
|
||||
finally:
|
||||
new_partners.unlink()
|
||||
|
||||
|
||||
@tagged('mail_composer', 'multi_lang')
|
||||
class TestComposerResultsComment(TestMailComposer, CronMixinCase):
|
||||
|
||||
@@ -228,7 +228,7 @@ class TestMailgateway(MailCommon):
|
||||
record = self.format_and_process(test_mail_data.MAIL_MULTIPART_IMAGE, self.email_from, f'groups@{self.alias_domain}')
|
||||
message = record.message_ids[0]
|
||||
for attachment in message.attachment_ids:
|
||||
self.assertIn('/web/image/%s' % attachment.id, message.body)
|
||||
self.assertIn(f'/web/image/{attachment.id}', message.body)
|
||||
self.assertEqual(
|
||||
set(message.attachment_ids.mapped('name')),
|
||||
set(['rosaçée.gif', 'verte!µ.gif', 'orangée.gif']))
|
||||
@@ -323,7 +323,7 @@ class TestMailgateway(MailCommon):
|
||||
self.assertNotSentEmail() # No notification / bounce should be sent
|
||||
|
||||
# Email recognized if partner has a formatted email
|
||||
self.partner_1.write({'email': '"Valid Lelitre" <%s>' % self.partner_1.email})
|
||||
self.partner_1.write({'email': f'"Valid Lelitre" <{self.partner_1.email}>'})
|
||||
record = self.format_and_process(MAIL_TEMPLATE, self.partner_1.email, f'groups@{self.alias_domain}', subject='Test2')
|
||||
|
||||
self.assertEqual(record.message_ids[0].author_id, self.partner_1,
|
||||
@@ -339,7 +339,7 @@ class TestMailgateway(MailCommon):
|
||||
self.partner_1.write({'email': f'{test_email}, "Valid Lelitre" <another.email@test.example.com>'})
|
||||
with self.mock_mail_gateway():
|
||||
record = self.format_and_process(
|
||||
MAIL_TEMPLATE, f'"Valid Lelitre" <{test_email}>', 'groups@test.com', subject='Test3')
|
||||
MAIL_TEMPLATE, f'"Valid Lelitre" <{test_email}>', f'groups@{self.alias_domain}', subject='Test3')
|
||||
|
||||
self.assertEqual(record.message_ids[0].author_id, self.partner_1,
|
||||
'message_process: found author based on first found email normalized, even with multi emails')
|
||||
@@ -349,7 +349,7 @@ class TestMailgateway(MailCommon):
|
||||
# Email not recognized if partner has a multi-email (source = std email)
|
||||
with self.mock_mail_gateway():
|
||||
record = self.format_and_process(
|
||||
MAIL_TEMPLATE, test_email, 'groups@test.com', subject='Test4')
|
||||
MAIL_TEMPLATE, test_email, f'groups@{self.alias_domain}', subject='Test4')
|
||||
|
||||
self.assertEqual(record.message_ids[0].author_id, self.partner_1,
|
||||
'message_process: found author based on first found email normalized, even with multi emails')
|
||||
@@ -394,18 +394,18 @@ class TestMailgateway(MailCommon):
|
||||
self.assertFalse(record.message_ids[0].author_id)
|
||||
self.assertEqual(record.message_ids[0].email_from, from_1.email_formatted)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.addons.mail.models.mail_thread', 'odoo.models')
|
||||
def test_message_route_alias_owner_author_notify(self):
|
||||
""" Make sure users are notified when a reply is sent to an alias address.
|
||||
Alias owner should impact the message creator, but not notifications. """
|
||||
test_record = self.env['mail.test.ticket'].create({})
|
||||
author_partner = self.env['res.partner'].create({
|
||||
'name': 'Author',
|
||||
'email': 'author-partner@test.com',
|
||||
'email': f'author-partner@{self.alias_domain}',
|
||||
})
|
||||
message = self.env['mail.message'].create({
|
||||
'body': '<p>test</p>',
|
||||
'email_from': 'author-partner@test.com', # email sent by author who also has an alias with their email
|
||||
'email_from': f'author-partner@{self.alias_domain}', # email sent by author who also has an alias with their email
|
||||
'message_type': 'email',
|
||||
'model': test_record._name,
|
||||
'res_id': test_record.id,
|
||||
@@ -423,7 +423,7 @@ class TestMailgateway(MailCommon):
|
||||
self.assertFalse(self.user_root.active, 'notification logic relies on odoobot being archived')
|
||||
|
||||
test_users = [self.user_employee, self.user_root]
|
||||
email_tos = ['author-partner@test.com', 'some_non_aliased_email@test.com']
|
||||
email_tos = [f'author-partner@{self.alias_domain}', f'some_non_aliased_email@{self.alias_domain}']
|
||||
for email_to, test_user in itertools.product(email_tos, test_users):
|
||||
with self.subTest(test_user=test_user, email_to=email_to):
|
||||
with self.mock_mail_gateway(), self.mock_mail_app():
|
||||
@@ -487,19 +487,19 @@ class TestMailgateway(MailCommon):
|
||||
self.assertSentEmail(
|
||||
f'"MAILER-DAEMON" <{self.alias_bounce}@{self.alias_domain}>',
|
||||
['whatever-2a840@postmaster.twitter.com'],
|
||||
body_content='<p>Dear Sender,<br /><br />The message below could not be accepted by the address %s' % self.alias.display_name.lower()
|
||||
body_content=f'<p>Dear Sender,<br /><br />The message below could not be accepted by the address {self.alias.display_name.lower()}',
|
||||
)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
def test_message_process_alias_config_bounced_to(self):
|
||||
""" Check bounce message contains the bouncing alias, not a generic "to" """
|
||||
self.alias.write({'alias_contact': 'partners'})
|
||||
bounce_message_with_alias = '<p>Dear Sender,<br /><br />The message below could not be accepted by the address %s' % self.alias.display_name.lower()
|
||||
bounce_message_with_alias = f'<p>Dear Sender,<br /><br />The message below could not be accepted by the address {self.alias.display_name.lower()}'
|
||||
|
||||
# Bounce is To
|
||||
with self.mock_mail_gateway():
|
||||
self.format_and_process(
|
||||
MAIL_TEMPLATE, self.email_from, 'groups@example.com',
|
||||
MAIL_TEMPLATE, self.email_from, f'groups@{self.alias_domain}',
|
||||
cc='other@gmail.com', subject='Should Bounce')
|
||||
self.assertIn(bounce_message_with_alias, self._mails[0].get('body'))
|
||||
|
||||
@@ -507,17 +507,17 @@ class TestMailgateway(MailCommon):
|
||||
with self.mock_mail_gateway():
|
||||
self.format_and_process(
|
||||
MAIL_TEMPLATE, self.email_from, 'other@gmail.com',
|
||||
cc='groups@example.com', subject='Should Bounce')
|
||||
cc=f'groups@{self.alias_domain}', subject='Should Bounce')
|
||||
self.assertIn(bounce_message_with_alias, self._mails[0].get('body'))
|
||||
|
||||
# Bounce is part of To
|
||||
with self.mock_mail_gateway():
|
||||
self.format_and_process(
|
||||
MAIL_TEMPLATE, self.email_from, 'other@gmail.com, groups@example.com',
|
||||
MAIL_TEMPLATE, self.email_from, f'other@gmail.com, groups@{self.alias_domain}',
|
||||
subject='Should Bounce')
|
||||
self.assertIn(bounce_message_with_alias, self._mails[0].get('body'))
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models', 'odoo.sql_db')
|
||||
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.addons.mail.models.mail_mail', 'odoo.models', 'odoo.sql_db')
|
||||
def test_message_process_alias_config_invalid_defaults(self):
|
||||
"""Sending a mail to a misconfigured alias must change its status to invalid + notify sender and responsible."""
|
||||
test_model_track = self.env['ir.model']._get('mail.test.track')
|
||||
@@ -706,7 +706,7 @@ class TestMailgateway(MailCommon):
|
||||
with self.subTest(partner_email=partner_email):
|
||||
self.partner_1.write({'email': partner_email})
|
||||
record = self.format_and_process(
|
||||
MAIL_TEMPLATE, email_from, 'groups@test.com',
|
||||
MAIL_TEMPLATE, email_from, f'groups@{self.alias_domain}',
|
||||
subject=f'Test for {partner_email}')
|
||||
|
||||
if passed:
|
||||
@@ -765,7 +765,10 @@ class TestMailgateway(MailCommon):
|
||||
self.assertEqual(record.message_ids[0].create_uid, self.user_root)
|
||||
self.assertEqual(record.message_ids[0].author_id, self.user_employee.partner_id)
|
||||
|
||||
record = self.format_and_process(MAIL_TEMPLATE, 'Another name <%s>' % self.user_employee.email, f'groups@{self.alias_domain}', subject='Email OtherName')
|
||||
record = self.format_and_process(
|
||||
MAIL_TEMPLATE, f'Another name <{self.user_employee.email}>',
|
||||
f'groups@{self.alias_domain}',
|
||||
subject='Email OtherName')
|
||||
self.assertEqual(record.create_uid, self.user_employee)
|
||||
self.assertEqual(record.message_ids[0].subject, 'Email OtherName')
|
||||
self.assertEqual(record.message_ids[0].create_uid, self.user_root)
|
||||
@@ -828,9 +831,9 @@ class TestMailgateway(MailCommon):
|
||||
})
|
||||
new_rec = self.format_and_process(
|
||||
MAIL_TEMPLATE, self.partner_1.email_formatted,
|
||||
'%s@%s, %s@%s' % (new_alias_2.alias_name, self.alias_domain, self.alias.alias_name, self.alias_domain),
|
||||
f'{new_alias_2.display_name}, {self.alias.display_name}',
|
||||
subject='Test Subject',
|
||||
extra='In-Reply-To:\r\n\t%s\n' % self.fake_email.message_id,
|
||||
extra=f'In-Reply-To:\r\n\t{self.fake_email.message_id}\n',
|
||||
target_model=new_alias_2.alias_model_id.model
|
||||
)
|
||||
# Forward created a new record in mail.test
|
||||
@@ -855,9 +858,9 @@ class TestMailgateway(MailCommon):
|
||||
})
|
||||
new_rec = self.format_and_process(
|
||||
MAIL_TEMPLATE, self.partner_1.email_formatted,
|
||||
'%s@%s, %s@%s' % (self.alias.alias_name, self.alias_domain, new_alias_2.alias_name, self.alias_domain),
|
||||
f'{self.alias.display_name}, {new_alias_2.display_name}',
|
||||
subject='Test Subject',
|
||||
extra='In-Reply-To:\r\n\t%s\n' % self.fake_email.message_id,
|
||||
extra=f'In-Reply-To:\r\n\t{self.fake_email.message_id}\n',
|
||||
target_model=new_alias_2.alias_model_id.model
|
||||
)
|
||||
# Forward created a new record in mail.test
|
||||
@@ -885,9 +888,9 @@ class TestMailgateway(MailCommon):
|
||||
})
|
||||
new_rec = self.format_and_process(
|
||||
MAIL_TEMPLATE, self.partner_1.email_formatted,
|
||||
'%s@%s, %s@%s' % (new_alias_2.alias_name, self.alias_domain, self.alias.alias_name, self.alias_domain),
|
||||
f'{new_alias_2.display_name}, {self.alias.display_name}',
|
||||
subject='Test Subject',
|
||||
extra='In-Reply-To:\r\n\t%s\n' % self.fake_email.message_id,
|
||||
extra=f'In-Reply-To:\r\n\t{self.fake_email.message_id}\n',
|
||||
target_model=new_alias_2.alias_model_id.model
|
||||
)
|
||||
# Forward created a new record in mail.test
|
||||
@@ -911,7 +914,7 @@ class TestMailgateway(MailCommon):
|
||||
})
|
||||
new_rec = self.format_and_process(
|
||||
MAIL_TEMPLATE, self.partner_1.email_formatted,
|
||||
'%s@%s, %s@%s' % (self.alias.alias_name, self.alias_domain, new_alias_2.alias_name, self.alias_domain),
|
||||
f'{self.alias.display_name}, {new_alias_2.display_name}',
|
||||
subject='Test Subject',
|
||||
target_model=new_alias_2.alias_model_id.model
|
||||
)
|
||||
@@ -923,44 +926,43 @@ class TestMailgateway(MailCommon):
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
|
||||
def test_message_route_alias_with_allowed_domains(self):
|
||||
""" Incoming email: check that if domains are set in the
|
||||
optional system parameter `mail.catchall.domain.allowed`,
|
||||
only incoming emails from these domains will generate records."""
|
||||
|
||||
""" Incoming email: check that if domains are set in the optional system
|
||||
parameter `mail.catchall.domain.allowed` only incoming emails from these
|
||||
domains will generate records."""
|
||||
MailTestGatewayModel = self.env['mail.test.gateway']
|
||||
MailTestContainerModel = self.env['mail.test.container']
|
||||
|
||||
allowed_domain = 'hello.com'
|
||||
not_allowed_domain = 'bonjour.com'
|
||||
|
||||
# test@.. will cause the creation of new mail.test
|
||||
new_alias_2 = self.env['mail.alias'].create({
|
||||
'alias_contact': 'everyone',
|
||||
'alias_model_id': self.env['ir.model']._get('mail.test.container').id,
|
||||
'alias_name': 'test',
|
||||
'alias_user_id': False,
|
||||
'alias_model_id': self.env['ir.model']._get('mail.test.container').id,
|
||||
'alias_contact': 'everyone',
|
||||
})
|
||||
|
||||
for subject, gateway_created, container_created, alias2_domain, sys_param in [
|
||||
# Test with 'mail.catchall.domain.allowed' not set in system parameters
|
||||
# and with a domain not allowed
|
||||
('Test Subject 1', True, True, not_allowed_domain, ""),
|
||||
# Test with 'mail.catchall.domain.allowed' set in system parameters
|
||||
# and with a domain not allowed
|
||||
('Test Subject 2', True, False, not_allowed_domain, allowed_domain),
|
||||
# Test with 'mail.catchall.domain.allowed' set in system parameters
|
||||
# and with a domain allowed
|
||||
('Test Subject 3', True, True, allowed_domain, allowed_domain),
|
||||
]:
|
||||
with self.subTest(subject=subject, gateway_created=gateway_created,
|
||||
container_created=container_created, alias2_domain=alias2_domain,
|
||||
sys_param=sys_param):
|
||||
self.env['ir.config_parameter'].set_param('mail.catchall.domain.allowed', sys_param)
|
||||
allowed_domain = 'hello.com'
|
||||
for (alias_right_part, allowed_domain), (gateway_created, container_created) in zip(
|
||||
[
|
||||
# Test with 'mail.catchall.domain.allowed' not set in system parameters
|
||||
# and with a domain not allowed
|
||||
('bonjour.com', ""),
|
||||
# Test with 'mail.catchall.domain.allowed' set in system parameters
|
||||
# and with a domain not allowed
|
||||
('bonjour.com', allowed_domain),
|
||||
# Test with 'mail.catchall.domain.allowed' set in system parameters
|
||||
# and with a domain allowed
|
||||
(allowed_domain, allowed_domain),
|
||||
], [
|
||||
(True, True),
|
||||
(True, False),
|
||||
(True, True),
|
||||
]
|
||||
):
|
||||
with self.subTest(alias_right_part=alias_right_part, allowed_domain=allowed_domain):
|
||||
self.env['ir.config_parameter'].set_param('mail.catchall.domain.allowed', allowed_domain)
|
||||
|
||||
email_to = '%s@%s, %s@%s' % (
|
||||
self.alias.alias_name, self.alias_domain,
|
||||
new_alias_2.alias_name, alias2_domain,
|
||||
)
|
||||
subject = f'Test wigh {alias_right_part}-{allowed_domain}'
|
||||
email_to = f'{self.alias.alias_name}@{self.alias_domain}, {new_alias_2.alias_name}@{alias_right_part}'
|
||||
|
||||
self.format_and_process(
|
||||
MAIL_TEMPLATE, self.partner_1.email_formatted, email_to,
|
||||
@@ -970,16 +972,8 @@ class TestMailgateway(MailCommon):
|
||||
|
||||
res_alias_1 = MailTestGatewayModel.search([('name', '=', subject)])
|
||||
res_alias_2 = MailTestContainerModel.search([('name', '=', subject)])
|
||||
self.assertEqual(
|
||||
bool(res_alias_1), gateway_created,
|
||||
'message_process (%s): a new mail.test.gateway %s have been created' %
|
||||
(subject, 'should' if gateway_created else "should not")
|
||||
)
|
||||
self.assertEqual(
|
||||
bool(res_alias_2), container_created,
|
||||
'message_process (%s): a new mail.test.container %s have been created' %
|
||||
(subject, 'should' if container_created else "should not")
|
||||
)
|
||||
self.assertEqual(bool(res_alias_1), gateway_created)
|
||||
self.assertEqual(bool(res_alias_2), container_created)
|
||||
|
||||
# --------------------------------------------------
|
||||
# Email Management
|
||||
@@ -991,7 +985,7 @@ class TestMailgateway(MailCommon):
|
||||
with self.mock_mail_gateway():
|
||||
new_recs = self.format_and_process(
|
||||
MAIL_TEMPLATE, self.partner_1.email_formatted,
|
||||
'%s@%s' % (self.alias_bounce, self.alias_domain),
|
||||
f'{self.alias_bounce}@{self.alias_domain}',
|
||||
subject='Should bounce',
|
||||
)
|
||||
self.assertFalse(new_recs)
|
||||
@@ -1003,10 +997,7 @@ class TestMailgateway(MailCommon):
|
||||
with self.mock_mail_gateway():
|
||||
new_recs = self.format_and_process(
|
||||
MAIL_TEMPLATE, self.partner_1.email_formatted,
|
||||
'%s@%s, %s@%s' % (
|
||||
self.alias.alias_name, self.alias_domain,
|
||||
self.alias_bounce, self.alias_domain
|
||||
),
|
||||
f'{self.alias.alias_name}@{self.alias_domain}, {self.alias_bounce}@{self.alias_domain}',
|
||||
subject='Should bounce',
|
||||
)
|
||||
self.assertFalse(new_recs)
|
||||
@@ -1019,11 +1010,11 @@ class TestMailgateway(MailCommon):
|
||||
with self.mock_mail_gateway():
|
||||
record = self.format_and_process(
|
||||
MAIL_TEMPLATE, self.partner_1.email_formatted,
|
||||
'"My Super Catchall" <%s@%s>' % (self.alias_catchall, self.alias_domain),
|
||||
f'"My Super Catchall" <{self.alias_catchall}@{self.alias_domain}',
|
||||
subject='Should Bounce')
|
||||
self.assertFalse(record)
|
||||
self.assertSentEmail(
|
||||
f'"MAILER-DAEMON" <{self.alias_bounce}@{self.alias_domain}>',
|
||||
self.mailer_daemon_email,
|
||||
['whatever-2a840@postmaster.twitter.com'],
|
||||
subject='Re: Should Bounce'
|
||||
)
|
||||
@@ -1035,7 +1026,7 @@ class TestMailgateway(MailCommon):
|
||||
with self.mock_mail_gateway():
|
||||
record = self.format_and_process(
|
||||
MAIL_TEMPLATE, self.partner_1.email_formatted,
|
||||
'%s@%s, %s@%s' % (self.alias_catchall, self.alias_domain, self.alias.alias_name, self.alias_domain),
|
||||
f'{self.alias_catchall}@{self.alias_domain}, {self.alias.alias_name}@{self.alias_domain}',
|
||||
subject='Catchall Not Blocking'
|
||||
)
|
||||
# Test: one group created
|
||||
@@ -1050,7 +1041,7 @@ class TestMailgateway(MailCommon):
|
||||
with self.mock_mail_gateway():
|
||||
record = self.format_and_process(
|
||||
MAIL_TEMPLATE, self.partner_1.email_formatted,
|
||||
'%s@%s, %s@%s' % (self.alias.alias_name, self.alias_domain, self.alias_catchall, self.alias_domain),
|
||||
f'{self.alias.alias_name}@{self.alias_domain}, {self.alias_catchall}@{self.alias_domain}',
|
||||
subject='Catchall Not Blocking'
|
||||
)
|
||||
# Test: one group created
|
||||
@@ -1187,10 +1178,10 @@ class TestMailgateway(MailCommon):
|
||||
def test_message_process_bounce_records_channel(self):
|
||||
""" Test blacklist allow to multi-bounce and auto update of discuss.channel """
|
||||
other_record = self.env['mail.test.gateway'].create({
|
||||
'email_from': 'Another name <%s>' % self.partner_1.email
|
||||
'email_from': f'Another name <{self.partner_1.email}>'
|
||||
})
|
||||
yet_other_record = self.env['mail.test.gateway'].create({
|
||||
'email_from': 'Yet Another name <%s>' % self.partner_1.email.upper()
|
||||
'email_from': f'Yet Another name <{self.partner_1.email.upper()}>'
|
||||
})
|
||||
test_channel = self.env['discuss.channel'].create({
|
||||
'name': 'Test',
|
||||
@@ -1207,7 +1198,11 @@ class TestMailgateway(MailCommon):
|
||||
|
||||
extra = self.fake_email.message_id
|
||||
for i in range(10):
|
||||
record = self.format_and_process(test_mail_data.MAIL_BOUNCE, 'A third name <%s>' % self.partner_1.email, f'groups@{self.alias_domain}', subject='Undelivered Mail Returned to Sender', extra=extra)
|
||||
record = self.format_and_process(
|
||||
test_mail_data.MAIL_BOUNCE, f'A third name <{self.partner_1.email}>',
|
||||
f'groups@{self.alias_domain}',
|
||||
subject='Undelivered Mail Returned to Sender',
|
||||
extra=extra)
|
||||
self.assertFalse(record)
|
||||
self.assertEqual(self.partner_1.message_bounce, 10)
|
||||
self.assertEqual(self.test_record.message_bounce, 0)
|
||||
@@ -1234,7 +1229,7 @@ class TestMailgateway(MailCommon):
|
||||
# Thread formation
|
||||
# --------------------------------------------------
|
||||
|
||||
@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_external_notification_reply(self):
|
||||
"""Ensure responses bot messages are discussions."""
|
||||
bot_notification_message = self._create_gateway_message(
|
||||
@@ -1282,7 +1277,7 @@ class TestMailgateway(MailCommon):
|
||||
init_msg_count = len(self.test_record.message_ids)
|
||||
self.format_and_process(
|
||||
MAIL_TEMPLATE, 'valid.other@gmail.com', f'erroneous@{self.alias_domain}',
|
||||
subject='Re: news', extra='In-Reply-To:\r\n\t%s\n' % self.fake_email.message_id)
|
||||
subject='Re: news', extra=f'In-Reply-To:\r\n\t{self.fake_email.message_id}\n')
|
||||
|
||||
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])
|
||||
@@ -1293,7 +1288,7 @@ class TestMailgateway(MailCommon):
|
||||
init_msg_count = len(self.test_record.message_ids)
|
||||
self.format_and_process(
|
||||
MAIL_TEMPLATE, self.email_from, f'erroneous@{self.alias_domain}',
|
||||
extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % self.fake_email.message_id)
|
||||
extra=f'References: <2233@a.com>\r\n\t<3edss_dsa@b.com> {self.fake_email.message_id}')
|
||||
|
||||
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])
|
||||
@@ -1442,7 +1437,7 @@ class TestMailgateway(MailCommon):
|
||||
init_msg_count = len(self.test_record.message_ids)
|
||||
self.format_and_process(
|
||||
MAIL_TEMPLATE, self.email_from, f'erroneous@{self.alias_domain}',
|
||||
extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % self.fake_email.message_id)
|
||||
extra=f'References: <2233@a.com>\r\n\t<3edss_dsa@b.com> {self.fake_email.message_id}')
|
||||
|
||||
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])
|
||||
@@ -1463,7 +1458,7 @@ class TestMailgateway(MailCommon):
|
||||
init_msg_count = len(self.test_record.message_ids)
|
||||
self.format_and_process(
|
||||
MAIL_TEMPLATE, self.email_from, f'erroneous@{self.alias_domain}',
|
||||
extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % buggy_message_id)
|
||||
extra=f'References: <2233@a.com>\r\n\t<3edss_dsa@b.com> {buggy_message_id}')
|
||||
|
||||
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])
|
||||
@@ -1480,7 +1475,8 @@ class TestMailgateway(MailCommon):
|
||||
init_msg_count = len(self.test_record.message_ids)
|
||||
res_test = self.format_and_process(
|
||||
MAIL_TEMPLATE, self.email_from, f'test.alias@{self.alias_domain}',
|
||||
subject='My Dear Forward', extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % self.fake_email.message_id,
|
||||
subject='My Dear Forward',
|
||||
extra=f'References: <2233@a.com>\r\n\t<3edss_dsa@b.com> {self.fake_email.message_id}',
|
||||
target_model='mail.test.container')
|
||||
|
||||
self.assertEqual(len(self.test_record.message_ids), init_msg_count)
|
||||
@@ -1500,7 +1496,8 @@ class TestMailgateway(MailCommon):
|
||||
init_msg_count = len(self.test_record.message_ids)
|
||||
res_test = self.format_and_process(
|
||||
MAIL_TEMPLATE, self.email_from, f'test.alias@{self.alias_domain}',
|
||||
subject='My Dear Forward', extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % self.fake_email.message_id,
|
||||
subject='My Dear Forward',
|
||||
extra=f'References: <2233@a.com>\r\n\t<3edss_dsa@b.com> {self.fake_email.message_id}',
|
||||
target_model='mail.test.container')
|
||||
|
||||
self.assertEqual(len(self.test_record.message_ids), init_msg_count + 1)
|
||||
@@ -1555,7 +1552,7 @@ class TestMailgateway(MailCommon):
|
||||
msgID = '<this.is.duplicate.test@iron.sky>'
|
||||
res_test = self.format_and_process(
|
||||
MAIL_TEMPLATE, self.email_from, record_msg.reply_to, cc='',
|
||||
subject='Re: Replies to Record', extra='In-Reply-To: %s' % record_msg.message_id,
|
||||
subject='Re: Replies to Record', extra=f'In-Reply-To: {record_msg.message_id}',
|
||||
msg_id=msgID, target_model='mail.test.simple')
|
||||
incoming_msg = self.env['mail.message'].search([('message_id', '=', msgID)])
|
||||
self.assertFalse(res_test)
|
||||
@@ -1567,7 +1564,7 @@ class TestMailgateway(MailCommon):
|
||||
msgID = '<this.is.for.testing@iron.sky>'
|
||||
res_test = self.format_and_process(
|
||||
MAIL_TEMPLATE, self.email_from, mail_msg.reply_to, cc='',
|
||||
subject='Re: Replies to Record', extra='In-Reply-To: %s' % mail_msg.message_id,
|
||||
subject='Re: Replies to Record', extra=f'In-Reply-To: {mail_msg.message_id}',
|
||||
msg_id=msgID, target_model='mail.test.gateway')
|
||||
incoming_msg = self.env['mail.message'].search([('message_id', '=', msgID)])
|
||||
self.assertEqual(len(res_test), 1)
|
||||
@@ -1592,7 +1589,7 @@ class TestMailgateway(MailCommon):
|
||||
})
|
||||
record = self.format_and_process(
|
||||
test_mail_data.MAIL_TEMPLATE_EXTRA_HTML, self.email_from,
|
||||
'%s@%s' % (alias.alias_name, self.alias_catchall),
|
||||
f'{alias.alias_name}@{self.alias_domain}',
|
||||
subject='base64 image to alias',
|
||||
target_model=target_model,
|
||||
extra_html='<img src="data:image/png;base64,iV/+OkI=">',
|
||||
@@ -1615,7 +1612,7 @@ class TestMailgateway(MailCommon):
|
||||
})
|
||||
record = self.format_and_process(
|
||||
test_mail_data.MAIL_TEMPLATE_EXTRA_HTML, self.email_from,
|
||||
'%s@%s' % (alias.alias_name, self.alias_catchall),
|
||||
f'{alias.alias_name}@{self.alias_domain}',
|
||||
subject='base64 image to alias',
|
||||
target_model=target_model,
|
||||
extra_html='<img src="data:image/png;base64,iV/+OkI=">',
|
||||
@@ -1635,7 +1632,7 @@ class TestMailgateway(MailCommon):
|
||||
self.assertRaises(ValueError,
|
||||
self.format_and_process, MAIL_TEMPLATE,
|
||||
self.partner_1.email_formatted, f'noone@{self.alias_domain}', subject='spam',
|
||||
extra='In-Reply-To: <12321321-openerp-%d-mail.test.gateway@%s>' % (self.test_record.id, socket.gethostname()))
|
||||
extra=f'In-Reply-To: <12321321-openerp-{self.test_record.id}-{self.test_record._name}@{socket.gethostname()}>')
|
||||
|
||||
# when 6.1 messages are present, compat mode is available
|
||||
# Odoo 10 update: compat mode has been removed and should not work anymore
|
||||
@@ -1645,7 +1642,7 @@ class TestMailgateway(MailCommon):
|
||||
ValueError,
|
||||
self.format_and_process, MAIL_TEMPLATE,
|
||||
self.partner_1.email_formatted, f'noone@{self.alias_domain}>', subject='spam',
|
||||
extra='In-Reply-To: <12321321-openerp-%d-mail.test.gateway@%s>' % (self.test_record.id, socket.gethostname()))
|
||||
extra=f'In-Reply-To: <12321321-openerp-{self.test_record.id}-mail.test.gateway@{socket.gethostname()}>')
|
||||
|
||||
# Test created messages
|
||||
self.assertEqual(len(self.test_record.message_ids), 1)
|
||||
@@ -1707,8 +1704,8 @@ class TestMailgateway(MailCommon):
|
||||
file_content_b64 = base64.b64encode(file_content.encode(encoding or 'utf-8')).decode()
|
||||
record = self.format_and_process(test_mail_data.MAIL_FILE_ENCODING,
|
||||
self.email_from, f'groups@{self.alias_domain}',
|
||||
subject='Test Charset %s' % encoding or 'Unset',
|
||||
charset='; charset="%s"' % encoding if encoding else '',
|
||||
subject=f'Test Charset {encoding or "Unset"}',
|
||||
charset=f'; charset="{encoding}"' if encoding else '',
|
||||
content=file_content_b64
|
||||
)
|
||||
attachment = record.message_ids.attachment_ids
|
||||
@@ -1835,6 +1832,7 @@ class TestMailgateway(MailCommon):
|
||||
# This explains the multiple "�" in the attachment.
|
||||
self.assertIn("Chauss������e de Bruxelles", record.message_ids.attachment_ids.raw.decode())
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_thread')
|
||||
def test_message_process_file_omitted_charset(self):
|
||||
""" For incoming email containing an xml attachment with omitted charset and containing an UTF8 payload we
|
||||
should parse the attachment using UTF-8.
|
||||
@@ -1843,6 +1841,7 @@ class TestMailgateway(MailCommon):
|
||||
self.assertEqual(record.message_ids.attachment_ids.name, 'bis3.xml')
|
||||
self.assertEqual("<Invoice>Chaussée de Bruxelles</Invoice>", record.message_ids.attachment_ids.raw.decode())
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_thread')
|
||||
def test_message_route_reply_model_none(self):
|
||||
"""
|
||||
Test the message routing and reply functionality when the model is None.
|
||||
@@ -1886,10 +1885,11 @@ class TestMailThreadCC(MailCommon):
|
||||
|
||||
cls.email_from = 'Sylvie Lelitre <test.sylvie.lelitre@agrolait.com>'
|
||||
cls.alias = cls.env['mail.alias'].create({
|
||||
'alias_contact': 'everyone',
|
||||
'alias_model_id': cls.env['ir.model']._get('mail.test.cc').id,
|
||||
'alias_name': 'cc_record',
|
||||
'alias_user_id': False,
|
||||
'alias_model_id': cls.env['ir.model']._get('mail.test.cc').id,
|
||||
'alias_contact': 'everyone'})
|
||||
})
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_thread')
|
||||
def test_message_cc_new(self):
|
||||
|
||||
@@ -13,7 +13,7 @@ from odoo.addons.mail.tests.common import MailCommon
|
||||
from odoo.addons.test_mail.tests.common import TestRecipients
|
||||
from odoo.exceptions import AccessError
|
||||
from odoo.tests import tagged, users, HttpCase
|
||||
from odoo.tools import formataddr, mute_logger
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
class TestMailMCCommon(MailCommon, TestRecipients):
|
||||
@@ -69,132 +69,6 @@ class TestMailMCCommon(MailCommon, TestRecipients):
|
||||
@tagged('multi_company')
|
||||
class TestMultiCompanySetup(TestMailMCCommon):
|
||||
|
||||
@users('erp_manager')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
def test_mail_composer_wtpl_populate_new_recipient(self):
|
||||
""" Test auto-populate of auto created partner with related record
|
||||
values when sending a mail with a template.
|
||||
"""
|
||||
companies = self.company_admin + self.company_2
|
||||
test_records = self.env['mail.test.ticket.mc'].create([
|
||||
{
|
||||
'email_from': f'newpartner{idx}@example.com',
|
||||
'company_id': companies[idx].id,
|
||||
'customer_id': False,
|
||||
'mobile_number': f'+3319900{idx:02d}{idx:02d}',
|
||||
'name': f'TestRecord{idx}',
|
||||
'phone_number': False,
|
||||
'user_id': False,
|
||||
} for idx in range(2)
|
||||
])
|
||||
manual_recipients = test_records.mapped('email_from')
|
||||
template = self.env['mail.template'].create({
|
||||
'email_to': '{{ object.email_from }}',
|
||||
'model_id': self.env['ir.model']._get_id(test_records._name),
|
||||
'partner_to': False,
|
||||
})
|
||||
|
||||
for composition_mode, batch_mode in product(
|
||||
('comment', 'mass_mail'),
|
||||
(True, False)
|
||||
):
|
||||
with self.subTest(composition_mode=composition_mode, batch_mode=batch_mode):
|
||||
test_records = test_records if batch_mode else test_records[0]
|
||||
|
||||
self.assertFalse(
|
||||
self.env['res.partner'].search(
|
||||
[('email_normalized', 'in', manual_recipients)]
|
||||
)
|
||||
)
|
||||
ctx = {
|
||||
'default_composition_mode': composition_mode,
|
||||
'default_model': test_records._name,
|
||||
'default_res_ids': test_records.ids,
|
||||
}
|
||||
composer = self.env['mail.compose.message'].with_context(ctx).create({
|
||||
'template_id': template.id,
|
||||
})
|
||||
|
||||
with self.mock_mail_gateway():
|
||||
composer._action_send_mail()
|
||||
|
||||
new_partners = self.env['res.partner'].search([('email_normalized', 'in', manual_recipients)],
|
||||
order='email')
|
||||
try:
|
||||
self.assertEqual(
|
||||
len(new_partners), len(test_records)
|
||||
)
|
||||
self.assertEqual(
|
||||
new_partners.mapped('company_id'),
|
||||
test_records.mapped('company_id')
|
||||
)
|
||||
self.assertEqual(
|
||||
new_partners.mapped('mobile'),
|
||||
test_records.mapped('mobile_number')
|
||||
)
|
||||
finally:
|
||||
new_partners.unlink()
|
||||
|
||||
@users('employee')
|
||||
def test_notify_reply_to_computation(self):
|
||||
test_record = self.env['mail.test.gateway'].browse(self.test_record.ids)
|
||||
res = test_record._notify_get_reply_to()
|
||||
self.assertEqual(
|
||||
res[test_record.id],
|
||||
formataddr((
|
||||
"%s %s" % (self.user_employee.company_id.name, test_record.name),
|
||||
"%s@%s" % (self.alias_catchall, self.alias_domain)))
|
||||
)
|
||||
|
||||
@users('employee_c2')
|
||||
def test_notify_reply_to_computation_mc(self):
|
||||
""" Test reply-to computation in multi company mode. Add notably tests
|
||||
depending on user and records company_id / company_ids. """
|
||||
|
||||
# Test1: no company_id field
|
||||
test_record = self.env['mail.test.gateway'].browse(self.test_record.ids)
|
||||
res = test_record._notify_get_reply_to()
|
||||
self.assertEqual(
|
||||
res[test_record.id],
|
||||
formataddr((
|
||||
"%s %s" % (self.user_employee_c2.company_id.name, test_record.name),
|
||||
"%s@%s" % (self.alias_catchall, self.alias_domain)))
|
||||
)
|
||||
|
||||
# Test2: MC environment get default value from env
|
||||
self.user_employee_c2.write({'company_ids': [(4, self.user_employee.company_id.id)]})
|
||||
test_records = self.env['mail.test.multi.company'].create([
|
||||
{'name': 'Test',
|
||||
'company_id': self.user_employee.company_id.id},
|
||||
{'name': 'Test',
|
||||
'company_id': self.user_employee_c2.company_id.id},
|
||||
])
|
||||
res = test_records._notify_get_reply_to()
|
||||
for test_record in test_records:
|
||||
self.assertEqual(
|
||||
res[test_record.id],
|
||||
formataddr((
|
||||
"%s %s" % (self.user_employee_c2.company_id.name, test_record.name),
|
||||
"%s@%s" % (self.alias_catchall, self.alias_domain)))
|
||||
)
|
||||
|
||||
# Test3: get company from record (company_id field)
|
||||
self.user_employee_c2.write({'company_ids': [(4, self.company_3.id)]})
|
||||
test_records = self.env['mail.test.multi.company'].create([
|
||||
{'name': 'Test1',
|
||||
'company_id': self.company_3.id},
|
||||
{'name': 'Test2',
|
||||
'company_id': self.company_3.id},
|
||||
])
|
||||
res = test_records._notify_get_reply_to()
|
||||
for test_record in test_records:
|
||||
self.assertEqual(
|
||||
res[test_record.id],
|
||||
formataddr((
|
||||
"%s %s" % (self.company_3.name, test_record.name),
|
||||
"%s@%s" % (self.alias_catchall, self.alias_domain)))
|
||||
)
|
||||
|
||||
@users('employee_c2')
|
||||
@mute_logger('odoo.addons.base.models.ir_rule')
|
||||
def test_post_with_read_access(self):
|
||||
|
||||
@@ -233,9 +233,9 @@ class TestMailNotifyAPI(TestMessagePostCommon):
|
||||
# employee: access button and link
|
||||
self.assertTrue(emp_info['has_button_access'])
|
||||
for param, value in link_vals.items():
|
||||
self.assertIn('%s=%s' % (param, value), emp_info['button_access']['url'])
|
||||
self.assertIn('model=%s' % base_record._name, emp_info['button_access']['url'])
|
||||
self.assertIn('res_id=%s' % base_record.id, emp_info['button_access']['url'])
|
||||
self.assertIn(f'{param}={value}', emp_info['button_access']['url'])
|
||||
self.assertIn(f'model={base_record._name}', emp_info['button_access']['url'])
|
||||
self.assertIn(f'res_id={base_record.id}', emp_info['button_access']['url'])
|
||||
self.assertNotIn('body', emp_info['button_access']['url'])
|
||||
self.assertNotIn('subject', emp_info['button_access']['url'])
|
||||
|
||||
@@ -284,6 +284,61 @@ class TestMailNotifyAPI(TestMessagePostCommon):
|
||||
self.assertFalse(partner_info['has_button_access'])
|
||||
self.assertFalse(emp_info['has_button_access'])
|
||||
|
||||
@users('employee_c2')
|
||||
def test_notify_reply_to_computation_mc(self):
|
||||
""" Test reply-to computation in multi company mode. Add notably tests
|
||||
depending on user and records company_id / company_ids. """
|
||||
|
||||
# Test1: no company_id field: depends on current user browsing
|
||||
test_record = self.test_record.with_env(self.env)
|
||||
self.assertEqual(
|
||||
test_record._notify_get_reply_to()[test_record.id],
|
||||
formataddr((
|
||||
f"{self.user_employee_c2.company_id.name} {test_record.name}",
|
||||
f"{self.alias_catchall}@{self.alias_domain}"))
|
||||
)
|
||||
test_record_c1 = test_record.with_user(self.user_employee)
|
||||
self.assertEqual(
|
||||
test_record_c1._notify_get_reply_to()[test_record_c1.id],
|
||||
formataddr((
|
||||
f"{self.user_employee.company_id.name} {test_record_c1.name}",
|
||||
f"{self.alias_catchall}@{self.alias_domain}"))
|
||||
)
|
||||
|
||||
# Test2: MC environment get default value from env
|
||||
self.user_employee_c2.write({'company_ids': [(4, self.user_employee.company_id.id)]})
|
||||
test_records = self.env['mail.test.multi.company'].create([
|
||||
{'name': 'Test',
|
||||
'company_id': self.user_employee.company_id.id},
|
||||
{'name': 'Test',
|
||||
'company_id': self.user_employee_c2.company_id.id},
|
||||
])
|
||||
res = test_records._notify_get_reply_to()
|
||||
for test_record in test_records:
|
||||
self.assertEqual(
|
||||
res[test_record.id],
|
||||
formataddr((
|
||||
f"{self.user_employee_c2.company_id.name} {test_record.name}",
|
||||
f"{self.alias_catchall}@{self.alias_domain}"))
|
||||
)
|
||||
|
||||
# Test3: get company from record (company_id field)
|
||||
self.user_employee_c2.write({'company_ids': [(4, self.company_3.id)]})
|
||||
test_records = self.env['mail.test.multi.company'].create([
|
||||
{'name': 'Test1',
|
||||
'company_id': self.company_3.id},
|
||||
{'name': 'Test2',
|
||||
'company_id': self.company_3.id},
|
||||
])
|
||||
res = test_records._notify_get_reply_to()
|
||||
for test_record in test_records:
|
||||
self.assertEqual(
|
||||
res[test_record.id],
|
||||
formataddr((
|
||||
f"{self.company_3.name} {test_record.name}",
|
||||
f"{self.alias_catchall}@{self.alias_domain}"))
|
||||
)
|
||||
|
||||
|
||||
@tagged('mail_post', 'mail_notify')
|
||||
class TestMessageNotify(TestMessagePostCommon):
|
||||
@@ -331,8 +386,8 @@ class TestMessageNotify(TestMessagePostCommon):
|
||||
self.assertTrue('model=' in admin_mail_body, 'The email sent to admin should contain an access link')
|
||||
admin_access_link = admin_mail_body[
|
||||
admin_mail_body.index('model='):admin_mail_body.index('/>', admin_mail_body.index('model=')) - 1]
|
||||
self.assertIn('model=%s' % self.test_record._name, admin_access_link, 'The access link should contain a valid model argument')
|
||||
self.assertIn('res_id=%d' % self.test_record.id, admin_access_link, 'The access link should contain a valid res_id argument')
|
||||
self.assertIn(f'model={self.test_record._name}', admin_access_link, 'The access link should contain a valid model argument')
|
||||
self.assertIn(f'res_id={self.test_record.id}', admin_access_link, 'The access link should contain a valid res_id argument')
|
||||
|
||||
partner_mails = [x for x in self._mails if self.partner_1.name in x.get('email_to')[0]]
|
||||
self.assertEqual(len(partner_mails), 1, 'There should be exactly one email sent to partner')
|
||||
@@ -397,38 +452,7 @@ class TestMessageNotify(TestMessagePostCommon):
|
||||
@users('employee')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_notify_from_user_id(self):
|
||||
""" Test notify coming from user_id assignment. """
|
||||
test_record = self.env['mail.test.track'].create({
|
||||
'company_id': self.env.user.company_id.id,
|
||||
'email_from': self.env.user.email_formatted,
|
||||
'name': 'Test UserId Track',
|
||||
'user_id': False,
|
||||
})
|
||||
self.flush_tracking()
|
||||
|
||||
with self.mock_mail_gateway(), self.mock_mail_app():
|
||||
test_record.write({'user_id': self.user_employee_2.id})
|
||||
self.flush_tracking()
|
||||
|
||||
self.assertEqual(len(self._new_msgs), 2, 'Should have 2 messages: tracking and assignment')
|
||||
assign_notif = self._new_msgs.filtered(lambda msg: msg.message_type == 'user_notification')
|
||||
self.assertTrue(assign_notif)
|
||||
self.assertMessageFields(
|
||||
assign_notif,
|
||||
{'author_id': self.partner_employee,
|
||||
'email_from': formataddr((self.partner_employee.name, self.partner_employee.email_normalized)),
|
||||
'model': test_record._name,
|
||||
'notified_partner_ids': self.partner_employee_2,
|
||||
'res_id': test_record.id,
|
||||
'subtype_id': self.env.ref('mail.mt_note'),
|
||||
}
|
||||
)
|
||||
self.assertIn('Dear %s' % self.partner_employee_2.name, assign_notif.body)
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail')
|
||||
def test_notify_from_user_id_batch(self):
|
||||
""" Test notify coming from user_id assignment. """
|
||||
""" Test notify coming from user_id assignment (in batch) """
|
||||
test_records, _ = self._create_records_for_batch(
|
||||
'mail.test.track', 10, {
|
||||
'company_id': self.env.user.company_id.id,
|
||||
@@ -682,7 +706,7 @@ class TestMessageLog(TestMessagePostCommon):
|
||||
'is_internal': True,
|
||||
'model': test_record._name,
|
||||
'notified_partner_ids': self.env['res.partner'],
|
||||
'reply_to': formataddr((self.company_admin.name, '%s@%s' % (self.alias_catchall, self.alias_domain))),
|
||||
'reply_to': formataddr((self.company_admin.name, f'{self.alias_catchall}@{self.alias_domain}')),
|
||||
'res_id': test_record.id,
|
||||
},
|
||||
'notif': [],
|
||||
@@ -718,7 +742,7 @@ class TestMessagePost(TestMessagePostCommon, CronMixinCase):
|
||||
'message_type': 'comment',
|
||||
'model': test_record._name,
|
||||
'notified_partner_ids': self.partner_employee_2,
|
||||
'reply_to': formataddr(("%s %s" % (self.company_admin.name, test_record.name), '%s@%s' % (self.alias_catchall, self.alias_domain))),
|
||||
'reply_to': formataddr((f'{self.company_admin.name} {test_record.name}', f'{self.alias_catchall}@{self.alias_domain}')),
|
||||
'res_id': test_record.id,
|
||||
'subtype_id': self.env.ref('mail.mt_comment'),
|
||||
},
|
||||
@@ -739,6 +763,11 @@ class TestMessagePost(TestMessagePostCommon, CronMixinCase):
|
||||
{'partner': self.partner_1, 'type': 'email'}],
|
||||
message_info={
|
||||
'content': 'NewBody',
|
||||
'email_values': {
|
||||
'headers': {
|
||||
'Return-Path': f'{self.alias_bounce}@{self.alias_domain}',
|
||||
},
|
||||
},
|
||||
'message_values': {
|
||||
'notified_partner_ids': self.partner_1 + self.partner_employee_2,
|
||||
},
|
||||
@@ -916,6 +945,57 @@ class TestMessagePost(TestMessagePostCommon, CronMixinCase):
|
||||
# notifications emails should not have been deleted: one for customers, one for user
|
||||
self.assertEqual(self.env['mail.mail'].sudo().search_count([('mail_message_id', '=', msg.id)]), 2)
|
||||
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
|
||||
@users('erp_manager')
|
||||
def test_message_post_mc(self):
|
||||
""" Test posting in multi-company environment, notably with aliases """
|
||||
records = self.env['mail.test.ticket.mc'].create([
|
||||
{
|
||||
'name': 'No Specific Company',
|
||||
}, {
|
||||
'company_id': self.company_admin.id,
|
||||
'name': 'Company1',
|
||||
}, {
|
||||
'company_id': self.company_2.id,
|
||||
'name': 'Company2',
|
||||
},
|
||||
])
|
||||
expected_companies = [self.company_2, self.company_admin, self.company_2]
|
||||
for record, expected_company in zip(records, expected_companies):
|
||||
with self.subTest(record=record):
|
||||
with self.assertSinglePostNotifications(
|
||||
[{'partner': self.partner_employee_2, 'type': 'email'}],
|
||||
message_info={
|
||||
'content': 'Body',
|
||||
'email_values': {
|
||||
'headers': {
|
||||
'Return-Path': f'{self.alias_bounce}@{self.alias_domain}',
|
||||
},
|
||||
},
|
||||
'mail_mail_values': {
|
||||
'headers': repr({
|
||||
'X-Odoo-Objects': f'{record._name}-{record.id}',
|
||||
}),
|
||||
},
|
||||
'message_values': {
|
||||
'author_id': self.user_erp_manager.partner_id,
|
||||
'email_from': formataddr((self.user_erp_manager.name, self.user_erp_manager.email_normalized)),
|
||||
'is_internal': False,
|
||||
'notified_partner_ids': self.partner_employee_2,
|
||||
'reply_to': formataddr(
|
||||
(f'{expected_company.name} {record.name}', f'{self.alias_catchall}@{self.alias_domain}')
|
||||
),
|
||||
},
|
||||
}
|
||||
):
|
||||
_new_message = record.message_post(
|
||||
body='Body',
|
||||
message_type='comment',
|
||||
subtype_xmlid='mail.mt_comment',
|
||||
partner_ids=[self.partner_employee_2.id],
|
||||
)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.tests')
|
||||
def test_message_post_recipients_email_field(self):
|
||||
""" Test various combinations of corner case / not standard filling of
|
||||
@@ -1278,7 +1358,7 @@ class TestMessagePost(TestMessagePostCommon, CronMixinCase):
|
||||
[self.partner_1],
|
||||
references_content='openerp-%d-mail.test.simple' % self.test_record.id,
|
||||
# references should be sorted from the oldest to the newest
|
||||
references='%s %s' % (parent_msg.message_id, msg.message_id),
|
||||
references=f'{parent_msg.message_id} {msg.message_id}',
|
||||
)
|
||||
|
||||
# post a reply to the reply: check parent is the first one
|
||||
@@ -1299,7 +1379,7 @@ class TestMessagePost(TestMessagePostCommon, CronMixinCase):
|
||||
reply_to=msg.reply_to,
|
||||
subject=self.test_record.name,
|
||||
references_content='openerp-%d-mail.test.simple' % self.test_record.id,
|
||||
references='%s %s' % (parent_msg.message_id, new_msg.message_id),
|
||||
references=f'{parent_msg.message_id} {new_msg.message_id}',
|
||||
)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.addons.mail.models.mail_thread')
|
||||
@@ -1323,7 +1403,7 @@ class TestMessagePost(TestMessagePostCommon, CronMixinCase):
|
||||
self.format_and_process(
|
||||
MAIL_TEMPLATE_PLAINTEXT, self.user_admin.email, 'not_my_businesss@example.com',
|
||||
msg_id='<1198923581.41972151344608186800.JavaMail.diff1@agrolait.example.com>',
|
||||
extra='In-Reply-To:\r\n\t%s\n' % msg.message_id,
|
||||
extra=f'In-Reply-To:\r\n\t{msg.message_id}\n',
|
||||
target_model='mail.test.simple')
|
||||
reply = test_record.message_ids - msg
|
||||
self.assertTrue(reply)
|
||||
|
||||
@@ -18,7 +18,7 @@ class BaseMailPerformance(MailCommon, TransactionCaseWithUserDemo):
|
||||
def setUpClass(cls):
|
||||
super(BaseMailPerformance, cls).setUpClass()
|
||||
|
||||
# creating partners is required notably witn template usage
|
||||
# creating partners is required notably with template usage
|
||||
cls.user_employee.write({'groups_id': [(4, cls.env.ref('base.group_partner_manager').id)]})
|
||||
cls.user_test = cls.user_test_inbox = cls.env['res.users'].with_context(cls._test_context).create({
|
||||
'name': 'Paulette Testouille',
|
||||
|
||||
Reference in New Issue
Block a user