diff --git a/README.md b/README.md index f3121ca370..87704dc345 100644 --- a/README.md +++ b/README.md @@ -17,23 +17,7 @@ [//]: # (addons) -Available addons ----------------- -addon | version | maintainers | summary ---- | --- | --- | --- -[base_search_mail_content](base_search_mail_content/) | 17.0.1.0.0 | | Base Search Mail Content -[mail_activity_board](mail_activity_board/) | 17.0.1.0.1 | | Add Activity Boards -[mail_activity_team](mail_activity_team/) | 17.0.1.0.0 | | Add Teams to Activities -[mail_attach_existing_attachment](mail_attach_existing_attachment/) | 17.0.1.0.0 | | Adding attachment on the object by sending this one -[mail_debrand](mail_debrand/) | 17.0.1.0.0 | [![pedrobaeza](https://github.com/pedrobaeza.png?size=30px)](https://github.com/pedrobaeza) [![joao-p-marques](https://github.com/joao-p-marques.png?size=30px)](https://github.com/joao-p-marques) | Remove Odoo branding in sent emails Removes anchor 20characters -[mail_notification_custom_subject](mail_notification_custom_subject/) | 17.0.1.0.0 | [![yajo](https://github.com/yajo.png?size=30px)](https://github.com/yajo) | Apply a custom subject to mail notifications -[mail_optional_autofollow](mail_optional_autofollow/) | 17.0.1.0.0 | | Choose if you want to automatically add new recipients as followers on mail.compose.message -[mail_outbound_static](mail_outbound_static/) | 17.0.1.0.1 | | Allows you to configure the from header for a mail server. -[mail_partner_forwarding](mail_partner_forwarding/) | 17.0.1.0.1 | | Forwarding notifications for partners -[mail_partner_opt_out](mail_partner_opt_out/) | 17.0.1.0.0 | | Add the partner's email to the blackmailed list -[mail_send_confirmation](mail_send_confirmation/) | 17.0.1.0.0 | | Mail Send Confirmation -[mass_mailing_partner](mass_mailing_partner/) | 17.0.1.0.0 | | Link partners with mass-mailing -[mass_mailing_resend](mass_mailing_resend/) | 17.0.1.1.0 | [![pedrobaeza](https://github.com/pedrobaeza.png?size=30px)](https://github.com/pedrobaeza) | Resend mass mailings +This part will be replaced when running the oca-gen-addons-table script from OCA/maintainer-tools. [//]: # (end addons) diff --git a/mail_tracking/README.rst b/mail_tracking/README.rst index 91c3e83eb5..cfb06373e3 100644 --- a/mail_tracking/README.rst +++ b/mail_tracking/README.rst @@ -17,20 +17,20 @@ Email tracking :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/16.0/mail_tracking + :target: https://github.com/OCA/social/tree/17.0/mail_tracking :alt: OCA/social .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/social-16-0/social-16-0-mail_tracking + :target: https://translation.odoo-community.org/projects/social-17-0/social-17-0-mail_tracking :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=16.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/social&target_branch=17.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| This module shows email notification tracking status for any messages in -mail thread (chatter). Each notified partner will have an intuitive icon just -right to his name. +mail thread (chatter). Each notified partner will have an intuitive icon +just right to his name. **Table of contents** @@ -40,107 +40,95 @@ right to his name. Installation ============ -If you're using a multi-database installation (with or without dbfilter option) -where /web/databse/selector returns a list of more than one database, then -you need to add ``mail_tracking`` addon to wide load addons list -(by default, only ``web`` addon), setting ``--load`` option. +If you're using a multi-database installation (with or without dbfilter +option) where /web/databse/selector returns a list of more than one +database, then you need to add ``mail_tracking`` addon to wide load +addons list (by default, only ``web`` addon), setting ``--load`` option. For example, ``--load=web,mail,mail_tracking`` Configuration ============= -As there can be scenarios where sending a tracking img in the email body is -not desired, there is a global system parameter +As there can be scenarios where sending a tracking img in the email body +is not desired, there is a global system parameter "mail_tracking.tracking_img_disabled" that can be set to True to remove -the tracking img from all outgoing emails. Note that the **Opened** status -will not be available in this case. +the tracking img from all outgoing emails. Note that the **Opened** +status will not be available in this case. Usage ===== -When user sends a message in mail_thread (chatter), for instance in partner -form, then an email tracking is created for each email notification. Then a -status icon will appear just right to name of notified partner. +When user sends a message in mail_thread (chatter), for instance in +partner form, then an email tracking is created for each email +notification. Then a status icon will appear just right to name of +notified partner. These are all available status icons: -.. |sent| image:: https://raw.githubusercontent.com/OCA/social/16.0/mail_tracking/static/src/img/sent.png - :width: 10px +|unknown| **Unknown**: No email tracking info available. Maybe this +notified partner has 'Receive Inbox Notifications by Email' == 'Never' -.. |delivered| image:: https://raw.githubusercontent.com/OCA/social/16.0/mail_tracking/static/src/img/delivered.png - :width: 15px +|waiting| **Waiting**: Waiting to be sent -.. |opened| image:: https://raw.githubusercontent.com/OCA/social/16.0/mail_tracking/static/src/img/opened.png - :width: 15px +|error| **Error**: Error while sending -.. |error| image:: https://raw.githubusercontent.com/OCA/social/16.0/mail_tracking/static/src/img/error.png - :width: 10px +|sent| **Sent**: Sent to SMTP server configured -.. |waiting| image:: https://raw.githubusercontent.com/OCA/social/16.0/mail_tracking/static/src/img/waiting.png - :width: 10px +|delivered| **Delivered**: Delivered to final MX server -.. |unknown| image:: https://raw.githubusercontent.com/OCA/social/16.0/mail_tracking/static/src/img/unknown.png - :width: 10px +|opened| **Opened**: Opened by partner -.. |cc| image:: https://raw.githubusercontent.com/OCA/social/16.0/mail_tracking/static/src/img/cc.png - :width: 10px +|cc| **Cc**: It's a Carbon-Copy recipient. Can't know the status so is +'Unknown' -.. |noemail| image:: https://raw.githubusercontent.com/OCA/social/16.0/mail_tracking/static/src/img/no_email.png - :width: 10px - -.. |anonuser| image:: https://raw.githubusercontent.com/OCA/social/16.0/mail_tracking/static/src/img/anon_user.png - :width: 10px - -|unknown| **Unknown**: No email tracking info available. Maybe this notified partner has 'Receive Inbox Notifications by Email' == 'Never' - -|waiting| **Waiting**: Waiting to be sent - -|error| **Error**: Error while sending - -|sent| **Sent**: Sent to SMTP server configured - -|delivered| **Delivered**: Delivered to final MX server - -|opened| **Opened**: Opened by partner - -|cc| **Cc**: It's a Carbon-Copy recipient. Can't know the status so is 'Unknown' - -|noemail| **No Email**: The partner doesn't have a defined email - -|anonuser| **No Partner**: The recipient doesn't have a defined partner +|noemail| **No Email**: The partner doesn't have a defined email +|anonuser| **No Partner**: The recipient doesn't have a defined partner If you want to see all tracking emails and events you can go to -* Settings > Technical > Email > Tracking emails -* Settings > Technical > Email > Tracking events +- Settings > Technical > Email > Tracking emails +- Settings > Technical > Email > Tracking events -When the message generates an 'error' status, it will apear on discuss 'Failed' -channel. Any view with chatter can show the failed messages +When the message generates an 'error' status, it will apear on discuss +'Failed' channel. Any view with chatter can show the failed messages too. -* Discuss +- Discuss - .. image:: https://raw.githubusercontent.com/OCA/social/16.0/mail_tracking/static/img/failed_message_discuss.png + |image| -* Chatter +- Chatter - .. image:: https://raw.githubusercontent.com/OCA/social/16.0/mail_tracking/static/img/failed_message_widget.png + |image1| -You can use "Failed sent messages" filter present in all views to show records -with messages in failed status and that needs an user action. +You can use "Failed sent messages" filter present in all views to show +records with messages in failed status and that needs an user action. -* Filter +- Filter - .. image:: https://raw.githubusercontent.com/OCA/social/16.0/mail_tracking/static/img/failed_message_filter.png + |image2| + +.. |unknown| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_tracking/static/src/img/unknown.png +.. |waiting| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_tracking/static/src/img/waiting.png +.. |error| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_tracking/static/src/img/error.png +.. |sent| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_tracking/static/src/img/sent.png +.. |delivered| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_tracking/static/src/img/delivered.png +.. |opened| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_tracking/static/src/img/opened.png +.. |cc| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_tracking/static/src/img/cc.png +.. |noemail| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_tracking/static/src/img/no_email.png +.. |anonuser| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_tracking/static/src/img/anon_user.png +.. |image| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_tracking/static/img/failed_message_discuss.png +.. |image1| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_tracking/static/img/failed_message_widget.png +.. |image2| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_tracking/static/img/failed_message_filter.png Known issues / Roadmap ====================== -* Integrate with the core `mail.notification` model. A soft way would be to write a - notification event along with the mail.tracking.event ones. Another way could be - to merge both models and build the module features on top of it. This might imply - a refactor though. +- Integrate with the core mail.notification model. A soft way would be + to write a notification event along with the mail.tracking.event + ones. Another way could be to merge both models and build the module + features on top of it. This might imply a refactor though. Bug Tracker =========== @@ -148,7 +136,7 @@ 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 `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -156,41 +144,44 @@ Credits ======= Authors -~~~~~~~ +------- * Tecnativa Contributors -~~~~~~~~~~~~ +------------ + +- `Tecnativa `__: + + - Pedro M. Baeza + - Antonio Espinosa + - David Vidal + - Ernesto Tejeda + - Rafael Blasco + - Alexandre Díaz -* `Tecnativa `_: +- `Eezee-IT `__: - * Pedro M. Baeza - * Antonio Espinosa - * David Vidal - * Ernesto Tejeda - * Rafael Blasco - * Alexandre Díaz + - Asma Elferkhsi -* `Eezee-IT `_: - * Asma Elferkhsi +- `Vauxoo `__: -* `Vauxoo `_: - * Agustín Payen Sandoval + - Agustín Payen Sandoval Other credits -~~~~~~~~~~~~~ +------------- Images ------- +~~~~~~ -* Odoo Community Association: `Icon `_. -* Thanks to `LlubNek `_ and `Openclipart - `_ for `the icon - `_. +- Odoo Community Association: + `Icon `__. +- Thanks to `LlubNek `__ + and `Openclipart `__ for `the + icon `__. Maintainers -~~~~~~~~~~~ +----------- This module is maintained by the OCA. @@ -202,6 +193,6 @@ 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. +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_tracking/__manifest__.py b/mail_tracking/__manifest__.py index 166b9d675c..7236da2b94 100644 --- a/mail_tracking/__manifest__.py +++ b/mail_tracking/__manifest__.py @@ -1,5 +1,5 @@ -# Copyright 2016 Antonio Espinosa - -# Copyright 2018 David Vidal - +# Copyright 2016 Tecnativa - Antonio Espinosa +# Copyright 2018 Tecnativa - David Vidal # Copyright 2018 Tecnativa - Ernesto Tejeda # Copyright 2019 Tecnativa - Pedro M. Baeza # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). @@ -7,7 +7,7 @@ { "name": "Email tracking", "summary": "Email tracking system for all mails sent", - "version": "16.0.1.0.4", + "version": "17.0.1.0.0", "category": "Social Network", "website": "https://github.com/OCA/social", "author": ("Tecnativa, " "Odoo Community Association (OCA)"), @@ -26,32 +26,30 @@ ], "assets": { "web.assets_backend": [ + "mail_tracking/static/src/web/chatter/*", + "mail_tracking/static/src/web/message/*", "mail_tracking/static/src/client_actions/failed_message_storage.esm.js", - "mail_tracking/static/src/models/chatter.esm.js", - "mail_tracking/static/src/models/discuss_sidebar_mailbox_view.esm.js", - "mail_tracking/static/src/models/discuss_view.esm.js", - "mail_tracking/static/src/models/mailbox.esm.js", - "mail_tracking/static/src/models/message_list_view_item.esm.js", - "mail_tracking/static/src/models/message_list_view.esm.js", - "mail_tracking/static/src/models/message_view.esm.js", - "mail_tracking/static/src/models/message.esm.js", - "mail_tracking/static/src/models/messaging_initializer.esm.js", - "mail_tracking/static/src/models/messaging.esm.js", - "mail_tracking/static/src/models/thread.esm.js", - "mail_tracking/static/src/components/discuss/discuss.xml", - "mail_tracking/static/src/components/message/message.xml", - "mail_tracking/static/src/components/message/message.esm.js", - "mail_tracking/static/src/components/message/message.scss", - "mail_tracking/static/src/components/message_list/message_list.esm.js", + # "mail_tracking/static/src/models/chatter.esm.js", + # "mail_tracking/static/src/models/discuss_sidebar_mailbox_view.esm.js", + # "mail_tracking/static/src/models/discuss_view.esm.js", + # "mail_tracking/static/src/models/mailbox.esm.js", + # "mail_tracking/static/src/models/message_list_view_item.esm.js", + # "mail_tracking/static/src/models/message_list_view.esm.js", + # "mail_tracking/static/src/models/message_view.esm.js", + # "mail_tracking/static/src/models/message.esm.js", + # "mail_tracking/static/src/models/messaging_initializer.esm.js", + # "mail_tracking/static/src/models/messaging.esm.js", + # "mail_tracking/static/src/models/thread.esm.js", + # "mail_tracking/static/src/components/discuss/discuss.xml", + # "mail_tracking/static/src/services/**/*js", + # "mail_tracking/static/src/components/message_list/message_list.esm.js", "mail_tracking/static/src/components/failed_message/failed_message.xml", "mail_tracking/static/src/components/failed_message/failed_message.esm.js", "mail_tracking/static/src/components/failed_message/failed_message.scss", - "mail_tracking/static/src/components/failed_message_list/failed_message_list.xml", - "mail_tracking/static/src/components/failed_message_list/failed_message_list.esm.js", # noqa: B950 - "mail_tracking/static/src/components/discuss_sidebar_mailbox/discuss_sidebar_mailbox.xml", # noqa: B950 - "mail_tracking/static/src/components/discuss_sidebar_mailbox/discuss_sidebar_mailbox.esm.js", # noqa: B950 + # "mail_tracking/static/src/components/failed_message_list/*, + # "mail_tracking/static/src/components/discuss_sidebar_mailbox/*, "mail_tracking/static/src/components/thread_view/thread_view.xml", - "mail_tracking/static/src/components/thread_view/thread_view.scss", + # "mail_tracking/static/src/components/thread_view/thread_view.scss", ], }, "demo": ["demo/demo.xml"], diff --git a/mail_tracking/controllers/__init__.py b/mail_tracking/controllers/__init__.py index e1674a137e..8c1b71247d 100644 --- a/mail_tracking/controllers/__init__.py +++ b/mail_tracking/controllers/__init__.py @@ -1,4 +1,4 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import main -from . import discuss +from . import webclient diff --git a/mail_tracking/controllers/discuss.py b/mail_tracking/controllers/discuss.py deleted file mode 100644 index b41a993416..0000000000 --- a/mail_tracking/controllers/discuss.py +++ /dev/null @@ -1,28 +0,0 @@ -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import http - -from odoo.addons.mail.controllers.discuss import DiscussController - - -class MailTrackingDiscussController(DiscussController): - @http.route() - def mail_init_messaging(self, **kwargs): - """Route used to initial values of Discuss app""" - values = super().mail_init_messaging(**kwargs) - values.update( - {"failed_counter": http.request.env["mail.message"].get_failed_count()} - ) - return values - - @http.route("/mail/failed/messages", methods=["POST"], type="json", auth="user") - def discuss_failed_messages(self, max_id=None, min_id=None, limit=30, **kwargs): - return ( - http.request.env["mail.message"] - ._message_fetch( - domain=[("is_failed_message", "=", True)], - max_id=max_id, - min_id=min_id, - limit=limit, - ) - .message_format() - ) diff --git a/mail_tracking/controllers/main.py b/mail_tracking/controllers/main.py index ab1ca78199..1f64c6a546 100644 --- a/mail_tracking/controllers/main.py +++ b/mail_tracking/controllers/main.py @@ -42,7 +42,7 @@ def _request_metadata(self): @http.route( [ - "/mail/tracking/open/" "//blank.gif", + "/mail/tracking/open///blank.gif", "/mail/tracking/open/" "///blank.gif", ], diff --git a/mail_tracking/controllers/webclient.py b/mail_tracking/controllers/webclient.py new file mode 100644 index 0000000000..b6e49a11e5 --- /dev/null +++ b/mail_tracking/controllers/webclient.py @@ -0,0 +1,30 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo.http import request, route + +from odoo.addons.mail.controllers.webclient import WebclientController +from odoo.addons.mail.models.discuss.mail_guest import add_guest_to_context + + +class MailTrackingWebclientController(WebclientController): + @route() + @add_guest_to_context + def mail_init_messaging(self): + """Route used to initial values of Discuss app""" + values = super().mail_init_messaging() + values.update( + {"failed_counter": request.env["mail.message"].get_failed_count()} + ) + return values + + @route("/mail/failed/messages", methods=["POST"], type="json", auth="user") + def webclient_failed_messages(self, max_id=None, min_id=None, limit=30, **kwargs): + return ( + request.env["mail.message"] + ._message_fetch( + domain=[("is_failed_message", "=", True)], + max_id=max_id, + min_id=min_id, + limit=limit, + ) + .message_format() + ) diff --git a/mail_tracking/demo/demo.xml b/mail_tracking/demo/demo.xml index c121998ed3..215c9d1999 100644 --- a/mail_tracking/demo/demo.xml +++ b/mail_tracking/demo/demo.xml @@ -16,10 +16,6 @@ - Message with CC @@ -47,10 +43,6 @@ - Failed Message @@ -78,10 +70,6 @@ - Failed Message @@ -109,10 +97,6 @@ - Failed Message diff --git a/mail_tracking/models/__init__.py b/mail_tracking/models/__init__.py index 1a5aded02f..248d07ecf4 100644 --- a/mail_tracking/models/__init__.py +++ b/mail_tracking/models/__init__.py @@ -10,4 +10,4 @@ from . import mail_thread from . import mail_resend_message from . import mail_alias -from . import ir_config_parameter +from . import mail_alias_domain diff --git a/mail_tracking/models/ir_mail_server.py b/mail_tracking/models/ir_mail_server.py index 567ec6b92f..f7b8935bd8 100644 --- a/mail_tracking/models/ir_mail_server.py +++ b/mail_tracking/models/ir_mail_server.py @@ -78,7 +78,7 @@ def build_email( # the tracking image in case it's to be disabled if self._tracking_img_disabled(tracking_email_id): body = self._tracking_img_remove(body) - msg = super(IrMailServer, self).build_email( + msg = super().build_email( email_from=email_from, email_to=email_to, subject=subject, @@ -143,7 +143,7 @@ def send_email( tracking_email = self._tracking_email_get(message) smtp_server_used = self.sudo()._smtp_server_get(mail_server_id, smtp_server) try: - message_id = super(IrMailServer, self).send_email( + message_id = super().send_email( message, mail_server_id=mail_server_id, smtp_server=smtp_server, diff --git a/mail_tracking/models/mail_alias.py b/mail_tracking/models/mail_alias.py index a02a65774e..6a177cc098 100644 --- a/mail_tracking/models/mail_alias.py +++ b/mail_tracking/models/mail_alias.py @@ -10,31 +10,30 @@ class MailAlias(models.Model): @api.model @tools.ormcache() def get_aliases(self): + """We want to discard these addresses for trackings""" aliases = { x["display_name"] for x in self.search_read([("alias_name", "!=", False)], ["display_name"]) } - IrConfigParamObj = self.env["ir.config_parameter"].sudo() - catchall = "{}@{}".format( - IrConfigParamObj.get_param("mail.catchall.alias"), - IrConfigParamObj.get_param("mail.catchall.domain"), - ) - aliases.add(catchall) - return aliases + catchall_emails = { + x["catchall_email"] + for x in self.env["mail.alias.domain"].search_read([], ["catchall_email"]) + } + return aliases | catchall_emails @api.model_create_multi def create(self, vals_list): res = super().create(vals_list) - self.clear_caches() + self.env.registry.clear_cache() return res def write(self, vals): res = super().write(vals) if "alias_name" in vals: - self.clear_caches() + self.env.registry.clear_cache() return res def unlink(self): res = super().unlink() - self.clear_caches() + self.env.registry.clear_cache() return res diff --git a/mail_tracking/models/ir_config_parameter.py b/mail_tracking/models/mail_alias_domain.py similarity index 60% rename from mail_tracking/models/ir_config_parameter.py rename to mail_tracking/models/mail_alias_domain.py index f5f7d1d982..8961c0bbc8 100644 --- a/mail_tracking/models/ir_config_parameter.py +++ b/mail_tracking/models/mail_alias_domain.py @@ -1,24 +1,26 @@ # Copyright 2020 Tecnativa - Alexandre Díaz +# Copyright 2024 Tecnativa - David Vidal # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import api, models -class IrConfigParameter(models.Model): - _inherit = "ir.config_parameter" +class MailAliasDomain(models.Model): + _inherit = "mail.alias.domain" @api.model_create_multi def create(self, vals_list): res = super().create(vals_list) - self.env["mail.alias"].clear_caches() + self.env.registry.clear_cache() return res def write(self, vals): res = super().write(vals) - self.env["mail.alias"].clear_caches() + if "catchall_alias" in vals: + self.env.registry.clear_cache() return res def unlink(self): res = super().unlink() - self.env["mail.alias"].clear_caches() + self.env.registry.clear_cache() return res diff --git a/mail_tracking/models/mail_mail.py b/mail_tracking/models/mail_mail.py index a286a055a5..e72c2237ca 100644 --- a/mail_tracking/models/mail_mail.py +++ b/mail_tracking/models/mail_mail.py @@ -11,7 +11,7 @@ class MailMail(models.Model): _inherit = "mail.mail" - def _tracking_email_prepare(self, partner, email): + def _tracking_email_prepare(self, email): """Prepare email.tracking.email record values""" ts = time.time() dt = datetime.utcfromtimestamp(ts) @@ -23,19 +23,21 @@ def _tracking_email_prepare(self, partner, email): "time": fields.Datetime.to_string(dt), "mail_id": self.id, "mail_message_id": self.mail_message_id.id, - "partner_id": partner.id if partner else False, + "partner_id": (email.get("partner_id") or self.env["res.partner"]).id, "recipient": email_to, "sender": self.email_from, } - def _send_prepare_values(self, partner=None): + def _prepare_outgoing_list(self, recipients_follower_status=None): """Creates the mail.tracking.email record and adds the image tracking to the email. Please note that because we can't add mail headers in this function, the added tracking image will later (IrMailServer.build_email) also be used to extract the mail.tracking.email record id and to set the X-Odoo-MailTracking-ID header there. """ - email = super()._send_prepare_values(partner=partner) - vals = self._tracking_email_prepare(partner, email) - tracking_email = self.env["mail.tracking.email"].sudo().create(vals) - return tracking_email.tracking_img_add(email) + emails = super()._prepare_outgoing_list(recipients_follower_status) + for email in emails: + vals = self._tracking_email_prepare(email) + tracking_email = self.env["mail.tracking.email"].sudo().create(vals) + tracking_email.tracking_img_add(email) + return emails diff --git a/mail_tracking/models/mail_message.py b/mail_tracking/models/mail_message.py index c62de8644b..be2fff4fbd 100644 --- a/mail_tracking/models/mail_message.py +++ b/mail_tracking/models/mail_message.py @@ -240,9 +240,9 @@ def _filter_alias(email): return list(filter(_filter_alias, mail_list)) - def message_format(self, format_reply=True): + def message_format(self, format_reply=True, msg_vals=None): """Preare values to be used by the chatter widget""" - res = super().message_format(format_reply) + res = super().message_format(format_reply, msg_vals) mail_message_ids = {m.get("id") for m in res if m.get("id")} mail_messages = self.browse(mail_message_ids) tracking_statuses = mail_messages.tracking_status() @@ -261,7 +261,7 @@ def _prepare_dict_failed_message(self): if not failed_trackings or not self.mail_tracking_needs_action: return failed_partners = failed_trackings.mapped("partner_id") - failed_recipients = failed_partners.name_get() + failed_recipients = failed_partners.read(["display_name"]) return { "id": self.id, "date": self.date, @@ -278,16 +278,10 @@ def get_failed_messages(self): ] def set_need_action_done(self): - """Set message tracking action as done - - This will mark them to be ignored in the tracking issues filter. - """ + """This will mark the messages to be ignored in the tracking issues filter""" self.check_access_rule("read") - self.write({"mail_tracking_needs_action": False}) - self.env["bus.bus"]._sendone( - self.env.user.partner_id, "toggle_tracking_status", self.ids - ) - return self.mail_tracking_needs_action + self.mail_tracking_needs_action = False + self._notify_message_notification_update() @api.model def get_failed_count(self): diff --git a/mail_tracking/models/mail_resend_message.py b/mail_tracking/models/mail_resend_message.py index 310e5c80a3..adf0b0d761 100644 --- a/mail_tracking/models/mail_resend_message.py +++ b/mail_tracking/models/mail_resend_message.py @@ -24,6 +24,12 @@ def default_get(self, fields): 0, 0, { + "notification_id": ( + mail_message_id.notification_ids.filtered( + lambda x, tracking=tracking: x.res_partner_id + == tracking.partner_id + ).id + ), "partner_id": tracking.partner_id.id, "name": tracking.partner_id.name, "email": tracking.partner_id.email, @@ -44,7 +50,7 @@ def resend_mail_action(self): wizard.mail_message_id.mail_tracking_needs_action = False # Reset mail.tracking.email state tracking_ids = wizard.mail_message_id.mail_tracking_ids.filtered( - lambda x: x.partner_id in to_send + lambda x, to_send=to_send: x.partner_id in to_send ) tracking_ids.sudo().write({"state": False}) # Send bus notifications to update Discuss and diff --git a/mail_tracking/models/mail_thread.py b/mail_tracking/models/mail_thread.py index 6807293082..47278920cd 100644 --- a/mail_tracking/models/mail_thread.py +++ b/mail_tracking/models/mail_thread.py @@ -20,6 +20,10 @@ class MailThread(models.AbstractModel): + self._get_failed_message_domain(), ) + def _get_message_create_valid_field_names(self): + valid_field_names = super()._get_message_create_valid_field_names() + return valid_field_names | {"email_to", "email_cc"} + def _get_failed_message_domain(self): """Domain used to display failed messages on the 'failed_messages' widget""" diff --git a/mail_tracking/models/mail_tracking_email.py b/mail_tracking/models/mail_tracking_email.py index 7debf3d488..a42e48fe7a 100644 --- a/mail_tracking/models/mail_tracking_email.py +++ b/mail_tracking/models/mail_tracking_email.py @@ -143,7 +143,7 @@ def write(self, vals): def _find_allowed_tracking_ids(self): """Filter trackings based on related records ACLs""" # Admins passby this filter - if not self or self.env.user.has_group("base.group_system"): + if not self.ids or self.env.user.has_group("base.group_system"): return self.ids # Override ORM to get the values directly self._cr.execute( @@ -156,7 +156,7 @@ def _find_allowed_tracking_ids(self): msg_linked = self._cr.fetchall() if not msg_linked: return [] - _, msg_ids, partner_ids = zip(*msg_linked) + _, msg_ids, partner_ids = zip(*msg_linked, strict=True) # Filter messages with their ACL rules avoiding False values fetched in the set msg_ids = self.env["mail.message"]._search( [("id", "in", [x for x in msg_ids if x])] @@ -181,16 +181,16 @@ def _search( offset=0, limit=None, order=None, - count=False, access_rights_uid=None, ): """Filter ids based on related records ACLs""" - ids = super()._search( - args, offset, limit, order, count=count, access_rights_uid=access_rights_uid + allowed = super()._search( + args, offset, limit, order, access_rights_uid=access_rights_uid ) - if not self.env.user.has_group("base.group_system") and not count: - ids = self.browse(ids)._find_allowed_tracking_ids() - return ids + if not self.env.user.has_group("base.group_system"): + ids = self.browse(allowed)._find_allowed_tracking_ids() + allowed = self.browse(ids)._as_query(order) + return allowed def check_access_rule(self, operation): """Rely on related messages ACLs""" @@ -317,25 +317,15 @@ def _get_mail_tracking_img(self): ) if self.token: path_url = ( - "mail/tracking/open/%(db)s/%(tracking_email_id)s/%(token)s/" - "blank.gif" - % { - "db": self.env.cr.dbname, - "tracking_email_id": self.id, - "token": self.token, - } + f"mail/tracking/open/{self.env.cr.dbname}/{self.id}/{self.token}/" + f"blank.gif" ) else: # This is here for compatibility with older records - path_url = "mail/tracking/open/{db}/{tracking_email_id}/blank.gif".format( - db=self.env.cr.dbname, tracking_email_id=self.id - ) + path_url = f"mail/tracking/open/{self.env.cr.dbname}/{self.id}/blank.gif" track_url = urllib.parse.urljoin(base_url, path_url) - return ( - '' - % {"url": track_url, "tracking_email_id": self.id} - ) + _logger.debug(f"Sending email will tracking url: {track_url}") + return f'' def _partners_email_bounced_set(self, reason, event=None): recipients = [] @@ -384,7 +374,6 @@ def tracking_img_add(self, email): content, tracking_url, plaintext=False, container_tag="div" ) email["body"] = body - return email def _message_partners_check(self, message, message_id): if not self.mail_message_id.exists(): # pragma: no cover diff --git a/mail_tracking/pyproject.toml b/mail_tracking/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/mail_tracking/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/mail_tracking/readme/CONFIGURE.rst b/mail_tracking/readme/CONFIGURE.md similarity index 65% rename from mail_tracking/readme/CONFIGURE.rst rename to mail_tracking/readme/CONFIGURE.md index ab2f79def1..c4e425cfdf 100644 --- a/mail_tracking/readme/CONFIGURE.rst +++ b/mail_tracking/readme/CONFIGURE.md @@ -1,5 +1,5 @@ -As there can be scenarios where sending a tracking img in the email body is -not desired, there is a global system parameter +As there can be scenarios where sending a tracking img in the email body +is not desired, there is a global system parameter "mail_tracking.tracking_img_disabled" that can be set to True to remove -the tracking img from all outgoing emails. Note that the **Opened** status -will not be available in this case. +the tracking img from all outgoing emails. Note that the **Opened** +status will not be available in this case. diff --git a/mail_tracking/readme/CONTRIBUTORS.md b/mail_tracking/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..2f60406dbb --- /dev/null +++ b/mail_tracking/readme/CONTRIBUTORS.md @@ -0,0 +1,11 @@ +- [Tecnativa](https://www.tecnativa.com): + - Pedro M. Baeza + - Antonio Espinosa + - David Vidal + - Ernesto Tejeda + - Rafael Blasco + - Alexandre Díaz +- [Eezee-IT](https://www.eezee-it.com): + - Asma Elferkhsi +- [Vauxoo](https://www.vauxoo.com): + - Agustín Payen Sandoval diff --git a/mail_tracking/readme/CONTRIBUTORS.rst b/mail_tracking/readme/CONTRIBUTORS.rst deleted file mode 100644 index ffcc606755..0000000000 --- a/mail_tracking/readme/CONTRIBUTORS.rst +++ /dev/null @@ -1,14 +0,0 @@ -* `Tecnativa `_: - - * Pedro M. Baeza - * Antonio Espinosa - * David Vidal - * Ernesto Tejeda - * Rafael Blasco - * Alexandre Díaz - -* `Eezee-IT `_: - * Asma Elferkhsi - -* `Vauxoo `_: - * Agustín Payen Sandoval diff --git a/mail_tracking/readme/CREDITS.md b/mail_tracking/readme/CREDITS.md new file mode 100644 index 0000000000..67067b48b3 --- /dev/null +++ b/mail_tracking/readme/CREDITS.md @@ -0,0 +1,7 @@ +## Images + +- Odoo Community Association: + [Icon](https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg). +- Thanks to [LlubNek](https://openclipart.org/user-detail/LlubNek) and + [Openclipart](https://openclipart.org) for [the + icon](https://openclipart.org/detail/19342/open-envelope). diff --git a/mail_tracking/readme/CREDITS.rst b/mail_tracking/readme/CREDITS.rst deleted file mode 100644 index efa5e9d493..0000000000 --- a/mail_tracking/readme/CREDITS.rst +++ /dev/null @@ -1,7 +0,0 @@ -Images ------- - -* Odoo Community Association: `Icon `_. -* Thanks to `LlubNek `_ and `Openclipart - `_ for `the icon - `_. diff --git a/mail_tracking/readme/DESCRIPTION.rst b/mail_tracking/readme/DESCRIPTION.md similarity index 80% rename from mail_tracking/readme/DESCRIPTION.rst rename to mail_tracking/readme/DESCRIPTION.md index d8dbc8bf84..17d20739f2 100644 --- a/mail_tracking/readme/DESCRIPTION.rst +++ b/mail_tracking/readme/DESCRIPTION.md @@ -1,3 +1,3 @@ This module shows email notification tracking status for any messages in -mail thread (chatter). Each notified partner will have an intuitive icon just -right to his name. +mail thread (chatter). Each notified partner will have an intuitive icon +just right to his name. diff --git a/mail_tracking/readme/INSTALL.md b/mail_tracking/readme/INSTALL.md new file mode 100644 index 0000000000..f9e4eab48c --- /dev/null +++ b/mail_tracking/readme/INSTALL.md @@ -0,0 +1,5 @@ +If you're using a multi-database installation (with or without dbfilter +option) where /web/databse/selector returns a list of more than one +database, then you need to add `mail_tracking` addon to wide load addons +list (by default, only `web` addon), setting `--load` option. For +example, `--load=web,mail,mail_tracking` diff --git a/mail_tracking/readme/INSTALL.rst b/mail_tracking/readme/INSTALL.rst deleted file mode 100644 index 49c06e74a0..0000000000 --- a/mail_tracking/readme/INSTALL.rst +++ /dev/null @@ -1,5 +0,0 @@ -If you're using a multi-database installation (with or without dbfilter option) -where /web/databse/selector returns a list of more than one database, then -you need to add ``mail_tracking`` addon to wide load addons list -(by default, only ``web`` addon), setting ``--load`` option. -For example, ``--load=web,mail,mail_tracking`` diff --git a/mail_tracking/readme/ROADMAP.md b/mail_tracking/readme/ROADMAP.md new file mode 100644 index 0000000000..0966bcb2a3 --- /dev/null +++ b/mail_tracking/readme/ROADMAP.md @@ -0,0 +1,4 @@ +- Integrate with the core mail.notification model. A soft way would be + to write a notification event along with the mail.tracking.event ones. + Another way could be to merge both models and build the module + features on top of it. This might imply a refactor though. diff --git a/mail_tracking/readme/ROADMAP.rst b/mail_tracking/readme/ROADMAP.rst deleted file mode 100644 index 52bf8be016..0000000000 --- a/mail_tracking/readme/ROADMAP.rst +++ /dev/null @@ -1,4 +0,0 @@ -* Integrate with the core `mail.notification` model. A soft way would be to write a - notification event along with the mail.tracking.event ones. Another way could be - to merge both models and build the module features on top of it. This might imply - a refactor though. diff --git a/mail_tracking/readme/USAGE.md b/mail_tracking/readme/USAGE.md new file mode 100644 index 0000000000..2f00b9e8d7 --- /dev/null +++ b/mail_tracking/readme/USAGE.md @@ -0,0 +1,56 @@ +When user sends a message in mail_thread (chatter), for instance in +partner form, then an email tracking is created for each email +notification. Then a status icon will appear just right to name of +notified partner. + +These are all available status icons: + +![unknown](../static/src/img/unknown.png) **Unknown**: No email tracking +info available. Maybe this notified partner has 'Receive Inbox +Notifications by Email' == 'Never' + +![waiting](../static/src/img/waiting.png) **Waiting**: Waiting to be +sent + +![error](../static/src/img/error.png) **Error**: Error while sending + +![sent](../static/src/img/sent.png) **Sent**: Sent to SMTP server +configured + +![delivered](../static/src/img/delivered.png) **Delivered**: Delivered +to final MX server + +![opened](../static/src/img/opened.png) **Opened**: Opened by partner + +![cc](../static/src/img/cc.png) **Cc**: It's a Carbon-Copy recipient. +Can't know the status so is 'Unknown' + +![noemail](../static/src/img/no_email.png) **No Email**: The partner +doesn't have a defined email + +![anonuser](../static/src/img/anon_user.png) **No Partner**: The +recipient doesn't have a defined partner + +If you want to see all tracking emails and events you can go to + +- Settings \> Technical \> Email \> Tracking emails +- Settings \> Technical \> Email \> Tracking events + +When the message generates an 'error' status, it will apear on discuss +'Failed' channel. Any view with chatter can show the failed messages +too. + +- Discuss + + ![image](../static/img/failed_message_discuss.png) + +- Chatter + + ![image](../static/img/failed_message_widget.png) + +You can use "Failed sent messages" filter present in all views to show +records with messages in failed status and that needs an user action. + +- Filter + + ![image](../static/img/failed_message_filter.png) diff --git a/mail_tracking/readme/USAGE.rst b/mail_tracking/readme/USAGE.rst deleted file mode 100644 index 2488328ece..0000000000 --- a/mail_tracking/readme/USAGE.rst +++ /dev/null @@ -1,75 +0,0 @@ -When user sends a message in mail_thread (chatter), for instance in partner -form, then an email tracking is created for each email notification. Then a -status icon will appear just right to name of notified partner. - -These are all available status icons: - -.. |sent| image:: ../static/src/img/sent.png - :width: 10px - -.. |delivered| image:: ../static/src/img/delivered.png - :width: 15px - -.. |opened| image:: ../static/src/img/opened.png - :width: 15px - -.. |error| image:: ../static/src/img/error.png - :width: 10px - -.. |waiting| image:: ../static/src/img/waiting.png - :width: 10px - -.. |unknown| image:: ../static/src/img/unknown.png - :width: 10px - -.. |cc| image:: ../static/src/img/cc.png - :width: 10px - -.. |noemail| image:: ../static/src/img/no_email.png - :width: 10px - -.. |anonuser| image:: ../static/src/img/anon_user.png - :width: 10px - -|unknown| **Unknown**: No email tracking info available. Maybe this notified partner has 'Receive Inbox Notifications by Email' == 'Never' - -|waiting| **Waiting**: Waiting to be sent - -|error| **Error**: Error while sending - -|sent| **Sent**: Sent to SMTP server configured - -|delivered| **Delivered**: Delivered to final MX server - -|opened| **Opened**: Opened by partner - -|cc| **Cc**: It's a Carbon-Copy recipient. Can't know the status so is 'Unknown' - -|noemail| **No Email**: The partner doesn't have a defined email - -|anonuser| **No Partner**: The recipient doesn't have a defined partner - - -If you want to see all tracking emails and events you can go to - -* Settings > Technical > Email > Tracking emails -* Settings > Technical > Email > Tracking events - -When the message generates an 'error' status, it will apear on discuss 'Failed' -channel. Any view with chatter can show the failed messages -too. - -* Discuss - - .. image:: ../static/img/failed_message_discuss.png - -* Chatter - - .. image:: ../static/img/failed_message_widget.png - -You can use "Failed sent messages" filter present in all views to show records -with messages in failed status and that needs an user action. - -* Filter - - .. image:: ../static/img/failed_message_filter.png diff --git a/mail_tracking/static/description/index.html b/mail_tracking/static/description/index.html index dfe93484d3..b3bc839b68 100644 --- a/mail_tracking/static/description/index.html +++ b/mail_tracking/static/description/index.html @@ -368,10 +368,10 @@

Email tracking

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:ea59e8bd25a451ed67c147ccaf3d3959d2530c856358e168205e7aaca19cc415 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

+

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

This module shows email notification tracking status for any messages in -mail thread (chatter). Each notified partner will have an intuitive icon just -right to his name.

+mail thread (chatter). Each notified partner will have an intuitive icon +just right to his name.

Table of contents

Installation

-

If you’re using a multi-database installation (with or without dbfilter option) -where /web/databse/selector returns a list of more than one database, then -you need to add mail_tracking addon to wide load addons list -(by default, only web addon), setting --load option. +

If you’re using a multi-database installation (with or without dbfilter +option) where /web/databse/selector returns a list of more than one +database, then you need to add mail_tracking addon to wide load +addons list (by default, only web addon), setting --load option. For example, --load=web,mail,mail_tracking

Configuration

-

As there can be scenarios where sending a tracking img in the email body is -not desired, there is a global system parameter +

As there can be scenarios where sending a tracking img in the email body +is not desired, there is a global system parameter “mail_tracking.tracking_img_disabled” that can be set to True to remove -the tracking img from all outgoing emails. Note that the Opened status -will not be available in this case.

+the tracking img from all outgoing emails. Note that the Opened +status will not be available in this case.

Usage

-

When user sends a message in mail_thread (chatter), for instance in partner -form, then an email tracking is created for each email notification. Then a -status icon will appear just right to name of notified partner.

+

When user sends a message in mail_thread (chatter), for instance in +partner form, then an email tracking is created for each email +notification. Then a status icon will appear just right to name of +notified partner.

These are all available status icons:

-

unknown Unknown: No email tracking info available. Maybe this notified partner has ‘Receive Inbox Notifications by Email’ == ‘Never’

-

waiting Waiting: Waiting to be sent

-

error Error: Error while sending

-

sent Sent: Sent to SMTP server configured

-

delivered Delivered: Delivered to final MX server

-

opened Opened: Opened by partner

-

cc Cc: It’s a Carbon-Copy recipient. Can’t know the status so is ‘Unknown’

-

noemail No Email: The partner doesn’t have a defined email

-

anonuser No Partner: The recipient doesn’t have a defined partner

+

unknown Unknown: No email tracking info available. Maybe this +notified partner has ‘Receive Inbox Notifications by Email’ == ‘Never’

+

waiting Waiting: Waiting to be sent

+

error Error: Error while sending

+

sent Sent: Sent to SMTP server configured

+

delivered Delivered: Delivered to final MX server

+

opened Opened: Opened by partner

+

cc Cc: It’s a Carbon-Copy recipient. Can’t know the status so is +‘Unknown’

+

noemail No Email: The partner doesn’t have a defined email

+

anonuser No Partner: The recipient doesn’t have a defined partner

If you want to see all tracking emails and events you can go to

-

When the message generates an ‘error’ status, it will apear on discuss ‘Failed’ -channel. Any view with chatter can show the failed messages +

When the message generates an ‘error’ status, it will apear on discuss +‘Failed’ channel. Any view with chatter can show the failed messages too.

-

You can use “Failed sent messages” filter present in all views to show records -with messages in failed status and that needs an user action.

+

You can use “Failed sent messages” filter present in all views to show +records with messages in failed status and that needs an user action.

Known issues / Roadmap

@@ -461,7 +464,7 @@

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.

+feedback.

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

@@ -484,10 +487,14 @@

Contributors

  • Alexandre Díaz
  • -
  • Eezee-IT: -* Asma Elferkhsi
  • -
  • Vauxoo: -* Agustín Payen Sandoval
  • +
  • Eezee-IT: +
  • +
  • Vauxoo: +
  • @@ -495,8 +502,11 @@

    Other credits

    Images

    @@ -507,7 +517,7 @@

    Maintainers

    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.

    +

    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_tracking/static/src/components/discuss/discuss.xml b/mail_tracking/static/src/components/discuss/discuss.xml index f3011c7365..7b36ed240b 100644 --- a/mail_tracking/static/src/components/discuss/discuss.xml +++ b/mail_tracking/static/src/components/discuss/discuss.xml @@ -1,16 +1,16 @@ - + - + - + diff --git a/mail_tracking/static/src/components/discuss_sidebar_mailbox/discuss_sidebar_mailbox.xml b/mail_tracking/static/src/components/discuss_sidebar_mailbox/discuss_sidebar_mailbox.xml index 709c4a150f..aabd54a1c0 100644 --- a/mail_tracking/static/src/components/discuss_sidebar_mailbox/discuss_sidebar_mailbox.xml +++ b/mail_tracking/static/src/components/discuss_sidebar_mailbox/discuss_sidebar_mailbox.xml @@ -1,6 +1,6 @@ - false - + --> diff --git a/mail_tracking/static/src/components/failed_message/failed_message-old.xml b/mail_tracking/static/src/components/failed_message/failed_message-old.xml new file mode 100644 index 0000000000..8133e7bfd3 --- /dev/null +++ b/mail_tracking/static/src/components/failed_message/failed_message-old.xml @@ -0,0 +1,63 @@ + + + + + + + props.message.doNothing + props.message.doNothing + + + + false + + + false + + + +
    + Failed Recipients: + + + +
    +
    + + false + + + +
    + +
    diff --git a/mail_tracking/static/src/components/failed_message/failed_message.esm.js b/mail_tracking/static/src/components/failed_message/failed_message.esm.js index d559b54f34..ff941e84fc 100644 --- a/mail_tracking/static/src/components/failed_message/failed_message.esm.js +++ b/mail_tracking/static/src/components/failed_message/failed_message.esm.js @@ -1,11 +1,103 @@ /** @odoo-module **/ +import {AvatarCardPopover} from "@mail/discuss/web/avatar_card/avatar_card_popover"; +import {usePopover} from "@web/core/popover/popover_hook"; +import {useService} from "@web/core/utils/hooks"; +import {RelativeTime} from "@mail/core/common/relative_time"; -import {Message} from "@mail/components/message/message"; -import {registerMessagingComponent} from "@mail/utils/messaging_component"; +const {Component, useState} = owl; -export class FailedMessage extends Message {} +export class FailedMessage extends Component { + static props = ["message", "onUpdate?", "reloadParentView"]; + static defaultProps = {onUpdate: () => {}}; + static template = "mail_tracking.FailedMessage"; + static components = { + RelativeTime, + }; -FailedMessage.props = {record: Object, isFailedMessage: true}; -FailedMessage.template = "mail_tracking.FailedMessage"; - -registerMessagingComponent(FailedMessage); + setup() { + this.avatarCard = usePopover(AvatarCardPopover); + this.threadService = useState(useService("mail.thread")); + this.state = useState({showDetails: false}); + this.message = useState(this.props.message); + this.orm = useService("orm"); + } + async setFailedMessageReviewed() { + await this.orm.call("mail.message", "set_need_action_done", [ + [this.message.id], + ]); + // debugger + const thread = this.env.services["mail.thread"].getThread( + this.message.model, + this.message.id + ); + this.env.services["mail.thread"].fetchNewMessages(thread); + this.props.reloadParentView(); + } + retryFailedMessage() { + this.env.services.action.doAction("mail.mail_resend_message_action", { + additionalContext: { + mail_message_to_resend: this.message.id, + }, + onClose: async () => { + // Check if message is still 'failed' after Retry + await this.orm.call("mail.message", "get_failed_messages", [ + [this.message.id], + ]); + }, + }); + } + async onClickJump() { + await this.env.messageHighlight?.highlightMessage( + this.message, + this.message.originThread + ); + } + toggleDetails() { + this.state.showDetails = !this.state.showDetails; + } + hasAuthorClickable() { + return this.message.author?.user; + } + onClickAvatar(ev) { + if (this.hasAuthorClickable()) { + const target = ev.currentTarget; + if (!this.avatarCard.isOpen) { + this.avatarCard.open(target, { + id: this.message.author.user.id, + }); + } + } + } + get authorAvatarAttClass() { + return { + o_object_fit_contain: this.props.message.author?.is_company, + o_object_fit_cover: !this.props.message.author?.is_company, + "cursor-pointer": this.hasAuthorClickable() || "initial", + }; + } + get authorAvatarUrl() { + if ( + this.message.type && + this.message.type.includes("email") && + !["partner", "guest"].includes(this.message.author?.type) + ) { + return url("/mail/static/src/img/email_icon.png"); + } + return this.threadService.avatarUrl( + this.message.author, + this.message.originThread + ); + } + get thread() { + return this.threadService.getThread( + this.message.res_model, + this.message.res_id + ); + } + get failed_recipients() { + let error_states = ["error", "rejected", "spam", "bounced", "soft-bounced"]; + return this.message.partner_trackings.filter((message) => { + return error_states.includes(message.status); + }); + } +} diff --git a/mail_tracking/static/src/components/failed_message/failed_message.xml b/mail_tracking/static/src/components/failed_message/failed_message.xml index c4ca59a5e1..32afbcac7d 100644 --- a/mail_tracking/static/src/components/failed_message/failed_message.xml +++ b/mail_tracking/static/src/components/failed_message/failed_message.xml @@ -1,57 +1,119 @@ - - - - messageView.doNothing - messageView.doNothing - - - - false - - - -
    - Failed Recipients: - - - + +
    +
    + - - - false - - - -
    - -
    -
    - - false - - +
    +
    + diff --git a/mail_tracking/static/src/components/failed_message_list/failed_message_list.xml b/mail_tracking/static/src/components/failed_message_list/failed_message_list.xml index 500a4c8e1e..1b5c328f50 100644 --- a/mail_tracking/static/src/components/failed_message_list/failed_message_list.xml +++ b/mail_tracking/static/src/components/failed_message_list/failed_message_list.xml @@ -1,7 +1,43 @@ - + +
    +
    +
    +
    + + Failed messages + +
    +
    +
    + + + + + +
    +
    + +
    diff --git a/mail_tracking/static/src/components/message/message.scss b/mail_tracking/static/src/components/message/message.scss deleted file mode 100644 index 8f125cc2e7..0000000000 --- a/mail_tracking/static/src/components/message/message.scss +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright 2016 Antonio Espinosa - - Copyright 2019 Alexandre Díaz - License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */ - -.mail_tracking { - span { - color: #909090; - - &.mail_tracking_opened { - color: #a34a8b; - } - } -} -.mail_tracking_pointer { - cursor: pointer; -} - -.o_mail_thread .o_thread_message .o_thread_message_core { - .o_mail_info { - margin: 0; - } - .o_mail_tracking { - margin: 0 0 0.2rem 0; - } -} diff --git a/mail_tracking/static/src/components/message/message.xml b/mail_tracking/static/src/components/message/message.xml deleted file mode 100644 index ff8da66b3b..0000000000 --- a/mail_tracking/static/src/components/message/message.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - Set as Reviewed - - - - Retry - - - - -

    - To: - - - - - - - - - - - - - -

    -
    -
    - -
    diff --git a/mail_tracking/static/src/components/message_list/message_list.esm.js b/mail_tracking/static/src/components/message_list/message_list.esm.js deleted file mode 100644 index 919b910420..0000000000 --- a/mail_tracking/static/src/components/message_list/message_list.esm.js +++ /dev/null @@ -1,12 +0,0 @@ -/** @odoo-module **/ - -import {MessageList} from "@mail/components/message_list/message_list"; -import {patch} from "web.utils"; -import {useStore} from "../../client_actions/failed_message_storage.esm"; - -patch(MessageList.prototype, "mail_tracking/static/src/js/message_list.esm.js", { - setup() { - this._super(...arguments); - this.store = useStore(); - }, -}); diff --git a/mail_tracking/static/src/components/thread_view/thread_view.xml b/mail_tracking/static/src/components/thread_view/thread_view.xml index 5952603ba7..7be14968e3 100644 --- a/mail_tracking/static/src/components/thread_view/thread_view.xml +++ b/mail_tracking/static/src/components/thread_view/thread_view.xml @@ -1,9 +1,9 @@ - - -
    + + +
    +
    diff --git a/mail_tracking/static/src/services/message_service_patch.esm.js b/mail_tracking/static/src/services/message_service_patch.esm.js new file mode 100644 index 0000000000..51cd40d2b5 --- /dev/null +++ b/mail_tracking/static/src/services/message_service_patch.esm.js @@ -0,0 +1,10 @@ +/** @odoo-module */ + +import {_t} from "@web/core/l10n/translation"; +import {MessageService} from "@mail/core/common/message_service"; +import {patch} from "@web/core/utils/patch"; + +/** @type {import("@mail/core/common/message_service").MessageService} */ +const messageServicePatch = {}; + +patch(MessageService.prototype, messageServicePatch); diff --git a/mail_tracking/static/src/services/thread_service_patch.esm.js b/mail_tracking/static/src/services/thread_service_patch.esm.js new file mode 100644 index 0000000000..6cb4a661db --- /dev/null +++ b/mail_tracking/static/src/services/thread_service_patch.esm.js @@ -0,0 +1,10 @@ +/** @odoo-module */ + +import {_t} from "@web/core/l10n/translation"; +import {ThreadService} from "@mail/core/common/thread_service"; +import {patch} from "@web/core/utils/patch"; + +/** @type {import("@mail/core/common/thread_service").ThreadService} */ +const ThreadServicePatch = {}; + +patch(ThreadService.prototype, ThreadServicePatch); diff --git a/mail_tracking/static/src/web/chatter/chatter.esm.js b/mail_tracking/static/src/web/chatter/chatter.esm.js new file mode 100644 index 0000000000..00b116cc3c --- /dev/null +++ b/mail_tracking/static/src/web/chatter/chatter.esm.js @@ -0,0 +1,38 @@ +/** @odoo-module */ + +import {_t} from "@web/core/l10n/translation"; +import {ThreadService} from "@mail/core/common/thread_service"; +import {Chatter} from "@mail/core/web/chatter"; +import {FailedMessage} from "@mail_tracking/components/failed_message/failed_message.esm"; +import {patch} from "@web/core/utils/patch"; + +const {useState} = owl; + +// TODO: Maybe not necessary +// Chatter.props.push("hasFailedMessages?"); + +Chatter.components = { + ...Chatter.components, + FailedMessage, +}; + +/** @type {import("@mail/core/common/chatter").Chatter} */ +const ChatterPatch = { + setup() { + super.setup(...arguments); + this.state = useState({ + ...this.state, + showFailedMessageList: true, + }); + }, + get failed_messages() { + return this.state.thread?.messages.filter((message) => { + return message.is_failed_message; + }); + }, + toggleFailedMessageList() { + this.state.showFailedMessageList = !this.state.showFailedMessageList; + }, +}; + +patch(Chatter.prototype, ChatterPatch); diff --git a/mail_tracking/static/src/web/chatter/chatter.xml b/mail_tracking/static/src/web/chatter/chatter.xml new file mode 100644 index 0000000000..0cf5fba8ab --- /dev/null +++ b/mail_tracking/static/src/web/chatter/chatter.xml @@ -0,0 +1,63 @@ + + + +
    +
    +
    +
    + + Failed messages + +
    +
    +
    + +
    + + + +
    +
    +
    +
    + + + + + + + + + + +
    diff --git a/mail_tracking/static/src/web/message/mail_tracking_status.xml b/mail_tracking/static/src/web/message/mail_tracking_status.xml new file mode 100644 index 0000000000..278c474543 --- /dev/null +++ b/mail_tracking/static/src/web/message/mail_tracking_status.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mail_tracking/static/src/components/message/message.esm.js b/mail_tracking/static/src/web/message/message.esm.js similarity index 89% rename from mail_tracking/static/src/components/message/message.esm.js rename to mail_tracking/static/src/web/message/message.esm.js index ede9d34e79..fa19e1f285 100644 --- a/mail_tracking/static/src/components/message/message.esm.js +++ b/mail_tracking/static/src/web/message/message.esm.js @@ -1,15 +1,14 @@ /** @odoo-module **/ -import {Message} from "@mail/components/message/message"; -import {patch} from "web.utils"; +import {Message} from "@mail/core/common/message"; +import {patch} from "@web/core/utils/patch"; import {useStore} from "../../client_actions/failed_message_storage.esm"; -patch(Message.prototype, "mail_tracking/static/src/components/message/message.esm.js", { - constructor() { - this._super(...arguments); - }, +Message.props.push("isFailedMessage?"); + +patch(Message.prototype, { setup() { - this._super(...arguments); + super.setup(...arguments); this.store = useStore(); }, _onTrackingStatusClick(event) { diff --git a/mail_tracking/static/src/web/message/message.xml b/mail_tracking/static/src/web/message/message.xml new file mode 100644 index 0000000000..ed18838e01 --- /dev/null +++ b/mail_tracking/static/src/web/message/message.xml @@ -0,0 +1,110 @@ + + + + + + - + +
    + + + + + + + + + + + + + +

    + To: + + + +

    +
    +
    + + diff --git a/mail_tracking/static/src/web/message/message_model.esm.js b/mail_tracking/static/src/web/message/message_model.esm.js new file mode 100644 index 0000000000..abb0456a7d --- /dev/null +++ b/mail_tracking/static/src/web/message/message_model.esm.js @@ -0,0 +1 @@ +/** @odoo-module **/ diff --git a/mail_tracking/static/src/web/thread/thread_models.esm.js b/mail_tracking/static/src/web/thread/thread_models.esm.js new file mode 100644 index 0000000000..3c6ffbc63e --- /dev/null +++ b/mail_tracking/static/src/web/thread/thread_models.esm.js @@ -0,0 +1,35 @@ +/* @odoo-module */ + +import {Thread} from "@mail/core/common/thread_model"; + +import {patch} from "@web/core/utils/patch"; +import {Record} from "../common/record"; + +patch(Thread.prototype, { + // /** @type {integer|undefined} */ + // recipientsCount: undefined, + // /** @type {Number} */ + // mt_comment_id: undefined, + // setup() { + // super.setup(); + // this.recipients = Record.many("Follower"); + // }, + // get recipientsFullyLoaded() { + // return this.recipientsCount === this.recipients.length; + // }, + // /** + // * @returns {import("models").Activity[]} + // */ + // get activities() { + // return Object.values(this._store.Activity.records) + // .filter((activity) => { + // return activity.res_model === this.model && activity.res_id === this.id; + // }) + // .sort(function (a, b) { + // if (a.date_deadline === b.date_deadline) { + // return a.id - b.id; + // } + // return a.date_deadline < b.date_deadline ? -1 : 1; + // }); + // }, +}); diff --git a/mail_tracking/tests/test_mail_tracking.py b/mail_tracking/tests/test_mail_tracking.py index d9510acda5..828674d149 100644 --- a/mail_tracking/tests/test_mail_tracking.py +++ b/mail_tracking/tests/test_mail_tracking.py @@ -1,6 +1,5 @@ # Copyright 2016 Antonio Espinosa - # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - import base64 import time from unittest.mock import patch @@ -12,13 +11,18 @@ from odoo.tests.common import TransactionCase from odoo.tools import mute_logger -from ..controllers.discuss import MailTrackingDiscussController -from ..controllers.main import BLANK, MailTrackingController +from odoo.addons.mail_tracking.controllers.main import BLANK, MailTrackingController + +# from odoo.addons.mail.controllers.webclient import WebclientController + mock_send_email = "odoo.addons.base.models.ir_mail_server." "IrMailServer.send_email" -class FakeUserAgent(object): +# from ..controllers.webclient import MailTrackingWebclientController + + +class FakeUserAgent: browser = "Test browser" platform = "Test platform" @@ -29,7 +33,7 @@ def __str__(self): class TestMailTracking(TransactionCase): def setUp(self, *args, **kwargs): - super(TestMailTracking, self).setUp(*args, **kwargs) + super().setUp(*args, **kwargs) self.sender = self.env["res.partner"].create( {"name": "Test sender", "email": "sender@example.com"} ) @@ -59,7 +63,7 @@ def setUp(self, *args, **kwargs): def tearDown(self, *args, **kwargs): http.request = self.last_request - return super(TestMailTracking, self).tearDown(*args, **kwargs) + return super().tearDown(*args, **kwargs) def test_empty_email(self): self.recipient.write({"email_bounced": True}) @@ -273,13 +277,14 @@ def test_email_to(self): self.assertEqual(len(recipients[self.recipient.id]), 4) self._check_partner_trackings_to(message) # Catchall + Alias - IrConfigParamObj = self.env["ir.config_parameter"].sudo() - IrConfigParamObj.set_param("mail.catchall.alias", "TheCatchall") - IrConfigParamObj.set_param("mail.catchall.domain", "test.com") + alias_domain_id = self.env["mail.alias.domain"].create( + {"catchall_alias": "TheCatchall", "name": "test.com"} + ) self.env["mail.alias"].create( { "alias_model_id": self.env["ir.model"]._get("res.partner").id, "alias_name": "support+unnamed", + "alias_domain_id": alias_domain_id.id, } ) recipients = self.recipient._message_get_suggested_recipients() @@ -338,7 +343,13 @@ def test_resend_failed_message(self): ) # Force error state tracking_email.state = "error" - # Create resend mail wizard + # Mock a bounce + message.notification_ids.update( + { + "notification_type": "email", + "notification_status": "bounce", + } + ) wizard = ( self.env["mail.resend.message"] .sudo() @@ -615,7 +626,7 @@ def test_bounce_tracking_event_created(self): message_dict = { "bounced_email": "test@test.net", "bounced_message": message, - "bounced_msg_id": [message.message_id], + "bounced_msg_ids": [message.message_id], "bounced_partner": self.recipient, "cc": "", "date": "2023-02-07 12:35:53", @@ -670,37 +681,39 @@ def assert_tracking_tag_side_effect(*args, **kwargs): "data-odoo-tracking-email not found", tracking.error_description ) - def test_mail_init_messaging(self): - def mock_json_response(*args, **kwargs): - return {"expected_result": True} - - controller = MailTrackingDiscussController() - # This is non-functional test to increase coverage - with patch( - "odoo.addons.mail.controllers.discuss.DiscussController.mail_init_messaging", - wraps=mock_json_response, - ): - res = controller.mail_init_messaging() - self.assertTrue(res["expected_result"]) - - def test_discuss_failed_messages(self): - def mock_json_response(*args, **kwargs): - return {"expected_result": True} - - def mock_message_fetch(*args, **kwargs): - return self.env["mail.message"] - - controller = MailTrackingDiscussController() - # This is non-functional test to increase coverage - with patch( - "odoo.addons.mail_tracking.models.mail_message.MailMessage.message_format", - wraps=mock_json_response, - ), patch( - "odoo.addons.mail.models.mail_message.Message._message_fetch", - wraps=mock_message_fetch, - ): - res = controller.discuss_failed_messages() - self.assertTrue(res["expected_result"]) + # def test_mail_init_messaging(self): + # def mock_json_response(*args, **kwargs): + # return {"expected_result": True} + + # controller = MailTrackingWebclientController() + # # This is non-functional test to increase coverage + # with patch( + # "odoo.addons.mail.controllers.webclient." + # "WebclientController.mail_init_messaging", + # wraps=mock_json_response, + # ): + # res = controller.mail_init_messaging() + # self.assertTrue(res["expected_result"]) + + # def test_webclient_failed_messages(self): + # def mock_json_response(*args, **kwargs): + # return {"expected_result": True} + + # def mock_message_fetch(*args, **kwargs): + # return self.env["mail.message"] + + # controller = MailTrackingWebclientController() + # # This is non-functional test to increase coverage + # with patch( + # "odoo.addons.mail_tracking.models." + # "mail_message.MailMessage.message_format", + # wraps=mock_json_response, + # ), patch( + # "odoo.addons.mail.models.mail_message.Message._message_fetch", + # wraps=mock_message_fetch, + # ): + # res = controller.webclient_failed_messages() + # self.assertTrue(res["expected_result"]) def test_unlink_mail_alias(self): self.env["ir.config_parameter"].search([], limit=1).unlink() diff --git a/mail_tracking/views/mail_tracking_email_view.xml b/mail_tracking/views/mail_tracking_email_view.xml index 247ff0d8a1..94bfa2afc5 100644 --- a/mail_tracking/views/mail_tracking_email_view.xml +++ b/mail_tracking/views/mail_tracking_email_view.xml @@ -34,14 +34,14 @@ - + - + diff --git a/mail_tracking/views/mail_tracking_event_view.xml b/mail_tracking/views/mail_tracking_event_view.xml index 84ffd5f559..1fb83893c5 100644 --- a/mail_tracking/views/mail_tracking_event_view.xml +++ b/mail_tracking/views/mail_tracking_event_view.xml @@ -26,17 +26,13 @@ - + - + - + @@ -49,10 +45,7 @@ - + diff --git a/mail_tracking/views/res_partner_view.xml b/mail_tracking/views/res_partner_view.xml index f0a2416d10..a43f8ea018 100644 --- a/mail_tracking/views/res_partner_view.xml +++ b/mail_tracking/views/res_partner_view.xml @@ -12,28 +12,22 @@
    - - + +