Browse Source

[MIG] mail_tracking: Migration to 11.0

pull/269/head
David 7 years ago
committed by Jairo Llopis
parent
commit
bae9999b19
  1. 11
      mail_tracking/README.rst
  2. 3
      mail_tracking/__init__.py
  3. 8
      mail_tracking/__manifest__.py
  4. 3
      mail_tracking/controllers/__init__.py
  5. 9
      mail_tracking/controllers/main.py
  6. 2
      mail_tracking/data/tracking_data.xml
  7. 3
      mail_tracking/hooks.py
  8. 3
      mail_tracking/models/__init__.py
  9. 18
      mail_tracking/models/ir_mail_server.py
  10. 3
      mail_tracking/models/mail_mail.py
  11. 3
      mail_tracking/models/mail_message.py
  12. 24
      mail_tracking/models/mail_tracking_email.py
  13. 3
      mail_tracking/models/mail_tracking_event.py
  14. 3
      mail_tracking/models/res_partner.py
  15. 2
      mail_tracking/security/mail_tracking_email_security.xml
  16. 2
      mail_tracking/static/src/css/mail_tracking.css
  17. 163
      mail_tracking/static/src/js/mail_tracking.js
  18. 4
      mail_tracking/static/src/xml/mail_tracking.xml
  19. 2
      mail_tracking/tests/__init__.py
  20. 13
      mail_tracking/tests/test_mail_tracking.py
  21. 2
      mail_tracking/views/assets.xml
  22. 2
      mail_tracking/views/mail_tracking_email_view.xml
  23. 2
      mail_tracking/views/mail_tracking_event_view.xml
  24. 2
      mail_tracking/views/res_partner_view.xml

11
mail_tracking/README.rst

@ -10,7 +10,6 @@ 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.
Installation
============
@ -20,7 +19,6 @@ 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_tracking``
Usage
=====
@ -63,7 +61,7 @@ These are all available status icons:
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/205/10.0
:target: https://runbot.odoo-community.org/runbot/205/11.0
If you want to see all tracking emails and events you can go to
@ -93,8 +91,11 @@ Images
Contributors
------------
* Pedro M. Baeza <pedro.baeza@tecnativa.com>
* Antonio Espinosa <antonio.espinosa@tecnativa.com>
* `Tecnativa <https://www.tecnativa.com>`_:
* Pedro M. Baeza <pedro.baeza@tecnativa.com>
* Antonio Espinosa <antonio.espinosa@tecnativa.com>
* David Vidal <david.vidal@tecnativa.com>
Maintainer
----------

3
mail_tracking/__init__.py

@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# flake8: noqa
from . import models
from . import controllers

8
mail_tracking/__manifest__.py

@ -1,13 +1,13 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# Copyright 2018 David Vidal - <david.vidal@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "Email tracking",
"summary": "Email tracking system for all mails sent",
"version": "10.0.1.1.1",
"version": "11.0.1.0.0",
"category": "Social Network",
"website": "http://www.tecnativa.com",
"website": "http://github.com/OCA/social",
"author": "Tecnativa, "
"Odoo Community Association (OCA)",
"license": "AGPL-3",

3
mail_tracking/controllers/__init__.py

@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# flake8: noqa
from . import main

9
mail_tracking/controllers/main.py

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import werkzeug
@ -8,7 +7,7 @@ from odoo import api, http, registry, SUPERUSER_ID
import logging
_logger = logging.getLogger(__name__)
BLANK = 'R0lGODlhAQABAIAAANvf7wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='
BLANK = b'R0lGODlhAQABAIAAANvf7wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='
def _env_get(db, callback, tracking_id, event_type, **kw):
@ -22,7 +21,7 @@ def _env_get(db, callback, tracking_id, event_type, **kw):
reg = registry(db)
except OperationalError:
_logger.warning("Selected BD '%s' not found", db)
except: # pragma: no cover
except Exception: # pragma: no cover
_logger.warning("Selected BD '%s' connection error", db)
if reg:
_logger.info("New environment for database '%s'", db)
@ -83,5 +82,5 @@ class MailTrackingController(http.Controller):
# Always return GIF blank image
response = werkzeug.wrappers.Response()
response.mimetype = 'image/gif'
response.data = BLANK.decode('base64')
response.data = BLANK
return response

