diff --git a/mail_tracking_mass_mailing/README.rst b/mail_tracking_mass_mailing/README.rst new file mode 100644 index 00000000..9b8bc85e --- /dev/null +++ b/mail_tracking_mass_mailing/README.rst @@ -0,0 +1,77 @@ +.. 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 for mass mailing +============================== + +Links mail statistics objects with mail tracking objects. + + +Installation +============ + +This addon will be automatically installed when 'mail_tracking' and +'mass_mailing' are both installed + + +Usage +===== + +From mail statistic object, you can see: +- Email tracking state +- Email related tracking object +- Email related tracking events + +From mass mailing contact, you can see: +- Email score, in order to clean up your lists from bad score emails + +As a bonus feature, you have a new checkbox 'Avoid resend' in mass mailing, +in order to not send twice the same email to the same recipient. This is very +useful when you want to resend the mass mailing after changing selection +recipients. Notice that recipient selection could be a domain over a model, so +result ids could change over the time. With this flag you can send +the same email several times but only once to each recipient. + +.. 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/8.0 + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Pedro M. Baeza +* Antonio Espinosa + +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. diff --git a/mail_tracking_mass_mailing/__init__.py b/mail_tracking_mass_mailing/__init__.py new file mode 100644 index 00000000..e5e39cc1 --- /dev/null +++ b/mail_tracking_mass_mailing/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import models +from .hooks import post_init_hook diff --git a/mail_tracking_mass_mailing/__openerp__.py b/mail_tracking_mass_mailing/__openerp__.py new file mode 100644 index 00000000..13a90342 --- /dev/null +++ b/mail_tracking_mass_mailing/__openerp__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Mail tracking for mass mailing", + "summary": "Improve mass mailing email tracking", + "version": "8.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, + 'auto_install': True, + "depends": [ + "mass_mailing", + "mail_tracking", + ], + "data": [ + "views/mail_tracking_email_view.xml", + "views/mail_mail_statistics_view.xml", + "views/mail_mass_mailing_view.xml", + "views/mail_mass_mailing_contact_view.xml", + ], + "post_init_hook": "post_init_hook", +} diff --git a/mail_tracking_mass_mailing/hooks.py b/mail_tracking_mass_mailing/hooks.py new file mode 100644 index 00000000..4ffb47a9 --- /dev/null +++ b/mail_tracking_mass_mailing/hooks.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging +from openerp import api, SUPERUSER_ID + +_logger = logging.getLogger(__name__) + + +def post_init_hook(cr, registry): + with api.Environment.manage(): + env = api.Environment(cr, SUPERUSER_ID, {}) + # Recalculate all mass_mailing contacts tracking_email_ids + contacts = env['mail.mass_mailing.contact'].search([ + ('email', '!=', False), + ]) + emails = contacts.mapped('email') + _logger.info( + "Recalculating 'tracking_email_ids' in " + "'mail.mass_mailing.contact' model for %d email addresses", + len(emails)) + for n, email in enumerate(emails): + env['mail.tracking.email'].tracking_ids_recalculate( + 'mail.mass_mailing.contact', 'email', 'tracking_email_ids', + email) + if n % 500 == 0: # pragma: no cover + _logger.info(" Recalculated %d of %d", n, len(emails)) diff --git a/mail_tracking_mass_mailing/i18n/en.po b/mail_tracking_mass_mailing/i18n/en.po new file mode 100644 index 00000000..eb0b0a51 --- /dev/null +++ b/mail_tracking_mass_mailing/i18n/en.po @@ -0,0 +1,130 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mail_tracking_mass_mailing +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-08-12 10:39+0000\n" +"PO-Revision-Date: 2016-08-12 10:39+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mail_tracking_mass_mailing +#: help:mail.mail.statistics,tracking_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 " * 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" +"" + +#. module: mail_tracking_mass_mailing +#: field:mail.mass_mailing,avoid_resend:0 +msgid "Avoid resend" +msgstr "Avoid resend" + +#. module: mail_tracking_mass_mailing +#: help:mail.mass_mailing,avoid_resend:0 +msgid "Avoid to send this mass mailing email twice to the same recipient" +msgstr "Avoid to send this mass mailing email twice to the same recipient" + +#. module: mail_tracking_mass_mailing +#: view:mail.mail.statistics:mail_tracking_mass_mailing.view_mail_mail_statistics_form +msgid "Country" +msgstr "Country" + +#. module: mail_tracking_mass_mailing +#: model:ir.model,name:mail_tracking_mass_mailing.model_mail_mail_statistics +msgid "Email Statistics" +msgstr "Email Statistics" + +#. module: mail_tracking_mass_mailing +#: field:mail.mass_mailing.contact,email_score:0 +msgid "Email score" +msgstr "Email score" + +#. module: mail_tracking_mass_mailing +#: field:mail.tracking.email,mail_id_int:0 +msgid "Mail ID" +msgstr "Mail ID" + +#. module: mail_tracking_mass_mailing +#: field:mail.tracking.email,mail_stats_id:0 +msgid "Mail statistics" +msgstr "Mail statistics" + +#. module: mail_tracking_mass_mailing +#: field:mail.mail.statistics,mail_tracking_id:0 +msgid "Mail tracking" +msgstr "Mail tracking" + +#. module: mail_tracking_mass_mailing +#: model:ir.model,name:mail_tracking_mass_mailing.model_mail_tracking_email +msgid "MailTracking email" +msgstr "MailTracking email" + +#. module: mail_tracking_mass_mailing +#: model:ir.model,name:mail_tracking_mass_mailing.model_mail_tracking_event +msgid "MailTracking event" +msgstr "MailTracking event" + +#. module: mail_tracking_mass_mailing +#: model:ir.model,name:mail_tracking_mass_mailing.model_mail_mass_mailing +msgid "Mass Mailing" +msgstr "Mass Mailing" + +#. module: mail_tracking_mass_mailing +#: model:ir.model,name:mail_tracking_mass_mailing.model_mail_mass_mailing_contact +msgid "Mass Mailing Contact" +msgstr "Mass Mailing Contact" + +#. module: mail_tracking_mass_mailing +#: field:mail.tracking.email,mass_mailing_id:0 +msgid "Mass mailing" +msgstr "Mass mailing" + +#. module: mail_tracking_mass_mailing +#: model:ir.model,name:mail_tracking_mass_mailing.model_mail_mail +msgid "Outgoing Mails" +msgstr "Outgoing Mails" + +#. module: mail_tracking_mass_mailing +#: field:mail.mail.statistics,tracking_state:0 +msgid "State" +msgstr "State" + +#. module: mail_tracking_mass_mailing +#: field:mail.mass_mailing.contact,tracking_email_ids:0 +msgid "Tracking emails" +msgstr "Tracking emails" + +#. module: mail_tracking_mass_mailing +#: view:mail.mail.statistics:mail_tracking_mass_mailing.view_mail_mail_statistics_form +#: field:mail.mail.statistics,tracking_event_ids:0 +msgid "Tracking events" +msgstr "Tracking events" + +#. module: mail_tracking_mass_mailing +#: view:mail.mail.statistics:mail_tracking_mass_mailing.view_mail_mail_statistics_form +msgid "User agent" +msgstr "User agent" diff --git a/mail_tracking_mass_mailing/i18n/es.po b/mail_tracking_mass_mailing/i18n/es.po new file mode 100644 index 00000000..2d2a085d --- /dev/null +++ b/mail_tracking_mass_mailing/i18n/es.po @@ -0,0 +1,129 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mail_tracking_mass_mailing +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-08-12 10:39+0000\n" +"PO-Revision-Date: 2016-08-12 10:39+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mail_tracking_mass_mailing +#: help:mail.mail.statistics,tracking_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 " * 'Error' indica que ha habido un error al intentar el envío del email, por ejemplo, 'Email de destino no válido'\n" +" * 'Enviado' indica que el email se ha envíado correctamente al servidor de correo saliente (SMTP)\n" +" * 'Entregado' indica que el email se ha entregado al servidor de correo del destinatario (MX)\n" +" * 'Abierto' indica que el destinatario ha abierto o clicado en el email\n" +" * 'Rechazado' indica que la dirección del destinatario esta en una lista negra en el servidor de correo saliente (SMTP)\n" +" * 'Spam' indica que el servidor de correo saliente (SMTP) considera el email como spam\n" +" * 'Desuscrito' indica que el destinatarios ha solicitado desuscribirse desde este email\n" +" * 'Rebotado' indica que el email no ha sido aceptado por el servidor de correo del destinatario (MX)\n" +" * 'Rebotado leve' indica que el email no ha sido aceptado por motivos temporales por el servidor de correo del destinatario (MX)\n" + +#. module: mail_tracking_mass_mailing +#: field:mail.mass_mailing,avoid_resend:0 +msgid "Avoid resend" +msgstr "Evitar reenvios" + +#. module: mail_tracking_mass_mailing +#: help:mail.mass_mailing,avoid_resend:0 +msgid "Avoid to send this mass mailing email twice to the same recipient" +msgstr "Evitar que se envíe este correo masivo dos veces al mismo destinatario" + +#. module: mail_tracking_mass_mailing +#: view:mail.mail.statistics:mail_tracking_mass_mailing.view_mail_mail_statistics_form +msgid "Country" +msgstr "País" + +#. module: mail_tracking_mass_mailing +#: model:ir.model,name:mail_tracking_mass_mailing.model_mail_mail_statistics +msgid "Email Statistics" +msgstr "Estadísticas del email" + +#. module: mail_tracking_mass_mailing +#: field:mail.mass_mailing.contact,email_score:0 +msgid "Email score" +msgstr "Reputación del email" + +#. module: mail_tracking_mass_mailing +#: field:mail.tracking.email,mail_id_int:0 +msgid "Mail ID" +msgstr "Mail ID" + +#. module: mail_tracking_mass_mailing +#: field:mail.tracking.email,mail_stats_id:0 +msgid "Mail statistics" +msgstr "Estadísticas del email" + +#. module: mail_tracking_mass_mailing +#: field:mail.mail.statistics,mail_tracking_id:0 +msgid "Mail tracking" +msgstr "Seguimiento del email" + +#. module: mail_tracking_mass_mailing +#: model:ir.model,name:mail_tracking_mass_mailing.model_mail_tracking_email +msgid "MailTracking email" +msgstr "MailTracking email" + +#. module: mail_tracking_mass_mailing +#: model:ir.model,name:mail_tracking_mass_mailing.model_mail_tracking_event +msgid "MailTracking event" +msgstr "MailTracking event" + +#. module: mail_tracking_mass_mailing +#: model:ir.model,name:mail_tracking_mass_mailing.model_mail_mass_mailing +msgid "Mass Mailing" +msgstr "Envío masivo" + +#. module: mail_tracking_mass_mailing +#: model:ir.model,name:mail_tracking_mass_mailing.model_mail_mass_mailing_contact +msgid "Mass Mailing Contact" +msgstr "Contacto de envío masivo" + +#. module: mail_tracking_mass_mailing +#: field:mail.tracking.email,mass_mailing_id:0 +msgid "Mass mailing" +msgstr "Envío masivo" + +#. module: mail_tracking_mass_mailing +#: model:ir.model,name:mail_tracking_mass_mailing.model_mail_mail +msgid "Outgoing Mails" +msgstr "Correos salientes" + +#. module: mail_tracking_mass_mailing +#: field:mail.mail.statistics,tracking_state:0 +msgid "State" +msgstr "Estado" + +#. module: mail_tracking_mass_mailing +#: field:mail.mass_mailing.contact,tracking_email_ids:0 +msgid "Tracking emails" +msgstr "Emails de seguimiento" + +#. module: mail_tracking_mass_mailing +#: view:mail.mail.statistics:mail_tracking_mass_mailing.view_mail_mail_statistics_form +#: field:mail.mail.statistics,tracking_event_ids:0 +msgid "Tracking events" +msgstr "Eventos de seguimiento" + +#. module: mail_tracking_mass_mailing +#: view:mail.mail.statistics:mail_tracking_mass_mailing.view_mail_mail_statistics_form +msgid "User agent" +msgstr "Aplicación del usuario" diff --git a/mail_tracking_mass_mailing/models/__init__.py b/mail_tracking_mass_mailing/models/__init__.py new file mode 100644 index 00000000..94fdb95c --- /dev/null +++ b/mail_tracking_mass_mailing/models/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import mail_mail +from . import mail_tracking_email +from . import mail_tracking_event +from . import mail_mail_statistics +from . import mail_mass_mailing +from . import mail_mass_mailing_contact diff --git a/mail_tracking_mass_mailing/models/mail_mail.py b/mail_tracking_mass_mailing/models/mail_mail.py new file mode 100644 index 00000000..952d3b42 --- /dev/null +++ b/mail_tracking_mass_mailing/models/mail_mail.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, api + + +class MailMail(models.Model): + _inherit = "mail.mail" + + @api.model + def _tracking_email_prepare(self, mail, partner, email): + res = super(MailMail, self)._tracking_email_prepare( + mail, partner, email) + res['mail_id_int'] = mail.id + res['mass_mailing_id'] = mail.mailing_id.id + res['mail_stats_id'] = mail.statistics_ids[:1].id \ + if mail.statistics_ids else False + return res + + @api.model + def _get_tracking_url(self, mail, partner=None): + # Invalid this tracking image, we have other to do the same + return False diff --git a/mail_tracking_mass_mailing/models/mail_mail_statistics.py b/mail_tracking_mass_mailing/models/mail_mail_statistics.py new file mode 100644 index 00000000..2dd26aba --- /dev/null +++ b/mail_tracking_mass_mailing/models/mail_mail_statistics.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, fields + + +class MailMailStatistics(models.Model): + _inherit = "mail.mail.statistics" + + mail_tracking_id = fields.Many2one( + string="Mail tracking", comodel_name='mail.tracking.email', + readonly=True) + tracking_event_ids = fields.One2many( + string="Tracking events", comodel_name='mail.tracking.event', + related='mail_tracking_id.tracking_event_ids', readonly=True) + tracking_state = fields.Selection( + string="State", related='mail_tracking_id.state', store=True) diff --git a/mail_tracking_mass_mailing/models/mail_mass_mailing.py b/mail_tracking_mass_mailing/models/mail_mass_mailing.py new file mode 100644 index 00000000..db32bc8d --- /dev/null +++ b/mail_tracking_mass_mailing/models/mail_mass_mailing.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, api, fields, _ +from openerp.exceptions import Warning as UserError + + +class MailMassMailing(models.Model): + _inherit = 'mail.mass_mailing' + + avoid_resend = fields.Boolean( + string="Avoid resend", + help="Avoid to send this mass mailing email twice " + "to the same recipient") + + @api.model + def get_recipients(self, mailing): + res_ids = super(MailMassMailing, self).get_recipients(mailing) + if mailing.avoid_resend: + already_sent = self.env['mail.mail.statistics'].search([ + ('mass_mailing_id', '=', mailing.id), + ('model', '=', mailing.mailing_model), + ]) + res_ids = list(set(res_ids).difference( + already_sent.mapped('res_id'))) + if not res_ids: + raise UserError(_( + "There is no more recipients to send and 'Avoid resend' " + "option is enabled")) + return res_ids diff --git a/mail_tracking_mass_mailing/models/mail_mass_mailing_contact.py b/mail_tracking_mass_mailing/models/mail_mass_mailing_contact.py new file mode 100644 index 00000000..8fc6c561 --- /dev/null +++ b/mail_tracking_mass_mailing/models/mail_mass_mailing_contact.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, api, fields + + +class MailMassMailingContact(models.Model): + _inherit = 'mail.mass_mailing.contact' + + tracking_email_ids = fields.Many2many( + string="Tracking emails", comodel_name="mail.tracking.email", + readonly=True) + email_score = fields.Float( + string="Email score", + compute="_compute_email_score", store=True, readonly=True) + + @api.one + @api.depends('tracking_email_ids', 'tracking_email_ids.state') + def _compute_email_score(self): + self.email_score = self.tracking_email_ids.email_score() + + @api.multi + def write(self, vals): + email = vals.get('email') + if email is not None: + vals['tracking_email_ids'] = \ + self.env['mail.tracking.email']._tracking_ids_to_write(email) + return super(MailMassMailingContact, self).write(vals) diff --git a/mail_tracking_mass_mailing/models/mail_tracking_email.py b/mail_tracking_mass_mailing/models/mail_tracking_email.py new file mode 100644 index 00000000..e8b0de6f --- /dev/null +++ b/mail_tracking_mass_mailing/models/mail_tracking_email.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, fields, api + + +class MailTrackingEmail(models.Model): + _inherit = "mail.tracking.email" + + mass_mailing_id = fields.Many2one( + string="Mass mailing", comodel_name='mail.mass_mailing', readonly=True) + mail_stats_id = fields.Many2one( + string="Mail statistics", comodel_name='mail.mail.statistics', + readonly=True) + mail_id_int = fields.Integer(string="Mail ID", readonly=True) + + @api.model + def _statistics_link_prepare(self, tracking): + return { + 'mail_tracking_id': tracking.id, + } + + @api.model + def create(self, vals): + tracking = super(MailTrackingEmail, self).create(vals) + # Link mail statistics with this tracking + if tracking.mail_stats_id: + tracking.mail_stats_id.write( + self._statistics_link_prepare(tracking)) + # Get partner from mail statistics + # if mass_mailing_partner addon installed + if ('partner_id' in tracking.mail_stats_id._fields and + tracking.mail_stats_id.partner_id and + not tracking.partner_id): + tracking.partner_id = tracking.mail_stats_id.partner_id.id + # Add this tracking to mass mailing contacts with this recipient + self.tracking_ids_recalculate( + 'mail.mass_mailing.contact', 'email', 'tracking_email_ids', + tracking.recipient_address, new_tracking=tracking) + return tracking diff --git a/mail_tracking_mass_mailing/models/mail_tracking_event.py b/mail_tracking_mass_mailing/models/mail_tracking_event.py new file mode 100644 index 00000000..c38fe903 --- /dev/null +++ b/mail_tracking_mass_mailing/models/mail_tracking_event.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, api + + +class MailTrackingEvent(models.Model): + _inherit = "mail.tracking.event" + + @api.model + def process_open(self, tracking_email, metadata): + res = super(MailTrackingEvent, self).process_open( + tracking_email, metadata) + mail_mail_stats = self.sudo().env['mail.mail.statistics'] + mail_mail_stats.set_opened(mail_mail_ids=[tracking_email.mail_id_int]) + return res diff --git a/mail_tracking_mass_mailing/static/description/icon.png b/mail_tracking_mass_mailing/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/mail_tracking_mass_mailing/static/description/icon.png differ diff --git a/mail_tracking_mass_mailing/tests/__init__.py b/mail_tracking_mass_mailing/tests/__init__.py new file mode 100644 index 00000000..b804cd49 --- /dev/null +++ b/mail_tracking_mass_mailing/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import test_mass_mailing diff --git a/mail_tracking_mass_mailing/tests/test_mass_mailing.py b/mail_tracking_mass_mailing/tests/test_mass_mailing.py new file mode 100644 index 00000000..9c18bb6e --- /dev/null +++ b/mail_tracking_mass_mailing/tests/test_mass_mailing.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# © 2016 Antonio Espinosa - +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp.tests.common import TransactionCase +from openerp.exceptions import Warning as UserError + + +# One test case per method +class TestMassMailing(TransactionCase): + def setUp(self): + super(TestMassMailing, self).setUp() + self.list = self.env['mail.mass_mailing.list'].create({ + 'name': 'Test mail tracking', + }) + self.contact_a = self.env['mail.mass_mailing.contact'].create({ + 'list_id': self.list.id, + 'name': 'Test contact A', + 'email': 'contact_a@example.com', + }) + self.mailing = self.env['mail.mass_mailing'].create({ + 'name': 'Test subject', + 'email_from': 'from@example.com', + 'mailing_model': 'mail.mass_mailing.contact', + 'mailing_domain': "[('list_id', 'in', [%d]), " + "('opt_out', '=', False)]" % self.list.id, + 'contact_list_ids': [(6, False, [self.list.id])], + 'body_html': '

