From cff89b09a48cb9a266b9beb36a515f8d502e12c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 23 Sep 2019 13:50:12 +0000 Subject: [PATCH 01/11] [FIX] mail: make recipients unique when parsing emails Purpose of this commit is to have recipients of an incoming email being present only once in recipients / to. Indeed there is no need to have duplicate entries, for example if Delivered-To is set with same content of To. Followup of 7b79045fab809679e17d774f9a510e07ac39aa0b . LINKS Task 2076366 (send now) Task 2067873 (template access) PR #37298 PR odoo/enterprise#5750 --- addons/mail/models/mail_thread.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 5daf717e26f..101766fe9e2 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -1384,7 +1384,7 @@ class MailThread(models.AbstractModel): msg_dict['cc'] = ','.join(email_cc_list) if email_cc_list else email_cc # Delivered-To is a safe bet in most modern MTAs, but we have to fallback on To + Cc values # for all the odd MTAs out there, as there is no standard header for the envelope's `rcpt_to` value. - msg_dict['recipients'] = ','.join(formatted_email + msg_dict['recipients'] = ','.join(set(formatted_email for address in [ tools.decode_message_header(message, 'Delivered-To'), tools.decode_message_header(message, 'To'), @@ -1392,14 +1392,15 @@ class MailThread(models.AbstractModel): tools.decode_message_header(message, 'Resent-To'), tools.decode_message_header(message, 'Resent-Cc') ] if address - for formatted_email in tools.email_split_and_format(address) + for formatted_email in tools.email_split_and_format(address)) ) - msg_dict['to'] = ','.join(formatted_email + msg_dict['to'] = ','.join(set(formatted_email for address in [ tools.decode_message_header(message, 'Delivered-To'), tools.decode_message_header(message, 'To') ] if address for formatted_email in tools.email_split_and_format(address)) + ) partner_ids = [x.id for x in self._mail_find_partner_from_emails(tools.email_split(msg_dict['recipients']), records=self) if x] msg_dict['partner_ids'] = partner_ids # compute references to find if email_message is a reply to an existing thread From 31aa195efa912eb315af62a22ad83fe83d25d5cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 24 Sep 2019 12:17:22 +0000 Subject: [PATCH 02/11] [FIX] sms: set correct value of batch when contacting IAP sms Batch of 10 text messages was ok for testing. Production environment should be able to handle more of them. LINKS Task 2076366 (send now) Task 2067873 (template access) PR #37298 PR odoo/enterprise#5750 --- addons/sms/models/sms_sms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sms/models/sms_sms.py b/addons/sms/models/sms_sms.py index 256bebf7eda..081547426ce 100644 --- a/addons/sms/models/sms_sms.py +++ b/addons/sms/models/sms_sms.py @@ -86,7 +86,7 @@ class SmsSms(models.Model): return res def _split_batch(self): - batch_size = int(self.env['ir.config_parameter'].sudo().get_param('sms.session.batch.size', 10)) + batch_size = int(self.env['ir.config_parameter'].sudo().get_param('sms.session.batch.size', 500)) for sms_batch in tools.split_every(batch_size, self.ids): yield sms_batch From e4ece3f7deaf86d8d39565d8acc106f250a05868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 24 Sep 2019 12:52:20 +0000 Subject: [PATCH 03/11] [FIX] mass_mailing: unlink traces when unlinking mailings There is no need to keep traces when unlinking mailings, being mail or sms. Indeed even with marketing automation unlinking mailings means traces will be lost and won't serve any statistics or reporting purpose anymore. LINKS Task 2076366 (send now) Task 2067873 (template access) PR #37298 PR odoo/enterprise#5750 --- addons/mass_mailing/models/mailing_trace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mass_mailing/models/mailing_trace.py b/addons/mass_mailing/models/mailing_trace.py index 38185845545..ef3c51f0141 100644 --- a/addons/mass_mailing/models/mailing_trace.py +++ b/addons/mass_mailing/models/mailing_trace.py @@ -31,7 +31,7 @@ class MailingTrace(models.Model): model = fields.Char(string='Document model') res_id = fields.Integer(string='Document ID') # campaign / wave data - mass_mailing_id = fields.Many2one('mailing.mailing', string='Mailing', index=True) + mass_mailing_id = fields.Many2one('mailing.mailing', string='Mailing', index=True, ondelete='cascade') campaign_id = fields.Many2one( related='mass_mailing_id.campaign_id', string='Campaign', From 889d30e2c80a561b41298a8fab52478c48b2c687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 24 Sep 2019 14:32:50 +0000 Subject: [PATCH 04/11] [FIX] mass_mailing_sms: make body required in sms mailings Sending void SMS marketing is not considered as a valid use case, more something we should prevent as each sent SMS consumes credits. Required is put in view as we have to support void sms body for mail mailings. LINKS Task 2076366 (send now) Task 2067873 (template access) PR #37298 PR odoo/enterprise#5750 --- addons/mass_mailing_sms/views/mailing_mailing_views.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mass_mailing_sms/views/mailing_mailing_views.xml b/addons/mass_mailing_sms/views/mailing_mailing_views.xml index 54d4c5375b2..61c14ce7228 100644 --- a/addons/mass_mailing_sms/views/mailing_mailing_views.xml +++ b/addons/mass_mailing_sms/views/mailing_mailing_views.xml @@ -90,7 +90,7 @@ - + From 48cc126137bb1abead26ca68ba8376cbd2cfe120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 24 Sep 2019 13:03:45 +0000 Subject: [PATCH 05/11] [FIX] (mass_mailing_)sms: allow to directly send SMS in mass mode PURPOSE Sending SMS is sometimes required as an immediate marketing tool. Using delayed crons is not always the best user choice. Implement a Send Now mechanism in batch SMS. SPECIFICATIONS Allow to send directly SMS when doing SMS marketing SMS Application * in sms composer, in mass mode: rename Send SMS to Put in queue and add a Send Now button by-passing the queue; * set Put in queue as primary, Send Now as secondary; SMS Marketing Application * in mailing view for SMS: rename Send SMS to Put in queue and add a Send Now button by-passing the queue; * set Put in queue as primary, Send Now as secondary; Tests of SMS marketing with 400 contacts to SMS indicates it takes about 10 seconds to be completed which is considered as ok. LINKS Task 2076366 (send now) Task 2067873 (template access) PR #37298 PR odoo/enterprise#5750 --- .../models/mailing_mailing.py | 18 ++++++++++----- .../views/mailing_mailing_views.xml | 11 ++++++--- .../mass_mailing_sms/wizard/sms_composer.py | 11 ++++----- addons/sms/wizard/sms_composer.py | 23 ++++++++++++------- addons/sms/wizard/sms_composer_views.xml | 7 +++++- 5 files changed, 45 insertions(+), 25 deletions(-) diff --git a/addons/mass_mailing_sms/models/mailing_mailing.py b/addons/mass_mailing_sms/models/mailing_mailing.py index 49d7b6a0a3c..9200bf8618a 100644 --- a/addons/mass_mailing_sms/models/mailing_mailing.py +++ b/addons/mass_mailing_sms/models/mailing_mailing.py @@ -20,6 +20,8 @@ class Mailing(models.Model): sms_has_insufficient_credit = fields.Boolean( 'Insufficient IAP credits', compute='_compute_sms_has_insufficient_credit', help='UX Field to propose to buy IAP credits') + sms_force_send = fields.Boolean( + 'Send Directly', help='Use at your own risks.') # opt_out_link sms_allow_unsubscribe = fields.Boolean('Include opt-out link', default=True) @@ -63,7 +65,15 @@ class Mailing(models.Model): # -------------------------------------------------- def action_put_in_queue_sms(self): - return self.action_put_in_queue() + res = self.action_put_in_queue() + if self.sms_force_send: + self.action_send_mail() + return res + + def action_send_now_sms(self): + if not self.sms_force_send: + self.write({'sms_force_send': True}) + return self.action_send_mail() def action_test(self): if self.mailing_type == 'sms': @@ -166,6 +176,7 @@ class Mailing(models.Model): 'composition_mode': 'mass', 'mailing_id': self.id, 'mass_keep_log': self.keep_archives, + 'mass_force_send': self.sms_force_send, 'mass_sms_allow_unsubscribe': self.sms_allow_unsubscribe, } @@ -183,11 +194,6 @@ class Mailing(models.Model): raise UserError(_('There is no recipients selected.')) composer = self.env['sms.composer'].with_context(active_id=False).create(mailing._send_sms_get_composer_values(res_ids)) - # extra_context = self._get_mass_mailing_context() - - # auto-commit except in testing mode - # auto_commit = not getattr(threading.currentThread(), 'testing', False) - # composer.send_mail(auto_commit=auto_commit) composer._action_send_sms() mailing.write({'state': 'done', 'sent_date': fields.Datetime.now()}) return True diff --git a/addons/mass_mailing_sms/views/mailing_mailing_views.xml b/addons/mass_mailing_sms/views/mailing_mailing_views.xml index 61c14ce7228..2c774bd9e9c 100644 --- a/addons/mass_mailing_sms/views/mailing_mailing_views.xml +++ b/addons/mass_mailing_sms/views/mailing_mailing_views.xml @@ -23,10 +23,14 @@ {'invisible': ['|', ('state', 'in', ('in_queue', 'done')), ('mailing_type', '!=', 'mail')]} -