diff --git a/mail_split_by_partner_conf/README.rst b/mail_split_by_partner_conf/README.rst new file mode 100644 index 00000000..162215ec --- /dev/null +++ b/mail_split_by_partner_conf/README.rst @@ -0,0 +1,74 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :alt: License: AGPL-3 + +======================= + Mail split by partner +======================= + +This module was written to allow you to choose how the mail was sent to multiple people. The default behavior of Odoo will send one mail for each recipients. The objective of this module would be to allow configuring if the native behavior should be applied or if only one email should be sent to all recipients (convenient to know who else has received the email). + +Configuration +============= + +* To configure this module, you need to go to `System parameters` and adjust `default_mail_split_by_partner_conf` as default option when you send mail (`split, merge`). + + +Usage +===== + +To use this module, you need to: + +* Go to email template, select `split`, `merge`, or `default` in the field `Split mail by recipient partner`. If choose `default`, the module will get the value defined on a config parameter `default_mail_split_by_partner_conf`. +* When create mail_message in a thread, the module will use `default` to send mail to followers. + +Example, when you choose `split`, it will send one mail for each recipients as default. + +Note: Field `Split mail by recipient partner` is available in mail.template and mail.mail so you can check how this email has been processed. + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/205/10.0 + +For further information, please visit: + +* https://www.odoo.com/forum/help-1 + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed feedback +`here `_. + +Credits +======= + +Contributors +------------ + +* Nguyen Tan Phuc + +Do not contact contributors directly about support or help with technical issues. + +Funders +------- + +The development of this module has been financially supported by: + +* Komit https://komit-consulting.com + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit http://odoo-community.org. diff --git a/mail_split_by_partner_conf/__init__.py b/mail_split_by_partner_conf/__init__.py new file mode 100644 index 00000000..eb69ef27 --- /dev/null +++ b/mail_split_by_partner_conf/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# © 2017 Phuc.nt - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import models +from . import wizard diff --git a/mail_split_by_partner_conf/__manifest__.py b/mail_split_by_partner_conf/__manifest__.py new file mode 100644 index 00000000..2dbb006e --- /dev/null +++ b/mail_split_by_partner_conf/__manifest__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# © 2017 Phuc.nt - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + 'name': "Mail split by partner", + "version": "10.0.1.0.0", + "author": "Komit, " + "Odoo Community Association (OCA)", + "license": "AGPL-3", + "category": "Marketing", + "website": "https://komit-consulting.com", + 'summary': "Split or merge recipients when send mail.", + 'depends': [ + 'mail', + ], + 'data': [ + 'views/mail_mail_view.xml', + 'views/mail_template_view.xml', + 'data/ir_config_parameter.xml', + ], + 'installable': True, +} diff --git a/mail_split_by_partner_conf/data/ir_config_parameter.xml b/mail_split_by_partner_conf/data/ir_config_parameter.xml new file mode 100644 index 00000000..62e0d92e --- /dev/null +++ b/mail_split_by_partner_conf/data/ir_config_parameter.xml @@ -0,0 +1,9 @@ + + + + + default_mail_split_by_partner_conf + split + + diff --git a/mail_split_by_partner_conf/models/__init__.py b/mail_split_by_partner_conf/models/__init__.py new file mode 100644 index 00000000..295aba3e --- /dev/null +++ b/mail_split_by_partner_conf/models/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# © 2017 Phuc.nt - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import mail_mail +from . import mail_template +from . import mail_thread diff --git a/mail_split_by_partner_conf/models/mail_mail.py b/mail_split_by_partner_conf/models/mail_mail.py new file mode 100644 index 00000000..16c5e023 --- /dev/null +++ b/mail_split_by_partner_conf/models/mail_mail.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# © 2017 Phuc.nt - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging +from email.utils import formataddr + +from odoo import api, fields, models +from odoo import tools + + +class MailMail(models.Model): + _inherit = 'mail.mail' + + split_mail_by_recipients = fields.Selection([ + ('split', 'One mail for each recipient'), + ('merge', 'One mail for all recipients'), + ('default', 'Project Default')], + string='Split mail by recipient partner', + default='default', + ) + + @api.multi + def send_get_mail_to(self, partner=None): + self.ensure_one() + email_to = super(MailMail, self).send_get_mail_to(partner=partner) + + if self._context.get('merge_mail'): + email_to = [formataddr((p.name, p.email)) + for p in self.recipient_ids] + if self.email_to: + email_to += tools.email_split_and_format(self.email_to) + logging.info('Merge email_to and recipients to %s', email_to) + return email_to + + @api.multi + def send_get_email_dict(self, partner=None): + self.ensure_one() + res = super(MailMail, self).send_get_email_dict(partner=partner) + + default = self.env['ir.config_parameter'].get_param( + 'default_mail_split_by_partner_conf') + + # check option merge or split recipients + send_type = self.split_mail_by_recipients + if send_type == 'merge' or send_type == 'default' and \ + default == 'merge': + email_to = [] + if self.recipient_ids and partner == self.recipient_ids[0] or \ + (not self.recipient_ids and self.email_to): + email_to = self.with_context( + {'merge_mail': True}).send_get_mail_to(partner=partner) + res.update({'email_to': email_to}) + return res diff --git a/mail_split_by_partner_conf/models/mail_template.py b/mail_split_by_partner_conf/models/mail_template.py new file mode 100644 index 00000000..61c46c64 --- /dev/null +++ b/mail_split_by_partner_conf/models/mail_template.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# © 2017 Phuc.nt - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, fields + + +class MailTemplate(models.Model): + _inherit = 'mail.template' + + split_mail_by_recipients = fields.Selection([ + ('split', 'One mail for each recipient'), + ('merge', 'One mail for all recipients'), + ('default', 'Project Default')], + string='Split mail by recipient partner', + default='default', + ) diff --git a/mail_split_by_partner_conf/models/mail_thread.py b/mail_split_by_partner_conf/models/mail_thread.py new file mode 100644 index 00000000..e54edaed --- /dev/null +++ b/mail_split_by_partner_conf/models/mail_thread.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# © 2017 Phuc.nt - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, api + + +class MailThread(models.AbstractModel): + _inherit = 'mail.thread' + + @api.multi + def message_get_recipient_values(self, notif_message=None, + recipient_ids=None): + res = super(MailThread, self).message_get_recipient_values( + notif_message=notif_message, recipient_ids=recipient_ids) + + res['recipient_ids'] = [(6, 0, recipient_ids)] + return res diff --git a/mail_split_by_partner_conf/static/description/icon.png b/mail_split_by_partner_conf/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/mail_split_by_partner_conf/static/description/icon.png differ diff --git a/mail_split_by_partner_conf/tests/__init__.py b/mail_split_by_partner_conf/tests/__init__.py new file mode 100644 index 00000000..ec7f65d6 --- /dev/null +++ b/mail_split_by_partner_conf/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# © 2017 Phuc.nt - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import test_mail_split_by_partner_conf diff --git a/mail_split_by_partner_conf/tests/test_mail_split_by_partner_conf.py b/mail_split_by_partner_conf/tests/test_mail_split_by_partner_conf.py new file mode 100644 index 00000000..ba0638c4 --- /dev/null +++ b/mail_split_by_partner_conf/tests/test_mail_split_by_partner_conf.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# © 2017 Phuc.nt - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging + +from mock import MagicMock +from odoo.tests.common import TransactionCase + + +class TestMailSplitByPartnerConf(TransactionCase): + def setUp(self): + super(TestMailSplitByPartnerConf, self).setUp() + self.ICP = self.env['ir.config_parameter'] + self.recipient1 = self.env['res.partner'].create({ + 'name': 'Test recipient 1', + 'email': 'recipient1@example.com', + 'notify_email': 'always', + }) + self.recipient2 = self.env['res.partner'].create({ + 'name': 'Test recipient 2', + 'email': 'recipient2@example.com', + 'notify_email': 'always', + }) + + def mail_send(self): + send_mail = MagicMock() + + def mock_send_email(self, message, *args, **kwargs): + message_id = message['Message-Id'] + if message['To']: + logging.info('Test send email to <%s>', message['To']) + send_mail() + return message_id + + self.env['ir.mail_server']._patch_method('send_email', mock_send_email) + + mail = self.env['mail.mail'].create({ + 'subject': 'Test mail', + 'email_from': 'from@domain.com', + 'email_to': 'to@domain.com', + 'body_html': '

