diff options
| author | Thibault Delavallée <tde@openerp.com> | 2016-08-18 13:55:00 +0200 |
|---|---|---|
| committer | Thibault Delavallée <tde@openerp.com> | 2016-09-01 13:22:59 +0200 |
| commit | 38e181ee2c858decbf8feb935f59019591506621 (patch) | |
| tree | d4963cfb747899a19d974ec74a216780c7808594 | |
| parent | 029d1baf359eabb7ed531287f3cb2b3b8d586d39 (diff) | |
[IMP] mail: send email notifications after transaction commit
Using after commit event notifications emails are now send once the current
transaction is finished. This allows having issues with emails being sent
while the transaction failed sometimes after email sending, but still in the
same transaction.
A small hook is done to allow invitation emails to be sent directly as some
data related to mail.message is unlinked directly in the wizard.
| -rw-r--r-- | addons/mail/models/mail_message.py | 4 | ||||
| -rw-r--r-- | addons/mail/models/res_partner.py | 34 | ||||
| -rw-r--r-- | addons/mail/wizard/invite.py | 2 |
3 files changed, 30 insertions, 10 deletions
diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py index a2f1c516560..53794d4038a 100644 --- a/addons/mail/models/mail_message.py +++ b/addons/mail/models/mail_message.py @@ -749,7 +749,7 @@ class Message(models.Model): #------------------------------------------------------ @api.multi - def _notify(self, force_send=False, user_signature=True): + def _notify(self, force_send=False, send_after_commit=True, user_signature=True): """ Add the related record followers to the destination partner_ids if is not a private message. Call mail_notification.notify to manage the email sending """ @@ -786,7 +786,7 @@ class Message(models.Model): self.write({'channel_ids': [(6, 0, channels.ids)], 'needaction_partner_ids': [(6, 0, partners.ids)]}) # notify partners and channels - partners._notify(self, force_send=force_send, user_signature=user_signature) + partners._notify(self, force_send=force_send, send_after_commit=send_after_commit, user_signature=user_signature) channels._notify(self) # Discard cache, because child / parent allow reading and therefore diff --git a/addons/mail/models/res_partner.py b/addons/mail/models/res_partner.py index 7c3a96ba36b..125acce8010 100644 --- a/addons/mail/models/res_partner.py +++ b/addons/mail/models/res_partner.py @@ -4,7 +4,7 @@ import logging import threading -from odoo import _, api, fields, models +from odoo import _, api, fields, models, registry, SUPERUSER_ID from odoo.osv import expression _logger = logging.getLogger(__name__) @@ -145,7 +145,7 @@ class Partner(models.Model): }) @api.multi - def _notify(self, message, force_send=False, user_signature=True): + def _notify(self, message, force_send=False, send_after_commit=True, user_signature=True): # TDE TODO: model-dependant ? (like customer -> always email ?) message_sudo = message.sudo() email_channels = message.channel_ids.filtered(lambda channel: channel.email_send) @@ -154,14 +154,19 @@ class Partner(models.Model): ('id', 'in', self.ids), ('channel_ids', 'in', email_channels.ids), ('email', '!=', message_sudo.author_id and message_sudo.author_id.email or message.email_from), - ('notify_email', '!=', 'none')])._notify_by_email(message, force_send=force_send, user_signature=user_signature) + ('notify_email', '!=', 'none')])._notify_by_email(message, force_send=force_send, send_after_commit=send_after_commit, user_signature=user_signature) self._notify_by_chat(message) return True @api.multi - def _notify_by_email(self, message, force_send=False, user_signature=True): + def _notify_by_email(self, message, force_send=False, send_after_commit=True, user_signature=True): """ Method to send email linked to notified messages. The recipients are - the recordset on which this method is called. """ + 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 user_signature: add current user signature to notification emails """ if not self.ids: return True @@ -220,9 +225,24 @@ class Partner(models.Model): # 2. do not send emails immediately if the registry is not loaded, # 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 \ - (not self.pool._init or getattr(threading.currentThread(), 'testing', False)): - emails.send() + (not self.pool._init or test_mode): + email_ids = emails.ids + dbname = self.env.cr.dbname + + def send_notifications(): + db_registry = registry(dbname) + with db_registry.cursor() as cr: + env = api.Environment(cr, SUPERUSER_ID, {}) + env['mail.mail'].browse(email_ids).send() + + # unless asked specifically, send emails after the transaction to + # avoid side effects due to emails being sent while the transaction fails + if not test_mode and send_after_commit: + self._cr.after('commit', send_notifications) + else: + emails.send() return True diff --git a/addons/mail/wizard/invite.py b/addons/mail/wizard/invite.py index 51b765bc95a..1d345af517a 100644 --- a/addons/mail/wizard/invite.py +++ b/addons/mail/wizard/invite.py @@ -60,6 +60,6 @@ class Invite(models.TransientModel): 'res_id': wizard.res_id, 'no_auto_thread': True, }) - new_partners.with_context(auto_delete=True)._notify(message, force_send=True, user_signature=True) + new_partners.with_context(auto_delete=True)._notify(message, force_send=True, send_after_commit=False, user_signature=True) message.unlink() return {'type': 'ir.actions.act_window_close'} |
