From 69ccabb212d83bfee60c7dade36ca4b06f9f2f12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 24 Oct 2019 09:05:16 +0000 Subject: [PATCH] [FIX] mail: restrict access to mail.mail model From now on mail.mail is considered as a technical model. Indeed people should not really manually craft mails by hand. Instead various functional flows should either send mails, either craft mails based on some user input. We therefore make mail restricted to admin users. Flows creating mail.mail are updated to use sudo, and ensure it was done in a context that makes sense to delegate this power to the user. Task ID 1853147 PR #32243 --- addons/calendar/models/calendar.py | 2 +- addons/calendar/tests/test_calendar.py | 2 +- addons/event/tests/test_mail_schedule.py | 4 ++-- addons/hr_expense/models/hr_expense.py | 3 ++- addons/im_livechat/controllers/main.py | 4 +++- addons/im_livechat/models/mail_channel.py | 2 +- addons/l10n_it_edi/models/account_invoice.py | 2 +- addons/mail/models/mail_channel.py | 4 ++-- addons/mail/models/mail_message.py | 2 +- addons/mail/models/mail_template.py | 12 ++++++++++-- addons/mail/models/mail_thread.py | 2 +- addons/mail/security/ir.model.access.csv | 3 +-- addons/mail/wizard/mail_compose_message.py | 11 +++++++---- addons/mass_mailing/models/mail_mail.py | 3 +-- .../tests/test_mass_mailing_shortener.py | 2 +- addons/mass_mailing/wizard/mailing_mailing_test.py | 8 ++++---- addons/survey/tests/test_certification_flow.py | 2 +- addons/test_mail/tests/test_ir_actions.py | 2 +- addons/test_mail/tests/test_mail_mail.py | 7 +++---- addons/test_mail/tests/test_mail_template.py | 2 +- addons/test_mail/tests/test_message_composer.py | 2 +- addons/test_mail/tests/test_message_post.py | 4 ++-- addons/test_mail/tests/test_performance.py | 4 ++-- 23 files changed, 50 insertions(+), 39 deletions(-) diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index b3b9124c677..98f25ab908a 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -213,7 +213,7 @@ class Attendee(models.Model): mail_ids.append(invitation_template.send_mail(attendee.id, email_values=email_values, notif_layout='mail.mail_notification_light')) if force_send and mail_ids: - res = self.env['mail.mail'].browse(mail_ids).send() + res = self.env['mail.mail'].sudo().browse(mail_ids).send() return res diff --git a/addons/calendar/tests/test_calendar.py b/addons/calendar/tests/test_calendar.py index 0624281ed0c..8ac53b7889d 100644 --- a/addons/calendar/tests/test_calendar.py +++ b/addons/calendar/tests/test_calendar.py @@ -398,7 +398,7 @@ class TestCalendar(SavepointCaseWithUserDemo): def _test_one_mail_per_attendee(self, m, partners): # check that every attendee receive a (single) mail for the event for partner in partners: - mail = self.env['mail.mail'].search([ + mail = self.env['mail.mail'].sudo().search([ ('recipient_ids', 'in', partner.id), ('subject', 'like', m.name), ]) diff --git a/addons/event/tests/test_mail_schedule.py b/addons/event/tests/test_mail_schedule.py index 7dcc446dc9c..678342c74fa 100644 --- a/addons/event/tests/test_mail_schedule.py +++ b/addons/event/tests/test_mail_schedule.py @@ -56,7 +56,7 @@ class TestMailSchedule(TestEventCommon): # verify that subscription scheduler was auto-executed after each registration self.assertEqual(len(schedulers[0].mail_registration_ids), 2, 'event: incorrect number of mail scheduled date') - mails = self.env['mail.mail'].search([('subject', 'ilike', 'registration'), ('date', '>=', now)], order='date DESC', limit=3) + mails = self.env['mail.mail'].sudo().search([('subject', 'ilike', 'registration'), ('date', '>=', now)], order='date DESC', limit=3) self.assertEqual(len(mails), 2, 'event: wrong number of registration mail sent') for registration in schedulers[0].mail_registration_ids: @@ -73,5 +73,5 @@ class TestMailSchedule(TestEventCommon): self.assertTrue(schedulers[0].mail_sent, 'event: reminder scheduler should have sent an email') self.assertTrue(schedulers[0].done, 'event: reminder scheduler should be done') - mails = self.env['mail.mail'].search([('subject', 'ilike', 'TestEventMail'), ('date', '>=', now)], order='date DESC', limit=3) + mails = self.env['mail.mail'].sudo().search([('subject', 'ilike', 'TestEventMail'), ('date', '>=', now)], order='date DESC', limit=3) self.assertEqual(len(mails), 3, 'event: wrong number of reminders in outgoing mail queue') diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py index 259cb7e0167..5d505bbc4cc 100644 --- a/addons/hr_expense/models/hr_expense.py +++ b/addons/hr_expense/models/hr_expense.py @@ -607,6 +607,7 @@ class HrExpense(models.Model): expense_template = self.env.ref(mail_template_id) rendered_body = expense_template.render({'expense': expense}, engine='ir.qweb') body = self.env['mail.thread']._replace_local_links(rendered_body) + # TDE TODO: seems louche, check to use notify if expense.employee_id.user_id.partner_id: expense.message_post( partner_ids=expense.employee_id.user_id.partner_id.ids, @@ -616,7 +617,7 @@ class HrExpense(models.Model): email_layout_xmlid='mail.mail_notification_light', ) else: - self.env['mail.mail'].create({ + self.env['mail.mail'].sudo().create({ 'email_from': self.env.user.email_formatted, 'author_id': self.env.user.partner_id.id, 'body_html': body, diff --git a/addons/im_livechat/controllers/main.py b/addons/im_livechat/controllers/main.py index a4b5c7f8f9d..84f8a83ac47 100644 --- a/addons/im_livechat/controllers/main.py +++ b/addons/im_livechat/controllers/main.py @@ -152,6 +152,8 @@ class LivechatController(http.Controller): @http.route('/im_livechat/email_livechat_transcript', type='json', auth='public', cors="*") def email_livechat_transcript(self, uuid, email): - channel = request.env['mail.channel'].sudo().search([('uuid', '=', uuid)], limit=1) + channel = request.env['mail.channel'].sudo().search([ + ('channel_type', '=', 'livechat'), + ('uuid', '=', uuid)], limit=1) if channel: channel._email_livechat_transcript(email) diff --git a/addons/im_livechat/models/mail_channel.py b/addons/im_livechat/models/mail_channel.py index b5397e38bdf..f7276374e13 100644 --- a/addons/im_livechat/models/mail_channel.py +++ b/addons/im_livechat/models/mail_channel.py @@ -171,7 +171,7 @@ class MailChannel(models.Model): template = self.env.ref('im_livechat.livechat_email_template') mail_body = template.render(render_context, engine='ir.qweb', minimal_qcontext=True) mail_body = self.env['mail.thread']._replace_local_links(mail_body) - mail = self.env['mail.mail'].create({ + mail = self.env['mail.mail'].sudo().create({ 'subject': _('Conversation with %s') % self.livechat_operator_id.name, 'email_from': company.catchall_formatted or company.email_formatted, 'author_id': self.env.user.partner_id.id, diff --git a/addons/l10n_it_edi/models/account_invoice.py b/addons/l10n_it_edi/models/account_invoice.py index bb480d53cb0..6a202f0be09 100644 --- a/addons/l10n_it_edi/models/account_invoice.py +++ b/addons/l10n_it_edi/models/account_invoice.py @@ -278,7 +278,7 @@ class AccountMove(models.Model): 'attachment_ids': [(6, 0, self.l10n_it_einvoice_id.ids)], }) - mail_fattura = self.env['mail.mail'].with_context(wo_return_path=True).create({ + mail_fattura = self.env['mail.mail'].sudo().with_context(wo_return_path=True).create({ 'mail_message_id': message.id, 'email_to': self.env.company.l10n_it_address_recipient_fatturapa, }) diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py index ad1a1ef42b4..2d3c54a9591 100644 --- a/addons/mail/models/mail_channel.py +++ b/addons/mail/models/mail_channel.py @@ -367,7 +367,7 @@ class Channel(models.Model): # Notifies the message author when his message is pending moderation if required on channel. # The fields "email_from" and "reply_to" are filled in automatically by method create in model mail.message. if self.moderation_notify and self.moderation_notify_msg and message_type == 'email' and moderation_status == 'pending_moderation': - self.env['mail.mail'].create({ + self.env['mail.mail'].sudo().create({ 'author_id': self.env.user.partner_id.id, 'email_from': self.env.user.company_id.catchall_formatted or self.env.user.company_id.email_formatted, 'body_html': self.moderation_notify_msg, @@ -426,7 +426,7 @@ class Channel(models.Model): 'subject': _("Guidelines of channel %s") % self.name, 'recipient_ids': [(4, partner.id)] } - mail = self.env['mail.mail'].create(create_values) + mail = self.env['mail.mail'].sudo().create(create_values) return True def _update_moderation_email(self, emails, status): diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py index 5be02450f87..0a038e381eb 100644 --- a/addons/mail/models/mail_message.py +++ b/addons/mail/models/mail_message.py @@ -134,7 +134,7 @@ class Message(models.Model): # By setting up the inverse one2many, we avoid to have to do a search to find the mails linked to the `mail.message` # as the cache value for this inverse one2many is up-to-date. # Besides for new messages, and messages never sending emails, there was no mail, and it was searching for nothing. - mail_ids = fields.One2many('mail.mail', 'mail_message_id', string='Mails') + mail_ids = fields.One2many('mail.mail', 'mail_message_id', string='Mails', groups="base.group_system") canned_response_ids = fields.One2many('mail.shortcode', 'message_ids', string="Canned Responses", store=False) def _get_needaction(self): diff --git a/addons/mail/models/mail_template.py b/addons/mail/models/mail_template.py index 2a0261623a2..ff161dc07a1 100644 --- a/addons/mail/models/mail_template.py +++ b/addons/mail/models/mail_template.py @@ -405,6 +405,11 @@ class MailTemplate(models.Model): # EMAIL # ---------------------------------------- + def _send_check_access(self, res_ids): + records = self.env[self.model].browse(res_ids) + records.check_access_rights('read') + records.check_access_rule('read') + def send_mail(self, res_id, force_send=False, raise_exception=False, email_values=None, notif_layout=False): """ Generates a new mail.mail. Template is rendered on record given by res_id and model coming from template. @@ -417,8 +422,11 @@ class MailTemplate(models.Model): :param str notif_layout: optional notification layout to encapsulate the generated email; :returns: id of the mail.mail that was created """ + + # Grant access to send_mail only if access to related document self.ensure_one() - Mail = self.env['mail.mail'] + self._send_check_access([res_id]) + Attachment = self.env['ir.attachment'] # TDE FIXME: should remove default_type from context # create a mail_mail based on values, without attachments @@ -447,7 +455,7 @@ class MailTemplate(models.Model): } body = template.render(template_ctx, engine='ir.qweb', minimal_qcontext=True) values['body_html'] = self.env['mail.thread']._replace_local_links(body) - mail = Mail.create(values) + mail = self.env['mail.mail'].sudo().create(values) # manage attachments for attachment in attachments: diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index d0abc8adab7..f3f703666b3 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -697,7 +697,7 @@ class MailThread(models.AbstractModel): else: bounce_mail_values['email_from'] = tools.decode_message_header(message, 'To') bounce_mail_values.update(mail_values) - self.env['mail.mail'].create(bounce_mail_values).send() + self.env['mail.mail'].sudo().create(bounce_mail_values).send() @api.model def _routing_handle_bounce(self, email_message, message_dict): diff --git a/addons/mail/security/ir.model.access.csv b/addons/mail/security/ir.model.access.csv index 42656580435..eb52637ff2e 100644 --- a/addons/mail/security/ir.model.access.csv +++ b/addons/mail/security/ir.model.access.csv @@ -4,7 +4,7 @@ access_mail_message_portal,mail.message.portal,model_mail_message,base.group_por access_mail_message_user,mail.message.user,model_mail_message,base.group_user,1,1,1,1 access_mail_mail_all,mail.mail.all,model_mail_mail,,0,0,0,0 access_mail_mail_portal,mail.mail.portal,model_mail_mail,base.group_portal,0,0,0,0 -access_mail_mail_user,mail.mail.user,model_mail_mail,base.group_user,1,1,1,0 +access_mail_mail_user,mail.mail.user,model_mail_mail,base.group_user,0,0,0,0 access_mail_mail_system,mail.mail.system,model_mail_mail,base.group_system,1,1,1,1 access_mail_followers_all,mail.followers.all,model_mail_followers,,1,0,0,0 access_mail_followers_portal,mail.followers.portal,model_mail_followers,base.group_portal,1,1,1,0 @@ -28,7 +28,6 @@ access_mail_tracking_value_all,mail.tracking.value.all,model_mail_tracking_value access_mail_tracking_value_portal,mail.tracking.value.portal,model_mail_tracking_value,base.group_portal,0,0,0,0 access_mail_tracking_value_user,mail.tracking.value.user,model_mail_tracking_value,base.group_user,0,0,0,0 access_mail_tracking_value_system,mail.tracking.value.system,model_mail_tracking_value,base.group_system,1,1,1,1 -access_mail_thread_all,mail.thread.all,model_mail_thread,,1,1,1,1 access_publisher_warranty_contract_all,publisher.warranty.contract.all,model_publisher_warranty_contract,,1,1,1,1 access_mail_template,mail.template,model_mail_template,base.group_user,1,1,1,0 access_mail_template_system,mail.template_system,model_mail_template,base.group_system,1,1,1,1 diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index d3b0e6f16bf..fe4660e451b 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -208,7 +208,6 @@ class MailComposer(models.TransientModel): # Mass Mailing mass_mode = wizard.composition_mode in ('mass_mail', 'mass_post') - Mail = self.env['mail.mail'] ActiveModel = self.env[wizard.model] if wizard.model and hasattr(self.env[wizard.model], 'message_post') else self.env['mail.thread'] if wizard.composition_mode == 'mass_post': # do not send emails directly but use the queue instead @@ -233,11 +232,15 @@ class MailComposer(models.TransientModel): subtype_id = self.env['ir.model.data'].xmlid_to_res_id('mail.mt_comment') for res_ids in sliced_res_ids: - batch_mails = Mail + # mass mail mode: mail are sudo-ed, as when going through get_mail_values + # standard access rights on related records will be checked when browsing them + # to compute mail values. If people have access to the records they have rights + # to create lots of emails in sudo as it is consdiered as a technical model. + batch_mails_sudo = self.env['mail.mail'].sudo() all_mail_values = wizard.get_mail_values(res_ids) for res_id, mail_values in all_mail_values.items(): if wizard.composition_mode == 'mass_mail': - batch_mails |= Mail.create(mail_values) + batch_mails_sudo |= self.env['mail.mail'].sudo().create(mail_values) else: post_params = dict( message_type=wizard.message_type, @@ -258,7 +261,7 @@ class MailComposer(models.TransientModel): ActiveModel.browse(res_id).message_post(**post_params) if wizard.composition_mode == 'mass_mail': - batch_mails.send(auto_commit=auto_commit) + batch_mails_sudo.send(auto_commit=auto_commit) def get_mail_values(self, res_ids): """Generate the values that will be used by send_mail to create mail_messages diff --git a/addons/mass_mailing/models/mail_mail.py b/addons/mass_mailing/models/mail_mail.py index a0f810c5c7b..749c6dc6133 100644 --- a/addons/mass_mailing/models/mail_mail.py +++ b/addons/mass_mailing/models/mail_mail.py @@ -23,8 +23,7 @@ class MailMail(models.Model): mails = super(MailMail, self).create(values_list) for mail, values in zip(mails, values_list): if values.get('mailing_trace_ids'): - mail_sudo = mail.sudo() - mail_sudo.mailing_trace_ids.write({'message_id': mail_sudo.message_id, 'state': 'outgoing'}) + mail.mailing_trace_ids.write({'message_id': mail.message_id, 'state': 'outgoing'}) return mails def _get_tracking_url(self): diff --git a/addons/mass_mailing/tests/test_mass_mailing_shortener.py b/addons/mass_mailing/tests/test_mass_mailing_shortener.py index 8bd247691ea..681bbbf0062 100644 --- a/addons/mass_mailing/tests/test_mass_mailing_shortener.py +++ b/addons/mass_mailing/tests/test_mass_mailing_shortener.py @@ -68,7 +68,7 @@ Email: test@odoo.com mass_mailing.action_put_in_queue() mass_mailing._process_mass_mailing_queue() - sent_mails = self.env['mail.mail'].search([('mailing_id', '=', mass_mailing.id)]) + sent_mails = self.env['mail.mail'].sudo().search([('mailing_id', '=', mass_mailing.id)]) sent_messages = sent_mails.mapped('mail_message_id') self.assertEqual(len(mailing_list_A.contact_ids), len(sent_messages), diff --git a/addons/mass_mailing/wizard/mailing_mailing_test.py b/addons/mass_mailing/wizard/mailing_mailing_test.py index 5aa09a71999..5a107a8a132 100644 --- a/addons/mass_mailing/wizard/mailing_mailing_test.py +++ b/addons/mass_mailing/wizard/mailing_mailing_test.py @@ -14,7 +14,7 @@ class TestMassMailing(models.TransientModel): def send_mail_test(self): self.ensure_one() - mails = self.env['mail.mail'] + mails_sudo = self.env['mail.mail'].sudo() mailing = self.mass_mailing_id test_emails = tools.email_split(self.email_to) mass_mail_layout = self.env.ref('mass_mailing.mass_mailing_mail_layout') @@ -33,7 +33,7 @@ class TestMassMailing(models.TransientModel): 'attachment_ids': [(4, attachment.id) for attachment in mailing.attachment_ids], 'auto_delete': True, } - mail = self.env['mail.mail'].create(mail_values) - mails |= mail - mails.send() + mail = self.env['mail.mail'].sudo().create(mail_values) + mails_sudo |= mail + mails_sudo.send() return True diff --git a/addons/survey/tests/test_certification_flow.py b/addons/survey/tests/test_certification_flow.py index f9a9010b68e..4625fff5d5e 100644 --- a/addons/survey/tests/test_certification_flow.py +++ b/addons/survey/tests/test_certification_flow.py @@ -133,7 +133,7 @@ class TestCertificationFlow(common.TestSurveyCommon, HttpCase): self.assertNotIn("I think they're great!", user_inputs.mapped('user_input_line_ids.value_free_text')) self.assertIn("Just kidding, I don't like it...", user_inputs.mapped('user_input_line_ids.value_free_text')) - certification_email = self.env['mail.mail'].search([], limit=1, order="create_date desc") + certification_email = self.env['mail.mail'].sudo().search([], limit=1, order="create_date desc") # Check certification email correctly sent and contains document self.assertIn("User Certification for SO lines", certification_email.subject) self.assertIn("employee@example.com", certification_email.email_to) diff --git a/addons/test_mail/tests/test_ir_actions.py b/addons/test_mail/tests/test_ir_actions.py index 6a547081a15..d67124b2153 100644 --- a/addons/test_mail/tests/test_ir_actions.py +++ b/addons/test_mail/tests/test_ir_actions.py @@ -12,7 +12,7 @@ class TestServerActionsEmail(TestMailCommon, TestServerActionsBase): self.action.write({'state': 'email', 'template_id': email_template.id}) self.action.with_context(self.context).run() # check an email is waiting for sending - mail = self.env['mail.mail'].search([('subject', '=', 'About TestingPartner')]) + mail = self.env['mail.mail'].sudo().search([('subject', '=', 'About TestingPartner')]) self.assertEqual(len(mail), 1) # check email content self.assertEqual(mail.body, '

