[FIX] mail, mail_group: recipients of mail groups
Mailing lists (mail.group) should not send specific notification emails. Indeed there can be a lot of recipients and customizing each email can take time to compute. This leads to posting a message on a mail.group being very slow. It is now possible for a model to customize the notification email recipients computation. The first use is to ensure that mail.group encodes recipients using email_to instead of recipients_ids. This way less processing is performed on notification emails.
This commit is contained in:
parent
a1db9c3ac0
commit
d4a1eb4435
|
@ -211,15 +211,19 @@ class mail_notification(osv.Model):
|
||||||
chunks = [email_pids[x:x + max_recipients] for x in xrange(0, len(email_pids), max_recipients)]
|
chunks = [email_pids[x:x + max_recipients] for x in xrange(0, len(email_pids), max_recipients)]
|
||||||
email_ids = []
|
email_ids = []
|
||||||
for chunk in chunks:
|
for chunk in chunks:
|
||||||
|
if message.model and message.res_id and self.pool.get(message.model) and hasattr(self.pool[message.model], 'message_get_recipient_values'):
|
||||||
|
recipient_values = self.pool[message.model].message_get_recipient_values(cr, uid, message.res_id, notif_message=message, recipient_ids=chunk, context=context)
|
||||||
|
else:
|
||||||
|
recipient_values = self.pool['mail.thread'].message_get_recipient_values(cr, uid, message.res_id, notif_message=message, recipient_ids=chunk, context=context)
|
||||||
mail_values = {
|
mail_values = {
|
||||||
'mail_message_id': message.id,
|
'mail_message_id': message.id,
|
||||||
'auto_delete': (context or {}).get('mail_auto_delete', True),
|
'auto_delete': (context or {}).get('mail_auto_delete', True),
|
||||||
'mail_server_id': (context or {}).get('mail_server_id', False),
|
'mail_server_id': (context or {}).get('mail_server_id', False),
|
||||||
'body_html': body_html,
|
'body_html': body_html,
|
||||||
'recipient_ids': [(4, id) for id in chunk],
|
|
||||||
'references': references,
|
'references': references,
|
||||||
}
|
}
|
||||||
mail_values.update(custom_values)
|
mail_values.update(custom_values)
|
||||||
|
mail_values.update(recipient_values)
|
||||||
email_ids.append(self.pool.get('mail.mail').create(cr, uid, mail_values, context=context))
|
email_ids.append(self.pool.get('mail.mail').create(cr, uid, mail_values, context=context))
|
||||||
# NOTE:
|
# NOTE:
|
||||||
# 1. for more than 50 followers, use the queue system
|
# 1. for more than 50 followers, use the queue system
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
|
from email.utils import formataddr
|
||||||
|
|
||||||
import openerp
|
import openerp
|
||||||
import openerp.tools as tools
|
import openerp.tools as tools
|
||||||
from openerp.osv import osv
|
from openerp.osv import osv
|
||||||
|
@ -240,3 +242,13 @@ class mail_group(osv.Model):
|
||||||
headers['X-Forge-To'] = list_to
|
headers['X-Forge-To'] = list_to
|
||||||
res['headers'] = repr(headers)
|
res['headers'] = repr(headers)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def message_get_recipient_values(self, cr, uid, id, notif_message=None, recipient_ids=None, context=None):
|
||||||
|
group = self.browse(cr, uid, id, context=context)
|
||||||
|
# real mailing list: multiple recipients (hidden by X-Forge-To)
|
||||||
|
if group.alias_domain and group.alias_name:
|
||||||
|
return {
|
||||||
|
'email_to': ','.join(formataddr((partner.name, partner.email)) for partner in self.pool['res.partner'].browse(cr, SUPERUSER_ID, recipient_ids, context=context)),
|
||||||
|
'recipient_ids': [],
|
||||||
|
}
|
||||||
|
return super(mail_group, self).message_get_recipient_values(cr, uid, id, notif_message=notif_message, recipient_ids=recipient_ids, context=context)
|
||||||
|
|
|
@ -755,6 +755,16 @@ class mail_thread(osv.AbstractModel):
|
||||||
res = dict()
|
res = dict()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def message_get_recipient_values(self, cr, uid, id, notif_message=None, recipient_ids=None, context=None):
|
||||||
|
""" Get specific notification recipient values to store on the notification
|
||||||
|
mail_mail. Basic method just set the recipient partners as mail_mail
|
||||||
|
recipients. Inherit this method to add custom behavior like using
|
||||||
|
recipient email_to to bypass the recipint_ids heuristics in the
|
||||||
|
mail sending mechanism. """
|
||||||
|
return {
|
||||||
|
'recipient_ids': [(4, pid) for pid in recipient_ids]
|
||||||
|
}
|
||||||
|
|
||||||
#------------------------------------------------------
|
#------------------------------------------------------
|
||||||
# Mail gateway
|
# Mail gateway
|
||||||
#------------------------------------------------------
|
#------------------------------------------------------
|
||||||
|
|
|
@ -47,9 +47,13 @@ class TestMail(common.SavepointCase):
|
||||||
def send_email(self, cr, uid, message, *args, **kwargs):
|
def send_email(self, cr, uid, message, *args, **kwargs):
|
||||||
return message['Message-Id']
|
return message['Message-Id']
|
||||||
|
|
||||||
|
def mail_group_message_get_recipient_values(self, cr, uid, id, notif_message=None, recipient_ids=None, context=None):
|
||||||
|
return self.pool['mail.thread'].message_get_recipient_values(cr, uid, id, notif_message=notif_message, recipient_ids=recipient_ids, context=context)
|
||||||
|
|
||||||
cls._init_mock_build_email()
|
cls._init_mock_build_email()
|
||||||
cls.registry('ir.mail_server')._patch_method('build_email', build_email)
|
cls.registry('ir.mail_server')._patch_method('build_email', build_email)
|
||||||
cls.registry('ir.mail_server')._patch_method('send_email', send_email)
|
cls.registry('ir.mail_server')._patch_method('send_email', send_email)
|
||||||
|
cls.registry('mail.group')._patch_method('message_get_recipient_values', mail_group_message_get_recipient_values)
|
||||||
|
|
||||||
# Usefull models
|
# Usefull models
|
||||||
cls.ir_model = cls.registry('ir.model')
|
cls.ir_model = cls.registry('ir.model')
|
||||||
|
@ -133,4 +137,5 @@ class TestMail(common.SavepointCase):
|
||||||
# Remove mocks
|
# Remove mocks
|
||||||
cls.registry('ir.mail_server')._revert_method('build_email')
|
cls.registry('ir.mail_server')._revert_method('build_email')
|
||||||
cls.registry('ir.mail_server')._revert_method('send_email')
|
cls.registry('ir.mail_server')._revert_method('send_email')
|
||||||
|
cls.registry('mail.group')._revert_method('message_get_recipient_values')
|
||||||
super(TestMail, cls).tearDownClass()
|
super(TestMail, cls).tearDownClass()
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
|
from email.utils import formataddr
|
||||||
|
|
||||||
from .common import TestMail
|
from .common import TestMail
|
||||||
from openerp.exceptions import AccessError
|
from openerp.exceptions import AccessError
|
||||||
from openerp.osv.orm import except_orm
|
from openerp.osv.orm import except_orm
|
||||||
|
@ -27,6 +29,20 @@ from openerp.tools import mute_logger
|
||||||
|
|
||||||
class TestMailGroup(TestMail):
|
class TestMailGroup(TestMail):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super(TestMailGroup, cls).setUpClass()
|
||||||
|
# for specific tests of mail group, get back to its expected behavior
|
||||||
|
cls.registry('mail.group')._revert_method('message_get_recipient_values')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
# set master class behavior back
|
||||||
|
def mail_group_message_get_recipient_values(self, cr, uid, id, notif_message=None, recipient_ids=None, context=None):
|
||||||
|
return self.pool['mail.thread'].message_get_recipient_values(cr, uid, id, notif_message=notif_message, recipient_ids=recipient_ids, context=context)
|
||||||
|
cls.registry('mail.group')._patch_method('message_get_recipient_values', mail_group_message_get_recipient_values)
|
||||||
|
super(TestMail, cls).tearDownClass()
|
||||||
|
|
||||||
@mute_logger('openerp.addons.base.ir.ir_model', 'openerp.models')
|
@mute_logger('openerp.addons.base.ir.ir_model', 'openerp.models')
|
||||||
def test_00_mail_group_access_rights(self):
|
def test_00_mail_group_access_rights(self):
|
||||||
""" Testing mail_group access rights and basic mail_thread features """
|
""" Testing mail_group access rights and basic mail_thread features """
|
||||||
|
@ -70,3 +86,39 @@ class TestMailGroup(TestMail):
|
||||||
self.assertFalse(fol_ids, 'unlinked document should not have any followers left')
|
self.assertFalse(fol_ids, 'unlinked document should not have any followers left')
|
||||||
msg_ids = self.mail_message.search(cr, uid, [('model', '=', 'mail.group'), ('res_id', '=', self.group_priv_id)])
|
msg_ids = self.mail_message.search(cr, uid, [('model', '=', 'mail.group'), ('res_id', '=', self.group_priv_id)])
|
||||||
self.assertFalse(msg_ids, 'unlinked document should not have any followers left')
|
self.assertFalse(msg_ids, 'unlinked document should not have any followers left')
|
||||||
|
|
||||||
|
def test_mail_group_notification_recipients_grouped(self):
|
||||||
|
# Data: set alias_domain to see emails with alias
|
||||||
|
self.registry('ir.config_parameter').set_param(self.cr, self.uid, 'mail.catchall.domain', 'schlouby.fr')
|
||||||
|
|
||||||
|
self.mail_group.message_subscribe_users(
|
||||||
|
self.cr, self.uid,
|
||||||
|
[self.group_pigs_id],
|
||||||
|
[self.user_raoul_id, self.user_bert_id]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.mail_group.message_post(self.cr, self.uid, [self.group_pigs_id], body="Test", type='comment', subtype='mt_comment')
|
||||||
|
sent_emails = self._build_email_kwargs_list
|
||||||
|
self.assertEqual(len(sent_emails), 1)
|
||||||
|
for email in sent_emails:
|
||||||
|
self.assertEqual(
|
||||||
|
set(email['email_to']),
|
||||||
|
set([self.user_raoul.email, self.user_bert.email]))
|
||||||
|
|
||||||
|
def test_mail_group_notification_recipients_separated(self):
|
||||||
|
# Remove alias, should trigger classic behavior of mail group
|
||||||
|
self.mail_group.write(self.cr, self.uid, [self.group_pigs_id], {'alias_name': False})
|
||||||
|
|
||||||
|
self.mail_group.message_subscribe_users(
|
||||||
|
self.cr, self.uid,
|
||||||
|
[self.group_pigs_id],
|
||||||
|
[self.user_raoul_id, self.user_bert_id]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.mail_group.message_post(self.cr, self.uid, [self.group_pigs_id], body="Test", type='comment', subtype='mt_comment')
|
||||||
|
sent_emails = self._build_email_kwargs_list
|
||||||
|
self.assertEqual(len(sent_emails), 2)
|
||||||
|
for email in sent_emails:
|
||||||
|
self.assertIn(
|
||||||
|
email['email_to'][0],
|
||||||
|
[formataddr((self.user_raoul.name, self.user_raoul.email)), formataddr((self.user_bert.name, self.user_bert.email))])
|
||||||
|
|
Loading…
Reference in New Issue