From f1cce86a3ceb3376e9e92d4902a6489c4b8a9079 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Tue, 1 Oct 2024 14:32:16 -0500 Subject: [PATCH] [ADD] mail_forward: new module to forward messages from the chatter --- mail_forward/README.rst | 90 ++++ mail_forward/__init__.py | 2 + mail_forward/__manifest__.py | 27 ++ mail_forward/i18n/es.po | 83 ++++ mail_forward/i18n/mail_forward.pot | 82 ++++ mail_forward/models/__init__.py | 2 + mail_forward/models/mail_message.py | 57 +++ mail_forward/models/mail_thread.py | 19 + mail_forward/readme/CONTRIBUTORS.rst | 2 + mail_forward/readme/DESCRIPTION.rst | 2 + mail_forward/readme/USAGE.rst | 8 + mail_forward/static/description/index.html | 444 ++++++++++++++++++ .../forward_message/forward_message.esm.js | 44 ++ .../forward_message/forward_message.xml | 13 + .../message_action_list.xml | 12 + .../static/tests/tours/mail_forward.esm.js | 116 +++++ mail_forward/tests/__init__.py | 1 + mail_forward/tests/test_mail_forward.py | 77 +++ mail_forward/wizards/__init__.py | 1 + mail_forward/wizards/mail_compose_message.py | 39 ++ .../wizards/mail_compose_message_view.xml | 27 ++ setup/mail_forward/odoo/addons/mail_forward | 1 + setup/mail_forward/setup.py | 6 + 23 files changed, 1155 insertions(+) create mode 100644 mail_forward/README.rst create mode 100644 mail_forward/__init__.py create mode 100644 mail_forward/__manifest__.py create mode 100644 mail_forward/i18n/es.po create mode 100644 mail_forward/i18n/mail_forward.pot create mode 100644 mail_forward/models/__init__.py create mode 100644 mail_forward/models/mail_message.py create mode 100644 mail_forward/models/mail_thread.py create mode 100644 mail_forward/readme/CONTRIBUTORS.rst create mode 100644 mail_forward/readme/DESCRIPTION.rst create mode 100644 mail_forward/readme/USAGE.rst create mode 100644 mail_forward/static/description/index.html create mode 100644 mail_forward/static/src/components/forward_message/forward_message.esm.js create mode 100644 mail_forward/static/src/components/forward_message/forward_message.xml create mode 100644 mail_forward/static/src/components/message_action_list/message_action_list.xml create mode 100644 mail_forward/static/tests/tours/mail_forward.esm.js create mode 100644 mail_forward/tests/__init__.py create mode 100644 mail_forward/tests/test_mail_forward.py create mode 100644 mail_forward/wizards/__init__.py create mode 100644 mail_forward/wizards/mail_compose_message.py create mode 100644 mail_forward/wizards/mail_compose_message_view.xml create mode 120000 setup/mail_forward/odoo/addons/mail_forward create mode 100644 setup/mail_forward/setup.py diff --git a/mail_forward/README.rst b/mail_forward/README.rst new file mode 100644 index 0000000000..a221fd3df7 --- /dev/null +++ b/mail_forward/README.rst @@ -0,0 +1,90 @@ +==================== +Mail Forward Message +==================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:dd21150507ec3adfe337e04f08c50127d7ecd7644dde4d56e77ce0ba6723ddd0 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github + :target: https://github.com/OCA/social/tree/15.0/mail_forward + :alt: OCA/social +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/social-15-0/social-15-0-mail_forward + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/social&target_branch=15.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows users to forward messages from the chatter of any document to other users, +adding them as followers of the document without notifying the current followers. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use this module, follow these steps: + +* Navigate to the chatter of any document. +* Hover the mouse over any message in the chatter (excluding internal notes). +* A Forward icon will appear next to the message. +* Click the button to display a wizard with the message. +* Select the users to forward the message to. +* Click the 'Send Mail' button to send the message to the selected users. + +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Tecnativa + +Contributors +~~~~~~~~~~~~ + +* `Tecnativa `_: + * Carlos López + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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. + +This module is part of the `OCA/social `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/mail_forward/__init__.py b/mail_forward/__init__.py new file mode 100644 index 0000000000..aee8895e7a --- /dev/null +++ b/mail_forward/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizards diff --git a/mail_forward/__manifest__.py b/mail_forward/__manifest__.py new file mode 100644 index 0000000000..d693cfb9c1 --- /dev/null +++ b/mail_forward/__manifest__.py @@ -0,0 +1,27 @@ +# Copyright 2024 Tecnativa - Carlos Lopez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +{ + "name": "Mail Forward Message", + "version": "15.0.1.0.0", + "summary": "Forward messages from the chatter of any document to other users.", + "author": "Tecnativa, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/social", + "depends": ["mail", "contacts"], + "data": [ + "wizards/mail_compose_message_view.xml", + ], + "assets": { + "web.assets_backend": [ + "mail_forward/static/src/components/**/*.esm.js", + ], + "web.assets_qweb": [ + "mail_forward/static/src/components/*/*.xml", + ], + "web.assets_tests": [ + "mail_forward/static/tests/tours/**/*", + ], + }, + "installable": True, + "auto_install": False, + "license": "AGPL-3", +} diff --git a/mail_forward/i18n/es.po b/mail_forward/i18n/es.po new file mode 100644 index 0000000000..c33ce81275 --- /dev/null +++ b/mail_forward/i18n/es.po @@ -0,0 +1,83 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mail_forward +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-10-02 12:25+0000\n" +"PO-Revision-Date: 2024-10-02 07:27-0500\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.0.1\n" + +#. module: mail_forward +#: code:addons/mail_forward/models/mail_message.py:0 +#, python-format +msgid "---------- Forwarded message ---------" +msgstr "---------- Mensaje reenviado ---------" + +#. module: mail_forward +#: code:addons/mail_forward/models/mail_message.py:0 +#, python-format +msgid "Date" +msgstr "Fecha" + +#. module: mail_forward +#: model:ir.model,name:mail_forward.model_mail_thread +msgid "Email Thread" +msgstr "Hilo de correos electrónicos" + +#. module: mail_forward +#: model:ir.model,name:mail_forward.model_mail_compose_message +msgid "Email composition wizard" +msgstr "Asistente de composición de correos electrónicos" + +#. module: mail_forward +#. openerp-web +#: code:addons/mail_forward/models/mail_message.py:0 +#: code:addons/mail_forward/static/src/components/forward_message/forward_message.xml:0 +#, python-format +msgid "Forward Message" +msgstr "Reenviar mensaje" + +#. module: mail_forward +#: code:addons/mail_forward/models/mail_message.py:0 +#, python-format +msgid "From" +msgstr "De" + +#. module: mail_forward +#: code:addons/mail_forward/wizards/mail_compose_message.py:0 +#, python-format +msgid "Fwd:" +msgstr "" + +#. module: mail_forward +#: model:ir.model,name:mail_forward.model_mail_message +msgid "Message" +msgstr "Mensaje" + +#. module: mail_forward +#: code:addons/mail_forward/wizards/mail_compose_message.py:0 +#, python-format +msgid "Re:" +msgstr "" + +#. module: mail_forward +#: code:addons/mail_forward/models/mail_message.py:0 +#, python-format +msgid "Subject" +msgstr "Asunto" + +#. module: mail_forward +#: code:addons/mail_forward/models/mail_message.py:0 +#, python-format +msgid "To" +msgstr "Para" diff --git a/mail_forward/i18n/mail_forward.pot b/mail_forward/i18n/mail_forward.pot new file mode 100644 index 0000000000..3b3cc7746c --- /dev/null +++ b/mail_forward/i18n/mail_forward.pot @@ -0,0 +1,82 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mail_forward +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-10-02 12:25+0000\n" +"PO-Revision-Date: 2024-10-02 12:25+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mail_forward +#: code:addons/mail_forward/models/mail_message.py:0 +#, python-format +msgid "---------- Forwarded message ---------" +msgstr "" + +#. module: mail_forward +#: code:addons/mail_forward/models/mail_message.py:0 +#, python-format +msgid "Date" +msgstr "" + +#. module: mail_forward +#: model:ir.model,name:mail_forward.model_mail_thread +msgid "Email Thread" +msgstr "" + +#. module: mail_forward +#: model:ir.model,name:mail_forward.model_mail_compose_message +msgid "Email composition wizard" +msgstr "" + +#. module: mail_forward +#. openerp-web +#: code:addons/mail_forward/models/mail_message.py:0 +#: code:addons/mail_forward/static/src/components/forward_message/forward_message.xml:0 +#: code:addons/mail_forward/static/src/components/forward_message/forward_message.xml:0 +#, python-format +msgid "Forward Message" +msgstr "" + +#. module: mail_forward +#: code:addons/mail_forward/models/mail_message.py:0 +#, python-format +msgid "From" +msgstr "" + +#. module: mail_forward +#: code:addons/mail_forward/wizards/mail_compose_message.py:0 +#, python-format +msgid "Fwd:" +msgstr "" + +#. module: mail_forward +#: model:ir.model,name:mail_forward.model_mail_message +msgid "Message" +msgstr "" + +#. module: mail_forward +#: code:addons/mail_forward/wizards/mail_compose_message.py:0 +#, python-format +msgid "Re:" +msgstr "" + +#. module: mail_forward +#: code:addons/mail_forward/models/mail_message.py:0 +#, python-format +msgid "Subject" +msgstr "" + +#. module: mail_forward +#: code:addons/mail_forward/models/mail_message.py:0 +#, python-format +msgid "To" +msgstr "" diff --git a/mail_forward/models/__init__.py b/mail_forward/models/__init__.py new file mode 100644 index 0000000000..eccc2881b4 --- /dev/null +++ b/mail_forward/models/__init__.py @@ -0,0 +1,2 @@ +from . import mail_message +from . import mail_thread diff --git a/mail_forward/models/mail_message.py b/mail_forward/models/mail_message.py new file mode 100644 index 0000000000..b5bacd6214 --- /dev/null +++ b/mail_forward/models/mail_message.py @@ -0,0 +1,57 @@ +# Copyright 2024 Tecnativa - Carlos Lopez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +from odoo import _, models +from odoo.tools import format_datetime + + +class MailMessage(models.Model): + _inherit = "mail.message" + + def action_wizard_forward(self): + view = self.env.ref("mail_forward.mail_compose_message_forward_form") + action = self.env["ir.actions.actions"]._for_xml_id( + "mail.action_email_compose_message_wizard" + ) + action["name"] = _("Forward Message") + action["view_mode"] = view.type + action["views"] = [(view.id, view.type)] + action["context"] = { + "default_model": self.model, + "default_res_id": self.res_id, + "default_composition_mode": "comment", + "default_body": self._build_message_body_for_forward(), + "default_attachment_ids": self.attachment_ids.ids, + "default_is_log": False, + "default_notify": True, + "force_email": True, + "message_forwarded_id": self.id, + } + return action + + def _build_message_body_for_forward(self): + partner_emails = [ + partner.email_formatted + for partner in self.partner_ids + if partner.email_formatted + ] + return """ +


