[FIX] mail: notify alias owner when fetching
[1] introduces an issue when a response is sent to an aliased email.
In that case, it is intended that the message should be created
by the owner of the alias by [2]
Which breaks the assumption of made in the first commit, as the message
is being passively processed by fetchmail.
This causes the owner of the alias to never be notified on reponses
in cases where the message could be an alias update.
i.e. on any model where the alias applies.
Because the responses are assumed to have been authored by the owner.
As we do not actually care who creates the message records
and deciding the alias owner 'created the message' does not
actually make sense.
We make sure messages are created by odoobot even
if the message was sent to an alias address.
[1]: c676ed3ea906e99d27a6116cd77218c5ec95b416
[2]: af80c68ae5
task-3383275
X-original-commit: 96fe37d37c94c3d6f4642bd6c28d13fcd87075b7
Part-of: odoo/odoo#130798
This commit is contained in:
committed by
Thibault Delavallée
parent
9da5f6e0f6
commit
4dd17a201b
@@ -1143,6 +1143,9 @@ class MailThread(models.AbstractModel):
|
||||
thread_id = thread.id
|
||||
subtype_id = thread._creation_subtype().id
|
||||
|
||||
# switch to odoobot for all incoming message creation
|
||||
# to have a priviledged archived user so real_author_id is correctly computed
|
||||
thread_root = thread.with_user(self.env.ref('base.user_root'))
|
||||
# replies to internal message are considered as notes, but parent message
|
||||
# author is added in recipients to ensure they are notified of a private answer
|
||||
parent_message = False
|
||||
@@ -1162,13 +1165,13 @@ class MailThread(models.AbstractModel):
|
||||
for x in ('from', 'to', 'cc', 'recipients', 'references', 'in_reply_to', 'is_bounce', 'bounced_email', 'bounced_message', 'bounced_msg_ids', 'bounced_partner'):
|
||||
post_params.pop(x, None)
|
||||
new_msg = False
|
||||
if thread._name == 'mail.thread': # message with parent_id not linked to record
|
||||
new_msg = thread.message_notify(**post_params)
|
||||
if thread_root._name == 'mail.thread': # message with parent_id not linked to record
|
||||
new_msg = thread_root.message_notify(**post_params)
|
||||
else:
|
||||
# parsing should find an author independently of user running mail gateway, and ensure it is not odoobot
|
||||
partner_from_found = message_dict.get('author_id') and message_dict['author_id'] != self.env['ir.model.data']._xmlid_to_res_id('base.partner_root')
|
||||
thread = thread.with_context(mail_create_nosubscribe=not partner_from_found)
|
||||
new_msg = thread.message_post(**post_params)
|
||||
thread_root = thread_root.with_context(mail_create_nosubscribe=not partner_from_found)
|
||||
new_msg = thread_root.message_post(**post_params)
|
||||
|
||||
if new_msg and original_partner_ids:
|
||||
# postponed after message_post, because this is an external message and we don't want to create
|
||||
|
||||
@@ -132,7 +132,7 @@ class MockEmail(common.BaseCase, MockSmtplibCase):
|
||||
def format_and_process(self, template, email_from, to, subject='Frogs', cc='',
|
||||
return_path='', extra='', msg_id=False,
|
||||
model=None, target_model='mail.test.gateway', target_field='name',
|
||||
**kwargs):
|
||||
with_user=None, **kwargs):
|
||||
self.assertFalse(self.env[target_model].search([(target_field, '=', subject)]))
|
||||
if not msg_id:
|
||||
msg_id = "<%.7f-test@iron.sky>" % (time.time())
|
||||
@@ -142,7 +142,7 @@ class MockEmail(common.BaseCase, MockSmtplibCase):
|
||||
email_from=email_from, msg_id=msg_id,
|
||||
**kwargs)
|
||||
# In real use case, fetched mail processing is executed with administrative right.
|
||||
self.env['mail.thread'].sudo().message_process(model, mail)
|
||||
self.env['mail.thread'].with_user(with_user or self.env.user).sudo().message_process(model, mail)
|
||||
return self.env[target_model].search([(target_field, '=', subject)])
|
||||
|
||||
def gateway_reply_wrecord(self, template, record, use_in_reply_to=True):
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import base64
|
||||
import itertools
|
||||
import socket
|
||||
|
||||
from datetime import datetime
|
||||
@@ -354,6 +355,61 @@ 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')
|
||||
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',
|
||||
})
|
||||
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
|
||||
'message_type': 'email',
|
||||
'model': test_record._name,
|
||||
'res_id': test_record.id,
|
||||
})
|
||||
self.env['mail.alias'].create({
|
||||
'alias_model_id': self.env['ir.model']._get_id(test_record._name),
|
||||
'alias_name': 'author-partner',
|
||||
'alias_user_id': self.user_employee.id
|
||||
})
|
||||
|
||||
test_record.message_subscribe((author_partner | self.user_employee.partner_id).ids)
|
||||
|
||||
messages = test_record.message_ids
|
||||
|
||||
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']
|
||||
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():
|
||||
self.format_and_process(
|
||||
MAIL_TEMPLATE, self.email_from, email_to,
|
||||
subject=message.message_id, extra=f'In-Reply-To:\r\n\t{message.message_id}\n',
|
||||
model=None, with_user=test_user)
|
||||
new_messages = test_record.message_ids - messages
|
||||
|
||||
self.assertEqual(len(new_messages), 1)
|
||||
self.assertEqual(new_messages.create_uid, self.user_root,
|
||||
'Odoobot should be creating the message')
|
||||
|
||||
# Make sure the alias owner is notified if they are a follower
|
||||
self.assertNotified(new_messages, [{
|
||||
'partner': self.user_employee.partner_id,
|
||||
'is_read': False,
|
||||
'type': 'inbox',
|
||||
}])
|
||||
# never notify the author of the incoming message
|
||||
with self.assertRaises(Exception):
|
||||
self.assertNotified(new_messages, [{'partner': author_partner}])
|
||||
|
||||
messages = test_record.message_ids
|
||||
|
||||
# --------------------------------------------------
|
||||
# Alias configuration
|
||||
# --------------------------------------------------
|
||||
@@ -626,7 +682,7 @@ class TestMailgateway(MailCommon):
|
||||
record = self.format_and_process(MAIL_TEMPLATE, self.user_employee.email_formatted, f'groups@{self.alias_domain}', subject='NoEmployeeAllowed')
|
||||
self.assertEqual(record.create_uid, self.user_employee)
|
||||
self.assertEqual(record.message_ids[0].subject, 'NoEmployeeAllowed')
|
||||
self.assertEqual(record.message_ids[0].create_uid, self.user_employee)
|
||||
self.assertEqual(record.message_ids[0].create_uid, self.user_root, 'Message should be created by caller of message_process.')
|
||||
self.assertEqual(record.message_ids[0].author_id, self.user_employee.partner_id)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_thread')
|
||||
@@ -634,19 +690,19 @@ class TestMailgateway(MailCommon):
|
||||
record = self.format_and_process(MAIL_TEMPLATE, self.user_employee.email_formatted, f'groups@{self.alias_domain}', subject='Email Found')
|
||||
self.assertEqual(record.create_uid, self.user_employee)
|
||||
self.assertEqual(record.message_ids[0].subject, 'Email Found')
|
||||
self.assertEqual(record.message_ids[0].create_uid, self.user_employee)
|
||||
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')
|
||||
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_employee)
|
||||
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, self.user_employee.email_normalized, f'groups@{self.alias_domain}', subject='Email SimpleEmail')
|
||||
self.assertEqual(record.create_uid, self.user_employee)
|
||||
self.assertEqual(record.message_ids[0].subject, 'Email SimpleEmail')
|
||||
self.assertEqual(record.message_ids[0].create_uid, self.user_employee)
|
||||
self.assertEqual(record.message_ids[0].create_uid, self.user_root)
|
||||
self.assertEqual(record.message_ids[0].author_id, self.user_employee.partner_id)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink')
|
||||
@@ -661,7 +717,7 @@ class TestMailgateway(MailCommon):
|
||||
record = self.format_and_process(MAIL_TEMPLATE, self.user_employee.email_formatted, f'groups@{self.alias_domain}', subject='FollowerWinner')
|
||||
self.assertEqual(record.create_uid, follower_user)
|
||||
self.assertEqual(record.message_ids[0].subject, 'FollowerWinner')
|
||||
self.assertEqual(record.message_ids[0].create_uid, follower_user)
|
||||
self.assertEqual(record.message_ids[0].create_uid, self.user_root)
|
||||
self.assertEqual(record.message_ids[0].author_id, follower_user.partner_id)
|
||||
|
||||
# name order win
|
||||
@@ -670,7 +726,7 @@ class TestMailgateway(MailCommon):
|
||||
record = self.format_and_process(MAIL_TEMPLATE, self.user_employee.email_formatted, f'groups@{self.alias_domain}', subject='FirstFoundWinner')
|
||||
self.assertEqual(record.create_uid, self.user_employee)
|
||||
self.assertEqual(record.message_ids[0].subject, 'FirstFoundWinner')
|
||||
self.assertEqual(record.message_ids[0].create_uid, self.user_employee)
|
||||
self.assertEqual(record.message_ids[0].create_uid, self.user_root)
|
||||
self.assertEqual(record.message_ids[0].author_id, self.user_employee.partner_id)
|
||||
|
||||
# --------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user