Merge PR #524 into 12.0

Signed-off-by pedrobaeza
pull/527/head
OCA-git-bot 2020-03-24 18:18:11 +00:00
commit 789f258140
10 changed files with 143 additions and 56 deletions

View File

@ -52,28 +52,31 @@ status icon will appear just right to name of notified partner.
These are all available status icons: These are all available status icons:
.. |sent| image:: ../static/src/img/sent.png .. |sent| image:: https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/sent.png
:width: 10px :width: 10px
.. |delivered| image:: ../static/src/img/delivered.png .. |delivered| image:: https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/delivered.png
:width: 15px :width: 15px
.. |opened| image:: ../static/src/img/opened.png .. |opened| image:: https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/opened.png
:width: 15px :width: 15px
.. |error| image:: ../static/src/img/error.png .. |error| image:: https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/error.png
:width: 10px :width: 10px
.. |waiting| image:: ../static/src/img/waiting.png .. |waiting| image:: https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/waiting.png
:width: 10px :width: 10px
.. |unknown| image:: ../static/src/img/unknown.png .. |unknown| image:: https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/unknown.png
:width: 10px :width: 10px
.. |cc| image:: ../static/src/img/cc.png .. |cc| image:: https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/cc.png
:width: 10px :width: 10px
.. |noemail| image:: ../static/src/img/no_email.png .. |noemail| image:: https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/no_email.png
:width: 10px
.. |anonuser| image:: https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/anon_user.png
:width: 10px :width: 10px
|unknown| **Unknown**: No email tracking info available. Maybe this notified partner has 'Receive Inbox Notifications by Email' == 'Never' |unknown| **Unknown**: No email tracking info available. Maybe this notified partner has 'Receive Inbox Notifications by Email' == 'Never'
@ -92,6 +95,8 @@ These are all available status icons:
|noemail| **No Email**: The partner doesn't have a defined email |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 If you want to see all tracking emails and events you can go to

View File

@ -9,3 +9,4 @@ from . import mail_tracking_event
from . import res_partner from . import res_partner
from . import mail_thread from . import mail_thread
from . import mail_resend_message from . import mail_resend_message
from . import mail_alias

View File

@ -0,0 +1,34 @@
# 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 set(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
@api.multi
def write(self, vals):
res = super().write(vals)
if 'alias_name' in vals:
self.clear_caches()
return res
@api.multi
def unlink(self):
res = super().unlink()
self.clear_caches()
return res

View File

@ -3,6 +3,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import _, models, api, fields from odoo import _, models, api, fields
from email.utils import getaddresses
from odoo.tools import email_split from odoo.tools import email_split
@ -12,6 +13,7 @@ class MailMessage(models.Model):
# Recipients # Recipients
email_cc = fields.Char("Cc", help='Additional recipients that receive a ' email_cc = fields.Char("Cc", help='Additional recipients that receive a '
'"Carbon Copy" of the e-mail') '"Carbon Copy" of the e-mail')
email_to = fields.Char("To", help='Raw TO recipients')
mail_tracking_ids = fields.One2many( mail_tracking_ids = fields.One2many(
comodel_name='mail.tracking.email', comodel_name='mail.tracking.email',
inverse_name='mail_message_id', inverse_name='mail_message_id',
@ -94,11 +96,16 @@ class MailMessage(models.Model):
trackings = self.env['mail.tracking.email'].sudo().search([ trackings = self.env['mail.tracking.email'].sudo().search([
('mail_message_id', '=', message.id), ('mail_message_id', '=', message.id),
]) ])
# Get Cc recipients # String to List
email_cc_list = email_split(message.email_cc) email_cc_list = self._drop_aliases(email_split(message.email_cc))
if any(email_cc_list): email_to_list = self._drop_aliases(email_split(message.email_to))
partners |= partners.search([('email', 'in', email_cc_list)]) # 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_cc_list = set(email_cc_list)
email_to_list = set(email_to_list) - email_cc_list
# Search all trackings for this message # Search all trackings for this message
for tracking in trackings: for tracking in trackings:
status = self._partner_tracking_status_get(tracking) status = self._partner_tracking_status_get(tracking)
@ -117,16 +124,19 @@ class MailMessage(models.Model):
'isCc': False, 'isCc': False,
}) })
if tracking.partner_id: if tracking.partner_id:
# Discard mails with tracking
email_cc_list.discard(tracking.partner_id.email) email_cc_list.discard(tracking.partner_id.email)
email_to_list.discard(tracking.partner_id.email)
partners_already |= tracking.partner_id partners_already |= tracking.partner_id
# Search all recipients for this message # Search all partner recipients for this message
if message.partner_ids: if message.partner_ids:
partners |= message.partner_ids partners |= message.partner_ids
if message.needaction_partner_ids: if message.needaction_partner_ids:
partners |= message.needaction_partner_ids partners |= message.needaction_partner_ids
# Remove recipients already included # Discard partner recipients already included
partners -= partners_already partners -= partners_already
tracking_unkown_values = { # Default tracking values
tracking_unknown_values = {
'status': 'unknown', 'status': 'unknown',
'status_human': self._partner_tracking_status_human_get( 'status_human': self._partner_tracking_status_human_get(
'unknown'), 'unknown'),
@ -134,33 +144,50 @@ class MailMessage(models.Model):
'error_description': False, 'error_description': False,
'tracking_id': False, 'tracking_id': False,
} }
# Process tracking status of partner recipients without tracking
for partner in partners: 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' # If there is partners not included, then status is 'unknown'
# and perhaps a Cc recipient # and perhaps a Cc recipient
isCc = False isCc = False
if partner.email in email_cc_list: if partner.email in email_cc_list:
email_cc_list.discard(partner.email) email_cc_list.discard(partner.email)
isCc = True isCc = True
tracking_unkown_values.update({ tracking_status = tracking_unknown_values.copy()
tracking_status.update({
'recipient': partner.name, 'recipient': partner.name,
'partner_id': partner.id, 'partner_id': partner.id,
'isCc': isCc, 'isCc': isCc,
}) })
partner_trackings.append(tracking_unkown_values.copy()) partner_trackings.append(tracking_status)
for email in email_cc_list: # Process Cc/To recipients without partner
# If there is Cc without partner for cc, lst in [(True, email_cc_list), (False, email_to_list)]:
tracking_unkown_values.update({ for email in lst:
'recipient': email, tracking_status = tracking_unknown_values.copy()
'partner_id': False, tracking_status.update({
'isCc': True, 'recipient': email,
}) 'partner_id': False,
partner_trackings.append(tracking_unkown_values.copy()) 'isCc': cc,
})
partner_trackings.append(tracking_status)
res[message.id] = { res[message.id] = {
'partner_trackings': partner_trackings, 'partner_trackings': partner_trackings,
'is_failed_message': message.is_failed_message, 'is_failed_message': message.is_failed_message,
} }
return res 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 @api.model
def _message_read_dict_postprocess(self, messages, message_tree): def _message_read_dict_postprocess(self, messages, message_tree):
"""Preare values to be used by the chatter widget""" """Preare values to be used by the chatter widget"""

