From bedeb56759a337d4dfb5c572fe9f7666d5e940fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20D=C3=ADaz?= Date: Thu, 19 Mar 2020 20:30:34 +0100 Subject: [PATCH] [IMP] mail_tracking: Store To recipients and omit aliases --- mail_tracking/README.rst | 5 ++ mail_tracking/models/__init__.py | 1 + mail_tracking/models/mail_alias.py | 33 ++++++++++ mail_tracking/models/mail_message.py | 59 +++++++++++++----- mail_tracking/models/mail_thread.py | 51 ++++++++------- mail_tracking/readme/USAGE.rst | 5 ++ mail_tracking/static/description/index.html | 1 + mail_tracking/static/src/img/anon_user.png | Bin 0 -> 483 bytes .../static/src/xml/mail_tracking.xml | 5 ++ mail_tracking/tests/test_mail_tracking.py | 5 +- 10 files changed, 126 insertions(+), 39 deletions(-) create mode 100644 mail_tracking/models/mail_alias.py create mode 100644 mail_tracking/static/src/img/anon_user.png diff --git a/mail_tracking/README.rst b/mail_tracking/README.rst index aaf3574..d37ee6b 100644 --- a/mail_tracking/README.rst +++ b/mail_tracking/README.rst @@ -76,6 +76,9 @@ These are all available status icons: .. |noemail| image:: https://raw.githubusercontent.com/OCA/social/13.0/mail_tracking/static/src/img/no_email.png :width: 10px +.. |anonuser| image:: https://raw.githubusercontent.com/OCA/social/13.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 @@ -92,6 +95,8 @@ These are all available status icons: |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 diff --git a/mail_tracking/models/__init__.py b/mail_tracking/models/__init__.py index 896721a..0f2e248 100644 --- a/mail_tracking/models/__init__.py +++ b/mail_tracking/models/__init__.py @@ -9,3 +9,4 @@ from . import mail_tracking_event from . import res_partner from . import mail_thread from . import mail_resend_message +from . import mail_alias diff --git a/mail_tracking/models/mail_alias.py b/mail_tracking/models/mail_alias.py new file mode 100644 index 0000000..800259c --- /dev/null +++ b/mail_tracking/models/mail_alias.py @@ -0,0 +1,33 @@ +# Copyright 2020 Alexandre Díaz +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, models, tools + + +class MailAlias(models.Model): + _inherit = "mail.alias" + + @api.model + @tools.ormcache() + def get_aliases(self): + return { + x["display_name"] + for x in self.search_read([("alias_name", "!=", False)], ["display_name"]) + } + + @api.model_create_multi + def create(self, vals_list): + res = super().create(vals_list) + self.clear_caches() + return res + + def write(self, vals): + res = super().write(vals) + if "alias_name" in vals: + self.clear_caches() + return res + + def unlink(self): + res = super().unlink() + self.clear_caches() + return res diff --git a/mail_tracking/models/mail_message.py b/mail_tracking/models/mail_message.py index c0c818a..bc093bb 100644 --- a/mail_tracking/models/mail_message.py +++ b/mail_tracking/models/mail_message.py @@ -2,6 +2,8 @@ # Copyright 2019 Alexandre Díaz # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from email.utils import getaddresses + from odoo import _, api, fields, models from odoo.tools import email_split @@ -13,6 +15,7 @@ class MailMessage(models.Model): email_cc = fields.Char( "Cc", help="Additional recipients that receive a " '"Carbon Copy" of the e-mail' ) + email_to = fields.Char("To", help="Raw TO recipients") mail_tracking_ids = fields.One2many( comodel_name="mail.tracking.email", inverse_name="mail_message_id", @@ -105,11 +108,16 @@ class MailMessage(models.Model): .sudo() .search([("mail_message_id", "=", message.id)]) ) - # Get Cc recipients - email_cc_list = email_split(message.email_cc) - if any(email_cc_list): - partners |= partners.search([("email", "in", email_cc_list)]) + # String to List + email_cc_list = self._drop_aliases(email_split(message.email_cc)) + email_to_list = self._drop_aliases(email_split(message.email_to)) + # Search related partners recipients + partners |= partners.search( + [("email", "in", email_cc_list + email_to_list)] + ) + # Operate over set's instead of lists email_cc_list = set(email_cc_list) + email_to_list = set(email_to_list) - email_cc_list # Search all trackings for this message for tracking in trackings: status = self._partner_tracking_status_get(tracking) @@ -127,45 +135,66 @@ class MailMessage(models.Model): } ) if tracking.partner_id: + # Discard mails with tracking email_cc_list.discard(tracking.partner_id.email) + email_to_list.discard(tracking.partner_id.email) partners_already |= tracking.partner_id - # Search all recipients for this message + # Search all partner recipients for this message if message.partner_ids: partners |= message.partner_ids if message.notified_partner_ids: partners |= message.notified_partner_ids - # Remove recipients already included + # Discard partner recipients already included partners -= partners_already - tracking_unkown_values = { + # Default tracking values + tracking_unknown_values = { "status": "unknown", "status_human": self._partner_tracking_status_human_get("unknown"), "error_type": False, "error_description": False, "tracking_id": False, } + # Process tracking status of partner recipients without tracking for partner in partners: + # Discard 'To' with partner + if partner.email in email_to_list: + email_to_list.discard(partner.email) # If there is partners not included, then status is 'unknown' # and perhaps a Cc recipient isCc = False if partner.email in email_cc_list: email_cc_list.discard(partner.email) isCc = True - tracking_unkown_values.update( + tracking_status = tracking_unknown_values.copy() + tracking_status.update( {"recipient": partner.name, "partner_id": partner.id, "isCc": isCc} ) - partner_trackings.append(tracking_unkown_values.copy()) - for email in email_cc_list: - # If there is Cc without partner - tracking_unkown_values.update( - {"recipient": email, "partner_id": False, "isCc": True} - ) - partner_trackings.append(tracking_unkown_values.copy()) + partner_trackings.append(tracking_status) + # Process Cc/To recipients without partner + for cc, lst in [(True, email_cc_list), (False, email_to_list)]: + for email in lst: + tracking_status = tracking_unknown_values.copy() + tracking_status.update( + {"recipient": email, "partner_id": False, "isCc": cc} + ) + partner_trackings.append(tracking_status) res[message.id] = { "partner_trackings": partner_trackings, "is_failed_message": message.is_failed_message, } return res + @api.model + def _drop_aliases(self, mail_list): + aliases = self.env["mail.alias"].get_aliases() + + def _filter_alias(email): + email_wn = getaddresses([email])[0][1] + if email_wn not in aliases: + return email_wn + + return list(filter(_filter_alias, mail_list)) + @api.model def _message_read_dict_postprocess(self, messages, message_tree): """Preare values to be used by the chatter widget""" diff --git a/mail_tracking/models/mail_thread.py b/mail_tracking/models/mail_thread.py index 3b1102b..c2718cc 100644 --- a/mail_tracking/models/mail_thread.py +++ b/mail_tracking/models/mail_thread.py @@ -33,41 +33,48 @@ class MailThread(models.AbstractModel): def message_post(self, *args, **kwargs): """Adds CC recipient to the message. - Because Odoo implementation avoid store cc recipients we ensure that - this information its written into the mail.message record. + Because Odoo implementation avoid store 'from, to, cc' recipients we + ensure that this information its written into the mail.message record. """ - new_message = super().message_post(*args, **kwargs) - email_cc = kwargs.get("cc") - if email_cc: - new_message.sudo().write({"email_cc": email_cc}) - return new_message + kwargs.update( + {"email_cc": kwargs.get("cc", False), "email_to": kwargs.get("to", False)} + ) + return super().message_post(*args, **kwargs) def _message_get_suggested_recipients(self): - """Adds email Cc recipients as suggested recipients. + """Adds email 'extra' recipients as suggested recipients. If the recipient has a res.partner, use it. """ res = super()._message_get_suggested_recipients() + self._add_extra_recipients_suggestions(res, "email_cc", _("Cc")) + self._add_extra_recipients_suggestions(res, "email_to", _("Anon. To")) + return res + + def _add_extra_recipients_suggestions(self, suggestions, field_mail, reason): ResPartnerObj = self.env["res.partner"] - email_cc_formated_list = [] + aliases = self.env["mail.alias"].get_aliases() + email_extra_formated_list = [] for record in self: - emails_cc = record.message_ids.mapped("email_cc") - for email in emails_cc: - email_cc_formated_list.extend(email_split_and_format(email)) - email_cc_formated_list = set(email_cc_formated_list) - for cc in email_cc_formated_list: - email_parts = getaddresses([cc])[0] - partner_id = record._message_partner_info_from_emails([email_parts[1]])[ - 0 - ].get("partner_id") + emails_extra = record.message_ids.mapped(field_mail) + for email in emails_extra: + email_extra_formated_list.extend(email_split_and_format(email)) + email_extra_formated_list = set(email_extra_formated_list) + email_extra_list = [x[1] for x in getaddresses(email_extra_formated_list)] + partners_info = self._message_partner_info_from_emails(email_extra_list) + for pinfo in partners_info: + partner_id = pinfo["partner_id"] + email = pinfo["full_name"] if not partner_id: - record._message_add_suggested_recipient(res, email=cc, reason=_("Cc")) + if email not in aliases: + self._message_add_suggested_recipient( + suggestions, email=email, reason=reason + ) else: partner = ResPartnerObj.browse(partner_id) - record._message_add_suggested_recipient( - res, partner=partner, reason=_("Cc") + self._message_add_suggested_recipient( + suggestions, partner=partner, reason=reason ) - return res @api.model def _fields_view_get( diff --git a/mail_tracking/readme/USAGE.rst b/mail_tracking/readme/USAGE.rst index aa63333..2488328 100644 --- a/mail_tracking/readme/USAGE.rst +++ b/mail_tracking/readme/USAGE.rst @@ -28,6 +28,9 @@ These are all available status icons: .. |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 @@ -44,6 +47,8 @@ These are all available status icons: |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 diff --git a/mail_tracking/static/description/index.html b/mail_tracking/static/description/index.html index 656a86f..61f9ec0 100644 --- a/mail_tracking/static/description/index.html +++ b/mail_tracking/static/description/index.html @@ -412,6 +412,7 @@ status icon will appear just right to name of notified partner.

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