Hello TestingPartner

') diff --git a/addons/test_mail/tests/test_mail_mail.py b/addons/test_mail/tests/test_mail_mail.py index 7fb29598e6f..7e6b0f98ba2 100644 --- a/addons/test_mail/tests/test_mail_mail.py +++ b/addons/test_mail/tests/test_mail_mail.py @@ -15,8 +15,7 @@ class TestMailMail(TestMailCommon): @mute_logger('odoo.addons.mail.models.mail_mail') def test_mail_message_notify_from_mail_mail(self): # Due ot post-commit hooks, store send emails in every step - # self.email_to_list = [] - mail = self.env['mail.mail'].create({ + mail = self.env['mail.mail'].sudo().create({ 'body_html': '

Test

', 'email_to': 'test@example.com', 'partner_ids': [(4, self.user_employee.partner_id.id)] @@ -28,7 +27,7 @@ class TestMailMail(TestMailCommon): @mute_logger('odoo.addons.mail.models.mail_mail') def test_mail_message_values_unicode(self): - mail = self.env['mail.mail'].create({ + mail = self.env['mail.mail'].sudo().create({ 'body_html': '

Test

', 'email_to': 'test.😊@example.com', 'partner_ids': [(4, self.user_employee.partner_id.id)] @@ -45,7 +44,7 @@ class TestMailMailRace(common.TransactionCase): 'name': 'Ernest Partner', }) # we need to simulate a mail sent by the cron task, first create mail, message and notification by hand - mail = self.env['mail.mail'].create({ + mail = self.env['mail.mail'].sudo().create({ 'body_html': '