View File

@ -30,43 +30,51 @@ class MailThread(models.AbstractModel):
def message_post(self, *args, **kwargs): def message_post(self, *args, **kwargs):
"""Adds CC recipient to the message. """Adds CC recipient to the message.
Because Odoo implementation avoid store cc recipients we ensure that Because Odoo implementation avoid store 'from, to, cc' recipients we
this information its written into the mail.message record. ensure that this information its written into the mail.message record.
""" """
new_message = super().message_post(*args, **kwargs) kwargs.update({
email_cc = kwargs.get('cc') 'email_cc': kwargs.get('cc', False),
if email_cc: 'email_to': kwargs.get('to', False),
new_message.sudo().write({ })
'email_cc': email_cc, return super().message_post(*args, **kwargs)
})
return new_message
@api.multi @api.multi
def message_get_suggested_recipients(self): 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. If the recipient has a res.partner, use it.
""" """
res = super().message_get_suggested_recipients() 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'] ResPartnerObj = self.env['res.partner']
email_cc_formated_list = [] aliases = self.env['mail.alias'].get_aliases()
email_extra_formated_list = []
for record in self: for record in self:
emails_cc = record.message_ids.mapped('email_cc') emails_extra = record.message_ids.mapped(field_mail)
for email in emails_cc: for email in emails_extra:
email_cc_formated_list.extend(email_split_and_format(email)) email_extra_formated_list.extend(email_split_and_format(email))
email_cc_formated_list = set(email_cc_formated_list) email_extra_formated_list = set(email_extra_formated_list)
for cc in email_cc_formated_list: email_extra_list = [
email_parts = getaddresses([cc])[0] x[1] for x in getaddresses(email_extra_formated_list)]
partner_id = record.message_partner_info_from_emails( partners_info = record.message_partner_info_from_emails(
[email_parts[1]])[0].get('partner_id') email_extra_list)
for pinfo in partners_info:
partner_id = pinfo['partner_id']
email = pinfo['full_name']
if not partner_id: if not partner_id:
record._message_add_suggested_recipient( if email not in aliases:
res, email=cc, reason=_('Cc')) record._message_add_suggested_recipient(
suggestions, email=email, reason=reason)
else: else:
partner = ResPartnerObj.browse(partner_id, self._prefetch) partner = ResPartnerObj.browse(partner_id, self._prefetch)
record._message_add_suggested_recipient( record._message_add_suggested_recipient(
res, partner=partner, reason=_('Cc')) suggestions, partner=partner, reason=reason)
return res
@api.model @api.model
def _fields_view_get(self, view_id=None, view_type='form', toolbar=False, def _fields_view_get(self, view_id=None, view_type='form', toolbar=False,

View File

@ -28,6 +28,9 @@ These are all available status icons:
.. |noemail| image:: ../static/src/img/no_email.png .. |noemail| image:: ../static/src/img/no_email.png
:width: 10px :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' |unknown| **Unknown**: No email tracking info available. Maybe this notified partner has 'Receive Inbox Notifications by Email' == 'Never'
|waiting| **Waiting**: Waiting to be sent |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 |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 If you want to see all tracking emails and events you can go to

View File

@ -404,14 +404,15 @@ For example, <tt class="docutils literal"><span class="pre">--load=web,mail_trac
form, then an email tracking is created for each email notification. Then a form, then an email tracking is created for each email notification. Then a
status icon will appear just right to name of notified partner.</p> status icon will appear just right to name of notified partner.</p>
<p>These are all available status icons:</p> <p>These are all available status icons:</p>
<p><img alt="unknown" src="../static/src/img/unknown.png" style="width: 10px;" /> <strong>Unknown</strong>: No email tracking info available. Maybe this notified partner has Receive Inbox Notifications by Email == Never</p> <p><img alt="unknown" src="https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/unknown.png" style="width: 10px;" /> <strong>Unknown</strong>: No email tracking info available. Maybe this notified partner has Receive Inbox Notifications by Email == Never</p>
<p><img alt="waiting" src="../static/src/img/waiting.png" style="width: 10px;" /> <strong>Waiting</strong>: Waiting to be sent</p> <p><img alt="waiting" src="https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/waiting.png" style="width: 10px;" /> <strong>Waiting</strong>: Waiting to be sent</p>
<p><img alt="error" src="../static/src/img/error.png" style="width: 10px;" /> <strong>Error</strong>: Error while sending</p> <p><img alt="error" src="https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/error.png" style="width: 10px;" /> <strong>Error</strong>: Error while sending</p>
<p><img alt="sent" src="../static/src/img/sent.png" style="width: 10px;" /> <strong>Sent</strong>: Sent to SMTP server configured</p> <p><img alt="sent" src="https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/sent.png" style="width: 10px;" /> <strong>Sent</strong>: Sent to SMTP server configured</p>
<p><img alt="delivered" src="../static/src/img/delivered.png" style="width: 15px;" /> <strong>Delivered</strong>: Delivered to final MX server</p> <p><img alt="delivered" src="https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/delivered.png" style="width: 15px;" /> <strong>Delivered</strong>: Delivered to final MX server</p>
<p><img alt="opened" src="../static/src/img/opened.png" style="width: 15px;" /> <strong>Opened</strong>: Opened by partner</p> <p><img alt="opened" src="https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/opened.png" style="width: 15px;" /> <strong>Opened</strong>: Opened by partner</p>
<p><img alt="cc" src="../static/src/img/cc.png" style="width: 10px;" /> <strong>Cc</strong>: Its a Carbon-Copy recipient. Cant know the status so is Unknown</p> <p><img alt="cc" src="https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/cc.png" style="width: 10px;" /> <strong>Cc</strong>: Its a Carbon-Copy recipient. Cant know the status so is Unknown</p>
<p><img alt="noemail" src="../static/src/img/no_email.png" style="width: 10px;" /> <strong>No Email</strong>: The partner doesnt have a defined email</p> <p><img alt="noemail" src="https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/no_email.png" style="width: 10px;" /> <strong>No Email</strong>: The partner doesnt have a defined email</p>
<p><img alt="anonuser" src="https://raw.githubusercontent.com/OCA/social/12.0/mail_tracking/static/src/img/anon_user.png" style="width: 10px;" /> <strong>No Partner</strong>: The recipient doesnt have a defined partner</p>
<p>If you want to see all tracking emails and events you can go to</p> <p>If you want to see all tracking emails and events you can go to</p>
<ul class="simple"> <ul class="simple">
<li>Settings &gt; Technical &gt; Email &gt; Tracking emails</li> <li>Settings &gt; Technical &gt; Email &gt; Tracking emails</li>

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

View File

@ -10,6 +10,11 @@
<i class="fa fa-cc"></i> <i class="fa fa-cc"></i>
</span> </span>
</t> </t>
<t t-elif="!tracking['isCc'] &amp;&amp; !tracking['partner_id']">
<span class="mail_anon_recipient">
<i class="fa fa-low-vision"></i>
</span>
</t>
<t t-elif="tracking['status'] === 'unknown'"> <t t-elif="tracking['status'] === 'unknown'">
<span class="mail_tracking_unknown"> <span class="mail_tracking_unknown">
<i class="fa fa-ban"></i> <i class="fa fa-ban"></i>

View File

@ -168,6 +168,7 @@ class TestMailTracking(TransactionCase):
'partner_id': self.sender.id, 'partner_id': self.sender.id,
'login': 'sender-test', 'login': 'sender-test',
}) })
# pylint: disable=C8107
message = self.recipient.sudo(user=sender_user).message_post( message = self.recipient.sudo(user=sender_user).message_post(
body='<p>This is a test message</p>', body='<p>This is a test message</p>',
cc='unnamed@test.com, sender@example.com' cc='unnamed@test.com, sender@example.com'