2
mail_tracking/data/tracking_data.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
<!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo>
<record forcecreate="True" id="decimal_tracking_timestamp" model="decimal.precision">

3
mail_tracking/hooks.py

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging

3
mail_tracking/models/__init__.py

@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# flake8: noqa
from . import ir_mail_server
from . import mail_mail

18
mail_tracking/models/ir_mail_server.py

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import re
@ -20,16 +19,10 @@ class IrMailServer(models.Model):
def _tracking_email_id_body_get(self, body):
body = body or ''
tracking_email_id = False
# https://regex101.com/r/lW4cB1/2
match = re.search(
r'<img[^>]*data-odoo-tracking-email=["\']([0-9]*)["\']', body)
if match:
try:
tracking_email_id = int(match.group(1))
except: # pragma: no cover
pass
return tracking_email_id
return int(match.group(1)) if match.group(1) else False
def build_email(self, email_from, email_to, subject, body, email_cc=None,
email_bcc=None, reply_to=False, attachments=None,
@ -64,14 +57,14 @@ class IrMailServer(models.Model):
mail_server = mail_server_ids[0] if mail_server_ids else None
if mail_server:
smtp_server_used = mail_server.smtp_host
else: # pragma: no cover
else:
smtp_server_used = smtp_server or tools.config.get('smtp_server')
return smtp_server_used
@api.model
def send_email(self, message, mail_server_id=None, smtp_server=None,
smtp_port=None, smtp_user=None, smtp_password=None,
smtp_encryption=None, smtp_debug=False):
smtp_encryption=None, smtp_debug=False, smtp_session=None):
message_id = False
tracking_email = self._tracking_email_get(message)
smtp_server_used = self.sudo()._smtp_server_get(
@ -82,7 +75,8 @@ class IrMailServer(models.Model):
message, mail_server_id=mail_server_id,
smtp_server=smtp_server, smtp_port=smtp_port,
smtp_user=smtp_user, smtp_password=smtp_password,
smtp_encryption=smtp_encryption, smtp_debug=smtp_debug)
smtp_encryption=smtp_encryption, smtp_debug=smtp_debug,
smtp_session=smtp_session)
except Exception as e:
if tracking_email:
tracking_email.smtp_error(self, smtp_server_used, e)

3
mail_tracking/models/mail_mail.py

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import time

3
mail_tracking/models/mail_message.py

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models, api

24
mail_tracking/models/mail_tracking_email.py