Test email body

', + 'reply_to_mode': 'email', + }) + + def resend_mass_mailing(self, first, second): + self.mailing.send_mail() + self.assertEqual(len(self.mailing.statistics_ids), first) + self.env['mail.mass_mailing.contact'].create({ + 'list_id': self.list.id, + 'name': 'Test contact B', + 'email': 'contact_b@example.com', + }) + self.mailing.send_mail() + self.assertEqual(len(self.mailing.statistics_ids), second) + + def test_avoid_resend_enable(self): + self.mailing.avoid_resend = True + self.resend_mass_mailing(1, 2) + with self.assertRaises(UserError): + self.mailing.send_mail() + + def test_avoid_resend_disable(self): + self.mailing.avoid_resend = False + self.resend_mass_mailing(1, 3) + + def test_tracking_email_link(self): + self.mailing.send_mail() + for stat in self.mailing.statistics_ids: + if stat.mail_mail_id: + stat.mail_mail_id.send() + tracking_email = self.env['mail.tracking.email'].search([ + ('mail_id_int', '=', stat.mail_mail_id_int), + ]) + self.assertTrue(tracking_email) + self.assertEqual( + tracking_email.mass_mailing_id.id, self.mailing.id) + self.assertEqual(tracking_email.mail_stats_id.id, stat.id) + self.assertEqual(stat.mail_tracking_id.id, tracking_email.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.assertTrue(stat.opened) + self.assertEqual(stat.tracking_state, 'opened') + + def test_contact_tracking_emails(self): + self.mailing.send_mail() + for stat in self.mailing.statistics_ids: + if stat.mail_mail_id: + stat.mail_mail_id.send() + self.assertEqual(len(self.contact_a.tracking_email_ids), 1) + self.contact_a.email = 'other_contact_a@example.com' + self.assertEqual(len(self.contact_a.tracking_email_ids), 0) + self.contact_a.email = 'contact_a@example.com' + self.assertEqual(len(self.contact_a.tracking_email_ids), 1) diff --git a/mail_tracking_mass_mailing/views/mail_mail_statistics_view.xml b/mail_tracking_mass_mailing/views/mail_mail_statistics_view.xml new file mode 100644 index 00000000..c424a956 --- /dev/null +++ b/mail_tracking_mass_mailing/views/mail_mail_statistics_view.xml @@ -0,0 +1,49 @@ + + + + + + + Add tracking email info + mail.mail.statistics + + + + + + + + + + + + + + + Add partner and state columns + mail.mail.statistics + + + + + + + + + + diff --git a/mail_tracking_mass_mailing/views/mail_mass_mailing_contact_view.xml b/mail_tracking_mass_mailing/views/mail_mass_mailing_contact_view.xml new file mode 100644 index 00000000..34dbc3eb --- /dev/null +++ b/mail_tracking_mass_mailing/views/mail_mass_mailing_contact_view.xml @@ -0,0 +1,19 @@ + + + + + + + Add email score and stars + mail.mass_mailing.contact + + + + + + + + + + diff --git a/mail_tracking_mass_mailing/views/mail_mass_mailing_view.xml b/mail_tracking_mass_mailing/views/mail_mass_mailing_view.xml new file mode 100644 index 00000000..c10a53fa --- /dev/null +++ b/mail_tracking_mass_mailing/views/mail_mass_mailing_view.xml @@ -0,0 +1,19 @@ + + + + + + + Add avoid resend field + mail.mass_mailing + + + + + + + + + + diff --git a/mail_tracking_mass_mailing/views/mail_tracking_email_view.xml b/mail_tracking_mass_mailing/views/mail_tracking_email_view.xml new file mode 100644 index 00000000..5549650e --- /dev/null +++ b/mail_tracking_mass_mailing/views/mail_tracking_email_view.xml @@ -0,0 +1,20 @@ + + + + + + + Add mass mailing and mail stadistics + mail.tracking.email + + + + + + + + + + +