[IMP] mail: mail_thread: routing: implement compat-mode routing
It now accepts <111...222..openerp-res_id-model@mydomain.com> partial matching only if the target record has messages without message_id, aka <= 6.1 record. Updated and added tests bzr revid: tde@openerp.com-20131128133226-ce1qyeswi9n83q8v
This commit is contained in:
+23
-14
@@ -723,8 +723,8 @@ class mail_thread(osv.AbstractModel):
|
||||
# Private message: should not contain any thread_id
|
||||
if not model and thread_id:
|
||||
if assert_model:
|
||||
assert thread_id == 0, 'Routing: posting a message without model should be with a null res_id (private message).'
|
||||
_warn('posting a message without model should be with a null res_id (private message), resetting thread_id')
|
||||
assert thread_id == 0, 'Routing: posting a message without model should be with a null res_id (private message), received %s.' % thread_id
|
||||
_warn('posting a message without model should be with a null res_id (private message), received %s, resetting thread_id' % thread_id)
|
||||
thread_id = 0
|
||||
# Private message: should have a parent_id (only answers)
|
||||
if not model and not message_dict.get('parent_id'):
|
||||
@@ -821,6 +821,7 @@ class mail_thread(osv.AbstractModel):
|
||||
:return: list of [model, thread_id, custom_values, user_id, alias]
|
||||
"""
|
||||
assert isinstance(message, Message), 'message must be an email.message.Message at this point'
|
||||
mail_msg_obj = self.pool['mail.message']
|
||||
fallback_model = model
|
||||
|
||||
# Get email.message.Message variables for future processing
|
||||
@@ -834,10 +835,9 @@ class mail_thread(osv.AbstractModel):
|
||||
# 1. message is a reply to an existing message (exact match of message_id)
|
||||
msg_references = thread_references.split()
|
||||
for msg_reference in msg_references:
|
||||
mail_message_ids = self.pool['mail.message'].search(
|
||||
cr, uid, [('message_id', '=', msg_reference)], context=context)
|
||||
mail_message_ids = mail_msg_obj.search(cr, uid, [('message_id', '=', msg_reference)], context=context)
|
||||
if mail_message_ids:
|
||||
original_msg = self.pool['mail.message'].browse(cr, SUPERUSER_ID, mail_message_ids[0], context=context)
|
||||
original_msg = mail_msg_obj.browse(cr, SUPERUSER_ID, mail_message_ids[0], context=context)
|
||||
model, thread_id = original_msg.model, original_msg.res_id
|
||||
_logger.info(
|
||||
'Routing mail from %s to %s with Message-Id %s: direct reply to msg: model: %s, thread_id: %s, custom_values: %s, uid: %s',
|
||||
@@ -848,29 +848,38 @@ class mail_thread(osv.AbstractModel):
|
||||
update_author=True, assert_model=True, create_fallback=True, context=context)
|
||||
return route and [route] or []
|
||||
|
||||
# 1. Verify if this is a reply to an existing thread
|
||||
# 2. message is a reply to an existign thread (6.1 compatibility)
|
||||
ref_match = thread_references and tools.reference_re.search(thread_references)
|
||||
if ref_match:
|
||||
thread_id = int(ref_match.group(1))
|
||||
model = ref_match.group(2) or fallback_model
|
||||
if thread_id and model in self.pool:
|
||||
model_obj = self.pool[model]
|
||||
if model_obj.exists(cr, uid, thread_id) and hasattr(model_obj, 'message_update'):
|
||||
_logger.info('Routing mail from %s to %s with Message-Id %s: direct reply to model: %s, thread_id: %s, custom_values: %s, uid: %s',
|
||||
email_from, email_to, message_id, model, thread_id, custom_values, uid)
|
||||
route = self.message_route_verify(cr, uid, message, message_dict,
|
||||
(model, thread_id, custom_values, uid, None),
|
||||
update_author=True, assert_model=True, create_fallback=True, context=context)
|
||||
compat_mail_msg_ids = mail_msg_obj.search(
|
||||
cr, uid, [
|
||||
('message_id', '=', False),
|
||||
('model', '=', model),
|
||||
('res_id', '=', thread_id),
|
||||
], context=context)
|
||||
print 'cacaprout', compat_mail_msg_ids
|
||||
if compat_mail_msg_ids and model_obj.exists(cr, uid, thread_id) and hasattr(model_obj, 'message_update'):
|
||||
_logger.info(
|
||||
'Routing mail from %s to %s with Message-Id %s: direct thread reply (compat-mode) to model: %s, thread_id: %s, custom_values: %s, uid: %s',
|
||||
email_from, email_to, message_id, model, thread_id, custom_values, uid)
|
||||
route = self.message_route_verify(
|
||||
cr, uid, message, message_dict,
|
||||
(model, thread_id, custom_values, uid, None),
|
||||
update_author=True, assert_model=True, create_fallback=True, context=context)
|
||||
return route and [route] or []
|
||||
|
||||
# 2. Reply to a private message
|
||||
if in_reply_to:
|
||||
mail_message_ids = self.pool.get('mail.message').search(cr, uid, [
|
||||
mail_message_ids = mail_msg_obj.search(cr, uid, [
|
||||
('message_id', '=', in_reply_to),
|
||||
'!', ('message_id', 'ilike', 'reply_to')
|
||||
], limit=1, context=context)
|
||||
if mail_message_ids:
|
||||
mail_message = self.pool.get('mail.message').browse(cr, uid, mail_message_ids[0], context=context)
|
||||
mail_message = mail_msg_obj.browse(cr, uid, mail_message_ids[0], context=context)
|
||||
_logger.info('Routing mail from %s to %s with Message-Id %s: direct reply to a private message: %s, custom_values: %s, uid: %s',
|
||||
email_from, email_to, message_id, mail_message.id, custom_values, uid)
|
||||
route = self.message_route_verify(cr, uid, message, message_dict,
|
||||
|
||||
@@ -163,7 +163,7 @@ class TestMailgateway(TestMail):
|
||||
self.assertIn('<div dir="ltr">Should create a multipart/mixed: from gmail, <b>bold</b>, with attachment.<br clear="all"><div><br></div>', res.get('body', ''),
|
||||
'message_parse: html version should be in body after parsing multipart/mixed')
|
||||
|
||||
@mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm')
|
||||
# @mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm')
|
||||
def test_10_message_process(self):
|
||||
""" Testing incoming emails processing. """
|
||||
cr, uid, user_raoul = self.cr, self.uid, self.user_raoul
|
||||
@@ -378,7 +378,7 @@ class TestMailgateway(TestMail):
|
||||
frog_groups = format_and_process(MAIL_TEMPLATE, email_from='other4@gmail.com',
|
||||
msg_id='<1198923581.41972151344608186760.JavaMail.diff1@agrolait.com>',
|
||||
to='erroneous@example.com>', subject='Re: news',
|
||||
extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id)
|
||||
extra='In-Reply-To: <1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>\n')
|
||||
# Test: no group 'Re: news' created, still only 1 Frogs group
|
||||
self.assertEqual(len(frog_groups), 0,
|
||||
'message_process: reply on Frogs should not have created a new group with new subject')
|
||||
@@ -387,16 +387,41 @@ class TestMailgateway(TestMail):
|
||||
'message_process: reply on Frogs should not have created a duplicate group with old subject')
|
||||
frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
|
||||
# Test: one new message
|
||||
self.assertEqual(len(frog_group.message_ids), 3, 'message_process: group should contain 2 messages after reply')
|
||||
self.assertEqual(len(frog_group.message_ids), 3, 'message_process: group should contain 3 messages after reply')
|
||||
# Test: author (and not recipient) added as follower
|
||||
frog_follower_ids = set([p.id for p in frog_group.message_follower_ids])
|
||||
self.assertEqual(frog_follower_ids, set([p1id, p2id]),
|
||||
'message_process: after reply, group should have 2 followers')
|
||||
|
||||
# Do: incoming email with ref holding model / res_id but that does not match any message in the thread: must raise since OpenERP saas-3
|
||||
self.assertRaises(AssertionError,
|
||||
format_and_process,
|
||||
MAIL_TEMPLATE, email_from='other5@gmail.com',
|
||||
to='noone@example.com', subject='spam',
|
||||
extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>' % frog_group.id,
|
||||
msg_id='<1.1.JavaMail.new@agrolait.com>')
|
||||
# There are 6.1 messages, activate compat mode
|
||||
tmp_msg_id = self.mail_message.create(cr, uid, {'message_id': False, 'model': 'mail.group', 'res_id': frog_group.id})
|
||||
# Do: compat mode accepts partial-matching emails
|
||||
frog_groups = format_and_process(MAIL_TEMPLATE, email_from='other5@gmail.com',
|
||||
msg_id='<1.2.JavaMail.new@agrolait.com>',
|
||||
to='noone@example.com>', subject='spam',
|
||||
extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>' % frog_group.id)
|
||||
self.mail_message.unlink(cr, uid, [tmp_msg_id])
|
||||
# Test: no group 'Re: news' created, still only 1 Frogs group
|
||||
self.assertEqual(len(frog_groups), 0,
|
||||
'message_process: reply on Frogs should not have created a new group with new subject')
|
||||
frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')])
|
||||
self.assertEqual(len(frog_groups), 1,
|
||||
'message_process: reply on Frogs should not have created a duplicate group with old subject')
|
||||
frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
|
||||
# Test: one new message
|
||||
self.assertEqual(len(frog_group.message_ids), 4, 'message_process: group should contain 4 messages after reply')
|
||||
|
||||
# Do: due to some issue, same email goes back into the mailgateway
|
||||
frog_groups = format_and_process(MAIL_TEMPLATE, email_from='other4@gmail.com',
|
||||
msg_id='<1198923581.41972151344608186760.JavaMail.diff1@agrolait.com>',
|
||||
subject='Re: news', extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id)
|
||||
subject='Re: news', extra='In-Reply-To: <1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>\n')
|
||||
# Test: no group 'Re: news' created, still only 1 Frogs group
|
||||
self.assertEqual(len(frog_groups), 0,
|
||||
'message_process: reply on Frogs should not have created a new group with new subject')
|
||||
@@ -405,7 +430,7 @@ class TestMailgateway(TestMail):
|
||||
'message_process: reply on Frogs should not have created a duplicate group with old subject')
|
||||
frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
|
||||
# Test: no new message
|
||||
self.assertEqual(len(frog_group.message_ids), 3, 'message_process: message with already existing message_id should not have been duplicated')
|
||||
self.assertEqual(len(frog_group.message_ids), 4, 'message_process: message with already existing message_id should not have been duplicated')
|
||||
# Test: message_id is still unique
|
||||
msg_ids = self.mail_message.search(cr, uid, [('message_id', 'ilike', '<1198923581.41972151344608186760.JavaMail.diff1@agrolait.com>')])
|
||||
self.assertEqual(len(msg_ids), 1,
|
||||
@@ -422,7 +447,7 @@ class TestMailgateway(TestMail):
|
||||
format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>',
|
||||
to='erroneous@example.com>', subject='Re: news (2)',
|
||||
msg_id='<1198923581.41972151344608186760.JavaMail.new1@agrolait.com>',
|
||||
extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id)
|
||||
extra='In-Reply-To: <1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>')
|
||||
frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')])
|
||||
frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
|
||||
# Test: author is A-Raoul (only existing)
|
||||
@@ -436,7 +461,7 @@ class TestMailgateway(TestMail):
|
||||
format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>',
|
||||
to='erroneous@example.com>', subject='Re: news (3)',
|
||||
msg_id='<1198923581.41972151344608186760.JavaMail.new2@agrolait.com>',
|
||||
extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id)
|
||||
extra='In-Reply-To: <1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>')
|
||||
frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')])
|
||||
frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
|
||||
# Test: author is Raoul (user), not A-Raoul
|
||||
@@ -451,7 +476,7 @@ class TestMailgateway(TestMail):
|
||||
format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>',
|
||||
to='erroneous@example.com>', subject='Re: news (3)',
|
||||
msg_id='<1198923581.41972151344608186760.JavaMail.new3@agrolait.com>',
|
||||
extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id)
|
||||
extra='In-Reply-To: <1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>')
|
||||
frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')])
|
||||
frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
|
||||
# Test: author is Raoul (user), not A-Raoul
|
||||
@@ -498,7 +523,7 @@ class TestMailgateway(TestMail):
|
||||
self.assertIn('<pre>\nPlease call me as soon as possible this afternoon!\n\n--\nSylvie\n</pre>', msg.body,
|
||||
'message_process: plaintext incoming email incorrectly parsed')
|
||||
|
||||
@mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm')
|
||||
# @mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm')
|
||||
def test_20_thread_parent_resolution(self):
|
||||
""" Testing parent/child relationships are correctly established when processing incoming mails """
|
||||
cr, uid = self.cr, self.uid
|
||||
|
||||
Reference in New Issue
Block a user