This is a test message

', + 'recipient_ids': + [(6, 0, [self.recipient1.id, self.recipient2.id])] + }) + mail.send() + return mail, send_mail.call_count + + def test_send_mail_merge_recipients(self): + self.ICP.set_param('default_mail_split_by_partner_conf', 'merge') + mail_sent_count = self.mail_send()[1] + self.assertEqual(mail_sent_count, 1) + + def test_send_mail_split_recipients(self): + self.ICP.set_param('default_mail_split_by_partner_conf', 'split') + mail, mail_count = self.mail_send() + count_recipients = len(mail.recipient_ids) + if mail.email_to: + count_recipients += 1 + self.assertEqual(mail_count, count_recipients) diff --git a/mail_split_by_partner_conf/views/mail_mail_view.xml b/mail_split_by_partner_conf/views/mail_mail_view.xml new file mode 100644 index 00000000..103d349e --- /dev/null +++ b/mail_split_by_partner_conf/views/mail_mail_view.xml @@ -0,0 +1,17 @@ + + + + + + Mail Mail Form with split emails + mail.mail + + + + + + + + + diff --git a/mail_split_by_partner_conf/views/mail_template_view.xml b/mail_split_by_partner_conf/views/mail_template_view.xml new file mode 100644 index 00000000..9c0d8189 --- /dev/null +++ b/mail_split_by_partner_conf/views/mail_template_view.xml @@ -0,0 +1,17 @@ + + + + + + Email Template Form with split emails + mail.template + + + + + + + + + diff --git a/mail_split_by_partner_conf/wizard/__init__.py b/mail_split_by_partner_conf/wizard/__init__.py new file mode 100644 index 00000000..41a5fec1 --- /dev/null +++ b/mail_split_by_partner_conf/wizard/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# © 2017 Phuc.nt - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import mail_compose_message diff --git a/mail_split_by_partner_conf/wizard/mail_compose_message.py b/mail_split_by_partner_conf/wizard/mail_compose_message.py new file mode 100644 index 00000000..db2e0fbf --- /dev/null +++ b/mail_split_by_partner_conf/wizard/mail_compose_message.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# © 2017 Phuc.nt - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, api + + +class MailComposer(models.TransientModel): + _inherit = 'mail.compose.message' + + @api.model + def generate_email_for_composer(self, template_id, res_ids, fields=None): + if fields is not None: + fields.append('split_mail_by_recipients') + + return super(MailComposer, self).generate_email_for_composer( + template_id, res_ids, fields=fields) + + @api.multi + def get_mail_values(self, res_ids): + res = super(MailComposer, self).get_mail_values(res_ids) + recipient_ids = [] + if self.composition_mode == 'mass_mail' \ + and res[res_ids[0]].get('split_mail_by_recipients') == 'merge': + result = {} + for res_id in res_ids: + recipient_ids += [int(i[1]) for i in + res[res_id]['recipient_ids']] + + res[res_ids[0]]['recipient_ids'] = [(6, 0, recipient_ids)] + result[res_ids[0]] = res[res_ids[0]] + return result + + return res