Merge pull request #87 from Tecnativa/9.0-mail_tracking
[MIG] mail_trackingpull/89/head
-
112mail_tracking/README.rst
-
8mail_tracking/__init__.py
-
32mail_tracking/__openerp__.py
-
6mail_tracking/controllers/__init__.py
-
86mail_tracking/controllers/main.py
-
13mail_tracking/data/tracking_data.xml
-
36mail_tracking/hooks.py
-
448mail_tracking/i18n/de.po
-
440mail_tracking/i18n/es.po
-
448mail_tracking/i18n/fr.po
-
458mail_tracking/i18n/sl.po
-
11mail_tracking/models/__init__.py
-
94mail_tracking/models/ir_mail_server.py
-
36mail_tracking/models/mail_mail.py
-
79mail_tracking/models/mail_message.py
-
313mail_tracking/models/mail_tracking_email.py
-
136mail_tracking/models/mail_tracking_event.py
-
46mail_tracking/models/res_partner.py
-
5mail_tracking/security/ir.model.access.csv
-
BINmail_tracking/static/description/icon.png
-
21mail_tracking/static/src/css/mail_tracking.css
-
BINmail_tracking/static/src/img/delivered.png
-
BINmail_tracking/static/src/img/error.png
-
BINmail_tracking/static/src/img/opened.png
-
BINmail_tracking/static/src/img/sent.png
-
BINmail_tracking/static/src/img/unknown.png
-
BINmail_tracking/static/src/img/waiting.png
-
103mail_tracking/static/src/js/mail_tracking.js
-
73mail_tracking/static/src/xml/mail_tracking.xml
-
6mail_tracking/tests/__init__.py
-
262mail_tracking/tests/test_mail_tracking.py
-
17mail_tracking/views/assets.xml
-
120mail_tracking/views/mail_tracking_email_view.xml
-
123mail_tracking/views/mail_tracking_event_view.xml
-
31mail_tracking/views/res_partner_view.xml
@ -0,0 +1,112 @@ |
|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
|||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html |
|||
:alt: License: AGPL-3 |
|||
|
|||
============= |
|||
Mail tracking |
|||
============= |
|||
|
|||
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 |
|||
============ |
|||
|
|||
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_tracking`` |
|||
|
|||
|
|||
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. |
|||
|
|||
These are all available status icons: |
|||
|
|||
.. |sent| image:: mail_tracking/static/src/img/sent.png |
|||
:width: 10px |
|||
|
|||
.. |delivered| image:: mail_tracking/static/src/img/delivered.png |
|||
:width: 15px |
|||
|
|||
.. |opened| image:: mail_tracking/static/src/img/opened.png |
|||
:width: 15px |
|||
|
|||
.. |error| image:: mail_tracking/static/src/img/error.png |
|||
:width: 10px |
|||
|
|||
.. |waiting| image:: mail_tracking/static/src/img/waiting.png |
|||
:width: 10px |
|||
|
|||
.. |unknown| image:: mail_tracking/static/src/img/unknown.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 |
|||
|
|||
|
|||
.. 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/9.0 |
|||
|
|||
If you want to see all tracking emails and events you can go to |
|||
|
|||
* Settings > Technical > Email > Tracking emails |
|||
* Settings > Technical > Email > Tracking events |
|||
|
|||
|
|||
Bug Tracker |
|||
=========== |
|||
|
|||
Bugs are tracked on `GitHub Issues |
|||
<https://github.com/OCA/social/issues>`_. In case of trouble, please |
|||
check there if your issue has already been reported. If you spotted it first, |
|||
help us smashing it by providing a detailed and welcomed feedback. |
|||
|
|||
Credits |
|||
======= |
|||
|
|||
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>`_. |
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* Pedro M. Baeza <pedro.baeza@tecnativa.com> |
|||
* Antonio Espinosa <antonio.espinosa@tecnativa.com> |
|||
|
|||
Maintainer |
|||
---------- |
|||
|
|||
.. image:: https://odoo-community.org/logo.png |
|||
:alt: Odoo Community Association |
|||
:target: https://odoo-community.org |
|||
|
|||
This module is maintained by the OCA. |
|||
|
|||
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. |
|||
|
|||
To contribute to this module, please visit https://odoo-community.org. |
@ -0,0 +1,8 @@ |
|||
# -*- 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 |
|||
from .hooks import pre_init_hook |
@ -0,0 +1,32 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Antonio Espinosa - <antonio.espinosa@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": "9.0.1.0.0", |
|||
"category": "Social Network", |
|||
"website": "http://www.tecnativa.com", |
|||
"author": "Tecnativa, " |
|||
"Odoo Community Association (OCA)", |
|||
"license": "AGPL-3", |
|||
"application": False, |
|||
"installable": True, |
|||
"depends": [ |
|||
"decimal_precision", |
|||
"mail", |
|||
], |
|||
"data": [ |
|||
"data/tracking_data.xml", |
|||
"security/ir.model.access.csv", |
|||
"views/assets.xml", |
|||
"views/mail_tracking_email_view.xml", |
|||
"views/mail_tracking_event_view.xml", |
|||
"views/res_partner_view.xml", |
|||
], |
|||
"qweb": [ |
|||
"static/src/xml/mail_tracking.xml", |
|||
], |
|||
"pre_init_hook": "pre_init_hook", |
|||
} |
@ -0,0 +1,6 @@ |
|||
# -*- 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 |
@ -0,0 +1,86 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import werkzeug |
|||
from psycopg2 import OperationalError |
|||
from openerp import api, http, registry, SUPERUSER_ID |
|||
import logging |
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
BLANK = 'R0lGODlhAQABAIAAANvf7wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==' |
|||
|
|||
|
|||
def _env_get(db): |
|||
reg = False |
|||
try: |
|||
reg = registry(db) |
|||
except OperationalError: |
|||
_logger.warning("Selected BD '%s' not found", db) |
|||
except: # pragma: no cover |
|||
_logger.warning("Selected BD '%s' connection error", db) |
|||
if reg: |
|||
return api.Environment(reg.cursor(), SUPERUSER_ID, {}) |
|||
return False |
|||
|
|||
|
|||
class MailTrackingController(http.Controller): |
|||
|
|||
def _request_metadata(self): |
|||
request = http.request.httprequest |
|||
return { |
|||
'ip': request.remote_addr or False, |
|||
'user_agent': request.user_agent or False, |
|||
'os_family': request.user_agent.platform or False, |
|||
'ua_family': request.user_agent.browser or False, |
|||
} |
|||
|
|||
@http.route('/mail/tracking/all/<string:db>', |
|||
type='http', auth='none', csrf=False) |
|||
def mail_tracking_all(self, db, **kw): |
|||
env = _env_get(db) |
|||
if not env: |
|||
return 'NOT FOUND' |
|||
metadata = self._request_metadata() |
|||
response = env['mail.tracking.email'].event_process( |
|||
http.request, kw, metadata) |
|||
env.cr.commit() |
|||
env.cr.close() |
|||
return response |
|||
|
|||
@http.route('/mail/tracking/event/<string:db>/<string:event_type>', |
|||
type='http', auth='none', csrf=False) |
|||
def mail_tracking_event(self, db, event_type, **kw): |
|||
env = _env_get(db) |
|||
if not env: |
|||
return 'NOT FOUND' |
|||
metadata = self._request_metadata() |
|||
response = env['mail.tracking.email'].event_process( |
|||
http.request, kw, metadata, event_type=event_type) |
|||
env.cr.commit() |
|||
env.cr.close() |
|||
return response |
|||
|
|||
@http.route('/mail/tracking/open/<string:db>' |
|||
'/<int:tracking_email_id>/blank.gif', |
|||
type='http', auth='none') |
|||
def mail_tracking_open(self, db, tracking_email_id, **kw): |
|||
env = _env_get(db) |
|||
if env: |
|||
tracking_email = env['mail.tracking.email'].search([ |
|||
('id', '=', tracking_email_id), |
|||
]) |
|||
if tracking_email: |
|||
metadata = self._request_metadata() |
|||
tracking_email.event_create('open', metadata) |
|||
else: |
|||
_logger.warning( |
|||
"MailTracking email '%s' not found", tracking_email_id) |
|||
env.cr.commit() |
|||
env.cr.close() |
|||
|
|||
# Always return GIF blank image |
|||
response = werkzeug.wrappers.Response() |
|||
response.mimetype = 'image/gif' |
|||
response.data = BLANK.decode('base64') |
|||
return response |
@ -0,0 +1,13 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record forcecreate="True" id="decimal_tracking_timestamp" model="decimal.precision"> |
|||
<field name="name">MailTracking Timestamp</field> |
|||
<field name="digits">6</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,36 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import logging |
|||
from psycopg2.extensions import AsIs |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
|
|||
def column_exists(cr, table, column): |
|||
cr.execute(""" |
|||
SELECT column_name |
|||
FROM information_schema.columns |
|||
WHERE table_name = %s AND column_name = %s""", (table, column)) |
|||
return bool(cr.fetchall()) |
|||
|
|||
|
|||
def column_add_with_value(cr, table, column, field_type, value): |
|||
if not column_exists(cr, table, column): |
|||
cr.execute(""" |
|||
ALTER TABLE %s |
|||
ADD COLUMN %s %s""", (AsIs(table), AsIs(column), AsIs(field_type))) |
|||
cr.execute(""" |
|||
UPDATE %s SET %s = %s""", (AsIs(table), AsIs(column), value)) |
|||
|
|||
|
|||
def pre_init_hook(cr): |
|||
_logger.info("Creating res.partner.tracking_emails_count column " |
|||
"with value 0") |
|||
column_add_with_value( |
|||
cr, "res_partner", "tracking_emails_count", "integer", 0) |
|||
_logger.info("Creating res.partner.email_score column " |
|||
"with value 50.0") |
|||
column_add_with_value( |
|||
cr, "res_partner", "email_score", "double precision", 50.0) |
@ -0,0 +1,448 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * mail_tracking |
|||
# |
|||
# Translators: |
|||
# OCA Transbot <transbot@odoo-community.org>, 2016 |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 8.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2016-09-02 02:43+0000\n" |
|||
"PO-Revision-Date: 2016-09-02 02:43+0000\n" |
|||
"Last-Translator: OCA Transbot <transbot@odoo-community.org>, 2016\n" |
|||
"Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Language: de\n" |
|||
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
|||
|
|||
#. module: mail_tracking |
|||
#: help:mail.tracking.email,state:0 |
|||
msgid "" |
|||
" * The 'Error' status indicates that there was an error when trying to sent the email, for example, 'No valid recipient'\n" |
|||
" * The 'Sent' status indicates that message was succesfully sent via outgoing email server (SMTP).\n" |
|||
" * The 'Delivered' status indicates that message was succesfully delivered to recipient Mail Exchange (MX) server.\n" |
|||
" * The 'Open' status indicates that message was opened or clicked by recipient.\n" |
|||
" * The 'Rejected' status indicates that recipient email address is blacklisted by outgoing email server (SMTP). It is recomended to delete this email address.\n" |
|||
" * The 'Spam' status indicates that outgoing email server (SMTP) consider this message as spam.\n" |
|||
" * The 'Unsubscribed' status indicates that recipient has requested to be unsubscribed from this message.\n" |
|||
" * The 'Bounced' status indicates that message was bounced by recipient Mail Exchange (MX) server.\n" |
|||
" * The 'Soft bounced' status indicates that message was soft bounced by recipient Mail Exchange (MX) server.\n" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Bounce" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,bounce_description:0 |
|||
msgid "Bounce description" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,bounce_type:0 |
|||
msgid "Bounce type" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
msgid "Bounced" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Click" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Clicked" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,url:0 |
|||
msgid "Clicked URL" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_tree |
|||
msgid "Country" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,create_uid:0 |
|||
#: field:mail.tracking.event,create_uid:0 |
|||
msgid "Created by" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,create_date:0 |
|||
#: field:mail.tracking.event,create_date:0 |
|||
msgid "Created on" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,date:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,date:0 |
|||
msgid "Date" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Deferral" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
msgid "Deferred" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Delivered" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,display_name:0 |
|||
msgid "Display Name" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,display_name:0 |
|||
msgid "Display name" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,mail_id:0 |
|||
msgid "Email" |
|||
msgstr "Email" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:res.partner,email_score:0 |
|||
msgid "Email score" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_form |
|||
msgid "Error" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,error_smtp_server:0 |
|||
msgid "Error SMTP server" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,error_description:0 |
|||
#: field:mail.tracking.event,error_description:0 |
|||
msgid "Error description" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,error_details:0 |
|||
msgid "Error details" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,error_type:0 |
|||
#: field:mail.tracking.event,error_type:0 |
|||
msgid "Error type" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,event_type:0 |
|||
msgid "Event type" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Failed" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Group By" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Hard bounce" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,id:0 field:mail.tracking.event,id:0 |
|||
msgid "ID" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,mobile:0 |
|||
msgid "Is mobile?" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,__last_update:0 |
|||
#: field:mail.tracking.event,__last_update:0 |
|||
msgid "Last Modified on" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,write_uid:0 field:mail.tracking.event,write_uid:0 |
|||
msgid "Last Updated by" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,write_date:0 |
|||
#: field:mail.tracking.event,write_date:0 |
|||
msgid "Last Updated on" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_tracking_email |
|||
msgid "MailTracking email" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
msgid "MailTracking email search" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.actions.act_window,name:mail_tracking.action_view_mail_tracking_email |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_tree |
|||
msgid "MailTracking emails" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_tracking_event |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_form |
|||
msgid "MailTracking event" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "MailTracking event search" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.actions.act_window,name:mail_tracking.action_view_mail_tracking_event |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_tree |
|||
msgid "MailTracking events" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_message |
|||
#: field:mail.tracking.email,mail_message_id:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,tracking_email_id:0 |
|||
msgid "Message" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#. openerp-web |
|||
#: code:addons/mail_tracking/static/src/js/mail_tracking.js:30 |
|||
#, python-format |
|||
msgid "Message tracking" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Month" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Open" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,os_family:0 |
|||
msgid "Operating system family" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_mail |
|||
msgid "Outgoing Mails" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_res_partner |
|||
#: field:mail.tracking.email,partner_id:0 |
|||
msgid "Partner" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_tree |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,recipient:0 |
|||
msgid "Recipient" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,recipient:0 |
|||
msgid "Recipient email" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,recipient_address:0 |
|||
msgid "Recipient email address" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Rejected" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,smtp_server:0 |
|||
msgid "SMTP server" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_tree |
|||
msgid "Sender" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,sender:0 |
|||
msgid "Sender email" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Sent" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Soft bounce" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
msgid "Soft bounced" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Spam" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,state:0 |
|||
msgid "State" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,name:0 |
|||
msgid "Subject" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,time:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,time:0 |
|||
msgid "Time" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.ui.menu,name:mail_tracking.menu_mail_tracking_email |
|||
#: view:res.partner:mail_tracking.view_partner_form |
|||
#: field:res.partner,tracking_email_ids:0 |
|||
msgid "Tracking emails" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:res.partner,tracking_emails_count:0 |
|||
msgid "Tracking emails count" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.ui.menu,name:mail_tracking.menu_mail_tracking_event |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: field:mail.tracking.email,tracking_event_ids:0 |
|||
msgid "Tracking events" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Type" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "URL" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,timestamp:0 field:mail.tracking.event,timestamp:0 |
|||
msgid "UTC timestamp" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Unsubscribe" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Unsubscribed" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,ip:0 |
|||
msgid "User IP" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_tree |
|||
#: field:mail.tracking.event,user_agent:0 |
|||
msgid "User agent" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,ua_family:0 |
|||
msgid "User agent family" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,ua_type:0 |
|||
msgid "User agent type" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,user_country_id:0 |
|||
msgid "User country" |
|||
msgstr "" |
@ -0,0 +1,440 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * mail_tracking |
|||
# |
|||
# Translators: |
|||
# OCA Transbot <transbot@odoo-community.org>, 2016 |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 8.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2016-08-08 00:45+0000\n" |
|||
"PO-Revision-Date: 2016-08-08 00:45+0000\n" |
|||
"Last-Translator: OCA Transbot <transbot@odoo-community.org>, 2016\n" |
|||
"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Language: es\n" |
|||
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
|||
|
|||
#. module: mail_tracking |
|||
#: help:mail.tracking.email,state:0 |
|||
msgid "" |
|||
" * The 'Error' status indicates that there was an error when trying to sent the email, for example, 'No valid recipient'\n" |
|||
" * The 'Sent' status indicates that message was succesfully sent via outgoing email server (SMTP).\n" |
|||
" * The 'Delivered' status indicates that message was succesfully delivered to recipient Mail Exchange (MX) server.\n" |
|||
" * The 'Open' status indicates that message was opened or clicked by recipient.\n" |
|||
" * The 'Rejected' status indicates that recipient email address is blacklisted by outgoing email server (SMTP). It is recomended to delete this email address.\n" |
|||
" * The 'Spam' status indicates that outgoing email server (SMTP) consider this message as spam.\n" |
|||
" * The 'Unsubscribed' status indicates that recipient has requested to be unsubscribed from this message.\n" |
|||
" * The 'Bounced' status indicates that message was bounced by recipient Mail Exchange (MX) server.\n" |
|||
" * The 'Soft bounced' status indicates that message was soft bounced by recipient Mail Exchange (MX) server.\n" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Bounce" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,bounce_description:0 |
|||
msgid "Bounce description" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,bounce_type:0 |
|||
msgid "Bounce type" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
msgid "Bounced" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Click" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Clicked" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,url:0 |
|||
msgid "Clicked URL" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_tree |
|||
msgid "Country" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,create_uid:0 |
|||
#: field:mail.tracking.event,create_uid:0 |
|||
msgid "Created by" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,create_date:0 |
|||
#: field:mail.tracking.event,create_date:0 |
|||
msgid "Created on" |
|||
msgstr "Creado en" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,date:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,date:0 |
|||
msgid "Date" |
|||
msgstr "Fecha" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Deferral" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
msgid "Deferred" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Delivered" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,display_name:0 |
|||
msgid "Display Name" |
|||
msgstr "Nombre mostrado" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,display_name:0 |
|||
msgid "Display name" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,mail_id:0 |
|||
msgid "Email" |
|||
msgstr "Correo electrónico" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:res.partner,email_score:0 |
|||
msgid "Email score" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
msgid "Error" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,error_smtp_server:0 |
|||
msgid "Error SMTP server" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,error_description:0 |
|||
msgid "Error description" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,error_type:0 |
|||
msgid "Error type" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,event_type:0 |
|||
msgid "Event type" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Failed" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Group By" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Hard bounce" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,id:0 field:mail.tracking.event,id:0 |
|||
msgid "ID" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,mobile:0 |
|||
msgid "Is mobile?" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,__last_update:0 |
|||
#: field:mail.tracking.event,__last_update:0 |
|||
msgid "Last Modified on" |
|||
msgstr "Última modificación en" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,write_uid:0 field:mail.tracking.event,write_uid:0 |
|||
msgid "Last Updated by" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,write_date:0 |
|||
#: field:mail.tracking.event,write_date:0 |
|||
msgid "Last Updated on" |
|||
msgstr "Última actualización en" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_tracking_email |
|||
msgid "MailTracking email" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
msgid "MailTracking email search" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.actions.act_window,name:mail_tracking.action_view_mail_tracking_email |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_tree |
|||
msgid "MailTracking emails" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_tracking_event |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_form |
|||
msgid "MailTracking event" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "MailTracking event search" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.actions.act_window,name:mail_tracking.action_view_mail_tracking_event |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_tree |
|||
msgid "MailTracking events" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_message |
|||
#: field:mail.tracking.email,mail_message_id:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,tracking_email_id:0 |
|||
msgid "Message" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#. openerp-web |
|||
#: code:addons/mail_tracking/static/src/js/mail_tracking.js:30 |
|||
#, python-format |
|||
msgid "Message tracking" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Month" |
|||
msgstr "Mes" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Open" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,os_family:0 |
|||
msgid "Operating system family" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_mail |
|||
msgid "Outgoing Mails" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_res_partner |
|||
#: field:mail.tracking.email,partner_id:0 |
|||
msgid "Partner" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_tree |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,recipient:0 |
|||
msgid "Recipient" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,recipient:0 |
|||
msgid "Recipient email" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,recipient_address:0 |
|||
msgid "Recipient email address" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Rejected" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,smtp_server:0 |
|||
msgid "SMTP server" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_tree |
|||
msgid "Sender" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,sender:0 |
|||
msgid "Sender email" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Sent" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Soft bounce" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
msgid "Soft bounced" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Spam" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,state:0 |
|||
msgid "State" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,name:0 |
|||
msgid "Subject" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,time:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,time:0 |
|||
msgid "Time" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.ui.menu,name:mail_tracking.menu_mail_tracking_email |
|||
#: view:res.partner:mail_tracking.view_partner_form |
|||
#: field:res.partner,tracking_email_ids:0 |
|||
msgid "Tracking emails" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:res.partner,tracking_emails_count:0 |
|||
msgid "Tracking emails count" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.ui.menu,name:mail_tracking.menu_mail_tracking_event |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: field:mail.tracking.email,tracking_event_ids:0 |
|||
msgid "Tracking events" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Type" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "URL" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,timestamp:0 field:mail.tracking.event,timestamp:0 |
|||
msgid "UTC timestamp" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Unsubscribe" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Unsubscribed" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,ip:0 |
|||
msgid "User IP" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_tree |
|||
#: field:mail.tracking.event,user_agent:0 |
|||
msgid "User agent" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,ua_family:0 |
|||
msgid "User agent family" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,ua_type:0 |
|||
msgid "User agent type" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,user_country_id:0 |
|||
msgid "User country" |
|||
msgstr "" |
@ -0,0 +1,448 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * mail_tracking |
|||
# |
|||
# Translators: |
|||
# OCA Transbot <transbot@odoo-community.org>, 2016 |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 8.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2016-09-02 02:43+0000\n" |
|||
"PO-Revision-Date: 2016-09-02 02:43+0000\n" |
|||
"Last-Translator: OCA Transbot <transbot@odoo-community.org>, 2016\n" |
|||
"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Language: fr\n" |
|||
"Plural-Forms: nplurals=2; plural=(n > 1);\n" |
|||
|
|||
#. module: mail_tracking |
|||
#: help:mail.tracking.email,state:0 |
|||
msgid "" |
|||
" * The 'Error' status indicates that there was an error when trying to sent the email, for example, 'No valid recipient'\n" |
|||
" * The 'Sent' status indicates that message was succesfully sent via outgoing email server (SMTP).\n" |
|||
" * The 'Delivered' status indicates that message was succesfully delivered to recipient Mail Exchange (MX) server.\n" |
|||
" * The 'Open' status indicates that message was opened or clicked by recipient.\n" |
|||
" * The 'Rejected' status indicates that recipient email address is blacklisted by outgoing email server (SMTP). It is recomended to delete this email address.\n" |
|||
" * The 'Spam' status indicates that outgoing email server (SMTP) consider this message as spam.\n" |
|||
" * The 'Unsubscribed' status indicates that recipient has requested to be unsubscribed from this message.\n" |
|||
" * The 'Bounced' status indicates that message was bounced by recipient Mail Exchange (MX) server.\n" |
|||
" * The 'Soft bounced' status indicates that message was soft bounced by recipient Mail Exchange (MX) server.\n" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Bounce" |
|||
msgstr "Erreurs de remise" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,bounce_description:0 |
|||
msgid "Bounce description" |
|||
msgstr "Descriptif du rebond" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,bounce_type:0 |
|||
msgid "Bounce type" |
|||
msgstr "Type de rebond" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
msgid "Bounced" |
|||
msgstr "Rebonds" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Click" |
|||
msgstr "Cliquer" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Clicked" |
|||
msgstr "Cliqué" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,url:0 |
|||
msgid "Clicked URL" |
|||
msgstr "URL cliquée" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_tree |
|||
msgid "Country" |
|||
msgstr "Pays" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,create_uid:0 |
|||
#: field:mail.tracking.event,create_uid:0 |
|||
msgid "Created by" |
|||
msgstr "Créée par" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,create_date:0 |
|||
#: field:mail.tracking.event,create_date:0 |
|||
msgid "Created on" |
|||
msgstr "Créée le" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,date:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,date:0 |
|||
msgid "Date" |
|||
msgstr "Date" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Deferral" |
|||
msgstr "Déférer" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
msgid "Deferred" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Delivered" |
|||
msgstr "Livré" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,display_name:0 |
|||
msgid "Display Name" |
|||
msgstr "Nom à afficher" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,display_name:0 |
|||
msgid "Display name" |
|||
msgstr "Nom affiché" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,mail_id:0 |
|||
msgid "Email" |
|||
msgstr "Courriel" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:res.partner,email_score:0 |
|||
msgid "Email score" |
|||
msgstr "Score du courriel" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_form |
|||
msgid "Error" |
|||
msgstr "Erreur" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,error_smtp_server:0 |
|||
msgid "Error SMTP server" |
|||
msgstr "Erreur du serveur SMTP" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,error_description:0 |
|||
#: field:mail.tracking.event,error_description:0 |
|||
msgid "Error description" |
|||
msgstr "Desciptif de l'erreur" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,error_details:0 |
|||
msgid "Error details" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,error_type:0 |
|||
#: field:mail.tracking.event,error_type:0 |
|||
msgid "Error type" |
|||
msgstr "Type d'erreur" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,event_type:0 |
|||
msgid "Event type" |
|||
msgstr "Type d'évènement" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Failed" |
|||
msgstr "Échec" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Group By" |
|||
msgstr "Regrouper par" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Hard bounce" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,id:0 field:mail.tracking.event,id:0 |
|||
msgid "ID" |
|||
msgstr "ID" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,mobile:0 |
|||
msgid "Is mobile?" |
|||
msgstr "Est mobile?" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,__last_update:0 |
|||
#: field:mail.tracking.event,__last_update:0 |
|||
msgid "Last Modified on" |
|||
msgstr "Dernière modification le" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,write_uid:0 field:mail.tracking.event,write_uid:0 |
|||
msgid "Last Updated by" |
|||
msgstr "Dernière modification par" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,write_date:0 |
|||
#: field:mail.tracking.event,write_date:0 |
|||
msgid "Last Updated on" |
|||
msgstr "Modifié le" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_tracking_email |
|||
msgid "MailTracking email" |
|||
msgstr "Suivi du courriel: courriel" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
msgid "MailTracking email search" |
|||
msgstr "Suivi du courriel: recherche du courriel" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.actions.act_window,name:mail_tracking.action_view_mail_tracking_email |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_tree |
|||
msgid "MailTracking emails" |
|||
msgstr "Suivi du courriel: courriels" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_tracking_event |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_form |
|||
msgid "MailTracking event" |
|||
msgstr "Suivi du courriel: évènement" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "MailTracking event search" |
|||
msgstr "Suivi du courriel: recherche d'un évènement" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.actions.act_window,name:mail_tracking.action_view_mail_tracking_event |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_tree |
|||
msgid "MailTracking events" |
|||
msgstr "Suivi du courriel: évènements" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_message |
|||
#: field:mail.tracking.email,mail_message_id:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,tracking_email_id:0 |
|||
msgid "Message" |
|||
msgstr "Message" |
|||
|
|||
#. module: mail_tracking |
|||
#. openerp-web |
|||
#: code:addons/mail_tracking/static/src/js/mail_tracking.js:30 |
|||
#, python-format |
|||
msgid "Message tracking" |
|||
msgstr "Destinataire du courriel" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Month" |
|||
msgstr "Mois" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Open" |
|||
msgstr "Ouverte" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,os_family:0 |
|||
msgid "Operating system family" |
|||
msgstr "Famille du système d'exploitation" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_mail |
|||
msgid "Outgoing Mails" |
|||
msgstr "Courriels sortants" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_res_partner |
|||
#: field:mail.tracking.email,partner_id:0 |
|||
msgid "Partner" |
|||
msgstr "Partenaire" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_tree |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,recipient:0 |
|||
msgid "Recipient" |
|||
msgstr "Destinataire" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,recipient:0 |
|||
msgid "Recipient email" |
|||
msgstr "Courriel du destinataire " |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,recipient_address:0 |
|||
msgid "Recipient email address" |
|||
msgstr "Adresse de courriel du destinataire" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Rejected" |
|||
msgstr "Refusé" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,smtp_server:0 |
|||
msgid "SMTP server" |
|||
msgstr "Serveur SMTP" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_tree |
|||
msgid "Sender" |
|||
msgstr "Émetteur" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,sender:0 |
|||
msgid "Sender email" |
|||
msgstr "Courriel de l'expéditeur" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Sent" |
|||
msgstr "Envoyé" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Soft bounce" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
msgid "Soft bounced" |
|||
msgstr "" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Spam" |
|||
msgstr "Pourriel" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,state:0 |
|||
msgid "State" |
|||
msgstr "État" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,name:0 |
|||
msgid "Subject" |
|||
msgstr "Objet" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,time:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,time:0 |
|||
msgid "Time" |
|||
msgstr "Heure" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.ui.menu,name:mail_tracking.menu_mail_tracking_email |
|||
#: view:res.partner:mail_tracking.view_partner_form |
|||
#: field:res.partner,tracking_email_ids:0 |
|||
msgid "Tracking emails" |
|||
msgstr "Suivi du courriel: courriels" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:res.partner,tracking_emails_count:0 |
|||
msgid "Tracking emails count" |
|||
msgstr "Suivi du courriel: nombre de courriels" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.ui.menu,name:mail_tracking.menu_mail_tracking_event |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: field:mail.tracking.email,tracking_event_ids:0 |
|||
msgid "Tracking events" |
|||
msgstr "Suivi du courriel: évènements" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Type" |
|||
msgstr "Type" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "URL" |
|||
msgstr "URL" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,timestamp:0 field:mail.tracking.event,timestamp:0 |
|||
msgid "UTC timestamp" |
|||
msgstr "Horodatage en UTC" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Unsubscribe" |
|||
msgstr "Se désabonner" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Unsubscribed" |
|||
msgstr "Désincrit" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,ip:0 |
|||
msgid "User IP" |
|||
msgstr "IP de l'utilisateur" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_tree |
|||
#: field:mail.tracking.event,user_agent:0 |
|||
msgid "User agent" |
|||
msgstr "Navigateur" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,ua_family:0 |
|||
msgid "User agent family" |
|||
msgstr "Famille du navigateur" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,ua_type:0 |
|||
msgid "User agent type" |
|||
msgstr "type de navigateur" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,user_country_id:0 |
|||
msgid "User country" |
|||
msgstr "Pays de l'utilisateur" |
@ -0,0 +1,458 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * mail_tracking |
|||
# |
|||
# Translators: |
|||
# OCA Transbot <transbot@odoo-community.org>, 2016 |
|||
# Matjaž Mozetič <m.mozetic@matmoz.si>, 2016 |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 8.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2016-09-02 02:43+0000\n" |
|||
"PO-Revision-Date: 2016-09-02 02:43+0000\n" |
|||
"Last-Translator: Matjaž Mozetič <m.mozetic@matmoz.si>, 2016\n" |
|||
"Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Language: sl\n" |
|||
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" |
|||
|
|||
#. module: mail_tracking |
|||
#: help:mail.tracking.email,state:0 |
|||
msgid "" |
|||
" * The 'Error' status indicates that there was an error when trying to sent the email, for example, 'No valid recipient'\n" |
|||
" * The 'Sent' status indicates that message was succesfully sent via outgoing email server (SMTP).\n" |
|||
" * The 'Delivered' status indicates that message was succesfully delivered to recipient Mail Exchange (MX) server.\n" |
|||
" * The 'Open' status indicates that message was opened or clicked by recipient.\n" |
|||
" * The 'Rejected' status indicates that recipient email address is blacklisted by outgoing email server (SMTP). It is recomended to delete this email address.\n" |
|||
" * The 'Spam' status indicates that outgoing email server (SMTP) consider this message as spam.\n" |
|||
" * The 'Unsubscribed' status indicates that recipient has requested to be unsubscribed from this message.\n" |
|||
" * The 'Bounced' status indicates that message was bounced by recipient Mail Exchange (MX) server.\n" |
|||
" * The 'Soft bounced' status indicates that message was soft bounced by recipient Mail Exchange (MX) server.\n" |
|||
msgstr "" |
|||
" * Stanje 'Napaka' pomeni, da je prišlo do napake pri pošiljanju e-pošte, npr. 'Ni veljavnih prejemnikov'\n" |
|||
" * Stanje 'Poslano' pomeni, da je bilo sporočilo uspešno poslano preko izhodnega e-poštnega strežnika (SMTP).\n" |
|||
" * Stanje 'Dostavljeno' pomeni, da je bilo sporočilo uspešno dostavljeno na prejemnikov Mail Exchange (MX) strežnik.\n" |
|||
" * Stanje 'Odprto' pomeni, da je prejemnik sporočilo odprl ali kliknil.\n" |
|||
" * Stanje 'Zavrnjeno' pomeni, da je prejemnikov e-poštni naslov na črni listi odhodnega e-poštnega strežnika (SMTP). Priporočeno je, da se ta e-poštni naslov izbriše.\n" |
|||
" * Stanje 'Neželjeno' pomeni, da izhodni strežnik (SMTP) obravnava to sporočilo kot neželjeno pošto.\n" |
|||
" * Stanje 'Izpisan' pomeni, da je prejemnik zahteval izpis iz seznama prejemnikov tega sporočila.\n" |
|||
" * Stanje 'Odbito' pomeni, da je bilo sporočilo odbito s strani prejemnikovega Mail Exchange (MX) strežnika.\n" |
|||
" * Stanje 'Mehko odbito' pomeni, da je bilo sporočilo 'mehko' odbito s strani prejemnikovega Mail Exchange (MX) strežnika.\n" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Bounce" |
|||
msgstr "Odboj" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,bounce_description:0 |
|||
msgid "Bounce description" |
|||
msgstr "Opis odboja" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,bounce_type:0 |
|||
msgid "Bounce type" |
|||
msgstr "Tip odboja" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
msgid "Bounced" |
|||
msgstr "Odbito" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Click" |
|||
msgstr "Kilk" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Clicked" |
|||
msgstr "Kliknjeno" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,url:0 |
|||
msgid "Clicked URL" |
|||
msgstr "Kliknjena URL" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_tree |
|||
msgid "Country" |
|||
msgstr "Država" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,create_uid:0 |
|||
#: field:mail.tracking.event,create_uid:0 |
|||
msgid "Created by" |
|||
msgstr "Ustvaril" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,create_date:0 |
|||
#: field:mail.tracking.event,create_date:0 |
|||
msgid "Created on" |
|||
msgstr "Ustvarjeno" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,date:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,date:0 |
|||
msgid "Date" |
|||
msgstr "Datum" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Deferral" |
|||
msgstr "Odložitev" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
msgid "Deferred" |
|||
msgstr "Odloženo" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Delivered" |
|||
msgstr "Dostavljeno" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,display_name:0 |
|||
msgid "Display Name" |
|||
msgstr "Prikazni naziv" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,display_name:0 |
|||
msgid "Display name" |
|||
msgstr "Prikazni naziv" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,mail_id:0 |
|||
msgid "Email" |
|||
msgstr "E-pošta" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:res.partner,email_score:0 |
|||
msgid "Email score" |
|||
msgstr "Točkovanje e-pošte" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_form |
|||
msgid "Error" |
|||
msgstr "Napaka" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,error_smtp_server:0 |
|||
msgid "Error SMTP server" |
|||
msgstr "Napaka SMTP strežnika" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,error_description:0 |
|||
#: field:mail.tracking.event,error_description:0 |
|||
msgid "Error description" |
|||
msgstr "Opis napake" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,error_details:0 |
|||
msgid "Error details" |
|||
msgstr "Podrobnosti o napaki" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,error_type:0 |
|||
#: field:mail.tracking.event,error_type:0 |
|||
msgid "Error type" |
|||
msgstr "Tip napake" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,event_type:0 |
|||
msgid "Event type" |
|||
msgstr "Tip dogodka" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Failed" |
|||
msgstr "Neuspelo" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Group By" |
|||
msgstr "Združi po" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Hard bounce" |
|||
msgstr "Trdo odbito" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,id:0 field:mail.tracking.event,id:0 |
|||
msgid "ID" |
|||
msgstr "ID" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,mobile:0 |
|||
msgid "Is mobile?" |
|||
msgstr "Mobilno?" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,__last_update:0 |
|||
#: field:mail.tracking.event,__last_update:0 |
|||
msgid "Last Modified on" |
|||
msgstr "Zadnjič spremenjeno" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,write_uid:0 field:mail.tracking.event,write_uid:0 |
|||
msgid "Last Updated by" |
|||
msgstr "Zadnji posodobil" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,write_date:0 |
|||
#: field:mail.tracking.event,write_date:0 |
|||
msgid "Last Updated on" |
|||
msgstr "Zadnjič posodobljeno" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_tracking_email |
|||
msgid "MailTracking email" |
|||
msgstr "Sledenje e-pošte" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
msgid "MailTracking email search" |
|||
msgstr "Iskalnik sledenja e-pošte" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.actions.act_window,name:mail_tracking.action_view_mail_tracking_email |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_tree |
|||
msgid "MailTracking emails" |
|||
msgstr "Sporočila sledenja" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_tracking_event |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_form |
|||
msgid "MailTracking event" |
|||
msgstr "Dogodek sledenja e-pošte" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "MailTracking event search" |
|||
msgstr "Iskalnik dogodkov sledenja e-pošte" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.actions.act_window,name:mail_tracking.action_view_mail_tracking_event |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_tree |
|||
msgid "MailTracking events" |
|||
msgstr "Dogodki sledenja e-pošte" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_message |
|||
#: field:mail.tracking.email,mail_message_id:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,tracking_email_id:0 |
|||
msgid "Message" |
|||
msgstr "Sporočilo" |
|||
|
|||
#. module: mail_tracking |
|||
#. openerp-web |
|||
#: code:addons/mail_tracking/static/src/js/mail_tracking.js:30 |
|||
#, python-format |
|||
msgid "Message tracking" |
|||
msgstr "Sledenje sporočila" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Month" |
|||
msgstr "Mesec" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Open" |
|||
msgstr "Odprto" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,os_family:0 |
|||
msgid "Operating system family" |
|||
msgstr "Družina operacijskega sistema" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_mail_mail |
|||
msgid "Outgoing Mails" |
|||
msgstr "Izhodna pošta" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.model,name:mail_tracking.model_res_partner |
|||
#: field:mail.tracking.email,partner_id:0 |
|||
msgid "Partner" |
|||
msgstr "Partner" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_tree |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,recipient:0 |
|||
msgid "Recipient" |
|||
msgstr "Prejemnik" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,recipient:0 |
|||
msgid "Recipient email" |
|||
msgstr "Prejemnikova e-pošta" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,recipient_address:0 |
|||
msgid "Recipient email address" |
|||
msgstr "Prejemnikova e-pošta" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Rejected" |
|||
msgstr "Zavrnjeno" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,smtp_server:0 |
|||
msgid "SMTP server" |
|||
msgstr "SMTP strežnik" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_tree |
|||
msgid "Sender" |
|||
msgstr "Pošiljatelj" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,sender:0 |
|||
msgid "Sender email" |
|||
msgstr "Pošiljateljeva e-pošta" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Sent" |
|||
msgstr "Poslano" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Soft bounce" |
|||
msgstr "Mehki odboj" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
msgid "Soft bounced" |
|||
msgstr "Mehko odbito" |
|||
|
|||
#. module: mail_tracking |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Spam" |
|||
msgstr "Spam" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,state:0 |
|||
msgid "State" |
|||
msgstr "Stanje" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,name:0 |
|||
msgid "Subject" |
|||
msgstr "Zadeva" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: field:mail.tracking.email,time:0 |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,time:0 |
|||
msgid "Time" |
|||
msgstr "Čas" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.ui.menu,name:mail_tracking.menu_mail_tracking_email |
|||
#: view:res.partner:mail_tracking.view_partner_form |
|||
#: field:res.partner,tracking_email_ids:0 |
|||
msgid "Tracking emails" |
|||
msgstr "Sledilna e-pošta" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:res.partner,tracking_emails_count:0 |
|||
msgid "Tracking emails count" |
|||
msgstr "Števec sledenja e-pošte" |
|||
|
|||
#. module: mail_tracking |
|||
#: model:ir.ui.menu,name:mail_tracking.menu_mail_tracking_event |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: field:mail.tracking.email,tracking_event_ids:0 |
|||
msgid "Tracking events" |
|||
msgstr "Sledilni dogodki" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Type" |
|||
msgstr "Tip" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "URL" |
|||
msgstr "URL" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.email,timestamp:0 field:mail.tracking.event,timestamp:0 |
|||
msgid "UTC timestamp" |
|||
msgstr "UTC časovni žig" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
msgid "Unsubscribe" |
|||
msgstr "Odjava" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_search |
|||
#: selection:mail.tracking.email,state:0 |
|||
#: selection:mail.tracking.event,event_type:0 |
|||
msgid "Unsubscribed" |
|||
msgstr "Odjavljeno" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,ip:0 |
|||
msgid "User IP" |
|||
msgstr "Uporabnikov IP" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.email:mail_tracking.view_mail_tracking_email_form |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_tree |
|||
#: field:mail.tracking.event,user_agent:0 |
|||
msgid "User agent" |
|||
msgstr "Uporabnikov odjemalec" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,ua_family:0 |
|||
msgid "User agent family" |
|||
msgstr "Družina uporabnikovih odjemalcev" |
|||
|
|||
#. module: mail_tracking |
|||
#: view:mail.tracking.event:mail_tracking.view_mail_tracking_event_search |
|||
#: field:mail.tracking.event,ua_type:0 |
|||
msgid "User agent type" |
|||
msgstr "Tip uporabnikovega odjemalca" |
|||
|
|||
#. module: mail_tracking |
|||
#: field:mail.tracking.event,user_country_id:0 |
|||
msgid "User country" |
|||
msgstr "Država uporabnika" |
@ -0,0 +1,11 @@ |
|||
# -*- 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 |
|||
from . import mail_message |
|||
from . import mail_tracking_email |
|||
from . import mail_tracking_event |
|||
from . import res_partner |
@ -0,0 +1,94 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import re |
|||
import threading |
|||
from openerp import models, api, tools |
|||
|
|||
|
|||
class IrMailServer(models.Model): |
|||
_inherit = "ir.mail_server" |
|||
|
|||
def _tracking_headers_add(self, tracking_email_id, headers): |
|||
"""Allow other addons to add its own tracking SMTP headers""" |
|||
headers = headers or {} |
|||
headers['X-Odoo-Database'] = getattr( |
|||
threading.currentThread(), 'dbname', None), |
|||
headers['X-Odoo-Tracking-ID'] = tracking_email_id |
|||
return headers |
|||
|
|||
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 |
|||
|
|||
def build_email(self, email_from, email_to, subject, body, email_cc=None, |
|||
email_bcc=None, reply_to=False, attachments=None, |
|||
message_id=None, references=None, object_id=False, |
|||
subtype='plain', headers=None, body_alternative=None, |
|||
subtype_alternative='plain'): |
|||
tracking_email_id = self._tracking_email_id_body_get(body) |
|||
if tracking_email_id: |
|||
headers = self._tracking_headers_add(tracking_email_id, headers) |
|||
msg = super(IrMailServer, self).build_email( |
|||
email_from, email_to, subject, body, email_cc=email_cc, |
|||
email_bcc=email_bcc, reply_to=reply_to, attachments=attachments, |
|||
message_id=message_id, references=references, object_id=object_id, |
|||
subtype=subtype, headers=headers, |
|||
body_alternative=body_alternative, |
|||
subtype_alternative=subtype_alternative) |
|||
return msg |
|||
|
|||
def _tracking_email_get(self, message): |
|||
tracking_email_id = False |
|||
if message.get('X-Odoo-Tracking-ID', '').isdigit(): |
|||
tracking_email_id = int(message['X-Odoo-Tracking-ID']) |
|||
return self.env['mail.tracking.email'].browse(tracking_email_id) |
|||
|
|||
def _smtp_server_get(self, mail_server_id, smtp_server): |
|||
smtp_server_used = False |
|||
mail_server = None |
|||
if mail_server_id: |
|||
mail_server = self.browse(mail_server_id) |
|||
elif not smtp_server: |
|||
mail_server_ids = self.search([], order='sequence', limit=1) |
|||
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 |
|||
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): |
|||
message_id = False |
|||
tracking_email = self._tracking_email_get(message) |
|||
smtp_server_used = self._smtp_server_get( |
|||
mail_server_id, smtp_server) |
|||
try: |
|||
message_id = super(IrMailServer, self).send_email( |
|||
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) |
|||
except Exception as e: |
|||
if tracking_email: |
|||
tracking_email.smtp_error(self, smtp_server_used, e) |
|||
raise |
|||
if message_id and tracking_email: |
|||
vals = tracking_email._tracking_sent_prepare( |
|||
self, smtp_server_used, message, message_id) |
|||
if vals: |
|||
self.env['mail.tracking.event'].sudo().create(vals) |
|||
return message_id |
@ -0,0 +1,36 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import time |
|||
from datetime import datetime |
|||
from email.utils import COMMASPACE |
|||
|
|||
from openerp import models, api, fields |
|||
|
|||
|
|||
class MailMail(models.Model): |
|||
_inherit = 'mail.mail' |
|||
|
|||
def _tracking_email_prepare(self, partner, email): |
|||
ts = time.time() |
|||
dt = datetime.utcfromtimestamp(ts) |
|||
email_to_list = email.get('email_to', []) |
|||
email_to = COMMASPACE.join(email_to_list) |
|||
return { |
|||
'name': email.get('subject', False), |
|||
'timestamp': '%.6f' % ts, |
|||
'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, |
|||
'recipient': email_to, |
|||
'sender': self.email_from, |
|||
} |
|||
|
|||
@api.multi |
|||
def send_get_email_dict(self, partner=None): |
|||
email = super(MailMail, self).send_get_email_dict(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) |
@ -0,0 +1,79 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from openerp import models, api |
|||
|
|||
|
|||
class MailMessage(models.Model): |
|||
_inherit = "mail.message" |
|||
|
|||
def _tracking_status_map_get(self): |
|||
return { |
|||
'False': 'waiting', |
|||
'error': 'error', |
|||
'deferred': 'sent', |
|||
'sent': 'sent', |
|||
'delivered': 'delivered', |
|||
'opened': 'opened', |
|||
'rejected': 'error', |
|||
'spam': 'error', |
|||
'unsub': 'opened', |
|||
'bounced': 'error', |
|||
'soft-bounced': 'error', |
|||
} |
|||
|
|||
def _partner_tracking_status_get(self, tracking_email): |
|||
tracking_status_map = self._tracking_status_map_get() |
|||
status = 'unknown' |
|||
if tracking_email: |
|||
tracking_email_status = str(tracking_email.state) |
|||
status = tracking_status_map.get(tracking_email_status, 'unknown') |
|||
return status |
|||
|
|||
@api.multi |
|||
def tracking_status(self): |
|||
res = {} |
|||
for message in self: |
|||
partner_trackings = [] |
|||
partners_already = self.env['res.partner'] |
|||
partners = self.env['res.partner'] |
|||
trackings = self.env['mail.tracking.email'].search([ |
|||
('mail_message_id', '=', message.id), |
|||
]) |
|||
# Search all trackings for this message |
|||
for tracking in trackings: |
|||
status = self._partner_tracking_status_get(tracking) |
|||
recipient = ( |
|||
tracking.partner_id.display_name or tracking.recipient) |
|||
partner_trackings.append(( |
|||
status, tracking.id, recipient, tracking.partner_id.id)) |
|||
if tracking.partner_id: |
|||
partners_already |= tracking.partner_id |
|||
# Search all recipients for this message |
|||
if message.partner_ids: |
|||
partners |= message.partner_ids |
|||
if message.needaction_partner_ids: |
|||
partners |= message.needaction_partner_ids |
|||
# Remove recipients already included |
|||
partners -= partners_already |
|||
for partner in partners: |
|||
# If there is partners not included, then status is 'unknown' |
|||
partner_trackings.append(( |
|||
'unknown', False, partner.display_name, partner.id)) |
|||
res[message.id] = partner_trackings |
|||
return res |
|||
|
|||
@api.model |
|||
def _message_read_dict_postprocess(self, messages, message_tree): |
|||
res = super(MailMessage, self)._message_read_dict_postprocess( |
|||
messages, message_tree) |
|||
mail_message_ids = {m.get('id') for m in messages if m.get('id')} |
|||
mail_messages = self.browse(mail_message_ids) |
|||
partner_trackings = mail_messages.tracking_status() |
|||
for message_dict in messages: |
|||
mail_message_id = message_dict.get('id', False) |
|||
if mail_message_id: |
|||
message_dict['partner_trackings'] = \ |
|||
partner_trackings[mail_message_id] |
|||
return res |
@ -0,0 +1,313 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 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 time |
|||
import re |
|||
from datetime import datetime |
|||
|
|||
from openerp import models, api, fields, tools |
|||
import openerp.addons.decimal_precision as dp |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
EVENT_OPEN_DELTA = 10 # seconds |
|||
EVENT_CLICK_DELTA = 5 # seconds |
|||
|
|||
|
|||
class MailTrackingEmail(models.Model): |
|||
_name = "mail.tracking.email" |
|||
_order = 'time desc' |
|||
_rec_name = 'display_name' |
|||
_description = 'MailTracking email' |
|||
|
|||
name = fields.Char(string="Subject", readonly=True, index=True) |
|||
display_name = fields.Char( |
|||
string="Display name", readonly=True, store=True, |
|||
compute="_compute_display_name") |
|||
timestamp = fields.Float( |
|||
string='UTC timestamp', readonly=True, |
|||
digits=dp.get_precision('MailTracking Timestamp')) |
|||
time = fields.Datetime(string="Time", readonly=True) |
|||
date = fields.Date( |
|||
string="Date", readonly=True, compute="_compute_date", store=True) |
|||
mail_message_id = fields.Many2one( |
|||
string="Message", comodel_name='mail.message', readonly=True) |
|||
mail_id = fields.Many2one( |
|||
string="Email", comodel_name='mail.mail', readonly=True) |
|||
partner_id = fields.Many2one( |
|||
string="Partner", comodel_name='res.partner', readonly=True) |
|||
recipient = fields.Char(string='Recipient email', readonly=True) |
|||
recipient_address = fields.Char( |
|||
string='Recipient email address', readonly=True, store=True, |
|||
compute='_compute_recipient_address') |
|||
sender = fields.Char(string='Sender email', readonly=True) |
|||
state = fields.Selection([ |
|||
('error', 'Error'), |
|||
('deferred', 'Deferred'), |
|||
('sent', 'Sent'), |
|||
('delivered', 'Delivered'), |
|||
('opened', 'Open'), |
|||
('rejected', 'Rejected'), |
|||
('spam', 'Spam'), |
|||
('unsub', 'Unsubscribed'), |
|||
('bounced', 'Bounced'), |
|||
('soft-bounced', 'Soft bounced'), |
|||
], string='State', index=True, readonly=True, default=False, |
|||
help=" * The 'Error' status indicates that there was an error " |
|||
"when trying to sent the email, for example, " |
|||
"'No valid recipient'\n" |
|||
" * The 'Sent' status indicates that message was succesfully " |
|||
"sent via outgoing email server (SMTP).\n" |
|||
" * The 'Delivered' status indicates that message was " |
|||
"succesfully delivered to recipient Mail Exchange (MX) server.\n" |
|||
" * The 'Open' status indicates that message was opened or " |
|||
"clicked by recipient.\n" |
|||
" * The 'Rejected' status indicates that recipient email " |
|||
"address is blacklisted by outgoing email server (SMTP). " |
|||
"It is recomended to delete this email address.\n" |
|||
" * The 'Spam' status indicates that outgoing email " |
|||
"server (SMTP) consider this message as spam.\n" |
|||
" * The 'Unsubscribed' status indicates that recipient has " |
|||
"requested to be unsubscribed from this message.\n" |
|||
" * The 'Bounced' status indicates that message was bounced " |
|||
"by recipient Mail Exchange (MX) server.\n" |
|||
" * The 'Soft bounced' status indicates that message was soft " |
|||
"bounced by recipient Mail Exchange (MX) server.\n") |
|||
error_smtp_server = fields.Char(string='Error SMTP server', readonly=True) |
|||
error_type = fields.Char(string='Error type', readonly=True) |
|||
error_description = fields.Char( |
|||
string='Error description', readonly=True) |
|||
bounce_type = fields.Char(string='Bounce type', readonly=True) |
|||
bounce_description = fields.Char( |
|||
string='Bounce description', readonly=True) |
|||
tracking_event_ids = fields.One2many( |
|||
string="Tracking events", comodel_name='mail.tracking.event', |
|||
inverse_name='tracking_email_id', readonly=True) |
|||
|
|||
@api.model |
|||
def tracking_ids_recalculate(self, model, email_field, tracking_field, |
|||
email, new_tracking=None): |
|||
objects = self.env[model].search([ |
|||
(email_field, '=ilike', email), |
|||
]) |
|||
for obj in objects: |
|||
trackings = obj[tracking_field] |
|||
if new_tracking: |
|||
trackings |= new_tracking |
|||
trackings = trackings._email_score_tracking_filter() |
|||
if set(obj[tracking_field].ids) != set(trackings.ids): |
|||
if trackings: |
|||
obj.write({ |
|||
tracking_field: [(6, False, trackings.ids)] |
|||
}) |
|||
else: |
|||
obj.write({ |
|||
tracking_field: [(5, False, False)] |
|||
}) |
|||
return objects |
|||
|
|||
@api.model |
|||
def _tracking_ids_to_write(self, email): |
|||
trackings = self.env['mail.tracking.email'].search([ |
|||
('recipient_address', '=ilike', email) |
|||
]) |
|||
trackings = trackings._email_score_tracking_filter() |
|||
if trackings: |
|||
return [(6, False, trackings.ids)] |
|||
else: |
|||
return [(5, False, False)] |
|||
|
|||
@api.multi |
|||
def _email_score_tracking_filter(self): |
|||
"""Default email score filter for tracking emails""" |
|||
# Consider only last 10 tracking emails |
|||
return self.sorted(key=lambda r: r.time, reverse=True)[:10] |
|||
|
|||
@api.model |
|||
def email_score_from_email(self, email): |
|||
trackings = self.env['mail.tracking.email'].search([ |
|||
('recipient_address', '=ilike', email) |
|||
]) |
|||
return trackings.email_score() |
|||
|
|||
@api.multi |
|||
def email_score(self): |
|||
"""Default email score algorimth""" |
|||
score = 50.0 |
|||
trackings = self._email_score_tracking_filter() |
|||
for tracking in trackings: |
|||
if tracking.state in ('error',): |
|||
score -= 50.0 |
|||
elif tracking.state in ('rejected', 'spam', 'bounced'): |
|||
score -= 25.0 |
|||
elif tracking.state in ('soft-bounced', 'unsub'): |
|||
score -= 10.0 |
|||
elif tracking.state in ('delivered',): |
|||
score += 5.0 |
|||
elif tracking.state in ('opened',): |
|||
score += 10.0 |
|||
if score > 100.0: |
|||
score = 100.0 |
|||
return score |
|||
|
|||
@api.multi |
|||
@api.depends('recipient') |
|||
def _compute_recipient_address(self): |
|||
for email in self: |
|||
matches = re.search(r'<(.*@.*)>', email.recipient) |
|||
if matches: |
|||
email.recipient_address = matches.group(1) |
|||
else: |
|||
email.recipient_address = email.recipient |
|||
|
|||
@api.multi |
|||
@api.depends('name', 'recipient') |
|||
def _compute_display_name(self): |
|||
for email in self: |
|||
parts = [email.name or ''] |
|||
if email.recipient: |
|||
parts.append(email.recipient) |
|||
email.display_name = ' - '.join(parts) |
|||
|
|||
@api.multi |
|||
@api.depends('time') |
|||
def _compute_date(self): |
|||
for email in self: |
|||
email.date = fields.Date.to_string( |
|||
fields.Date.from_string(email.time)) |
|||
|
|||
@api.model |
|||
def create(self, vals): |
|||
tracking = super(MailTrackingEmail, self).create(vals) |
|||
self.tracking_ids_recalculate( |
|||
'res.partner', 'email', 'tracking_email_ids', |
|||
tracking.recipient_address, new_tracking=tracking) |
|||
return tracking |
|||
|
|||
def _get_mail_tracking_img(self): |
|||
base_url = self.env['ir.config_parameter'].get_param('web.base.url') |
|||
path_url = ( |
|||
'mail/tracking/open/%(db)s/%(tracking_email_id)s/blank.gif' % { |
|||
'db': self.env.cr.dbname, |
|||
'tracking_email_id': self.id, |
|||
}) |
|||
track_url = urlparse.urljoin(base_url, path_url) |
|||
return ( |
|||
'<img src="%(url)s" alt="" ' |
|||
'data-odoo-tracking-email="%(tracking_email_id)s"/>' % { |
|||
'url': track_url, |
|||
'tracking_email_id': self.id, |
|||
}) |
|||
|
|||
@api.multi |
|||
def smtp_error(self, mail_server, smtp_server, exception): |
|||
self.sudo().write({ |
|||
'error_smtp_server': tools.ustr(smtp_server), |
|||
'error_type': exception.__class__.__name__, |
|||
'error_description': tools.ustr(exception), |
|||
'state': 'error', |
|||
}) |
|||
return True |
|||
|
|||
@api.multi |
|||
def tracking_img_add(self, email): |
|||
self.ensure_one() |
|||
tracking_url = self._get_mail_tracking_img() |
|||
if tracking_url: |
|||
body = tools.append_content_to_html( |
|||
email.get('body', ''), tracking_url, plaintext=False, |
|||
container_tag='div') |
|||
email['body'] = body |
|||
return email |
|||
|
|||
def _message_partners_check(self, message, message_id): |
|||
mail_message = self.mail_message_id |
|||
partners = ( |
|||
mail_message.needaction_partner_ids | mail_message.partner_ids) |
|||
if (self.partner_id and self.partner_id not in partners): |
|||
# If mail_message haven't tracking partner, then |
|||
# add it in order to see his tracking status in chatter |
|||
if mail_message.subtype_id: |
|||
mail_message.sudo().write({ |
|||
'needaction_partner_ids': [(4, self.partner_id.id)], |
|||
}) |
|||
else: |
|||
mail_message.sudo().write({ |
|||
'partner_ids': [(4, self.partner_id.id)], |
|||
}) |
|||
return True |
|||
|
|||
@api.multi |
|||
def _tracking_sent_prepare(self, mail_server, smtp_server, message, |
|||
message_id): |
|||
self.ensure_one() |
|||
ts = time.time() |
|||
dt = datetime.utcfromtimestamp(ts) |
|||
self._message_partners_check(message, message_id) |
|||
self.sudo().write({'state': 'sent'}) |
|||
return { |
|||
'recipient': message['To'], |
|||
'timestamp': '%.6f' % ts, |
|||
'time': fields.Datetime.to_string(dt), |
|||
'tracking_email_id': self.id, |
|||
'event_type': 'sent', |
|||
'smtp_server': smtp_server, |
|||
} |
|||
|
|||
def _event_prepare(self, event_type, metadata): |
|||
self.ensure_one() |
|||
m_event = self.env['mail.tracking.event'] |
|||
method = getattr(m_event, 'process_' + event_type, None) |
|||
if method and hasattr(method, '__call__'): |
|||
return method(self, metadata) |
|||
else: # pragma: no cover |
|||
_logger.info('Unknown event type: %s' % event_type) |
|||
return False |
|||
|
|||
def _concurrent_events(self, event_type, metadata): |
|||
m_event = self.env['mail.tracking.event'] |
|||
self.ensure_one() |
|||
concurrent_event_ids = False |
|||
if event_type in {'open', 'click'}: |
|||
ts = metadata.get('timestamp', time.time()) |
|||
delta = EVENT_OPEN_DELTA if event_type == 'open' \ |
|||
else EVENT_CLICK_DELTA |
|||
domain = [ |
|||
('timestamp', '>=', ts - delta), |
|||
('timestamp', '<=', ts + delta), |
|||
('tracking_email_id', '=', self.id), |
|||
('event_type', '=', event_type), |
|||
] |
|||
if event_type == 'click': |
|||
domain.append(('url', '=', metadata.get('url', False))) |
|||
concurrent_event_ids = m_event.search(domain) |
|||
return concurrent_event_ids |
|||
|
|||
@api.multi |
|||
def event_create(self, event_type, metadata): |
|||
event_ids = self.env['mail.tracking.event'] |
|||
for tracking_email in self: |
|||
other_ids = tracking_email._concurrent_events(event_type, metadata) |
|||
if not other_ids: |
|||
vals = tracking_email._event_prepare(event_type, metadata) |
|||
if vals: |
|||
event_ids += event_ids.sudo().create(vals) |
|||
partners = self.tracking_ids_recalculate( |
|||
'res.partner', 'email', 'tracking_email_ids', |
|||
tracking_email.recipient_address) |
|||
if partners: |
|||
partners.email_score_calculate() |
|||
else: |
|||
_logger.debug("Concurrent event '%s' discarded", event_type) |
|||
return event_ids |
|||
|
|||
@api.model |
|||
def event_process(self, request, post, metadata, event_type=None): |
|||
# Generic event process hook, inherit it and |
|||
# - return 'OK' if processed |
|||
# - return 'NONE' if this request is not for you |
|||
# - return 'ERROR' if any error |
|||
return 'NONE' # pragma: no cover |
@ -0,0 +1,136 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import time |
|||
from datetime import datetime |
|||
|
|||
from openerp import models, api, fields |
|||
import openerp.addons.decimal_precision as dp |
|||
|
|||
|
|||
class MailTrackingEvent(models.Model): |
|||
_name = "mail.tracking.event" |
|||
_order = 'timestamp desc' |
|||
_rec_name = 'event_type' |
|||
_description = 'MailTracking event' |
|||
|
|||
recipient = fields.Char(string="Recipient", readonly=True) |
|||
timestamp = fields.Float( |
|||
string='UTC timestamp', readonly=True, |
|||
digits=dp.get_precision('MailTracking Timestamp')) |
|||
time = fields.Datetime(string="Time", readonly=True) |
|||
date = fields.Date( |
|||
string="Date", readonly=True, compute="_compute_date", store=True) |
|||
tracking_email_id = fields.Many2one( |
|||
string='Message', readonly=True, |
|||
comodel_name='mail.tracking.email') |
|||
event_type = fields.Selection(string='Event type', selection=[ |
|||
('sent', 'Sent'), |
|||
('delivered', 'Delivered'), |
|||
('deferral', 'Deferral'), |
|||
('hard_bounce', 'Hard bounce'), |
|||
('soft_bounce', 'Soft bounce'), |
|||
('open', 'Open'), |
|||
('click', 'Clicked'), |
|||
('spam', 'Spam'), |
|||
('unsub', 'Unsubscribed'), |
|||
('reject', 'Rejected'), |
|||
], readonly=True) |
|||
smtp_server = fields.Char(string='SMTP server', readonly=True) |
|||
url = fields.Char(string='Clicked URL', readonly=True) |
|||
ip = fields.Char(string='User IP', readonly=True) |
|||
user_agent = fields.Char(string='User agent', readonly=True) |
|||
mobile = fields.Boolean(string='Is mobile?', readonly=True) |
|||
os_family = fields.Char(string='Operating system family', readonly=True) |
|||
ua_family = fields.Char(string='User agent family', readonly=True) |
|||
ua_type = fields.Char(string='User agent type', readonly=True) |
|||
user_country_id = fields.Many2one(string='User country', readonly=True, |
|||
comodel_name='res.country') |
|||
error_type = fields.Char(string='Error type', readonly=True) |
|||
error_description = fields.Char(string='Error description', readonly=True) |
|||
error_details = fields.Text(string='Error details', readonly=True) |
|||
|
|||
@api.multi |
|||
@api.depends('time') |
|||
def _compute_date(self): |
|||
for email in self: |
|||
email.date = fields.Date.to_string( |
|||
fields.Date.from_string(email.time)) |
|||
|
|||
def _process_data(self, tracking_email, metadata, event_type, state): |
|||
ts = time.time() |
|||
dt = datetime.utcfromtimestamp(ts) |
|||
return { |
|||
'recipient': metadata.get('recipient', tracking_email.recipient), |
|||
'timestamp': metadata.get('timestamp', ts), |
|||
'time': metadata.get('time', fields.Datetime.to_string(dt)), |
|||
'date': metadata.get('date', fields.Date.to_string(dt)), |
|||
'tracking_email_id': tracking_email.id, |
|||
'event_type': event_type, |
|||
'ip': metadata.get('ip', False), |
|||
'url': metadata.get('url', False), |
|||
'user_agent': metadata.get('user_agent', False), |
|||
'mobile': metadata.get('mobile', False), |
|||
'os_family': metadata.get('os_family', False), |
|||
'ua_family': metadata.get('ua_family', False), |
|||
'ua_type': metadata.get('ua_type', False), |
|||
'user_country_id': metadata.get('user_country_id', False), |
|||
'error_type': metadata.get('error_type', False), |
|||
'error_description': metadata.get('error_description', False), |
|||
'error_details': metadata.get('error_details', False), |
|||
} |
|||
|
|||
def _process_status(self, tracking_email, metadata, event_type, state): |
|||
tracking_email.sudo().write({'state': state}) |
|||
return self._process_data(tracking_email, metadata, event_type, state) |
|||
|
|||
def _process_bounce(self, tracking_email, metadata, event_type, state): |
|||
tracking_email.sudo().write({ |
|||
'state': state, |
|||
'bounce_type': metadata.get('bounce_type', False), |
|||
'bounce_description': metadata.get('bounce_description', False), |
|||
}) |
|||
return self._process_data(tracking_email, metadata, event_type, state) |
|||
|
|||
@api.model |
|||
def process_delivered(self, tracking_email, metadata): |
|||
return self._process_status( |
|||
tracking_email, metadata, 'delivered', 'delivered') |
|||
|
|||
@api.model |
|||
def process_deferral(self, tracking_email, metadata): |
|||
return self._process_status( |
|||
tracking_email, metadata, 'deferral', 'deferred') |
|||
|
|||
@api.model |
|||
def process_hard_bounce(self, tracking_email, metadata): |
|||
return self._process_bounce( |
|||
tracking_email, metadata, 'hard_bounce', 'bounced') |
|||
|
|||
@api.model |
|||
def process_soft_bounce(self, tracking_email, metadata): |
|||
return self._process_bounce( |
|||
tracking_email, metadata, 'soft_bounce', 'soft-bounced') |
|||
|
|||
@api.model |
|||
def process_open(self, tracking_email, metadata): |
|||
return self._process_status(tracking_email, metadata, 'open', 'opened') |
|||
|
|||
@api.model |
|||
def process_click(self, tracking_email, metadata): |
|||
return self._process_status( |
|||
tracking_email, metadata, 'click', 'opened') |
|||
|
|||
@api.model |
|||
def process_spam(self, tracking_email, metadata): |
|||
return self._process_status(tracking_email, metadata, 'spam', 'spam') |
|||
|
|||
@api.model |
|||
def process_unsub(self, tracking_email, metadata): |
|||
return self._process_status(tracking_email, metadata, 'unsub', 'unsub') |
|||
|
|||
@api.model |
|||
def process_reject(self, tracking_email, metadata): |
|||
return self._process_status( |
|||
tracking_email, metadata, 'reject', 'rejected') |
@ -0,0 +1,46 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from openerp import models, api, fields |
|||
|
|||
|
|||
class ResPartner(models.Model): |
|||
_inherit = 'res.partner' |
|||
|
|||
tracking_email_ids = fields.Many2many( |
|||
string="Tracking emails", comodel_name="mail.tracking.email", |
|||
readonly=True) |
|||
tracking_emails_count = fields.Integer( |
|||
string="Tracking emails count", store=True, readonly=True, |
|||
compute="_compute_tracking_emails_count") |
|||
email_score = fields.Float( |
|||
string="Email score", readonly=True, default=50.0) |
|||
|
|||
@api.multi |
|||
def email_score_calculate(self): |
|||
# This is not a compute method because is causing a inter-block |
|||
# in mail_tracking_email PostgreSQL table |
|||
# We suspect that tracking_email write to state field block that |
|||
# table and then inside write ORM try to read from DB |
|||
# tracking_email_ids because it's not in cache. |
|||
# PostgreSQL blocks read because we have not committed yet the write |
|||
for partner in self: |
|||
partner.email_score = partner.tracking_email_ids.email_score() |
|||
|
|||
@api.one |
|||
@api.depends('tracking_email_ids') |
|||
def _compute_tracking_emails_count(self): |
|||
self.tracking_emails_count = self.env['mail.tracking.email'].\ |
|||
search_count([ |
|||
('recipient_address', '=ilike', self.email) |
|||
]) |
|||
|
|||
@api.multi |
|||
def write(self, vals): |
|||
email = vals.get('email') |
|||
if email is not None: |
|||
m_track = self.env['mail.tracking.email'] |
|||
vals['tracking_email_ids'] = m_track._tracking_ids_to_write(email) |
|||
vals['email_score'] = m_track.email_score_from_email(email) |
|||
return super(ResPartner, self).write(vals) |
@ -0,0 +1,5 @@ |
|||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" |
|||
"access_mail_tracking_email_group_user","mail_tracking_email group_user","model_mail_tracking_email","base.group_user",1,0,0,0 |
|||
"access_mail_tracking_event_group_user","mail_tracking_event group_user","model_mail_tracking_event","base.group_user",1,0,0,0 |
|||
"access_mail_tracking_email_group_system","mail_tracking_email group_system","model_mail_tracking_email","base.group_system",1,1,1,1 |
|||
"access_mail_tracking_event_group_system","mail_tracking_event group_system","model_mail_tracking_event","base.group_system",1,1,1,1 |
After Width: 128 | Height: 128 | Size: 5.8 KiB |
@ -0,0 +1,21 @@ |
|||
/* © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */ |
|||
|
|||
.mail_tracking span { |
|||
color: #909090; |
|||
} |
|||
.mail_tracking_pointer { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.mail_tracking span.mail_tracking_opened { |
|||
color: #a34a8b; |
|||
} |
|||
|
|||
.o_mail_thread .o_thread_message .o_thread_message_core .o_mail_info { |
|||
margin: 0; |
|||
} |
|||
|
|||
.o_mail_thread .o_thread_message .o_thread_message_core .o_mail_tracking { |
|||
margin: 0 0 2px 0; |
|||
} |
After Width: 23 | Height: 16 | Size: 285 B |
After Width: 16 | Height: 16 | Size: 257 B |
After Width: 23 | Height: 16 | Size: 368 B |
After Width: 16 | Height: 16 | Size: 294 B |
After Width: 16 | Height: 16 | Size: 425 B |
After Width: 16 | Height: 16 | Size: 348 B |
@ -0,0 +1,103 @@ |
|||
/* © 2016 Antonio Espinosa - <antonio.espinosa@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"; |
|||
|
|||
var $ = require('$'); |
|||
var core = require('web.core'); |
|||
var session = require('web.session'); |
|||
var Model = require('web.Model'); |
|||
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); |
|||
|
|||
// 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; |
|||
}; |
|||
|
|||
ChatThread.include({ |
|||
on_tracking_partner_click: function (event) { |
|||
var partner_id = $(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]); |
|||
}); |
|||
}, |
|||
|
|||
}); |
|||
|
|||
}); // odoo.define
|
@ -0,0 +1,73 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> |
|||
<template> |
|||
|
|||
<t t-name="mail.tracking.status"> |
|||
<t t-if="tracking[0] == 'unknown'"> |
|||
<span class="mail_tracking_unknown"> |
|||
<i class="fa fa-ban"></i> |
|||
</span> |
|||
</t> |
|||
<t t-if="tracking[0] == 'waiting'"> |
|||
<span class="mail_tracking_waiting mail_tracking_pointer"> |
|||
<i class="fa fa-clock-o"></i> |
|||
</span> |
|||
</t> |
|||
<t t-if="tracking[0] == 'error'"> |
|||
<span class="mail_tracking_error mail_tracking_pointer"> |
|||
<i class="fa fa-remove"></i> |
|||
</span> |
|||
</t> |
|||
<t t-if="tracking[0] == 'sent'"> |
|||
<span class="mail_tracking_sent mail_tracking_pointer"> |
|||
<i class="fa fa-check"></i> |
|||
</span> |
|||
</t> |
|||
<t t-if="tracking[0] == 'delivered'"> |
|||
<span class="fa-stack mail_tracking_delivered mail_tracking_pointer"> |
|||
<i class="fa fa-check fa-stack-1x" style="margin-left:1px"></i> |
|||
<i class="fa fa-check fa-inverse fa-stack-1x" style="margin-left:-2px;"></i> |
|||
<i class="fa fa-check fa-stack-1x" style="margin-left:-3px"></i> |
|||
</span> |
|||
</t> |
|||
<t t-if="tracking[0] == 'opened'"> |
|||
<span class="fa-stack mail_tracking_opened mail_tracking_pointer"> |
|||
<i class="fa fa-check fa-stack-1x" style="margin-left:1px"></i> |
|||
<i class="fa fa-check fa-inverse fa-stack-1x" style="margin-left:-2px;"></i> |
|||
<i class="fa fa-check fa-stack-1x" style="margin-left:-3px"></i> |
|||
</span> |
|||
</t> |
|||
</t> |
|||
|
|||
<t t-extend="mail.ChatThread.Message"> |
|||
<t t-jquery="p[class='o_mail_info']" t-operation="after"> |
|||
<p class="o_mail_tracking"> |
|||
<strong>To:</strong> |
|||
<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" |
|||
t-att-data-partner="tracking[3]" |
|||
t-attf-href="#model=res.partner&id=#{tracking[3]}"> |
|||
<t t-esc="tracking[2]"/> |
|||
</a> |
|||
</t> |
|||
<t t-if="!tracking[3]"> |
|||
<span><t t-esc="tracking[2]"/></span> |
|||
</t> |
|||
<span class="mail_tracking o_mail_action_tracking_status" |
|||
t-att-data-tracking="tracking[1]" |
|||
t-attf-title="Status: #{tracking[0]}"> |
|||
<t t-call="mail.tracking.status"/> |
|||
</span> |
|||
<t t-set="first_tracking" t-value="false"/> |
|||
</t> |
|||
</p> |
|||
</t> |
|||
</t> |
|||
|
|||
</template> |
@ -0,0 +1,6 @@ |
|||
# -*- 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 test_mail_tracking |
@ -0,0 +1,262 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import mock |
|||
import base64 |
|||
import time |
|||
from openerp.tests.common import TransactionCase |
|||
from ..controllers.main import MailTrackingController, BLANK |
|||
|
|||
mock_request = 'openerp.http.request' |
|||
mock_send_email = ('openerp.addons.base.ir.ir_mail_server.' |
|||
'ir_mail_server.send_email') |
|||
|
|||
|
|||
class FakeUserAgent(object): |
|||
browser = 'Test browser' |
|||
platform = 'Test platform' |
|||
|
|||
def __str__(self): |
|||
"""Return name""" |
|||
return 'Test suite' |
|||
|
|||
|
|||
# One test case per method |
|||
class TestMailTracking(TransactionCase): |
|||
# Use case : Prepare some data for current test case |
|||
def setUp(self): |
|||
super(TestMailTracking, self).setUp() |
|||
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.request = { |
|||
'httprequest': type('obj', (object,), { |
|||
'remote_addr': '123.123.123.123', |
|||
'user_agent': FakeUserAgent(), |
|||
}), |
|||
} |
|||
|
|||
def test_message_post(self): |
|||
# This message will generate a notification for recipient |
|||
message = self.env['mail.message'].create({ |
|||
'subject': 'Message test', |
|||
'author_id': self.sender.id, |
|||
'email_from': self.sender.email, |
|||
'type': 'comment', |
|||
'model': 'res.partner', |
|||
'res_id': self.recipient.id, |
|||
'partner_ids': [(4, self.recipient.id)], |
|||
'body': '<p>This is a test message</p>', |
|||
}) |
|||
# Search tracking created |
|||
tracking_email = self.env['mail.tracking.email'].search([ |
|||
('mail_message_id', '=', message.id), |
|||
('partner_id', '=', self.recipient.id), |
|||
]) |
|||
# The tracking email must be sent |
|||
self.assertTrue(tracking_email) |
|||
self.assertEqual(tracking_email.state, 'sent') |
|||
# message_dict read by web interface |
|||
message_dict = message.message_read() |
|||
# First item in threads is message content |
|||
message_dict = message_dict['threads'][0][0] |
|||
self.assertTrue(len(message_dict['partner_ids']) > 0) |
|||
# First partner is recipient |
|||
partner_id = message_dict['partner_ids'][0][0] |
|||
self.assertEqual(partner_id, self.recipient.id) |
|||
status = message_dict['partner_trackings'][0] |
|||
# Tracking status must be sent and |
|||
# mail tracking must be the one search before |
|||
self.assertEqual(status[0], 'sent') |
|||
self.assertEqual(status[1], tracking_email.id) |
|||
self.assertEqual(status[2], self.recipient.display_name) |
|||
self.assertEqual(status[3], self.recipient.id) |
|||
# And now open the email |
|||
metadata = { |
|||
'ip': '127.0.0.1', |
|||
'user_agent': 'Odoo Test/1.0', |
|||
'os_family': 'linux', |
|||
'ua_family': 'odoo', |
|||
} |
|||
tracking_email.event_create('open', metadata) |
|||
self.assertEqual(tracking_email.state, 'opened') |
|||
|
|||
def mail_send(self, recipient): |
|||
mail = self.env['mail.mail'].create({ |
|||
'subject': 'Test subject', |
|||
'email_from': 'from@domain.com', |
|||
'email_to': recipient, |
|||
'body_html': '<p>This is a test message</p>', |
|||
}) |
|||
mail.send() |
|||
# Search tracking created |
|||
tracking_email = self.env['mail.tracking.email'].search([ |
|||
('mail_id', '=', mail.id), |
|||
]) |
|||
return mail, tracking_email |
|||
|
|||
def test_mail_send(self): |
|||
controller = MailTrackingController() |
|||
db = self.env.cr.dbname |
|||
image = base64.decodestring(BLANK) |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
self.assertEqual(mail.email_to, tracking.recipient) |
|||
self.assertEqual(mail.email_from, tracking.sender) |
|||
with mock.patch(mock_request) as mock_func: |
|||
mock_func.return_value = type('obj', (object,), self.request) |
|||
res = controller.mail_tracking_open(db, tracking.id) |
|||
self.assertEqual(image, res.response[0]) |
|||
|
|||
def test_concurrent_open(self): |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
ts = time.time() |
|||
metadata = { |
|||
'ip': '127.0.0.1', |
|||
'user_agent': 'Odoo Test/1.0', |
|||
'os_family': 'linux', |
|||
'ua_family': 'odoo', |
|||
'timestamp': ts, |
|||
} |
|||
# First open event |
|||
tracking.event_create('open', metadata) |
|||
opens = tracking.tracking_event_ids.filtered( |
|||
lambda r: r.event_type == 'open' |
|||
) |
|||
self.assertEqual(len(opens), 1) |
|||
# Concurrent open event |
|||
metadata['timestamp'] = ts + 2 |
|||
tracking.event_create('open', metadata) |
|||
opens = tracking.tracking_event_ids.filtered( |
|||
lambda r: r.event_type == 'open' |
|||
) |
|||
self.assertEqual(len(opens), 1) |
|||
# Second open event |
|||
metadata['timestamp'] = ts + 350 |
|||
tracking.event_create('open', metadata) |
|||
opens = tracking.tracking_event_ids.filtered( |
|||
lambda r: r.event_type == 'open' |
|||
) |
|||
self.assertEqual(len(opens), 2) |
|||
|
|||
def test_concurrent_click(self): |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
ts = time.time() |
|||
metadata = { |
|||
'ip': '127.0.0.1', |
|||
'user_agent': 'Odoo Test/1.0', |
|||
'os_family': 'linux', |
|||
'ua_family': 'odoo', |
|||
'timestamp': ts, |
|||
'url': 'https://www.example.com/route/1', |
|||
} |
|||
# First click event (URL 1) |
|||
tracking.event_create('click', metadata) |
|||
opens = tracking.tracking_event_ids.filtered( |
|||
lambda r: r.event_type == 'click' |
|||
) |
|||
self.assertEqual(len(opens), 1) |
|||
# Concurrent click event (URL 1) |
|||
metadata['timestamp'] = ts + 2 |
|||
tracking.event_create('click', metadata) |
|||
opens = tracking.tracking_event_ids.filtered( |
|||
lambda r: r.event_type == 'click' |
|||
) |
|||
self.assertEqual(len(opens), 1) |
|||
# Second click event (URL 1) |
|||
metadata['timestamp'] = ts + 350 |
|||
tracking.event_create('click', metadata) |
|||
opens = tracking.tracking_event_ids.filtered( |
|||
lambda r: r.event_type == 'click' |
|||
) |
|||
self.assertEqual(len(opens), 2) |
|||
# Concurrent click event (URL 2) |
|||
metadata['timestamp'] = ts + 2 |
|||
metadata['url'] = 'https://www.example.com/route/2' |
|||
tracking.event_create('click', metadata) |
|||
opens = tracking.tracking_event_ids.filtered( |
|||
lambda r: r.event_type == 'click' |
|||
) |
|||
self.assertEqual(len(opens), 3) |
|||
|
|||
def test_smtp_error(self): |
|||
with mock.patch(mock_send_email) as mock_func: |
|||
mock_func.side_effect = Warning('Test error') |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
self.assertEqual('error', tracking.state) |
|||
self.assertEqual('Warning', tracking.error_type) |
|||
self.assertEqual('Test error', tracking.error_description) |
|||
|
|||
def test_partner_email_change(self): |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
tracking.event_create('open', {}) |
|||
orig_score = self.recipient.email_score |
|||
orig_email = self.recipient.email |
|||
self.recipient.email = orig_email + '2' |
|||
self.assertEqual(50.0, self.recipient.email_score) |
|||
self.recipient.email = orig_email |
|||
self.assertEqual(orig_score, self.recipient.email_score) |
|||
|
|||
def test_process_hard_bounce(self): |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
tracking.event_create('hard_bounce', {}) |
|||
self.assertEqual('bounced', tracking.state) |
|||
|
|||
def test_process_soft_bounce(self): |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
tracking.event_create('soft_bounce', {}) |
|||
self.assertEqual('soft-bounced', tracking.state) |
|||
|
|||
def test_process_delivered(self): |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
tracking.event_create('delivered', {}) |
|||
self.assertEqual('delivered', tracking.state) |
|||
|
|||
def test_process_deferral(self): |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
tracking.event_create('deferral', {}) |
|||
self.assertEqual('deferred', tracking.state) |
|||
|
|||
def test_process_spam(self): |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
tracking.event_create('spam', {}) |
|||
self.assertEqual('spam', tracking.state) |
|||
|
|||
def test_process_unsub(self): |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
tracking.event_create('unsub', {}) |
|||
self.assertEqual('unsub', tracking.state) |
|||
|
|||
def test_process_reject(self): |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
tracking.event_create('reject', {}) |
|||
self.assertEqual('rejected', tracking.state) |
|||
|
|||
def test_process_open(self): |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
tracking.event_create('open', {}) |
|||
self.assertEqual('opened', tracking.state) |
|||
|
|||
def test_process_click(self): |
|||
mail, tracking = self.mail_send(self.recipient.email) |
|||
tracking.event_create('click', {}) |
|||
self.assertEqual('opened', tracking.state) |
|||
|
|||
def test_db(self): |
|||
db = self.env.cr.dbname |
|||
controller = MailTrackingController() |
|||
with mock.patch(mock_request) as mock_func: |
|||
mock_func.return_value = type('obj', (object,), self.request) |
|||
not_found = controller.mail_tracking_all('not_found_db') |
|||
self.assertEqual('NOT FOUND', not_found.response[0]) |
|||
none = controller.mail_tracking_all(db) |
|||
self.assertEqual('NONE', none.response[0]) |
|||
none = controller.mail_tracking_event(db, 'open') |
|||
self.assertEqual('NONE', none.response[0]) |
@ -0,0 +1,17 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- © 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" |
|||
name="mail_tracking assets" |
|||
inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<link rel="stylesheet" |
|||
href="/mail_tracking/static/src/css/mail_tracking.css"/> |
|||
<script type="text/javascript" |
|||
src="/mail_tracking/static/src/js/mail_tracking.js"/> |
|||
</xpath> |
|||
</template> |
|||
|
|||
</odoo> |
@ -0,0 +1,120 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> |
|||
<odoo> |
|||
|
|||
<record model="ir.ui.view" id="view_mail_tracking_email_form"> |
|||
<field name="name">mail.tracking.email.form</field> |
|||
<field name="model">mail.tracking.email</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="MailTracking event" create="false" edit="false" delete="false"> |
|||
<header> |
|||
<field name="state" widget="statusbar"/> |
|||
</header> |
|||
<sheet> |
|||
<group> |
|||
<field name="name"/> |
|||
</group> |
|||
<group> |
|||
<group> |
|||
<field name="mail_message_id"/> |
|||
<field name="mail_id"/> |
|||
<field name="partner_id"/> |
|||
<field name="recipient"/> |
|||
<field name="sender"/> |
|||
</group> |
|||
<group> |
|||
<field name="timestamp"/> |
|||
<field name="time"/> |
|||
<field name="date"/> |
|||
</group> |
|||
</group> |
|||
<group attrs="{'invisible': [('bounce_type', '=', False)]}"> |
|||
<field name="bounce_type"/> |
|||
<field name="bounce_description"/> |
|||
</group> |
|||
<group attrs="{'invisible': [('error_type', '=', False)]}"> |
|||
<field name="error_smtp_server" |
|||
attrs="{'invisible': [('error_smtp_server', '=', False)]}"/> |
|||
<field name="error_type"/> |
|||
<field name="error_description"/> |
|||
</group> |
|||
<label for="tracking_event_ids"/> |
|||
<div> |
|||
<field name="tracking_event_ids"> |
|||
<tree string="Tracking events" colors="grey:event_type in ('deferral');black:event_type in ('send');red:event_type in ('hard_bounce', 'soft_bounce', 'spam', 'reject');blue:event_type in ('unsub', 'click', 'open')"> |
|||
<field name="time"/> |
|||
<field name="event_type"/> |
|||
<field name="ip"/> |
|||
<field name="url"/> |
|||
<field name="user_country_id" string="Country"/> |
|||
<field name="os_family" string="OS"/> |
|||
<field name="ua_family" string="User agent"/> |
|||
</tree> |
|||
</field> |
|||
</div> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="view_mail_tracking_email_tree"> |
|||
<field name="name">mail.tracking.email.tree</field> |
|||
<field name="model">mail.tracking.email</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="MailTracking emails" create="false" edit="false" delete="false" |
|||
colors="grey:state in (False, 'deferred');black:state in ('sent', 'delivered');green:state in ('opened');red:state in ('rejected', 'spam', 'bounced', 'soft-bounced');blue:state in ('unsub')"> |
|||
<field name="time"/> |
|||
<field name="date" invisible="1"/> |
|||
<field name="name"/> |
|||
<field name="sender" string="Sender"/> |
|||
<field name="recipient" string="Recipient"/> |
|||
<field name="state"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="view_mail_tracking_email_search"> |
|||
<field name="name">mail.tracking.email.search</field> |
|||
<field name="model">mail.tracking.email</field> |
|||
<field name="arch" type="xml"> |
|||
<search string="MailTracking email search"> |
|||
<field name="display_name" string="Email" |
|||
filter_domain="['|', ('sender', 'ilike', self), ('recipient', 'ilike', self)]"/> |
|||
<field name="sender" string="Sender"/> |
|||
<field name="recipient" string="Sender"/> |
|||
<field name="name" string="Subject"/> |
|||
<field name="time" string="Time"/> |
|||
<field name="date" string="Date"/> |
|||
<filter name="sent" string="Sent" domain="[('state', 'in', ('sent',))]"/> |
|||
<filter name="deferred" string="Deferred" domain="[('state', '=', 'deferred')]"/> |
|||
<filter name="delivered" string="Delivered" domain="[('state', 'in', ('delivered', 'opened'))]"/> |
|||
<filter name="unsub" string="Unsubscribed" domain="[('state', '=', 'unsub')]"/> |
|||
<filter name="exception" string="Failed" |
|||
domain="[('state', 'in', ('error', 'rejected', 'spam', 'bounced', 'soft-bounced'))]"/> |
|||
<separator/> |
|||
<group expand="0" string="Group By"> |
|||
<filter string="State" domain="[]" context="{'group_by': 'state'}"/> |
|||
<filter string="Subject" domain="[]" context="{'group_by': 'name'}"/> |
|||
<filter string="Sender" domain="[]" context="{'group_by': 'sender'}"/> |
|||
<filter string="Month" domain="[]" context="{'group_by': 'date'}"/> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
|
|||
<record id="action_view_mail_tracking_email" model="ir.actions.act_window"> |
|||
<field name="name">MailTracking emails</field> |
|||
<field name="res_model">mail.tracking.email</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
<field name="search_view_id" ref="view_mail_tracking_email_search"/> |
|||
</record> |
|||
|
|||
<!-- Add menu entry in Settings/Email --> |
|||
<menuitem name="Tracking emails" id="menu_mail_tracking_email" |
|||
parent="base.menu_email" |
|||
action="action_view_mail_tracking_email"/> |
|||
|
|||
</odoo> |
@ -0,0 +1,123 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> |
|||
<odoo> |
|||
|
|||
<record model="ir.ui.view" id="view_mail_tracking_event_form"> |
|||
<field name="name">mail.tracking.event.form</field> |
|||
<field name="model">mail.tracking.event</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="MailTracking event" create="false" edit="false" delete="false"> |
|||
<sheet> |
|||
<group> |
|||
<group> |
|||
<field name="tracking_email_id"/> |
|||
<field name="recipient"/> |
|||
<field name="event_type"/> |
|||
</group> |
|||
<group> |
|||
<field name="timestamp"/> |
|||
<field name="time"/> |
|||
<field name="date"/> |
|||
</group> |
|||
</group> |
|||
<group attrs="{'invisible': [('event_type', 'not in', ('sent',))]}"> |
|||
<field name="smtp_server"/> |
|||
</group> |
|||
<group attrs="{'invisible': [('event_type', 'not in', ('open', 'click'))]}"> |
|||
<field name="url"/> |
|||
</group> |
|||
<group attrs="{'invisible': [('event_type', 'not in', ('open', 'click'))]}"> |
|||
<group> |
|||
<field name="mobile"/> |
|||
<field name="ip"/> |
|||
<field name="user_country_id"/> |
|||
</group> |
|||
<group> |
|||
<field name="user_agent"/> |
|||
<field name="ua_family"/> |
|||
<field name="ua_type"/> |
|||
<field name="os_family"/> |
|||
</group> |
|||
</group> |
|||
<group string="Error" |
|||
attrs="{'invisible': [('error_type', '=', False)]}"> |
|||
<field name="error_type"/> |
|||
<field name="error_description"/> |
|||
<field name="error_details"/> |
|||
</group> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="view_mail_tracking_event_tree"> |
|||
<field name="name">mail.tracking.event.tree</field> |
|||
<field name="model">mail.tracking.event</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="MailTracking events" create="false" edit="false" delete="false" |
|||
colors="grey:event_type in ('deferral',);black:event_type in ('sent', 'delivered');red:event_type in ('hard_bounce', 'soft_bounce', 'spam', 'reject');blue:event_type in ('unsub', 'click', 'open')"> |
|||
<field name="time"/> |
|||
<field name="tracking_email_id"/> |
|||
<field name="recipient"/> |
|||
<field name="event_type"/> |
|||
<field name="date" invisible="1"/> |
|||
<field name="ip"/> |
|||
<field name="url"/> |
|||
<field name="user_country_id" string="Country"/> |
|||
<field name="os_family" string="OS"/> |
|||
<field name="ua_family" string="User agent"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="view_mail_tracking_event_search"> |
|||
<field name="name">mail.tracking.event.search</field> |
|||
<field name="model">mail.tracking.event</field> |
|||
<field name="arch" type="xml"> |
|||
<search string="MailTracking event search"> |
|||
<field name="tracking_email_id" string="Message" |
|||
filter_domain="[('tracking_email_id', 'ilike', self)]"/> |
|||
<field name="recipient" string="Recipient"/> |
|||
<field name="time" string="Time"/> |
|||
<field name="date" string="Date"/> |
|||
<field name="ip" string="IP"/> |
|||
<field name="url" string="URL"/> |
|||
<filter name="sent" string="Sent" domain="[('event_type', '=', 'sent')]"/> |
|||
<filter name="delivered" string="Delivered" domain="[('event_type', '=', 'delivered')]"/> |
|||
<filter name="click" string="Click" domain="[('event_type', '=', 'click')]"/> |
|||
<filter name="open" string="Open" domain="[('event_type', '=', 'open')]"/> |
|||
<filter name="unsub" string="Unsubscribe" domain="[('event_type', '=', 'unsub')]"/> |
|||
<filter name="bounce" string="Bounce" |
|||
domain="[('event_type', 'in', ('hard_bounce', 'soft_bounce'))]"/> |
|||
<filter name="exception" string="Failed" |
|||
domain="[('event_type', 'in', ('reject', 'spam'))]"/> |
|||
<separator/> |
|||
<group expand="0" string="Group By"> |
|||
<filter string="Type" domain="[]" context="{'group_by': 'event_type'}"/> |
|||
<filter string="Message" domain="[]" context="{'group_by': 'tracking_email_id'}"/> |
|||
<filter string="OS" domain="[('os_family', '!=', False)]" context="{'group_by': 'os_family'}"/> |
|||
<filter string="User agent" domain="[('ua_family', '!=', False)]" context="{'group_by': 'ua_family'}"/> |
|||
<filter string="User agent type" domain="[('ua_type', '!=', False)]" context="{'group_by': 'ua_type'}"/> |
|||
<filter string="Country" domain="[('user_country_id', '!=', False)]" context="{'group_by': 'user_country_id'}"/> |
|||
<filter string="Month" domain="[]" context="{'group_by': 'date'}"/> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_view_mail_tracking_event" model="ir.actions.act_window"> |
|||
<field name="name">MailTracking events</field> |
|||
<field name="res_model">mail.tracking.event</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
<field name="search_view_id" ref="view_mail_tracking_event_search"/> |
|||
</record> |
|||
|
|||
<!-- Add menu entry in Settings/Email --> |
|||
<menuitem name="Tracking events" id="menu_mail_tracking_event" |
|||
parent="base.menu_email" |
|||
action="action_view_mail_tracking_event"/> |
|||
|
|||
|
|||
</odoo> |
@ -0,0 +1,31 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com> |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> |
|||
<odoo> |
|||
|
|||
<record model="ir.ui.view" id="view_partner_form"> |
|||
<field name="name">Partner Form with tracking emails</field> |
|||
<field name="model">res.partner</field> |
|||
<field name="inherit_id" ref="base.view_partner_form"/> |
|||
<field name="arch" type="xml"> |
|||
<div name="button_box" position="inside"> |
|||
<button name="%(mail_tracking.action_view_mail_tracking_email)d" |
|||
context="{'search_default_recipient': email, |
|||
'default_recipient': email}" |
|||
type="action" |
|||
class="oe_stat_button oe_inline" |
|||
icon="fa-envelope-o" |
|||
attrs="{'invisible': [('email', '=', False)]}"> |
|||
<field name="tracking_emails_count" |
|||
widget="statinfo" |
|||
string="Tracking emails"/> |
|||
</button> |
|||
</div> |
|||
<field name="email" position="after"> |
|||
<field name="email_score" widget="progressbar" |
|||
attrs="{'invisible': [('email', '=', False)]}"/> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |