diff --git a/addons/crm_sms/__manifest__.py b/addons/crm_sms/__manifest__.py index a32d0b718fe..5b5780916e2 100644 --- a/addons/crm_sms/__manifest__.py +++ b/addons/crm_sms/__manifest__.py @@ -10,6 +10,8 @@ 'depends': ['crm', 'sms'], 'data': [ 'views/crm_lead_views.xml', + 'security/ir.model.access.csv', + 'security/sms_security.xml', ], 'installable': True, 'application': False, diff --git a/addons/crm_sms/security/ir.model.access.csv b/addons/crm_sms/security/ir.model.access.csv new file mode 100644 index 00000000000..f94b6f7ffde --- /dev/null +++ b/addons/crm_sms/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_sms_template_sale_manager,access.sms.template.sale.manager,sms.model_sms_template,sales_team.group_sale_manager,1,1,1,1 diff --git a/addons/crm_sms/security/sms_security.xml b/addons/crm_sms/security/sms_security.xml new file mode 100644 index 00000000000..a3a88f045e9 --- /dev/null +++ b/addons/crm_sms/security/sms_security.xml @@ -0,0 +1,9 @@ + + + + SMS Template: sale manager CRUD on opportunity / partner templates + + + [('res_model_id.model', 'in', ('crm.lead', 'res.partner'))] + + diff --git a/addons/event_sms/__manifest__.py b/addons/event_sms/__manifest__.py index 756ade6c0e3..94d9df26851 100644 --- a/addons/event_sms/__manifest__.py +++ b/addons/event_sms/__manifest__.py @@ -11,6 +11,8 @@ 'data/sms_data.xml', 'views/event_views.xml', 'views/event_mail_views.xml', + 'security/ir.model.access.csv', + 'security/sms_security.xml', ], 'demo': [ ], diff --git a/addons/event_sms/security/ir.model.access.csv b/addons/event_sms/security/ir.model.access.csv new file mode 100644 index 00000000000..b34e4dd5b87 --- /dev/null +++ b/addons/event_sms/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_sms_template_event_manager,access.sms.template.event.manager,sms.model_sms_template,event.group_event_manager,1,1,1,1 diff --git a/addons/event_sms/security/sms_security.xml b/addons/event_sms/security/sms_security.xml new file mode 100644 index 00000000000..94bc733cf7a --- /dev/null +++ b/addons/event_sms/security/sms_security.xml @@ -0,0 +1,9 @@ + + + + SMS Template: event manager CRUD on event / registrations templates + + + [('res_model_id.model', 'in', ('event.event', 'event.registration'))] + + 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 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', diff --git a/addons/mass_mailing_sms/models/mailing_mailing.py b/addons/mass_mailing_sms/models/mailing_mailing.py index 49d7b6a0a3c..b71cf3cc274 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,30 @@ 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_retry_failed(self): + mass_sms = self.filtered(lambda m: m.mailing_type == 'sms') + if mass_sms: + mass_sms.action_retry_failed_sms() + return super(Mailing, self - mass_sms).action_retry_failed() + + def action_retry_failed_sms(self): + failed_sms = self.env['sms.sms'].sudo().search([ + ('mailing_id', 'in', self.ids), + ('state', '=', 'error') + ]) + failed_sms.mapped('mailing_trace_ids').unlink() + failed_sms.unlink() + self.write({'state': 'in_queue'}) def action_test(self): if self.mailing_type == 'sms': @@ -166,6 +191,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 +209,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 54d4c5375b2..b0fb2c129b9 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')]} -