diff --git a/mail_tracking_mass_mailing/__manifest__.py b/mail_tracking_mass_mailing/__manifest__.py index eea6d1723..1b190b2dd 100644 --- a/mail_tracking_mass_mailing/__manifest__.py +++ b/mail_tracking_mass_mailing/__manifest__.py @@ -10,16 +10,12 @@ "version": "12.0.1.0.0", "category": "Social Network", "website": "https://github.com/OCA/social", - "author": "Tecnativa, " - "Odoo Community Association (OCA)", + "author": "Tecnativa, " "Odoo Community Association (OCA)", "license": "AGPL-3", "application": False, "installable": True, - 'auto_install': True, - "depends": [ - "mass_mailing", - "mail_tracking", - ], + "auto_install": True, + "depends": ["mass_mailing", "mail_tracking"], "data": [ "views/mail_tracking_email_view.xml", "views/mail_mail_statistics_view.xml", diff --git a/mail_tracking_mass_mailing/hooks.py b/mail_tracking_mass_mailing/hooks.py index c1553ca3f..046635590 100644 --- a/mail_tracking_mass_mailing/hooks.py +++ b/mail_tracking_mass_mailing/hooks.py @@ -3,6 +3,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import logging + try: from odoo.addons.mail_tracking.hooks import column_add_with_value except ImportError: @@ -13,8 +14,7 @@ _logger = logging.getLogger(__name__) def pre_init_hook(cr): if column_add_with_value: - _logger.info("Creating mail.mass_mailing.contact.email_score column " - "with value 50.0") + _logger.info("Creating mail.mass_mailing.contact.email_score column " "with value 50.0") column_add_with_value( - cr, 'mail_mass_mailing_contact', 'email_score', 'double precision', - 50.0) + cr, "mail_mass_mailing_contact", "email_score", "double precision", 50.0 + ) diff --git a/mail_tracking_mass_mailing/models/mail_mail.py b/mail_tracking_mass_mailing/models/mail_mail.py index b3aad63e3..a24f73c8f 100644 --- a/mail_tracking_mass_mailing/models/mail_mail.py +++ b/mail_tracking_mass_mailing/models/mail_mail.py @@ -2,7 +2,7 @@ # Copyright 2017 Vicent Cubells - # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import models, api +from odoo import api, models class MailMail(models.Model): @@ -11,10 +11,11 @@ class MailMail(models.Model): @api.model def _tracking_email_prepare(self, partner, email): res = super(MailMail, self)._tracking_email_prepare(partner, email) - res['mail_id_int'] = self.id - res['mass_mailing_id'] = self.mailing_id.id - res['mail_stats_id'] = self.statistics_ids[:1].id \ - if self.statistics_ids else False + res["mail_id_int"] = self.id + res["mass_mailing_id"] = self.mailing_id.id + res["mail_stats_id"] = ( + self.statistics_ids[:1].id if self.statistics_ids else False + ) return res @api.model diff --git a/mail_tracking_mass_mailing/models/mail_mail_statistics.py b/mail_tracking_mass_mailing/models/mail_mail_statistics.py index d418c5e3a..690fbce9a 100644 --- a/mail_tracking_mass_mailing/models/mail_mail_statistics.py +++ b/mail_tracking_mass_mailing/models/mail_mail_statistics.py @@ -2,15 +2,18 @@ # Copyright 2017 Vicent Cubells - # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import models, fields +from odoo import fields, models class MailMailStatistics(models.Model): _inherit = "mail.mail.statistics" mail_tracking_id = fields.Many2one( - string="Mail tracking", comodel_name='mail.tracking.email', - readonly=True) + 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) + string="Tracking events", + comodel_name="mail.tracking.event", + related="mail_tracking_id.tracking_event_ids", + readonly=True, + ) diff --git a/mail_tracking_mass_mailing/models/mail_mass_mailing_contact.py b/mail_tracking_mass_mailing/models/mail_mass_mailing_contact.py index 42a35c257..fdfac2240 100644 --- a/mail_tracking_mass_mailing/models/mail_mass_mailing_contact.py +++ b/mail_tracking_mass_mailing/models/mail_mass_mailing_contact.py @@ -2,20 +2,21 @@ # Copyright 2017 Vicent Cubells - # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import models, api, fields +from odoo import api, fields, models class MailMassMailingContact(models.Model): - _name = 'mail.mass_mailing.contact' - _inherit = ['mail.mass_mailing.contact', 'mail.bounced.mixin'] + _name = "mail.mass_mailing.contact" + _inherit = ["mail.mass_mailing.contact", "mail.bounced.mixin"] email_score = fields.Float( - string="Email score", readonly=True, store=False, - compute='_compute_email_score') + string="Email score", readonly=True, store=False, compute="_compute_email_score" + ) @api.multi - @api.depends('email') + @api.depends("email") def _compute_email_score(self): - for contact in self.filtered('email'): - contact.email_score = self.env['mail.tracking.email'].\ - email_score_from_email(contact.email) + for contact in self.filtered("email"): + contact.email_score = self.env[ + "mail.tracking.email" + ].email_score_from_email(contact.email) diff --git a/mail_tracking_mass_mailing/models/mail_tracking_email.py b/mail_tracking_mass_mailing/models/mail_tracking_email.py index 953d832eb..3c981a368 100644 --- a/mail_tracking_mass_mailing/models/mail_tracking_email.py +++ b/mail_tracking_mass_mailing/models/mail_tracking_email.py @@ -2,33 +2,31 @@ # Copyright 2017 Vicent Cubells - # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import models, fields, api +from odoo import api, fields, models class MailTrackingEmail(models.Model): _inherit = "mail.tracking.email" mass_mailing_id = fields.Many2one( - string="Mass mailing", comodel_name='mail.mass_mailing', readonly=True) + 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) + 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): """Inherit this method to link other object to mail.mail.statistics""" - return { - 'mail_tracking_id': tracking.id, - } + 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)) + tracking.mail_stats_id.write(self._statistics_link_prepare(tracking)) return tracking @api.multi @@ -37,22 +35,23 @@ class MailTrackingEmail(models.Model): if event and event.recipient_address: recipients.append(event.recipient_address) else: - recipients = list(filter(None, self.mapped('recipient_address'))) + recipients = list(filter(None, self.mapped("recipient_address"))) for recipient in recipients: - self.env['mail.mass_mailing.contact'].search([ - ('email', '=ilike', recipient) - ]).email_bounced_set(self, reason, event=event) + self.env["mail.mass_mailing.contact"].search( + [("email", "=ilike", recipient)] + ).email_bounced_set(self, reason, event=event) @api.multi def smtp_error(self, mail_server, smtp_server, exception): res = super(MailTrackingEmail, self).smtp_error( - mail_server, smtp_server, exception) - self._contacts_email_bounced_set('error') + mail_server, smtp_server, exception + ) + self._contacts_email_bounced_set("error") return res @api.multi def event_create(self, event_type, metadata): res = super(MailTrackingEmail, self).event_create(event_type, metadata) - if event_type in {'hard_bounce', 'spam', 'reject'}: + if event_type in {"hard_bounce", "spam", "reject"}: self._contacts_email_bounced_set(event_type) return res diff --git a/mail_tracking_mass_mailing/models/mail_tracking_event.py b/mail_tracking_mass_mailing/models/mail_tracking_event.py index 41c1a384d..e36c7bce2 100644 --- a/mail_tracking_mass_mailing/models/mail_tracking_event.py +++ b/mail_tracking_mass_mailing/models/mail_tracking_event.py @@ -9,45 +9,48 @@ class MailTrackingEvent(models.Model): _inherit = "mail.tracking.event" mass_mailing_id = fields.Many2one( - string="Mass mailing", comodel_name='mail.mass_mailing', readonly=True, - related='tracking_email_id.mass_mailing_id', store=True) + string="Mass mailing", + comodel_name="mail.mass_mailing", + readonly=True, + related="tracking_email_id.mass_mailing_id", + store=True, + ) @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'] + 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 def _tracking_set_bounce(self, tracking_email, metadata): - mail_mail_stats = self.sudo().env['mail.mail.statistics'] + mail_mail_stats = self.sudo().env["mail.mail.statistics"] mail_mail_stats.set_bounced(mail_mail_ids=[tracking_email.mail_id_int]) @api.model def process_hard_bounce(self, tracking_email, metadata): res = super(MailTrackingEvent, self).process_hard_bounce( - tracking_email, metadata) + tracking_email, metadata + ) self._tracking_set_bounce(tracking_email, metadata) return res @api.model def process_soft_bounce(self, tracking_email, metadata): res = super(MailTrackingEvent, self).process_soft_bounce( - tracking_email, metadata) + tracking_email, metadata + ) self._tracking_set_bounce(tracking_email, metadata) return res @api.model def process_reject(self, tracking_email, metadata): - res = super(MailTrackingEvent, self).process_reject( - tracking_email, metadata) + res = super(MailTrackingEvent, self).process_reject(tracking_email, metadata) self._tracking_set_bounce(tracking_email, metadata) return res @api.model def process_spam(self, tracking_email, metadata): - res = super(MailTrackingEvent, self).process_spam( - tracking_email, metadata) + res = super(MailTrackingEvent, self).process_spam(tracking_email, metadata) self._tracking_set_bounce(tracking_email, metadata) return res diff --git a/mail_tracking_mass_mailing/tests/test_mass_mailing.py b/mail_tracking_mass_mailing/tests/test_mass_mailing.py index 43fc02b4e..faf042aa0 100644 --- a/mail_tracking_mass_mailing/tests/test_mass_mailing.py +++ b/mail_tracking_mass_mailing/tests/test_mass_mailing.py @@ -5,11 +5,11 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import mock -from odoo.tools import mute_logger -from odoo.tests.common import at_install, post_install, TransactionCase -mock_send_email = ('odoo.addons.base.models.ir_mail_server.' - 'IrMailServer.send_email') +from odoo.tests.common import TransactionCase, at_install, post_install +from odoo.tools import mute_logger + +mock_send_email = "odoo.addons.base.models.ir_mail_server." "IrMailServer.send_email" @at_install(False) @@ -17,43 +17,44 @@ mock_send_email = ('odoo.addons.base.models.ir_mail_server.' class TestMassMailing(TransactionCase): def setUp(self, *args, **kwargs): super(TestMassMailing, self).setUp(*args, **kwargs) - self.list = self.env['mail.mass_mailing.list'].create({ - 'name': 'Test mail tracking', - }) - self.list.name = '%s #%s' % (self.list.name, self.list.id) - self.contact_a = self.env['mail.mass_mailing.contact'].create({ - 'list_ids': [(6, 0, self.list.ids)], - '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_id': self.env.ref( - 'mass_mailing.model_mail_mass_mailing_contact' - ).id, - 'mailing_domain': "[('list_ids', 'in', %d)]" % self.list.id, - 'contact_list_ids': [(6, False, [self.list.id])], - 'body_html': '