+ {str_forwarded_message}
+ {str_from}: {email_from}
+ {str_date}: {date}
+ {str_subject}: {subject}
+ {str_to}: {to}
+

+ {body} + """.format( + str_forwarded_message=_("---------- Forwarded message ---------"), + email_from=self.email_from, + date=format_datetime(self.env, self.date), + subject=self.subject, + to=", ".join(partner_emails), + str_date=_("Date"), + str_subject=_("Subject"), + str_from=_("From"), + str_to=_("To"), + body=self.body, + ) diff --git a/mail_forward/models/mail_thread.py b/mail_forward/models/mail_thread.py new file mode 100644 index 0000000000..ea0bfac3e1 --- /dev/null +++ b/mail_forward/models/mail_thread.py @@ -0,0 +1,19 @@ +# Copyright 2024 Tecnativa - Carlos Lopez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +from odoo import models + + +class MailThread(models.AbstractModel): + _inherit = "mail.thread" + + def _notify_compute_recipients(self, message, msg_vals): + recipients_data = super()._notify_compute_recipients(message, msg_vals) + # only notify to explicit partners, remove others(followers). + if self.env.context.get("message_forwarded_id"): + current_partners_ids = message.partner_ids.ids + new_recipeints = [] + for recipeint in recipients_data: + if recipeint["id"] in current_partners_ids: + new_recipeints.append(recipeint) + recipients_data = new_recipeints + return recipients_data diff --git a/mail_forward/readme/CONTRIBUTORS.rst b/mail_forward/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..fa014938a8 --- /dev/null +++ b/mail_forward/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* `Tecnativa `_: + * Carlos López \ No newline at end of file diff --git a/mail_forward/readme/DESCRIPTION.rst b/mail_forward/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..10e246711c --- /dev/null +++ b/mail_forward/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module allows users to forward messages from the chatter of any document to other users, +adding them as followers of the document without notifying the current followers. diff --git a/mail_forward/readme/USAGE.rst b/mail_forward/readme/USAGE.rst new file mode 100644 index 0000000000..611bacf030 --- /dev/null +++ b/mail_forward/readme/USAGE.rst @@ -0,0 +1,8 @@ +To use this module, follow these steps: + +* Navigate to the chatter of any document. +* Hover the mouse over any message in the chatter (excluding internal notes). +* A Forward icon will appear next to the message. +* Click the button to display a wizard with the message. +* Select the users to forward the message to. +* Click the 'Send Mail' button to send the message to the selected users. diff --git a/mail_forward/static/description/index.html b/mail_forward/static/description/index.html new file mode 100644 index 0000000000..7509b9aab2 --- /dev/null +++ b/mail_forward/static/description/index.html @@ -0,0 +1,444 @@ + + + + + +Mail Forward Message + + + +
+

Mail Forward Message

+ + +

Beta License: AGPL-3 OCA/social Translate me on Weblate Try me on Runboat

+

This module allows users to forward messages from the chatter of any document to other users, +adding them as followers of the document without notifying the current followers.

+

Table of contents

+ +
+

Usage

+

To use this module, follow these steps:

+
    +
  • Navigate to the chatter of any document.
  • +
  • Hover the mouse over any message in the chatter (excluding internal notes).
  • +
  • A Forward icon will appear next to the message.
  • +
  • Click the button to display a wizard with the message.
  • +
  • Select the users to forward the message to.
  • +
  • Click the ‘Send Mail’ button to send the message to the selected users.
  • +
+
+
+

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 to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Tecnativa
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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.

+

This module is part of the OCA/social project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/mail_forward/static/src/components/forward_message/forward_message.esm.js b/mail_forward/static/src/components/forward_message/forward_message.esm.js new file mode 100644 index 0000000000..654b74a077 --- /dev/null +++ b/mail_forward/static/src/components/forward_message/forward_message.esm.js @@ -0,0 +1,44 @@ +/** @odoo-module **/ +/* Copyright 2024 Tecnativa - Carlos Lopez + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +*/ +import {registerMessagingComponent} from "@mail/utils/messaging_component"; +const {Component} = owl; + +export class ForwardMessage extends Component { + async onClickForwardMessage() { + const composer = this.props.message.originThread.composer; + const action = await this.env.services.rpc({ + model: "mail.message", + method: "action_wizard_forward", + args: [[this.props.message.id]], + }); + this.env.bus.trigger("do-action", { + action: action, + options: { + additional_context: { + active_id: this.props.message.id, + active_ids: [this.props.message.id], + active_model: "mail.message", + }, + on_close: () => { + if (composer.exists()) { + composer._reset(); + if (composer.activeThread) { + composer.activeThread.loadNewMessages(); + composer.activeThread.refreshFollowers(); + composer.activeThread.fetchAndUpdateSuggestedRecipients(); + } + } + }, + }, + }); + } +} + +ForwardMessage.template = "mail_forward.ForwardMessage"; +ForwardMessage.props = { + message: Object, +}; + +registerMessagingComponent(ForwardMessage); diff --git a/mail_forward/static/src/components/forward_message/forward_message.xml b/mail_forward/static/src/components/forward_message/forward_message.xml new file mode 100644 index 0000000000..894d8a0c20 --- /dev/null +++ b/mail_forward/static/src/components/forward_message/forward_message.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/mail_forward/static/src/components/message_action_list/message_action_list.xml b/mail_forward/static/src/components/message_action_list/message_action_list.xml new file mode 100644 index 0000000000..4f13fa8fb2 --- /dev/null +++ b/mail_forward/static/src/components/message_action_list/message_action_list.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/mail_forward/static/tests/tours/mail_forward.esm.js b/mail_forward/static/tests/tours/mail_forward.esm.js new file mode 100644 index 0000000000..363e1cbe2b --- /dev/null +++ b/mail_forward/static/tests/tours/mail_forward.esm.js @@ -0,0 +1,116 @@ +/** @odoo-module */ + +import tour from "web_tour.tour"; +const contact_steps = [ + ...tour.stepUtils.goToAppSteps("contacts.menu_contacts", "Go to the Contacts."), + { + content: "Search Contact", + trigger: ".o_searchview_input", + run: "text Test", + }, + { + trigger: ".o_menu_item", + content: "Validate search", + run: "click", + }, + { + content: "Switch to list view", + trigger: ".o_list", + run: "click", + }, + { + content: "Open contact", + trigger: ".o_list_table td[name='display_name']:contains('Test')", + }, +]; +tour.register( + "mail_forward.mail_forward_tour", + { + test: true, + url: "/web", + }, + [ + ...contact_steps, + { + content: "Open Chat", + trigger: ".o_ChatterTopbar_buttonSendMessage", + run: "click", + }, + { + content: "Write a message", + trigger: ".o_ComposerTextInput_textarea", + run: "text Hello World", + }, + { + content: "Post a message", + trigger: ".o_Composer_buttonSend", + }, + { + content: "Hover a message", + trigger: "div.o_Message.o-discussion", + run: "click", + }, + { + content: "Forward a message", + trigger: ".o_MessageActionList_actionForward", + run: "click", + }, + { + content: "Select a Forward", + trigger: ".o_field_widget[name=partner_ids] input", + extra_trigger: ".modal-dialog", + run: "text Forward", + }, + { + content: "Valid Forward", + trigger: ".ui-menu-item a:contains(Forward)", + run: "click", + in_modal: false, + }, + { + content: "Send mail", + trigger: "button[name=action_send_mail]", + run: "click", + }, + { + content: "Check Mail Forward", + trigger: + ".o_Message_prettyBody:contains(---------- Forwarded message ---------)", + }, + ] +); + +tour.register( + "mail_forward.mail_note_not_forward_tour", + { + test: true, + url: "/web", + }, + [ + ...contact_steps, + { + content: "Open Chat", + trigger: ".o_ChatterTopbar_buttonLogNote", + run: "click", + }, + { + content: "Write a note", + trigger: ".o_ComposerTextInput_textarea", + run: "text This is a note", + }, + { + content: "Post a note", + trigger: ".o_Composer_buttonSend", + }, + { + content: "Hover a note", + trigger: "div.o_Message.o-not-discussion", + run: "click", + }, + { + content: "Verify that the Forward button does not exist.", + trigger: + "div.o_Message.o-not-discussion:not(.o_MessageActionList_actionForward)", + }, + ] +); diff --git a/mail_forward/tests/__init__.py b/mail_forward/tests/__init__.py new file mode 100644 index 0000000000..d83263f3cc --- /dev/null +++ b/mail_forward/tests/__init__.py @@ -0,0 +1 @@ +from . import test_mail_forward diff --git a/mail_forward/tests/test_mail_forward.py b/mail_forward/tests/test_mail_forward.py new file mode 100644 index 0000000000..b6e632b353 --- /dev/null +++ b/mail_forward/tests/test_mail_forward.py @@ -0,0 +1,77 @@ +# Copyright 2024 Tecnativa - Carlos Lopez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo.tests import Form, RecordCapturer, tagged +from odoo.tests.common import HttpCase + +from odoo.addons.mail.tests.test_mail_composer import TestMailComposer + + +@tagged("post_install", "-at_install") +class TestMailForward(TestMailComposer, HttpCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.partner_follower1 = cls.env["res.partner"].create( + {"name": "Follower1", "email": "follower1@example.com"} + ) + cls.partner_follower2 = cls.env["res.partner"].create( + {"name": "Follower2", "email": "follower2@example.com"} + ) + cls.partner_forward = cls.env["res.partner"].create( + {"name": "Forward", "email": "forward@example.com"} + ) + + def test_01_mail_forward(self): + """ + Send an email to followers + and forward it to another partner. + """ + ctx = { + "default_model": self.test_record._name, + "default_res_id": self.test_record.id, + } + composer_form = Form(self.env["mail.compose.message"].with_context(**ctx)) + composer_form.body = "

Hello

" + composer_form.partner_ids.add(self.partner_follower1) + composer_form.partner_ids.add(self.partner_follower2) + composer = composer_form.save() + with self.mock_mail_gateway(): + composer._action_send_mail() + # Verify recipients of mail.message + message = self.test_record.message_ids[0] + self.assertEqual(len(message.partner_ids), 2) + self.assertIn(self.partner_follower1, message.partner_ids) + self.assertIn(self.partner_follower2, message.partner_ids) + self.assertNotIn(self.partner_forward, message.partner_ids) + self.assertNotIn("---------- Forwarded message ---------", message.body) + # Forward the email + # only the partner_forward should receive the email + action_forward = message.action_wizard_forward() + Message = self.env["mail.compose.message"].with_context( + **action_forward["context"] + ) + composer_form = Form(Message, view=action_forward["views"][0][0]) + composer_form.partner_ids.add(self.partner_forward) + composer = composer_form.save() + message_domain = [ + ("model", "=", self.test_record._name), + ("res_id", "=", self.test_record.id), + ] + with RecordCapturer(self.env["mail.message"], message_domain) as capture: + with self.mock_mail_gateway(): + composer._action_send_mail() + # Verify recipients of mail.message + forward_message = capture.records + self.assertEqual(len(forward_message.partner_ids), 1) + self.assertNotIn(self.partner_follower1, forward_message.partner_ids) + self.assertIn(self.partner_forward, forward_message.partner_ids) + self.assertIn("---------- Forwarded message ---------", forward_message.body) + + def test_02_mail_forward_tour(self): + self.start_tour("/web", "mail_forward.mail_forward_tour", login="admin") + + def test_03_mail_note_not_forward_tour(self): + self.start_tour( + "/web", "mail_forward.mail_note_not_forward_tour", login="admin" + ) diff --git a/mail_forward/wizards/__init__.py b/mail_forward/wizards/__init__.py new file mode 100644 index 0000000000..b528d997d1 --- /dev/null +++ b/mail_forward/wizards/__init__.py @@ -0,0 +1 @@ +from . import mail_compose_message diff --git a/mail_forward/wizards/mail_compose_message.py b/mail_forward/wizards/mail_compose_message.py new file mode 100644 index 0000000000..19ccfcb890 --- /dev/null +++ b/mail_forward/wizards/mail_compose_message.py @@ -0,0 +1,39 @@ +# Copyright 2024 Tecnativa - Carlos Lopez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +from odoo import Command, _, api, models + + +class MailComposeMessage(models.TransientModel): + _inherit = "mail.compose.message" + + @api.model + def get_record_data(self, values): + result = super().get_record_data(values) + re_prefix = _("Re:") + fwd_prefix = _("Fwd:") + if self.env.context.get("message_forwarded_id"): + # remove 'Re: ' prefixes and add 'Fwd:' prefix to the subject + subject = result.get("subject") + if subject and subject.startswith(re_prefix): + subject = "%s %s" % (fwd_prefix, subject[4:]) + result["subject"] = subject + return result + + def _action_send_mail(self, auto_commit=False): + # duplicate attachments from original message + message_forwarded_id = self.env.context.get("message_forwarded_id") + if message_forwarded_id: + message_forwarded = self.env["mail.message"].browse(message_forwarded_id) + for wizard in self: + new_attachment_ids = [] + for attachment in wizard.attachment_ids: + if attachment in message_forwarded.attachment_ids: + new_attachment = attachment.copy( + {"res_model": "mail.compose.message", "res_id": wizard.id} + ) + new_attachment_ids.append(new_attachment.id) + else: + new_attachment_ids.append(attachment.id) + new_attachment_ids.reverse() + wizard.write({"attachment_ids": [Command.set(new_attachment_ids)]}) + return super()._action_send_mail(auto_commit=auto_commit) diff --git a/mail_forward/wizards/mail_compose_message_view.xml b/mail_forward/wizards/mail_compose_message_view.xml new file mode 100644 index 0000000000..bda46bed9c --- /dev/null +++ b/mail_forward/wizards/mail_compose_message_view.xml @@ -0,0 +1,27 @@ + + + + mail.compose.message.form.forward + mail.compose.message + primary + + + + + 1 + + + 1 + + + 1 + + + 1 + + + + diff --git a/setup/mail_forward/odoo/addons/mail_forward b/setup/mail_forward/odoo/addons/mail_forward new file mode 120000 index 0000000000..07914b3022 --- /dev/null +++ b/setup/mail_forward/odoo/addons/mail_forward @@ -0,0 +1 @@ +../../../../mail_forward \ No newline at end of file diff --git a/setup/mail_forward/setup.py b/setup/mail_forward/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/mail_forward/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)