diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py
index fed4ad94c88..78487f35af7 100644
--- a/addons/mail/models/mail_message.py
+++ b/addons/mail/models/mail_message.py
@@ -1062,8 +1062,8 @@ class Message(models.Model):
message_values['channel_ids'] = [(6, 0, [r['id'] for r in rdata['channels']])]
if rdata['partners']:
message_values['needaction_partner_ids'] = [(6, 0, [r['id'] for r in rdata['partners']])]
- if self.model and self.res_id and hasattr(self.env[self.model], 'message_get_message_notify_values'):
- message_values.update(self.env[self.model].browse(self.res_id).message_get_message_notify_values(self, message_values))
+ if message_values and record and hasattr(record, 'message_get_message_notify_values'):
+ message_values.update(record.message_get_message_notify_values(self, message_values))
if message_values:
self.write(message_values)
@@ -1076,9 +1076,10 @@ class Message(models.Model):
('id', 'in', email_pids),
('channel_ids', 'in', email_cids),
('email', '!=', self.author_id.email or self.email_from),
- ])._notify(self, force_send=force_send, send_after_commit=send_after_commit, model_description=model_description, mail_auto_delete=mail_auto_delete)
+ ])._notify(self, record, force_send=force_send, send_after_commit=send_after_commit, model_description=model_description, mail_auto_delete=mail_auto_delete)
- self.env['res.partner'].sudo().browse(inbox_pids)._notify_by_chat(self)
+ if inbox_pids:
+ self.env['res.partner'].sudo().browse(inbox_pids)._notify_by_chat(self)
if rdata['channels']:
self.env['mail.channel'].sudo().browse([r['id'] for r in rdata['channels']])._notify(self)
diff --git a/addons/mail/models/res_partner.py b/addons/mail/models/res_partner.py
index a8df8efce74..aa52ca8d339 100644
--- a/addons/mail/models/res_partner.py
+++ b/addons/mail/models/res_partner.py
@@ -37,32 +37,27 @@ class Partner(models.Model):
return dict((res_id, {'partner_ids': [res_id], 'email_to': False, 'email_cc': False}) for res_id in self.ids)
@api.model
- def _notify_prepare_template_context(self, message, model_description=False, mail_auto_delete=True):
- # compute signature
- if not message.add_sign:
- signature = False
- elif message.author_id and message.author_id.user_ids and message.author_id.user_ids[0].signature:
- signature = message.author_id.user_ids[0].signature
- elif message.author_id:
- signature = "
--
%s
" % message.author_id.name
- else:
- signature = ""
-
- # compute Sent by
+ def _notify_prepare_template_context(self, message, record, model_description=False, mail_auto_delete=True):
+ # compute send user and its related signature
+ signature = ''
if message.author_id and message.author_id.user_ids:
user = message.author_id.user_ids[0]
+ if message.add_sign:
+ signature = user.signature
else:
user = self.env.user
- if user.company_id.website:
- website_url = 'http://%s' % user.company_id.website if not user.company_id.website.lower().startswith(('http:', 'https:')) else user.company_id.website
+ if message.add_sign:
+ signature = "--
%s
" % message.author_id.name
+
+ company = record.company_id if record and 'company_id' in record else user.company_id
+ if company.website:
+ website_url = 'http://%s' % company.website if not company.website.lower().startswith(('http:', 'https:')) else company.website
else:
website_url = False
if not model_description and message.model:
model_description = self.env['ir.model']._get(message.model).display_name
- record_name = message.record_name
-
tracking = []
for tracking_value in self.env['mail.tracking.value'].sudo().search([('mail_message_id', '=', message.id)]):
tracking.append((tracking_value.field_desc,
@@ -71,14 +66,6 @@ class Partner(models.Model):
is_discussion = message.subtype_id.id == self.env['ir.model.data'].xmlid_to_res_id('mail.mt_comment')
- record = False
- if message.res_id and message.model in self.env:
- record = self.env[message.model].browse(message.res_id)
-
- company = user.company_id
- if record and hasattr(record, 'company_id'):
- company = record.company_id
-
return {
'message': message,
'signature': signature,
@@ -86,79 +73,26 @@ class Partner(models.Model):
'company': company,
'model_description': model_description,
'record': record,
- 'record_name': record_name,
+ 'record_name': message.record_name,
'tracking_values': tracking,
'is_discussion': is_discussion,
'subtype': message.subtype_id,
}
- @api.model
- def _notify_prepare_email_values(self, message, mail_auto_delete=True):
- # compute email references
- references = message.parent_id.message_id if message.parent_id else False
-
- # custom values
- custom_values = dict()
- if message.res_id and message.model:
- custom_values = self.env['mail.thread']._notify_specific_email_values_on_records(message, records=self.env[message.model].browse(message.res_id))
-
- mail_values = {
- 'mail_message_id': message.id,
- 'mail_server_id': message.mail_server_id.id,
- 'auto_delete': mail_auto_delete,
- 'references': references,
- }
- mail_values.update(custom_values)
- return mail_values
-
- @api.model
- def _notify_send(self, body, subject, recipients, **mail_values):
- emails = self.env['mail.mail']
- recipients_nbr = len(recipients)
- for email_chunk in split_every(50, recipients.ids):
- # TDE FIXME: missing message parameter. So we will find mail_message_id
- # in the mail_values and browse it. It should already be in the
- # cache so should not impact performances.
- mail_message_id = mail_values.get('mail_message_id')
- message = self.env['mail.message'].browse(mail_message_id) if mail_message_id else None
- tig = self.env[message.model].browse(message.res_id) if message and message.model and message.res_id else False
- recipient_values = self.env['mail.thread']._notify_email_recipients_on_records(message, email_chunk, records=tig)
- create_values = {
- 'body_html': body,
- 'subject': subject,
- }
- create_values.update(mail_values)
- create_values.update(recipient_values)
- emails |= self.env['mail.mail'].create(create_values)
- return emails, recipients_nbr
-
- @api.model
- def _notify_udpate_notifications(self, emails):
- for email in emails:
- notifications = self.env['mail.notification'].sudo().search([
- ('mail_message_id', '=', email.mail_message_id.id),
- ('res_partner_id', 'in', email.recipient_ids.ids)])
- notifications.write({
- 'mail_id': email.id,
- 'is_email': True,
- 'is_read': True, # handle by email discards Inbox notification
- 'email_status': 'ready',
- })
-
@api.multi
- def _notify(self, message, force_send=False, send_after_commit=True, model_description=False, mail_auto_delete=True):
+ def _notify(self, message, record, force_send=False, send_after_commit=True, model_description=False, mail_auto_delete=True):
""" Method to send email linked to notified messages. The recipients are
the recordset on which this method is called.
- :param boolean force_send: send notification emails now instead of letting the scheduler handle the email queue
- :param boolean send_after_commit: send notification emails after the transaction end instead of durign the
- transaction; this option is used only if force_send is True
- :param dict values: values used to compute the notification process, containing
-
- * add_sign: add user signature to notification email, default is True
- * mail_auto_delete: auto delete send emails, default is True
- * other values are given to the context used to render the notification template, allowing customization
-
+ :param message: mail.message record to notify;
+ :param record: optional record on which the message was posted;
+ :param force_send: tells whether to send notification emails within the
+ current transaction or to use the email queue;
+ :param send_after_commit: if force_send, tells whether to send emails after
+ the transaction has been committed using a post-commit hook;
+ :param model_description: optional data used in notification process (see
+ notification templates);
+ :param mail_auto_delete: delete notification emails once sent;
"""
if not self.ids:
return True
@@ -170,31 +104,52 @@ class Partner(models.Model):
_logger.warning('QWeb template %s not found when sending notification emails. Sending without layouting.' % (template_xmlid))
base_template = False
- base_template_ctx = self._notify_prepare_template_context(message, model_description=model_description)
- base_mail_values = self._notify_prepare_email_values(message, mail_auto_delete=mail_auto_delete)
+ base_template_ctx = self._notify_prepare_template_context(message, record, model_description=model_description)
+
+ # prepare notification mail values
+ base_mail_values = {
+ 'mail_message_id': message.id,
+ 'mail_server_id': message.mail_server_id.id,
+ 'auto_delete': mail_auto_delete,
+ 'references': message.parent_id.message_id if message.parent_id else False
+ }
+ if record:
+ base_mail_values.update(self.env['mail.thread']._notify_specific_email_values_on_records(message, records=record))
# classify recipients: actions / no action
- tig = self.env[message.model].browse(message.res_id) if message.model and message.res_id else False
- recipients = self.env['mail.thread']._notify_classify_recipients_on_records(message, self, records=tig)
+ recipients = self.env['mail.thread']._notify_classify_recipients_on_records(message, self, records=record)
emails = self.env['mail.mail']
recipients_nbr, recipients_max = 0, 50
- for email_type, recipient_template_values in recipients.items():
- if recipient_template_values['recipients']:
- # generate notification email content
- template_ctx = {**base_template_ctx, **recipient_template_values} # fixme: set button_unfollow to none
- fol_values = {
- 'subject': message.subject or (message.record_name and 'Re: %s' % message.record_name),
- 'body': base_template.render(template_ctx, engine='ir.qweb', minimal_qcontext=True) if base_template else message.body,
- }
- fol_values['body'] = self.env['mail.thread']._replace_local_links(fol_values['body'])
- # send email
- new_emails, new_recipients_nbr = self._notify_send(fol_values['body'], fol_values['subject'], recipient_template_values['recipients'], **base_mail_values)
- # update notifications
- self._notify_udpate_notifications(new_emails)
+ for group_tpl_values in [group for group in recipients.values() if group['recipients']]:
+ # generate notification email content
+ template_ctx = {**base_template_ctx, **group_tpl_values}
+ mail_body = base_template.render(template_ctx, engine='ir.qweb', minimal_qcontext=True)
+ mail_body = self.env['mail.thread']._replace_local_links(mail_body)
+ mail_subject = message.subject or (message.record_name and 'Re: %s' % message.record_name)
- emails |= new_emails
- recipients_nbr += new_recipients_nbr
+ # send email
+ for email_chunk in split_every(50, group_tpl_values['recipients'].ids):
+ recipient_values = self.env['mail.thread']._notify_email_recipients_on_records(message, email_chunk, records=record)
+ create_values = {
+ 'body_html': mail_body,
+ 'subject': mail_subject,
+ }
+ create_values.update(base_mail_values)
+ create_values.update(recipient_values)
+ emails |= self.env['mail.mail'].create(create_values)
+
+ # update notifications
+ for email in emails:
+ notifications = self.env['mail.notification'].sudo().search([
+ ('mail_message_id', '=', email.mail_message_id.id),
+ ('res_partner_id', 'in', email.recipient_ids.ids)])
+ notifications.write({
+ 'mail_id': email.id,
+ 'is_email': True,
+ 'is_read': True, # handle by email discards Inbox notification
+ 'email_status': 'ready',
+ })
# NOTE:
# 1. for more than 50 followers, use the queue system
@@ -202,7 +157,7 @@ class Partner(models.Model):
# to prevent sending email during a simple update of the database
# using the command-line.
test_mode = getattr(threading.currentThread(), 'testing', False)
- if force_send and recipients_nbr < recipients_max and \
+ if force_send and len(emails) < recipients_max and \
(not self.pool._init or test_mode):
email_ids = emails.ids
dbname = self.env.cr.dbname
diff --git a/addons/mail/wizard/invite.py b/addons/mail/wizard/invite.py
index 6aa42e05f3f..541d3c1ea4f 100644
--- a/addons/mail/wizard/invite.py
+++ b/addons/mail/wizard/invite.py
@@ -60,6 +60,6 @@ class Invite(models.TransientModel):
'no_auto_thread': True,
'add_sign': True,
})
- new_partners.with_context(auto_delete=True)._notify(message, force_send=True, send_after_commit=False)
+ new_partners.with_context(auto_delete=True)._notify(message, document, force_send=True, send_after_commit=False)
message.unlink()
return {'type': 'ir.actions.act_window_close'}
diff --git a/addons/mail/wizard/mail_resend_message.py b/addons/mail/wizard/mail_resend_message.py
index 38815c1a64d..bf56128ad61 100644
--- a/addons/mail/wizard/mail_resend_message.py
+++ b/addons/mail/wizard/mail_resend_message.py
@@ -57,7 +57,10 @@ class MailResendMessage(models.TransientModel):
to_send = wizard.partner_ids.filtered(lambda p: p.resend).mapped("partner_id")
notif_to_cancel = wizard.notification_ids.filtered(lambda notif: notif.res_partner_id in to_cancel and notif.email_status in ('exception', 'bounce'))
notif_to_cancel.sudo().write({'email_status': 'canceled'})
- to_send.sudo()._notify(self.mail_message_id, force_send=True, send_after_commit=False)
+ if to_send:
+ message = wizard.mail_message_id
+ record = self.env[message.model].browse(message.res_id) if message.model and message.res_id else None
+ to_send.sudo()._notify(self.mail_message_id, record, force_send=True, send_after_commit=False)
self.mail_message_id._notify_failure_update()
return {'type': 'ir.actions.act_window_close'}
diff --git a/addons/test_mail/tests/test_performance.py b/addons/test_mail/tests/test_performance.py
index 43ecaa3f236..95e950fa97c 100644
--- a/addons/test_mail/tests/test_performance.py
+++ b/addons/test_mail/tests/test_performance.py
@@ -199,7 +199,7 @@ class TestAdvMailPerformance(TransactionCase):
self.user_test.write({'notification_type': 'email'})
record = self.env['mail.test.track'].create({'name': 'Test'})
- with self.assertQueryCount(margin=1, admin=59, emp=77): # com runbot: 59 - 77 // test_mail only: 59 - 77
+ with self.assertQueryCount(margin=1, admin=59, emp=76): # com runbot: 59 - 76 // test_mail only: 59 - 76
record.write({
'user_id': self.user_test.id,
})
@@ -209,7 +209,7 @@ class TestAdvMailPerformance(TransactionCase):
def test_message_assignation_inbox(self):
record = self.env['mail.test.track'].create({'name': 'Test'})
- with self.assertQueryCount(margin=1, admin=37, emp=48): # test_mail only: 37 - 48
+ with self.assertQueryCount(margin=1, admin=36, emp=46): # test_mail only: 36 - 46
record.write({
'user_id': self.user_test.id,
})
@@ -253,7 +253,7 @@ class TestAdvMailPerformance(TransactionCase):
def test_message_post_one_email_notification(self):
record = self.env['mail.test.simple'].create({'name': 'Test'})
- with self.assertQueryCount(margin=1, admin=50, emp=69): # com runbot: 48 - 67 // test_mail only: 50 - 69
+ with self.assertQueryCount(margin=1, admin=50, emp=68): # com runbot: 48 - 66 // test_mail only: 50 - 68
record.message_post(
body='Test Post Performances with an email ping
',
partner_ids=self.customer.ids,
@@ -389,7 +389,7 @@ class TestHeavyMailPerformance(TransactionCase):
self.umbrella.message_subscribe(self.user_portal.partner_id.ids)
record = self.umbrella.sudo(self.env.user)
- with self.assertQueryCount(admin=85, emp=107): # com runbot 83 - 105 // test_mail only: 85 - 107
+ with self.assertQueryCount(admin=82, emp=103): # com runbot 80 - 101 // test_mail only: 82 - 103
record.message_post(
body='Test Post Performances
',
message_type='comment',
@@ -406,7 +406,7 @@ class TestHeavyMailPerformance(TransactionCase):
record = self.umbrella.sudo(self.env.user)
template_id = self.env.ref('test_mail.mail_test_tpl').id
- with self.assertQueryCount(admin=104, emp=138): # com runbot 102 - 136 // test_mail only: 104 - 138
+ with self.assertQueryCount(admin=101, emp=134): # com runbot 99 - 132 // test_mail only: 101 - 134
record.message_post_with_template(template_id, message_type='comment', composition_mode='comment')
self.assertEqual(record.message_ids[0].body, 'Adding stuff on %s
' % record.name)
@@ -476,7 +476,7 @@ class TestHeavyMailPerformance(TransactionCase):
})
self.assertEqual(rec.message_partner_ids, self.partners | self.env.user.partner_id)
- with self.assertQueryCount(admin=61, emp=79): # com runbot: 61 - 79 // test_mail only: 61 - 79
+ with self.assertQueryCount(admin=61, emp=78): # com runbot: 61 - 78 // test_mail only: 61 - 78
rec.write({'user_id': self.user_portal.id})
self.assertEqual(rec.message_partner_ids, self.partners | self.env.user.partner_id | self.user_portal.partner_id)
@@ -499,7 +499,7 @@ class TestHeavyMailPerformance(TransactionCase):
customer_id = self.customer.id
user_id = self.user_portal.id
- with self.assertQueryCount(margin=1, admin=163, emp=198): # com runbot: 163 - 198 // test_mail only: 163 - 198
+ with self.assertQueryCount(margin=1, admin=160, emp=193): # com runbot: 160 - 193 // test_mail only: 160 - 193
rec = self.env['mail.test.full'].create({
'name': 'Test',
'umbrella_id': umbrella_id,
@@ -528,7 +528,7 @@ class TestHeavyMailPerformance(TransactionCase):
})
self.assertEqual(rec.message_partner_ids, self.user_portal.partner_id | self.env.user.partner_id)
- with self.assertQueryCount(margin=1, admin=99, emp=117): # com runbot: 99 - 117 // test_mail only: 99 - 117
+ with self.assertQueryCount(margin=1, admin=96, emp=112): # com runbot: 96 - 112 // test_mail only: 96 - 112
rec.write({
'name': 'Test2',
'umbrella_id': self.umbrella.id,
@@ -566,7 +566,7 @@ class TestHeavyMailPerformance(TransactionCase):
})
self.assertEqual(rec.message_partner_ids, self.user_portal.partner_id | self.env.user.partner_id)
- with self.assertQueryCount(margin=1, admin=106, emp=127): # test_mail only: 106 - 127
+ with self.assertQueryCount(margin=1, admin=103, emp=122): # test_mail only: 103 - 122
rec.write({
'name': 'Test2',
'umbrella_id': umbrella_id,