diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/test_mass_mailing | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/test_mass_mailing')
17 files changed, 1147 insertions, 0 deletions
diff --git a/addons/test_mass_mailing/__init__.py b/addons/test_mass_mailing/__init__.py new file mode 100644 index 00000000..b1475da4 --- /dev/null +++ b/addons/test_mass_mailing/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import data +from . import models diff --git a/addons/test_mass_mailing/__manifest__.py b/addons/test_mass_mailing/__manifest__.py new file mode 100644 index 00000000..60978c8a --- /dev/null +++ b/addons/test_mass_mailing/__manifest__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- + +{ + 'name': 'Mass Mail Tests', + 'version': '1.0', + 'category': 'Hidden', + 'sequence': 8765, + 'summary': 'Mass Mail Tests: feature and performance tests for mass mailing', + 'description': """This module contains tests related to mass mailing. Those +are present in a separate module to use specific test models defined in +test_mail. """, + 'depends': ['test_mail', 'mass_mailing'], + 'data': [ + 'security/ir.model.access.csv', + ], + 'demo': [ + ], + 'installable': True, + 'application': False, + 'license': 'LGPL-3', +} diff --git a/addons/test_mass_mailing/data/__init__.py b/addons/test_mass_mailing/data/__init__.py new file mode 100644 index 00000000..5d1373b6 --- /dev/null +++ b/addons/test_mass_mailing/data/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import mail_test_data diff --git a/addons/test_mass_mailing/data/mail_test_data.py b/addons/test_mass_mailing/data/mail_test_data.py new file mode 100644 index 00000000..92183d04 --- /dev/null +++ b/addons/test_mass_mailing/data/mail_test_data.py @@ -0,0 +1,42 @@ + +MAIL_TEMPLATE = """Return-Path: <whatever-2a840@postmaster.twitter.com> +To: {to} +cc: {cc} +Received: by mail1.openerp.com (Postfix, from userid 10002) + id 5DF9ABFB2A; Fri, 10 Aug 2012 16:16:39 +0200 (CEST) +From: {email_from} +Subject: {subject} +MIME-Version: 1.0 +Content-Type: multipart/alternative; + boundary="----=_Part_4200734_24778174.1344608186754" +Date: Fri, 10 Aug 2012 14:16:26 +0000 +Message-ID: {msg_id} +{extra} +------=_Part_4200734_24778174.1344608186754 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + +I would gladly answer to your mass mailing ! + +-- +Your Dear Customer +------=_Part_4200734_24778174.1344608186754 +Content-Type: text/html; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<html> + <head>=20 + <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8" /> + </head>=20 + <body style=3D"margin: 0; padding: 0; background: #ffffff;-webkit-text-size-adjust: 100%;">=20 + + <p>I would gladly answer to your mass mailing !</p> + + <p>--<br/> + Your Dear Customer + <p> + </body> +</html> +------=_Part_4200734_24778174.1344608186754-- +""" diff --git a/addons/test_mass_mailing/models/__init__.py b/addons/test_mass_mailing/models/__init__.py new file mode 100644 index 00000000..ea86084e --- /dev/null +++ b/addons/test_mass_mailing/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import mailing_mailing +from . import mailing_models diff --git a/addons/test_mass_mailing/models/mailing_mailing.py b/addons/test_mass_mailing/models/mailing_mailing.py new file mode 100644 index 00000000..12c888db --- /dev/null +++ b/addons/test_mass_mailing/models/mailing_mailing.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import logging + +from odoo import models + +_logger = logging.getLogger(__name__) + + +class Mailing(models.Model): + _inherit = 'mailing.mailing' + + def _get_opt_out_list(self): + """Returns a set of emails opted-out in target model""" + self.ensure_one() + if self.mailing_model_real == 'mailing.test.optout': + res_ids = self._get_recipients() + opt_out_contacts = set(self.env['mailing.test.optout'].search([ + ('id', 'in', res_ids), + ('opt_out', '=', True) + ]).mapped('email_normalized')) + _logger.info( + "Mass-mailing %s targets %s, optout: %s emails", + self, self.mailing_model_real, len(opt_out_contacts)) + return opt_out_contacts + return super(Mailing, self)._get_opt_out_list() diff --git a/addons/test_mass_mailing/models/mailing_models.py b/addons/test_mass_mailing/models/mailing_models.py new file mode 100644 index 00000000..54ede3f8 --- /dev/null +++ b/addons/test_mass_mailing/models/mailing_models.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, fields, models + + +class MailingSimple(models.Model): + """ A very simple model only inheriting from mail.thread to test pure mass + mailing features and base performances. """ + _description = 'Simple Mailing' + _name = 'mailing.test.simple' + _inherit = ['mail.thread'] + + name = fields.Char() + email_from = fields.Char() + + +class MailingUTM(models.Model): + """ Model inheriting from mail.thread and utm.mixin for checking utm of mailing is caught and set on reply """ + _description = 'Mailing: UTM enabled to test UTM sync with mailing' + _name = 'mailing.test.utm' + _inherit = ['mail.thread', 'utm.mixin'] + + name = fields.Char() + + +class MailingBLacklist(models.Model): + """ Model using blacklist mechanism for mass mailing features. """ + _description = 'Mailing Blacklist Enabled' + _name = 'mailing.test.blacklist' + _inherit = ['mail.thread.blacklist'] + _primary_email = 'email_from' + + name = fields.Char() + email_from = fields.Char() + customer_id = fields.Many2one('res.partner', 'Customer', tracking=True) + user_id = fields.Many2one('res.users', 'Responsible', tracking=True) + + +class MailingOptOut(models.Model): + """ Model using blacklist mechanism and a hijacked opt-out mechanism for + mass mailing features. """ + _description = 'Mailing Blacklist / Optout Enabled' + _name = 'mailing.test.optout' + _inherit = ['mail.thread.blacklist'] + _primary_email = 'email_from' + + name = fields.Char() + email_from = fields.Char() + opt_out = fields.Boolean() + customer_id = fields.Many2one('res.partner', 'Customer', tracking=True) + user_id = fields.Many2one('res.users', 'Responsible', tracking=True) + + +class MailingPerformance(models.Model): + """ A very simple model only inheriting from mail.thread to test pure mass + mailing performances. """ + _name = 'mailing.performance' + _description = 'Mailing: base performance' + _inherit = ['mail.thread'] + + name = fields.Char() + email_from = fields.Char() + + +class MailingPerformanceBL(models.Model): + """ Model using blacklist mechanism for mass mailing performance. """ + _name = 'mailing.performance.blacklist' + _description = 'Mailing: blacklist performance' + _inherit = ['mail.thread.blacklist'] + _primary_email = 'email_from' # blacklist field to check + + name = fields.Char() + email_from = fields.Char() + user_id = fields.Many2one( + 'res.users', 'Responsible', + tracking=True) + container_id = fields.Many2one( + 'mail.test.container', 'Meta Container Record', + tracking=True) diff --git a/addons/test_mass_mailing/security/ir.model.access.csv b/addons/test_mass_mailing/security/ir.model.access.csv new file mode 100644 index 00000000..5deee89f --- /dev/null +++ b/addons/test_mass_mailing/security/ir.model.access.csv @@ -0,0 +1,13 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_mailing_test_simple_all,access.mailing.test.simple.all,model_mailing_test_simple,,0,0,0,0 +access_mailing_test_simple_user,access.mailing.test.simple.user,model_mailing_test_simple,base.group_user,1,1,1,1 +access_mailing_test_blacklist_all,access.mailing.test.blacklist.all,model_mailing_test_blacklist,,0,0,0,0 +access_mailing_test_blacklist_user,access.mailing.test.blacklist.user,model_mailing_test_blacklist,base.group_user,1,1,1,1 +access_mailing_test_optout_all,access.mailing.test.optout.all,model_mailing_test_optout,,0,0,0,0 +access_mailing_test_optout_user,access.mailing.test.optout.user,model_mailing_test_optout,base.group_user,1,1,1,1 +access_mailing_performance_all,access.mailing.performance.all,model_mailing_performance,,0,0,0,0 +access_mailing_performance_user,access.mailing.performance.user,model_mailing_performance,base.group_user,1,1,1,1 +access_mailing_performance_blacklist_all,access.mailing.performance.blacklist.all,model_mailing_performance_blacklist,,0,0,0,0 +access_mailing_performance_blacklist_user,access.mailing.performance.blacklist.user,model_mailing_performance_blacklist,base.group_user,1,1,1,1 +access_mailing_test_utm_all,access.mailing.test.utm.all,model_mailing_test_utm,,0,0,0,0 +access_mailing_test_utm_user,access.mailing.test.utm.user,model_mailing_test_utm,base.group_user,1,1,1,1 diff --git a/addons/test_mass_mailing/tests/__init__.py b/addons/test_mass_mailing/tests/__init__.py new file mode 100644 index 00000000..978ceb47 --- /dev/null +++ b/addons/test_mass_mailing/tests/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import test_blacklist +from . import test_blacklist_behavior +from . import test_blacklist_mixin +from . import test_link_tracker +from . import test_mailing_test +from . import test_mailing +from . import test_performance diff --git a/addons/test_mass_mailing/tests/common.py b/addons/test_mass_mailing/tests/common.py new file mode 100644 index 00000000..ff368bf5 --- /dev/null +++ b/addons/test_mass_mailing/tests/common.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.addons.mass_mailing.tests.common import MassMailCommon +from odoo.addons.test_mail.tests.common import TestMailCommon + + +class TestMassMailCommon(MassMailCommon, TestMailCommon): + + @classmethod + def setUpClass(cls): + super(TestMassMailCommon, cls).setUpClass() + + cls.test_alias = cls.env['mail.alias'].create({ + 'alias_name': 'test.alias', + 'alias_user_id': False, + 'alias_model_id': cls.env['ir.model']._get('mailing.test.simple').id, + 'alias_contact': 'everyone' + }) + + # enforce last update by user_marketing to match _process_mass_mailing_queue + # taking last writer as user running a batch + cls.mailing_bl = cls.env['mailing.mailing'].with_user(cls.user_marketing).create({ + 'name': 'SourceName', + 'subject': 'MailingSubject', + 'preview': 'Hi ${object.name} :)', + 'body_html': """<div><p>Hello ${object.name}</p>, +% set url = "www.odoo.com" +% set httpurl = "https://www.odoo.eu" +<span>Website0: <a id="url0" href="https://www.odoo.tz/my/${object.name}">https://www.odoo.tz/my/${object.name}</a></span> +<span>Website1: <a id="url1" href="https://www.odoo.be">https://www.odoo.be</a></span> +<span>Website2: <a id="url2" href="https://${url}">https://${url}</a></span> +<span>Website3: <a id="url3" href="${httpurl}">${httpurl}</a></span> +<span>External1: <a id="url4" href="https://www.example.com/foo/bar?baz=qux">Youpie</a></span> +<span>Internal1: <a id="url5" href="/event/dummy-event-0">Internal link</a></span> +<span>Internal2: <a id="url6" href="/view"/>View link</a></span> +<span>Email: <a id="url7" href="mailto:test@odoo.com">test@odoo.com</a></span> +<p>Stop spam ? <a id="url8" role="button" href="/unsubscribe_from_list">Ok</a></p> +</div>""", + 'mailing_type': 'mail', + 'mailing_model_id': cls.env['ir.model']._get('mailing.test.blacklist').id, + 'reply_to_mode': 'thread', + }) + + @classmethod + def _create_test_blacklist_records(cls, model='mailing.test.blacklist', count=1): + """ Deprecated, remove in 14.4 """ + return cls.__create_mailing_test_records(model=model, count=count) + + @classmethod + def _create_mailing_test_records(cls, model='mailing.test.blacklist', partners=None, count=1): + """ Helper to create data. Currently simple, to be improved. """ + Model = cls.env[model] + email_field = 'email' if 'email' in Model else 'email_from' + partner_field = 'customer_id' if 'customer_id' in Model else 'partner_id' + + vals_list = [] + for x in range(0, count): + vals = { + 'name': 'TestRecord_%02d' % x, + email_field: '"TestCustomer %02d" <test.record.%02d@test.example.com>' % (x, x), + } + if partners: + vals[partner_field] = partners[x % len(partners)] + + vals_list.append(vals) + + return cls.env[model].create(vals_list) diff --git a/addons/test_mass_mailing/tests/test_blacklist.py b/addons/test_mass_mailing/tests/test_blacklist.py new file mode 100644 index 00000000..c00a752c --- /dev/null +++ b/addons/test_mass_mailing/tests/test_blacklist.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.tests.common import users +from odoo.addons.test_mass_mailing.tests import common +from odoo.exceptions import AccessError + + +class TestBLAccessRights(common.TestMassMailCommon): + + @classmethod + def setUpClass(cls): + super(TestBLAccessRights, cls).setUpClass() + cls._create_portal_user() + + cls.bl_rec = cls.env['mail.blacklist'].create([ + {'email': 'Not A Stark <john.snow@example.com>'}, + ]) + cls.bl_previous = cls.env['mail.blacklist'].search([]) + + @users('employee') + def test_bl_crud_employee(self): + with self.assertRaises(AccessError): + self.env['mail.blacklist'].create([{'email': 'Arya.Stark@example.com'}]) + + with self.assertRaises(AccessError): + self.bl_rec.with_user(self.env.user).read([]) + + with self.assertRaises(AccessError): + self.bl_rec.with_user(self.env.user).write({'email': 'jaimie.lannister@example.com'}) + + with self.assertRaises(AccessError): + self.bl_rec.with_user(self.env.user).unlink() + + @users('portal_test') + def test_bl_crud_portal(self): + with self.assertRaises(AccessError): + self.env['mail.blacklist'].create([{'email': 'Arya.Stark@example.com'}]) + + with self.assertRaises(AccessError): + self.bl_rec.with_user(self.env.user).read([]) + + with self.assertRaises(AccessError): + self.bl_rec.with_user(self.env.user).write({'email': 'jaimie.lannister@example.com'}) + + with self.assertRaises(AccessError): + self.bl_rec.with_user(self.env.user).unlink() + + @users('user_marketing') + def test_bl_crud_marketing(self): + self.env['mail.blacklist'].create([{'email': 'Arya.Stark@example.com'}]) + + read_res = self.bl_rec.with_user(self.env.user).read([]) + self.assertEqual(read_res[0]['id'], self.bl_rec.id) + + self.bl_rec.with_user(self.env.user).write({'email': 'jaimie.lannister@example.com'}) + self.assertEqual(self.bl_rec.email, 'jaimie.lannister@example.com') + + self.bl_rec.with_user(self.env.user).unlink() + + +class TestBLConsistency(common.TestMassMailCommon): + _base_list = ['Arya.Stark@example.com', 'ned.stark@example.com'] + + def setUp(self): + super(TestBLConsistency, self).setUp() + self.bl_rec = self.env['mail.blacklist'].create([ + {'email': 'Not A Stark <john.snow@example.com>'}, + ]) + + self.bl_previous = self.env['mail.blacklist'].search([]) + + @users('user_marketing') + def test_bl_check_case_add(self): + """ Test emails case when adding through _add """ + bl_sudo = self.env['mail.blacklist'].sudo() + existing = bl_sudo.create({ + 'email': 'arya.stark@example.com', + 'active': False, + }) + + added = self.env['mail.blacklist']._add('Arya.Stark@EXAMPLE.com') + self.assertEqual(existing, added) + self.assertTrue(existing.active) + + @users('user_marketing') + def test_bl_check_case_remove(self): + """ Test emails case when deactivating through _remove """ + bl_sudo = self.env['mail.blacklist'].sudo() + existing = bl_sudo.create({ + 'email': 'arya.stark@example.com', + 'active': True, + }) + + added = self.env['mail.blacklist']._remove('Arya.Stark@EXAMPLE.com') + self.assertEqual(existing, added) + self.assertFalse(existing.active) + + @users('user_marketing') + def test_bl_create_duplicate(self): + """ Test emails are inserted only once if duplicated """ + bl_sudo = self.env['mail.blacklist'].sudo() + self.env['mail.blacklist'].create([ + {'email': self._base_list[0]}, + {'email': self._base_list[1]}, + {'email': 'Another Ned Stark <%s>' % self._base_list[1]}, + ]) + + new_bl = bl_sudo.search([('id', 'not in', self.bl_previous.ids)]) + + self.assertEqual(len(new_bl), 2) + self.assertEqual( + set(v.lower() for v in self._base_list), + set(v.lower() for v in new_bl.mapped('email')) + ) + + @users('user_marketing') + def test_bl_create_parsing(self): + """ Test email is correctly extracted from given entries """ + bl_sudo = self.env['mail.blacklist'].sudo() + self.env['mail.blacklist'].create([ + {'email': self._base_list[0]}, + {'email': self._base_list[1]}, + {'email': 'Not Ned Stark <jaimie.lannister@example.com>'}, + ]) + + new_bl = bl_sudo.search([('id', 'not in', self.bl_previous.ids)]) + + self.assertEqual(len(new_bl), 3) + self.assertEqual( + set(v.lower() for v in self._base_list + ['jaimie.lannister@example.com']), + set(v.lower() for v in new_bl.mapped('email')) + ) + + @users('user_marketing') + def test_bl_search_exact(self): + search_res = self.env['mail.blacklist'].search([('email', '=', 'john.snow@example.com')]) + self.assertEqual(search_res, self.bl_rec) + + @users('user_marketing') + def test_bl_search_parsing(self): + search_res = self.env['mail.blacklist'].search([('email', '=', 'Not A Stark <john.snow@example.com>')]) + + self.assertEqual(search_res, self.bl_rec) + + search_res = self.env['mail.blacklist'].search([('email', '=', '"John J. Snow" <john.snow@example.com>')]) + self.assertEqual(search_res, self.bl_rec) + + search_res = self.env['mail.blacklist'].search([('email', '=', 'Aegon? <john.snow@example.com>')]) + self.assertEqual(search_res, self.bl_rec) + + search_res = self.env['mail.blacklist'].search([('email', '=', '"John; \"You know Nothing\" Snow" <john.snow@example.com>')]) + self.assertEqual(search_res, self.bl_rec) + + @users('user_marketing') + def test_bl_search_case(self): + search_res = self.env['mail.blacklist'].search([('email', '=', 'john.SNOW@example.COM>')]) + self.assertEqual(search_res, self.bl_rec) + + @users('user_marketing') + def test_bl_search_partial(self): + search_res = self.env['mail.blacklist'].search([('email', 'ilike', 'John')]) + self.assertEqual(search_res, self.bl_rec) + search_res = self.env['mail.blacklist'].search([('email', 'ilike', 'n.SNOW@example.cO>')]) + self.assertEqual(search_res, self.bl_rec) diff --git a/addons/test_mass_mailing/tests/test_blacklist_behavior.py b/addons/test_mass_mailing/tests/test_blacklist_behavior.py new file mode 100644 index 00000000..a5a77c7d --- /dev/null +++ b/addons/test_mass_mailing/tests/test_blacklist_behavior.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import datetime + +from odoo.addons.test_mass_mailing.tests import common +from odoo.tests.common import users +from odoo.addons.mass_mailing.models.mail_thread import BLACKLIST_MAX_BOUNCED_LIMIT + + +class TestAutoBlacklist(common.TestMassMailCommon): + + @classmethod + def setUpClass(cls): + super(TestAutoBlacklist, cls).setUpClass() + cls.target_rec = cls._create_mailing_test_records()[0] + cls.mailing_bl.write({'mailing_domain': [('id', 'in', cls.target_rec.ids)]}) + + @users('user_marketing') + def test_mailing_bounce_w_auto_bl(self): + self._test_mailing_bounce_w_auto_bl(None) + + @users('user_marketing') + def test_mailing_bounce_w_auto_bl_partner(self): + bounced_partner = self.env['res.partner'].sudo().create({ + 'name': 'Bounced Partner', + 'email': self.target_rec.email_from, + 'message_bounce': BLACKLIST_MAX_BOUNCED_LIMIT, + }) + self._test_mailing_bounce_w_auto_bl({'bounced_partner': bounced_partner}) + + @users('user_marketing') + def test_mailing_bounce_w_auto_bl_partner_duplicates(self): + bounced_partners = self.env['res.partner'].sudo().create({ + 'name': 'Bounced Partner1', + 'email': self.target_rec.email_from, + 'message_bounce': BLACKLIST_MAX_BOUNCED_LIMIT, + }) | self.env['res.partner'].sudo().create({ + 'name': 'Bounced Partner2', + 'email': self.target_rec.email_from, + 'message_bounce': BLACKLIST_MAX_BOUNCED_LIMIT, + }) + self._test_mailing_bounce_w_auto_bl({'bounced_partner': bounced_partners}) + + def _test_mailing_bounce_w_auto_bl(self, bounce_base_values): + mailing = self.env['mailing.mailing'].browse(self.mailing_bl.ids) + target = self.env['mailing.test.blacklist'].browse(self.target_rec.ids) + + # create bounced history of 4 statistics + for idx in range(4): + new_mailing = mailing.copy() + self._create_bounce_trace(new_mailing, target, dt=datetime.datetime.now() - datetime.timedelta(weeks=idx+2)) + self.gateway_mail_bounce(new_mailing, target, bounce_base_values) + + # mass mail record: ok, not blacklisted yet + mailing.action_put_in_queue() + with self.mock_mail_gateway(mail_unlink_sent=False): + mailing._process_mass_mailing_queue() + + self.assertMailTraces( + [{'email': 'test.record.00@test.example.com'}], + mailing, target, + check_mail=True + ) + + # call bounced + self.gateway_mail_bounce(mailing, target, bounce_base_values) + + # check blacklist + blacklist_record = self.env['mail.blacklist'].sudo().search([('email', '=', target.email_normalized)]) + self.assertEqual(len(blacklist_record), 1) + self.assertTrue(target.is_blacklisted) + + # mass mail record: ko, blacklisted + new_mailing = mailing.copy() + new_mailing.write({'mailing_domain': [('id', 'in', target.ids)]}) + new_mailing.action_put_in_queue() + with self.mock_mail_gateway(mail_unlink_sent=False): + new_mailing._process_mass_mailing_queue() + self.assertMailTraces( + [{'email': 'test.record.00@test.example.com', 'state': 'ignored'}], + new_mailing, target, check_mail=True + ) diff --git a/addons/test_mass_mailing/tests/test_blacklist_mixin.py b/addons/test_mass_mailing/tests/test_blacklist_mixin.py new file mode 100644 index 00000000..57504fb5 --- /dev/null +++ b/addons/test_mass_mailing/tests/test_blacklist_mixin.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.addons.test_mass_mailing.models.mailing_models import MailingBLacklist +from odoo.addons.test_mass_mailing.tests import common +from odoo.exceptions import UserError +from odoo.tests.common import users + + +class TestBLMixin(common.TestMassMailCommon): + + @classmethod + def setUpClass(cls): + super(TestBLMixin, cls).setUpClass() + + cls.env['mail.blacklist'].create([{ + 'email': 'Arya.Stark@example.com', + 'active': True, + }, { + 'email': 'Sansa.Stark@example.com', + 'active': False, + }]) + + @users('employee') + def test_bl_mixin_primary_field_consistency(self): + MailingBLacklist._primary_email = 'not_a_field' + with self.assertRaises(UserError): + self.env['mailing.test.blacklist'].search([('is_blacklisted', '=', False)]) + + MailingBLacklist._primary_email = ['not_a_str'] + with self.assertRaises(UserError): + self.env['mailing.test.blacklist'].search([('is_blacklisted', '=', False)]) + + MailingBLacklist._primary_email = 'email_from' + self.env['mailing.test.blacklist'].search([('is_blacklisted', '=', False)]) + + @users('employee') + def test_bl_mixin_is_blacklisted(self): + """ Test is_blacklisted field computation """ + record = self.env['mailing.test.blacklist'].create({'email_from': 'arya.stark@example.com'}) + self.assertTrue(record.is_blacklisted) + + record = self.env['mailing.test.blacklist'].create({'email_from': 'not.arya.stark@example.com'}) + self.assertFalse(record.is_blacklisted) + + @users('employee') + def test_bl_mixin_search_blacklisted(self): + """ Test is_blacklisted field search implementation """ + record1 = self.env['mailing.test.blacklist'].create({'email_from': 'arya.stark@example.com'}) + record2 = self.env['mailing.test.blacklist'].create({'email_from': 'not.arya.stark@example.com'}) + + search_res = self.env['mailing.test.blacklist'].search([('is_blacklisted', '=', False)]) + self.assertEqual(search_res, record2) + + search_res = self.env['mailing.test.blacklist'].search([('is_blacklisted', '!=', True)]) + self.assertEqual(search_res, record2) + + search_res = self.env['mailing.test.blacklist'].search([('is_blacklisted', '=', True)]) + self.assertEqual(search_res, record1) + + search_res = self.env['mailing.test.blacklist'].search([('is_blacklisted', '!=', False)]) + self.assertEqual(search_res, record1) + + @users('employee') + def test_bl_mixin_search_blacklisted_format(self): + """ Test is_blacklisted field search using email parsing """ + record1 = self.env['mailing.test.blacklist'].create({'email_from': 'Arya Stark <arya.stark@example.com>'}) + self.assertTrue(record1.is_blacklisted) + + search_res = self.env['mailing.test.blacklist'].search([('is_blacklisted', '=', True)]) + self.assertEqual(search_res, record1) diff --git a/addons/test_mass_mailing/tests/test_link_tracker.py b/addons/test_mass_mailing/tests/test_link_tracker.py new file mode 100644 index 00000000..df2a23ae --- /dev/null +++ b/addons/test_mass_mailing/tests/test_link_tracker.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.tests.common import users +from odoo.addons.test_mass_mailing.tests import common + + +class TestLinkTracker(common.TestMassMailCommon): + + def setUp(self): + super(TestLinkTracker, self).setUp() + + self.link = self.env['link.tracker'].create({ + 'url': 'https://www.example.com' + }) + + self.click = self.env['link.tracker.click'].create({ + 'link_id': self.link.id, + 'ip': '100.00.00.00', + 'country_id': self.env.ref('base.fr').id, + }) + + def test_add_link(self): + code = self.link.code + self.assertEqual(self.link.count, 1) + + # click from a new IP should create a new entry + click = self.env['link.tracker.click'].sudo().add_click( + code, + ip='100.00.00.01', + country_code='BEL' + ) + self.assertEqual(click.ip, '100.00.00.01') + self.assertEqual(click.country_id, self.env.ref('base.be')) + self.assertEqual(self.link.count, 2) + + # click from same IP (even another country) does not create a new entry + click = self.env['link.tracker.click'].sudo().add_click( + code, + ip='100.00.00.01', + country_code='FRA' + ) + self.assertEqual(click, None) + self.assertEqual(self.link.count, 2) + + @users('user_marketing') + def test_add_link_mail_stat(self): + mailing = self.env['mailing.mailing'].create({'name': 'Test Mailing', "subject": "Hi!"}) + code = self.link.code + self.assertEqual(self.link.count, 1) + stat = self.env['mailing.trace'].create({'mass_mailing_id': mailing.id}) + self.assertFalse(stat.opened) + self.assertFalse(stat.clicked) + + # click from a new IP should create a new entry and update stat when provided + click = self.env['link.tracker.click'].sudo().add_click( + code, + ip='100.00.00.01', + country_code='BEL', + mailing_trace_id=stat.id + ) + self.assertEqual(self.link.count, 2) + self.assertEqual(click.mass_mailing_id, mailing) + self.assertTrue(stat.opened) + self.assertTrue(stat.clicked) diff --git a/addons/test_mass_mailing/tests/test_mailing.py b/addons/test_mass_mailing/tests/test_mailing.py new file mode 100644 index 00000000..4f6fa34f --- /dev/null +++ b/addons/test_mass_mailing/tests/test_mailing.py @@ -0,0 +1,340 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.addons.test_mass_mailing.data.mail_test_data import MAIL_TEMPLATE +from odoo.addons.test_mass_mailing.tests.common import TestMassMailCommon +from odoo.tests import tagged +from odoo.tests.common import users +from odoo.tools import mute_logger + + +@tagged('mass_mailing') +class TestMassMailing(TestMassMailCommon): + + @classmethod + def setUpClass(cls): + super(TestMassMailing, cls).setUpClass() + + @users('user_marketing') + @mute_logger('odoo.addons.mail.models.mail_thread') + def test_mailing_gateway_reply(self): + customers = self.env['res.partner'] + for x in range(0, 3): + customers |= self.env['res.partner'].create({ + 'name': 'Customer_%02d' % x, + 'email': '"Customer_%02d" <customer_%02d@test.example.com' % (x, x), + }) + + mailing = self.env['mailing.mailing'].create({ + 'name': 'TestName', + 'subject': 'TestSubject', + 'body_html': 'Hello ${object.name}', + 'reply_to_mode': 'email', + 'reply_to': '%s@%s' % (self.test_alias.alias_name, self.test_alias.alias_domain), + 'keep_archives': True, + 'mailing_model_id': self.env['ir.model']._get('res.partner').id, + 'mailing_domain': '%s' % [('id', 'in', customers.ids)], + }) + mailing.action_put_in_queue() + with self.mock_mail_gateway(mail_unlink_sent=False): + mailing.action_send_mail() + + self.gateway_mail_reply_wrecord(MAIL_TEMPLATE, customers[0], use_in_reply_to=True) + self.gateway_mail_reply_wrecord(MAIL_TEMPLATE, customers[1], use_in_reply_to=False) + + # customer2 looses headers + mail_mail = self._find_mail_mail_wrecord(customers[2]) + self.format_and_process( + MAIL_TEMPLATE, + mail_mail.email_to, + mail_mail.reply_to, + subject='Re: %s' % mail_mail.subject, + extra='', + msg_id='<123456.%s.%d@test.example.com>' % (customers[2]._name, customers[2].id), + target_model=customers[2]._name, target_field=customers[2]._rec_name, + ) + mailing.flush() + + # check traces status + traces = self.env['mailing.trace'].search([('model', '=', customers._name), ('res_id', 'in', customers.ids)]) + self.assertEqual(len(traces), 3) + customer0_trace = traces.filtered(lambda t: t.res_id == customers[0].id) + self.assertEqual(customer0_trace.state, 'replied') + customer1_trace = traces.filtered(lambda t: t.res_id == customers[1].id) + self.assertEqual(customer1_trace.state, 'replied') + customer2_trace = traces.filtered(lambda t: t.res_id == customers[2].id) + self.assertEqual(customer2_trace.state, 'sent') + + # check mailing statistics + self.assertEqual(mailing.sent, 3) + self.assertEqual(mailing.delivered, 3) + self.assertEqual(mailing.opened, 2) + self.assertEqual(mailing.replied, 2) + + @users('user_marketing') + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_mailing_gateway_update(self): + mailing = self.env['mailing.mailing'].browse(self.mailing_bl.ids) + recipients = self._create_mailing_test_records(model='mailing.test.optout', count=5) + self.assertEqual(len(recipients), 5) + + mailing.write({ + 'mailing_model_id': self.env['ir.model']._get('mailing.test.optout'), + 'mailing_domain': [('id', 'in', recipients.ids)] + }) + mailing.action_put_in_queue() + with self.mock_mail_gateway(mail_unlink_sent=False): + mailing._process_mass_mailing_queue() + + self.assertMailTraces( + [{'email': record.email_normalized} + for record in recipients], + mailing, recipients, + mail_links_info=[[ + ('url0', 'https://www.odoo.tz/my/%s' % record.name, True, {}), + ('url1', 'https://www.odoo.be', True, {}), + ('url2', 'https://www.odoo.com', True, {}), + ('url3', 'https://www.odoo.eu', True, {}), + ('url4', 'https://www.example.com/foo/bar?baz=qux', True, {'baz': 'qux'}), + ('url5', '%s/event/dummy-event-0' % mailing.get_base_url(), True, {}), + # view is not shortened and parsed at sending + ('url6', '%s/view' % mailing.get_base_url(), False, {}), + ('url7', 'mailto:test@odoo.com', False, {}), + # unsubscribe is not shortened and parsed at sending + ('url8', '%s/unsubscribe_from_list' % mailing.get_base_url(), False, {}), + ] for record in recipients], + check_mail=True + ) + self.assertMailingStatistics(mailing, expected=5, delivered=5, sent=5) + + # simulate a click + self.gateway_mail_click(mailing, recipients[0], 'https://www.odoo.be') + mailing.invalidate_cache() + self.assertMailingStatistics(mailing, expected=5, delivered=5, sent=5, opened=1, clicked=1) + + # simulate a bounce + self.assertEqual(recipients[1].message_bounce, 0) + self.gateway_mail_bounce(mailing, recipients[1]) + mailing.invalidate_cache() + self.assertMailingStatistics(mailing, expected=5, delivered=4, sent=5, opened=1, clicked=1, bounced=1) + self.assertEqual(recipients[1].message_bounce, 1) + + @users('user_marketing') + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_mailing_reply_to_mode_new(self): + mailing = self.env['mailing.mailing'].browse(self.mailing_bl.ids) + recipients = self._create_mailing_test_records(model='mailing.test.blacklist', count=5) + self.assertEqual(len(recipients), 5) + initial_messages = recipients.message_ids + mailing.write({ + 'mailing_domain': [('id', 'in', recipients.ids)], + 'keep_archives': False, + 'reply_to_mode': 'email', + 'reply_to': self.test_alias.display_name, + }) + + with self.mock_mail_gateway(mail_unlink_sent=True): + mailing.action_send_mail() + + answer_rec = self.gateway_mail_reply_wemail(MAIL_TEMPLATE, recipients[0].email_normalized, target_model=self.test_alias.alias_model_id.model) + self.assertTrue(bool(answer_rec)) + self.assertEqual(answer_rec.name, 'Re: %s' % mailing.subject) + self.assertEqual( + answer_rec.message_ids.subject, 'Re: %s' % mailing.subject, + 'Answer should be logged') + self.assertEqual(recipients.message_ids, initial_messages) + + self.assertMailingStatistics(mailing, expected=5, delivered=5, sent=5, opened=1, replied=1) + + @users('user_marketing') + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_mailing_reply_to_mode_update(self): + mailing = self.env['mailing.mailing'].browse(self.mailing_bl.ids) + recipients = self._create_mailing_test_records(model='mailing.test.blacklist', count=5) + self.assertEqual(len(recipients), 5) + mailing.write({ + 'mailing_domain': [('id', 'in', recipients.ids)], + 'keep_archives': False, + 'reply_to_mode': 'thread', + 'reply_to': self.test_alias.display_name, + }) + + with self.mock_mail_gateway(mail_unlink_sent=True): + mailing.action_send_mail() + + answer_rec = self.gateway_mail_reply_wemail(MAIL_TEMPLATE, recipients[0].email_normalized, target_model=self.test_alias.alias_model_id.model) + self.assertFalse(bool(answer_rec)) + self.assertEqual( + recipients[0].message_ids[1].subject, mailing.subject, + 'Should have keep a log (to enable thread-based answer)') + self.assertEqual( + recipients[0].message_ids[0].subject, 'Re: %s' % mailing.subject, + 'Answer should be logged') + + self.assertMailingStatistics(mailing, expected=5, delivered=5, sent=5, opened=1, replied=1) + + @users('user_marketing') + @mute_logger('odoo.addons.mail.models.mail_thread') + def test_mailing_trace_utm(self): + """ Test mailing UTMs are caught on reply""" + self._create_mailing_list() + self.test_alias.write({ + 'alias_model_id': self.env['ir.model']._get('mailing.test.utm').id + }) + + source = self.env['utm.source'].create({'name': 'Source test'}) + medium = self.env['utm.medium'].create({'name': 'Medium test'}) + campaign = self.env['utm.campaign'].create({'name': 'Campaign test'}) + subject = 'MassMailingTestUTM' + + mailing = self.env['mailing.mailing'].create({ + 'name': 'UTMTest', + 'subject': subject, + 'body_html': '<p>Hello ${object.name}</p>', + 'reply_to_mode': 'email', + 'reply_to': '%s@%s' % (self.test_alias.alias_name, self.test_alias.alias_domain), + 'keep_archives': True, + 'mailing_model_id': self.env['ir.model']._get('mailing.list').id, + 'contact_list_ids': [(4, self.mailing_list_1.id)], + 'source_id': source.id, + 'medium_id': medium.id, + 'campaign_id': campaign.id + }) + + mailing.action_put_in_queue() + with self.mock_mail_gateway(mail_unlink_sent=False): + mailing._process_mass_mailing_queue() + + traces = self.env['mailing.trace'].search([('model', '=', self.mailing_list_1.contact_ids._name), ('res_id', 'in', self.mailing_list_1.contact_ids.ids)]) + self.assertEqual(len(traces), 3) + + # simulate response to mailing + self.gateway_mail_reply_wrecord(MAIL_TEMPLATE, self.mailing_list_1.contact_ids[0], use_in_reply_to=True) + self.gateway_mail_reply_wrecord(MAIL_TEMPLATE, self.mailing_list_1.contact_ids[1], use_in_reply_to=False) + + mailing_test_utms = self.env['mailing.test.utm'].search([('name', '=', 'Re: %s' % subject)]) + self.assertEqual(len(mailing_test_utms), 2) + for test_utm in mailing_test_utms: + self.assertEqual(test_utm.campaign_id, campaign) + self.assertEqual(test_utm.source_id, source) + self.assertEqual(test_utm.medium_id, medium) + + @users('user_marketing') + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_mailing_w_blacklist(self): + mailing = self.env['mailing.mailing'].browse(self.mailing_bl.ids) + recipients = self._create_mailing_test_records(count=5) + + # blacklist records 2, 3, 4 + self.env['mail.blacklist'].create({'email': recipients[2].email_normalized}) + self.env['mail.blacklist'].create({'email': recipients[3].email_normalized}) + self.env['mail.blacklist'].create({'email': recipients[4].email_normalized}) + + # unblacklist record 2 + self.env['mail.blacklist'].action_remove_with_reason( + recipients[2].email_normalized, "human error" + ) + self.env['mail.blacklist'].flush(['active']) + + mailing.write({'mailing_domain': [('id', 'in', recipients.ids)]}) + mailing.action_put_in_queue() + with self.mock_mail_gateway(mail_unlink_sent=False): + mailing._process_mass_mailing_queue() + + self.assertMailTraces( + [{'email': 'test.record.00@test.example.com'}, + {'email': 'test.record.01@test.example.com'}, + {'email': 'test.record.02@test.example.com'}, + {'email': 'test.record.03@test.example.com', 'state': 'ignored'}, + {'email': 'test.record.04@test.example.com', 'state': 'ignored'}], + mailing, recipients, check_mail=True + ) + self.assertEqual(mailing.ignored, 2) + + @users('user_marketing') + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_mailing_w_opt_out(self): + mailing = self.env['mailing.mailing'].browse(self.mailing_bl.ids) + recipients = self._create_mailing_test_records(model='mailing.test.optout', count=5) + + # optout records 0 and 1 + (recipients[0] | recipients[1]).write({'opt_out': True}) + # blacklist records 4 + self.env['mail.blacklist'].create({'email': recipients[4].email_normalized}) + + mailing.write({ + 'mailing_model_id': self.env['ir.model']._get('mailing.test.optout'), + 'mailing_domain': [('id', 'in', recipients.ids)] + }) + mailing.action_put_in_queue() + with self.mock_mail_gateway(mail_unlink_sent=False): + mailing._process_mass_mailing_queue() + + self.assertMailTraces( + [{'email': 'test.record.00@test.example.com', 'state': 'ignored'}, + {'email': 'test.record.01@test.example.com', 'state': 'ignored'}, + {'email': 'test.record.02@test.example.com'}, + {'email': 'test.record.03@test.example.com'}, + {'email': 'test.record.04@test.example.com', 'state': 'ignored'}], + mailing, recipients, check_mail=True + ) + self.assertEqual(mailing.ignored, 3) + + @users('user_marketing') + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_mailing_mailing_list_optout(self): + """ Test mailing list model specific optout behavior """ + mailing_contact_1 = self.env['mailing.contact'].create({'name': 'test 1A', 'email': 'test@test.example.com'}) + mailing_contact_2 = self.env['mailing.contact'].create({'name': 'test 1B', 'email': 'test@test.example.com'}) + mailing_contact_3 = self.env['mailing.contact'].create({'name': 'test 3', 'email': 'test3@test.example.com'}) + mailing_contact_4 = self.env['mailing.contact'].create({'name': 'test 4', 'email': 'test4@test.example.com'}) + mailing_contact_5 = self.env['mailing.contact'].create({'name': 'test 5', 'email': 'test5@test.example.com'}) + + # create mailing list record + mailing_list_1 = self.env['mailing.list'].create({ + 'name': 'A', + 'contact_ids': [ + (4, mailing_contact_1.id), + (4, mailing_contact_2.id), + (4, mailing_contact_3.id), + (4, mailing_contact_5.id), + ] + }) + mailing_list_2 = self.env['mailing.list'].create({ + 'name': 'B', + 'contact_ids': [ + (4, mailing_contact_3.id), + (4, mailing_contact_4.id), + ] + }) + # contact_1 is optout but same email is not optout from the same list + # contact 3 is optout in list 1 but not in list 2 + # contact 5 is optout + Sub = self.env['mailing.contact.subscription'] + Sub.search([('contact_id', '=', mailing_contact_1.id), ('list_id', '=', mailing_list_1.id)]).write({'opt_out': True}) + Sub.search([('contact_id', '=', mailing_contact_3.id), ('list_id', '=', mailing_list_1.id)]).write({'opt_out': True}) + Sub.search([('contact_id', '=', mailing_contact_5.id), ('list_id', '=', mailing_list_1.id)]).write({'opt_out': True}) + + # create mass mailing record + mailing = self.env['mailing.mailing'].create({ + 'name': 'SourceName', + 'subject': 'MailingSubject', + 'body_html': '<p>Hello ${object.name}</p>', + 'mailing_model_id': self.env['ir.model']._get('mailing.list').id, + 'contact_list_ids': [(4, ml.id) for ml in mailing_list_1 | mailing_list_2], + }) + mailing.action_put_in_queue() + with self.mock_mail_gateway(mail_unlink_sent=False): + mailing._process_mass_mailing_queue() + + self.assertMailTraces( + [{'email': 'test@test.example.com', 'state': 'sent'}, + {'email': 'test@test.example.com', 'state': 'ignored'}, + {'email': 'test3@test.example.com'}, + {'email': 'test4@test.example.com'}, + {'email': 'test5@test.example.com', 'state': 'ignored'}], + mailing, + mailing_contact_1 + mailing_contact_2 + mailing_contact_3 + mailing_contact_4 + mailing_contact_5, + check_mail=True + ) + self.assertEqual(mailing.ignored, 2) diff --git a/addons/test_mass_mailing/tests/test_mailing_test.py b/addons/test_mass_mailing/tests/test_mailing_test.py new file mode 100644 index 00000000..33c0419a --- /dev/null +++ b/addons/test_mass_mailing/tests/test_mailing_test.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.addons.test_mass_mailing.tests.common import TestMassMailCommon +from odoo.tests.common import users +from odoo.tools import mute_logger + + +class TestMailingTest(TestMassMailCommon): + + @users('user_marketing') + @mute_logger('odoo.addons.mail.models.mail_render_mixin') + def test_mailing_test_button(self): + mailing = self.env['mailing.mailing'].create({ + 'name': 'TestButton', + 'subject': 'Subject ${object.name}', + 'preview': 'Preview ${object.name}', + 'state': 'draft', + 'mailing_type': 'mail', + 'body_html': '<p>Hello ${object.name}</p>', + 'mailing_model_id': self.env['ir.model']._get('res.partner').id, + }) + mailing_test = self.env['mailing.mailing.test'].create({ + 'email_to': 'test@test.com', + 'mass_mailing_id': mailing.id, + }) + + with self.mock_mail_gateway(): + mailing_test.send_mail_test() + + # Test if bad jinja in the subject raises an error + mailing.write({'subject': 'Subject ${object.name_id.id}'}) + with self.mock_mail_gateway(), self.assertRaises(Exception): + mailing_test.send_mail_test() + + # Test if bad jinja in the body raises an error + mailing.write({ + 'subject': 'Subject ${object.name}', + 'body_html': '<p>Hello ${object.name_id.id}</p>', + }) + with self.mock_mail_gateway(), self.assertRaises(Exception): + mailing_test.send_mail_test() + + # Test if bad jinja in the preview raises an error + mailing.write({ + 'body_html': '<p>Hello ${object.name}</p>', + 'preview': 'Preview ${object.name_id.id}', + }) + with self.mock_mail_gateway(), self.assertRaises(Exception): + mailing_test.send_mail_test() diff --git a/addons/test_mass_mailing/tests/test_performance.py b/addons/test_mass_mailing/tests/test_performance.py new file mode 100644 index 00000000..680eacf5 --- /dev/null +++ b/addons/test_mass_mailing/tests/test_performance.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.addons.mail.tests.common import mail_new_test_user +from odoo.tests.common import TransactionCase, users, warmup +from odoo.tests import tagged +from odoo.tools import mute_logger + + +class TestMassMailPerformanceBase(TransactionCase): + + def setUp(self): + super(TestMassMailPerformanceBase, self).setUp() + + self.user_employee = mail_new_test_user( + self.env, login='emp', + groups='base.group_user', + name='Ernest Employee', notification_type='inbox') + + self.user_marketing = mail_new_test_user( + self.env, login='marketing', + groups='base.group_user,mass_mailing.group_mass_mailing_user', + name='Martial Marketing', signature='--\nMartial') + + # patch registry to simulate a ready environment + self.patch(self.env.registry, 'ready', True) + + +@tagged('mail_performance') +class TestMassMailPerformance(TestMassMailPerformanceBase): + + def setUp(self): + super(TestMassMailPerformance, self).setUp() + values = [{ + 'name': 'Recipient %s' % x, + 'email_from': 'Recipient <rec.%s@example.com>' % x, + } for x in range(0, 50)] + self.mm_recs = self.env['mailing.performance'].create(values) + + @users('__system__', 'marketing') + @warmup + @mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink', 'odoo.tests') + def test_send_mailing(self): + mailing = self.env['mailing.mailing'].create({ + 'name': 'Test', + 'subject': 'Test', + 'body_html': '<p>Hello <a role="button" href="https://www.example.com/foo/bar?baz=qux">quux</a><a role="button" href="/unsubscribe_from_list">Unsubscribe</a></p>', + 'reply_to_mode': 'email', + 'mailing_model_id': self.ref('test_mass_mailing.model_mailing_performance'), + 'mailing_domain': [('id', 'in', self.mm_recs.ids)], + }) + + # runbot needs +51 compared to local + with self.assertQueryCount(__system__=1715, marketing=1716): # test_mass_mailing_only: 1664 - 1665 + mailing.action_send_mail() + + self.assertEqual(mailing.sent, 50) + self.assertEqual(mailing.delivered, 50) + + +@tagged('mail_performance') +class TestMassMailBlPerformance(TestMassMailPerformanceBase): + + def setUp(self): + """ In this setup we prepare 20 blacklist entries. We therefore add + 20 recipients compared to first test in order to have comparable results. """ + super(TestMassMailBlPerformance, self).setUp() + values = [{ + 'name': 'Recipient %s' % x, + 'email_from': 'Recipient <rec.%s@example.com>' % x, + } for x in range(0, 62)] + self.mm_recs = self.env['mailing.performance.blacklist'].create(values) + + for x in range(1, 13): + self.env['mail.blacklist'].create({ + 'email': 'rec.%s@example.com' % (x * 5) + }) + self.env['mailing.performance.blacklist'].flush() + + @users('__system__', 'marketing') + @warmup + @mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink', 'odoo.tests') + def test_send_mailing_w_bl(self): + mailing = self.env['mailing.mailing'].create({ + 'name': 'Test', + 'subject': 'Test', + 'body_html': '<p>Hello <a role="button" href="https://www.example.com/foo/bar?baz=qux">quux</a><a role="button" href="/unsubscribe_from_list">Unsubscribe</a></p>', + 'reply_to_mode': 'email', + 'mailing_model_id': self.ref('test_mass_mailing.model_mailing_performance_blacklist'), + 'mailing_domain': [('id', 'in', self.mm_recs.ids)], + }) + + # runbot needs +63 compared to local + with self.assertQueryCount(__system__=1992, marketing=1993): # test_mass_mailing only: 1929 - 1930 + mailing.action_send_mail() + + self.assertEqual(mailing.sent, 50) + self.assertEqual(mailing.delivered, 50) |
