[IMP] mail: better heuristic to find the author of an incoming email: in document's followers, or partner that is an user, or partner.

bzr revid: tde@openerp.com-20130214140701-y2nrnc163szni202
This commit is contained in:
Thibault Delavallée 2013-02-14 15:07:01 +01:00
parent 6e1ab1dbf0
commit a395638dfa
2 changed files with 40 additions and 9 deletions

View File

@ -415,9 +415,15 @@ class mail_thread(osv.AbstractModel):
def _message_find_partners(self, cr, uid, message, header_fields=['From'], context=None):
""" Find partners related to some header fields of the message. """
partner_obj = self.pool.get('res.partner')
partner_ids = []
s = ', '.join([decode(message.get(h)) for h in header_fields if message.get(h)])
return [partner_id for email in tools.email_split(s)
for partner_id in self.pool.get('res.partner').search(cr, uid, [('email', 'ilike', email)], limit=1, context=context)]
for email_address in tools.email_split(s):
related_partners = partner_obj.search(cr, uid, [('email', 'ilike', email_address), ('user_ids', '!=', False)], limit=1, context=context)
if not related_partners:
related_partners = partner_obj.search(cr, uid, [('email', 'ilike', email_address)], limit=1, context=context)
partner_ids += related_partners
return partner_ids
def _message_find_user_id(self, cr, uid, message, context=None):
from_local_part = tools.email_split(decode(message.get('From')))[0]
@ -611,10 +617,11 @@ class mail_thread(osv.AbstractModel):
assert thread_id == 0, "Posting a message without model should be with a null res_id, to create a private message."
model_pool = self.pool.get('mail.thread')
new_msg_id = model_pool.message_post_user_api(cr, uid, [thread_id], context=context, content_subtype='html', **msg)
new_msg = self.pool.get('mail.message').browse(cr, uid, new_msg_id, context=context)
# when posting an incoming email to a document: subscribe the author, if a partner, as follower
if model and thread_id and msg.get('author_id'):
model_pool.message_subscribe(cr, uid, [thread_id], [msg.get('author_id')], context=context)
if model and thread_id and new_msg.author_id:
model_pool.message_subscribe(cr, uid, [thread_id], [new_msg.author_id.id], context=context)
if partner_ids:
# postponed after message_post, because this is an external message and we don't want to create
@ -771,8 +778,7 @@ class mail_thread(osv.AbstractModel):
author_ids = self._message_find_partners(cr, uid, message, ['From'], context=context)
if author_ids:
msg_dict['author_id'] = author_ids[0]
else:
msg_dict['email_from'] = message.get('from')
msg_dict['email_from'] = message.get('from')
partner_ids = self._message_find_partners(cr, uid, message, ['To', 'Cc'], context=context)
msg_dict['partner_ids'] = [(4, partner_id) for partner_id in partner_ids]
@ -883,8 +889,21 @@ class mail_thread(osv.AbstractModel):
if isinstance(thread_id, (list, tuple)):
thread_id = thread_id and thread_id[0]
mail_message = self.pool.get('mail.message')
partner_obj = self.pool.get('res.partner')
model = context.get('thread_model', self._name) if thread_id else False
# 0: parse email-from, try to find a better author_id based on document's followers
email_from = kwargs.get('email_from')
author_ids = None
if email_from and thread_id:
email_list = tools.email_split(email_from)
if email_list:
doc = self.browse(cr, uid, thread_id, context=context)
doc_fol_ids = [follower.id for follower in doc.message_follower_ids]
author_ids = partner_obj.search(cr, uid, [('email', 'ilike', email_list[0]), ('id', 'in', doc_fol_ids)], limit=1, context=context)
if author_ids:
kwargs['author_id'] = author_ids[0]
attachment_ids = kwargs.pop('attachment_ids', [])
for name, content in attachments:
if isinstance(content, unicode):

View File

@ -104,6 +104,7 @@ class test_mail(TestMailBase):
def test_00_message_process(self):
""" Testing incoming emails processing. """
cr, uid, user_raoul = self.cr, self.uid, self.user_raoul
extra_partner_id = self.res_partner.create(cr, uid, {'name': 'Raoul Extra', 'email': 'raoul@raoul.fr'})
# groups@.. will cause the creation of new mail groups
self.mail_group_model_id = self.ir_model.search(cr, uid, [('model', '=', 'mail.group')])[0]
@ -146,15 +147,15 @@ class test_mail(TestMailBase):
self.assertEqual(new_mail.body, '<pre>\nPlease call me as soon as possible this afternoon!\n\n--\nSylvie\n</pre>',
'plaintext mail incorrectly parsed')
# Do: post a new message, with a known partner
# Do: post a new message, with a known partner -> duplicate emails -> should take the user-one
test_msg_id = '<deadcafe.1337-2@smtp.agrolait.com>'
TEMPLATE_MOD = MAIL_TEMPLATE_PLAINTEXT.replace('Sylvie Lelitre <sylvie.lelitre@agrolait.com>', user_raoul.email)
mail_new = TEMPLATE_MOD.format(to='Friendly Frogs <group+frogs@example.com>', subject='extra news', extra='', msg_id=test_msg_id)
self.mail_thread.message_process(cr, uid, None, mail_new)
new_mail = self.mail_message.browse(cr, uid, self.mail_message.search(cr, uid, [('message_id', '=', test_msg_id)])[0])
# Test: author_id set, not email_from
self.assertEqual(new_mail.author_id, user_raoul.partner_id, 'message process wrong author found')
self.assertFalse(new_mail.email_from, 'message process should not set the email_from when an author is found')
self.assertEqual(new_mail.author_id.id, user_raoul.partner_id.id, 'message process wrong author found')
self.assertEqual(new_mail.email_from, user_raoul.email, 'message process should set the email_from of incoming emails')
# Do: post a new message, with a unknown partner
test_msg_id = '<deadcafe.1337-3@smtp.agrolait.com>'
@ -166,6 +167,17 @@ class test_mail(TestMailBase):
self.assertFalse(new_mail.author_id, 'message process shnould not have found a partner for _abcd_ email address')
self.assertIn('_abcd_', new_mail.email_from, 'message process should set en email_from when not finding a partner_id')
# Do: post a new message, with a known partner -> duplicate emails -> should take the follower-one
test_msg_id = '<deadcafe.1337-2@smtp.agrolait.com>'
frog_group.message_subscribe([extra_partner_id])
TEMPLATE_MOD = MAIL_TEMPLATE_PLAINTEXT.replace('Sylvie Lelitre <sylvie.lelitre@agrolait.com>', user_raoul.email)
mail_new = TEMPLATE_MOD.format(to='Friendly Frogs <group+frogs@example.com>', subject='extra news', extra='', msg_id=test_msg_id)
self.mail_thread.message_process(cr, uid, None, mail_new)
new_mail = self.mail_message.browse(cr, uid, self.mail_message.search(cr, uid, [('message_id', '=', test_msg_id)])[0])
# Test: author_id set, not email_from
self.assertEqual(new_mail.author_id.id, extra_partner_id, 'message process wrong author found')
self.assertEqual(new_mail.email_from, user_raoul.email, 'message process should set the email_from of incoming emails')
def test_05_thread_parent_resolution(self):
"""Verify parent/child relationships are correctly established when processing incoming mails"""
cr, uid = self.cr, self.uid