Test

', 'notification': True, 'state': 'outgoing', diff --git a/addons/test_mail/tests/test_mail_template.py b/addons/test_mail/tests/test_mail_template.py index a6634ac34f8..a845ffc0a79 100644 --- a/addons/test_mail/tests/test_mail_template.py +++ b/addons/test_mail/tests/test_mail_template.py @@ -48,7 +48,7 @@ class TestMailTemplate(TestMailCommon, TestRecipients): @mute_logger('odoo.addons.mail.models.mail_mail') def test_template_send_email(self): mail_id = self.email_template.send_mail(self.test_record.id) - mail = self.env['mail.mail'].browse(mail_id) + mail = self.env['mail.mail'].sudo().browse(mail_id) self.assertEqual(mail.subject, 'About %s' % self.test_record.name) self.assertEqual(mail.email_to, self.email_template.email_to) self.assertEqual(mail.email_cc, self.email_template.email_cc) diff --git a/addons/test_mail/tests/test_message_composer.py b/addons/test_mail/tests/test_message_composer.py index 563f4390d9f..e94b5a533c3 100644 --- a/addons/test_mail/tests/test_message_composer.py +++ b/addons/test_mail/tests/test_message_composer.py @@ -72,7 +72,7 @@ class TestComposer(TestMailCommon, TestRecipients): }).send_mail() # check mail_mail - mails = self.env['mail.mail'].search([('subject', 'ilike', 'Testing')]) + mails = self.env['mail.mail'].sudo().search([('subject', 'ilike', 'Testing')]) for mail in mails: self.assertEqual(mail.recipient_ids, self.partner_1 | self.partner_2, 'compose wizard: mail_mail mass mailing: mail.mail in mass mail incorrect recipients') diff --git a/addons/test_mail/tests/test_message_post.py b/addons/test_mail/tests/test_message_post.py index 14a8e9e3628..bf894fafe12 100644 --- a/addons/test_mail/tests/test_message_post.py +++ b/addons/test_mail/tests/test_message_post.py @@ -86,7 +86,7 @@ class TestMessagePost(TestMailCommon, TestRecipients): self.assertEqual(msg.channel_ids, self.env['mail.channel']) # notifications emails should have been deleted - self.assertFalse(self.env['mail.mail'].search([('mail_message_id', '=', msg.id)]), + self.assertFalse(self.env['mail.mail'].sudo().search([('mail_message_id', '=', msg.id)]), 'message_post: mail.mail notifications should have been auto-deleted') @mute_logger('odoo.addons.mail.models.mail_mail') @@ -101,7 +101,7 @@ class TestMessagePost(TestMailCommon, TestRecipients): ) # notifications emails should not have been deleted: one for customers, one for user - self.assertEqual(len(self.env['mail.mail'].search([('mail_message_id', '=', msg.id)])), 2) + self.assertEqual(len(self.env['mail.mail'].sudo().search([('mail_message_id', '=', msg.id)])), 2) @mute_logger('odoo.addons.mail.models.mail_mail') def test_post_notifications_emails_tweak(self): diff --git a/addons/test_mail/tests/test_performance.py b/addons/test_mail/tests/test_performance.py index 00676a580d3..b7948c23a4b 100644 --- a/addons/test_mail/tests/test_performance.py +++ b/addons/test_mail/tests/test_performance.py @@ -459,8 +459,8 @@ class TestMailComplexPerformance(BaseMailPerformance): 'recipient_ids': [(4, pid) for pid in self.partners.ids], }) mail_ids = mail.ids - with self.assertQueryCount(__system__=8, emp=9): - self.env['mail.mail'].browse(mail_ids).send() + with self.assertQueryCount(__system__=8, emp=8): + self.env['mail.mail'].sudo().browse(mail_ids).send() self.assertEqual(mail.body_html, '

Test

') self.assertEqual(mail.reply_to, formataddr(('%s %s' % (self.env.company.name, self.umbrella.name), 'test-alias@example.com')))