@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging
import urlparse
import urllib.parse
import time
import re
from datetime import datetime
@ -93,27 +92,20 @@ class MailTrackingEmail(models.Model):
string="Tracking events", comodel_name='mail.tracking.event',
inverse_name='tracking_email_id', readonly=True)
@api.model
def _email_score_tracking_filter(self, domain, order='time desc',
limit=10):
"""Default tracking search. Ready to be inherited."""
return self.search(domain, limit=limit, order=order)
@api.model
def email_is_bounced(self, email):
if email:
return len(self._email_score_tracking_filter([
return self.search_count([
('recipient_address', '=', email.lower()),
('state', 'in', ('error', 'rejected', 'spam', 'bounced')),
])) > 0
]) > 0
return False
@api.model
def email_score_from_email(self, email):
if email:
return self._email_score_tracking_filter([
('recipient_address', '=', email.lower())
]).email_score()
return self.search([
('recipient_address', '=', email.lower())]).email_score()
return 0.
@api.model
@ -183,7 +175,7 @@ class MailTrackingEmail(models.Model):
'db': self.env.cr.dbname,
'tracking_email_id': self.id,
})
track_url = urlparse.urljoin(base_url, path_url)
track_url = urllib.parse.urljoin(base_url, path_url)
return (
'<img src="%(url)s" alt="" '
'data-odoo-tracking-email="%(tracking_email_id)s"/>' % {
@ -197,7 +189,7 @@ class MailTrackingEmail(models.Model):
if event and event.recipient_address:
recipients.append(event.recipient_address)
else:
recipients = list(filter(None, self.mapped('recipient_address')))
recipients = [x for x in self.mapped('recipient_address') if x]
for recipient in recipients:
self.env['res.partner'].search([
('email', '=ilike', recipient)

3
mail_tracking/models/mail_tracking_event.py

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import re

3
mail_tracking/models/res_partner.py

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models, api, fields

2
mail_tracking/security/mail_tracking_email_security.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
<!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo>

2
mail_tracking/static/src/css/mail_tracking.css

@ -1,4 +1,4 @@
/* © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
/* Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */
.mail_tracking span {

163
mail_tracking/static/src/js/mail_tracking.js

@ -1,98 +1,83 @@
/* © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
/* Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
Copyright 2018 David Vidal - <david.vidal@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */
odoo.define('mail_tracking.partner_tracking', function(require){
"use strict";
"use strict";
var core = require('web.core');
var session = require('web.session');
var Model = require('web.Model');
var ActionManager = require('web.ActionManager');
var ChatThread = require('mail.ChatThread');
var core = require('web.core');
var session = require('web.session');
var data = require('web.data');
var ActionManager = require('web.ActionManager');
var chat_manager = require('mail.chat_manager');
var ChatThread = require('mail.ChatThread');
var Chatter = require('mail.Chatter');
var _t = core._t;
var MessageModel = new Model('mail.message', session.context);
var _t = core._t;
ChatThread.include({
_preprocess_message: function (message) {
var msg = this._super.apply(this, arguments);
msg.partner_trackings = msg.partner_trackings || [];
// chat_manager is a simple dictionary, not an OdooClass
chat_manager._make_message_super = chat_manager.make_message;
chat_manager.make_message = function(data) {
var msg = this._make_message_super(data);
msg.partner_trackings = data.partner_trackings || [];
return msg;
},
on_tracking_partner_click: function (event) {
var partner_id = this.$el.find(event.currentTarget).data('partner');
var state = {
'model': 'res.partner',
'id': partner_id,
'title': _t("Tracking partner"),
};
event.preventDefault();
this.action_manager.do_push_state(state);
var action = {
type:'ir.actions.act_window',
view_type: 'form',
view_mode: 'form',
res_model: 'res.partner',
views: [[false, 'form']],
target: 'current',
res_id: partner_id,
};
this.do_action(action);
},
on_tracking_status_click: function (event) {
var tracking_email_id = $(event.currentTarget).data('tracking');
var state = {
'model': 'mail.tracking.email',
'id': tracking_email_id,
'title': _t("Message tracking"),
};
event.preventDefault();
this.action_manager.do_push_state(state);
var action = {
type:'ir.actions.act_window',
view_type: 'form',
view_mode: 'form',
res_model: 'mail.tracking.email',
views: [[false, 'form']],
target: 'new',
res_id: tracking_email_id,
};
this.do_action(action);
},
bind_events: function () {
this.$el.on('click', '.o_mail_action_tracking_partner',
this.on_tracking_partner_click);
this.$el.on('click', '.o_mail_action_tracking_status',
this.on_tracking_status_click);
},
init: function (parent, options) {
this._super.apply(this, arguments);
this.action_manager = this.findAncestor(function(ancestor){
return ancestor instanceof ActionManager;
});
},
start: function () {
this._super();
this.bind_events();
},
render: function(messages, options) {
var self = this, render_super = this._super,
msgs = {},
msg_ids = [];
// Update trackings (async) each time we re-render thread
_.each(messages, function (message) {
msgs[message.id] = message;
msg_ids.push(message.id);
});
MessageModel.call('tracking_status', [msg_ids]).then(function (trackings) {
_.each(trackings, function (tracking, id) {
msgs[id].partner_trackings = tracking;
});
render_super.apply(self, [messages, options]);
});
},
};
ChatThread.include({
events: _.extend(ChatThread.prototype.events, {
'click .o_mail_action_tracking_partner': 'on_tracking_partner_click',
'click .o_mail_action_tracking_status': 'on_tracking_status_click',
}),
_preprocess_message: function (message) {
var msg = this._super.apply(this, arguments);
msg.partner_trackings = msg.partner_trackings || [];
return msg;
},
on_tracking_partner_click: function (event) {
var partner_id = this.$el.find(event.currentTarget).data('partner');
var state = {
'model': 'res.partner',
'id': partner_id,
'title': _t("Tracking partner"),
};
event.preventDefault();
this.action_manager.do_push_state(state);
var action = {
type:'ir.actions.act_window',
view_type: 'form',
view_mode: 'form',
res_model: 'res.partner',
views: [[false, 'form']],
target: 'current',
res_id: partner_id,
};
this.do_action(action);
},
on_tracking_status_click: function (event) {
var tracking_email_id = $(event.currentTarget).data('tracking');
var state = {
'model': 'mail.tracking.email',
'id': tracking_email_id,
'title': _t("Message tracking"),
};
event.preventDefault();
this.action_manager.do_push_state(state);
var action = {
type:'ir.actions.act_window',
view_type: 'form',
view_mode: 'form',
res_model: 'mail.tracking.email',
views: [[false, 'form']],
target: 'new',
res_id: tracking_email_id,
};
this.do_action(action);
},
init: function (parent, options) {
this._super.apply(this, arguments);
this.action_manager = this.findAncestor(function(ancestor){
return ancestor instanceof ActionManager;
});
},
});
});
}); // odoo.define

4
mail_tracking/static/src/xml/mail_tracking.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
<!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<template>
@ -47,7 +47,7 @@
<t t-set="first_tracking" t-value="true"/>
<t t-foreach="message.partner_trackings" t-as="tracking">
<t t-if="!first_tracking">
-
-
</t>
<t t-if="tracking[3]">
<a class="o_mail_action_tracking_partner"

2
mail_tracking/tests/__init__.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# flake8: noqa

13
mail_tracking/tests/test_mail_tracking.py

@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import mock
from odoo.tools import mute_logger
import base64
import time
from odoo import http
from odoo.tests.common import TransactionCase
@ -29,12 +28,10 @@ class TestMailTracking(TransactionCase):
self.sender = self.env['res.partner'].create({
'name': 'Test sender',
'email': 'sender@example.com',
'notify_email': 'always',
})
self.recipient = self.env['res.partner'].create({
'name': 'Test recipient',
'email': 'recipient@example.com',
'notify_email': 'always',
})
self.last_request = http.request
http.request = type('obj', (object,), {
@ -138,7 +135,7 @@ class TestMailTracking(TransactionCase):
def test_mail_send(self):
controller = MailTrackingController()
db = self.env.cr.dbname
image = base64.decodestring(BLANK)
image = BLANK
mail, tracking = self.mail_send(self.recipient.email)
self.assertEqual(mail.email_to, tracking.recipient)
self.assertEqual(mail.email_from, tracking.sender)
@ -310,8 +307,8 @@ class TestMailTracking(TransactionCase):
db = self.env.cr.dbname
controller = MailTrackingController()
not_found = controller.mail_tracking_all('not_found_db')
self.assertEqual('NOT FOUND', not_found.response[0])
self.assertEqual(b'NOT FOUND', not_found.response[0])
none = controller.mail_tracking_all(db)
self.assertEqual('NONE', none.response[0])
self.assertEqual(b'NONE', none.response[0])
none = controller.mail_tracking_event(db, 'open')
self.assertEqual('NONE', none.response[0])
self.assertEqual(b'NONE', none.response[0])

2
mail_tracking/views/assets.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
<!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo>
<template id="assets_backend"

2
mail_tracking/views/mail_tracking_email_view.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
<!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo>

2
mail_tracking/views/mail_tracking_event_view.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
<!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo>

2
mail_tracking/views/res_partner_view.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
<!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo>

Loading…
Cancel
Save