Test email body

', - 'reply_to_mode': 'email', - }) + self.list = self.env["mail.mass_mailing.list"].create({"name": "Test mail tracking"}) + self.list.name = "{} #{}".format(self.list.name, self.list.id) + self.contact_a = self.env["mail.mass_mailing.contact"].create( + { + "list_ids": [(6, 0, self.list.ids)], + "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_id": self.env.ref( + "mass_mailing.model_mail_mass_mailing_contact" + ).id, + "mailing_domain": "[('list_ids', 'in', %d)]" % self.list.id, + "contact_list_ids": [(6, False, [self.list.id])], + "body_html": "

Test email body

", + "reply_to_mode": "email", + } + ) - @mute_logger('odoo.addons.mail.models.mail_mail') + @mute_logger("odoo.addons.mail.models.mail_mail") def test_smtp_error(self): with mock.patch(mock_send_email) as mock_func: - mock_func.side_effect = Warning('Mock test error') + mock_func.side_effect = Warning("Mock test error") self.mailing.send_mail() for stat in self.mailing.statistics_ids: if stat.mail_mail_id: stat.mail_mail_id.send() - tracking = self.env['mail.tracking.email'].search([ - ('mail_id_int', '=', stat.mail_mail_id_int), - ]) + tracking = self.env["mail.tracking.email"].search( + [("mail_id_int", "=", stat.mail_mail_id_int)] + ) for track in tracking: - self.assertEqual('error', track.state) - self.assertEqual('Warning', track.error_type) - self.assertEqual('Mock test error', - track.error_description) + self.assertEqual("error", track.state) + self.assertEqual("Warning", track.error_type) + self.assertEqual("Mock test error", track.error_description) self.assertTrue(self.contact_a.email_bounced) def test_tracking_email_link(self): @@ -61,22 +62,21 @@ class TestMassMailing(TransactionCase): 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), - ]) + 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.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', + "ip": "127.0.0.1", + "user_agent": "Odoo Test/1.0", + "os_family": "linux", + "ua_family": "odoo", } - tracking_email.event_create('open', metadata) + tracking_email.event_create("open", metadata) self.assertTrue(stat.opened) def _tracking_email_bounce(self, event_type, state): @@ -84,36 +84,36 @@ class TestMassMailing(TransactionCase): 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), - ]) + tracking_email = self.env["mail.tracking.email"].search( + [("mail_id_int", "=", stat.mail_mail_id_int)] + ) # And now mark the email as bounce metadata = { - 'bounce_type': '499', - 'bounce_description': 'Unable to connect to MX servers', + "bounce_type": "499", + "bounce_description": "Unable to connect to MX servers", } tracking_email.event_create(event_type, metadata) self.assertTrue(stat.bounced) def test_tracking_email_hard_bounce(self): - self._tracking_email_bounce('hard_bounce', 'bounced') + self._tracking_email_bounce("hard_bounce", "bounced") def test_tracking_email_soft_bounce(self): - self._tracking_email_bounce('soft_bounce', 'soft-bounced') + self._tracking_email_bounce("soft_bounce", "soft-bounced") def test_tracking_email_reject(self): - self._tracking_email_bounce('reject', 'rejected') + self._tracking_email_bounce("reject", "rejected") def test_tracking_email_spam(self): - self._tracking_email_bounce('spam', 'spam') + self._tracking_email_bounce("spam", "spam") def test_contact_tracking_emails(self): - self._tracking_email_bounce('hard_bounce', 'bounced') + self._tracking_email_bounce("hard_bounce", "bounced") self.assertTrue(self.contact_a.email_bounced) self.assertTrue(self.contact_a.email_score < 50.0) - self.contact_a.email = 'other_contact_a@example.com' + self.contact_a.email = "other_contact_a@example.com" self.assertFalse(self.contact_a.email_bounced) self.assertTrue(self.contact_a.email_score == 50.0) - self.contact_a.email = 'contact_a@example.com' + self.contact_a.email = "contact_a@example.com" self.assertTrue(self.contact_a.email_bounced) self.assertTrue(self.contact_a.email_score < 50.0)