[IMP] link_tracker, (test_)mass_mailing: improve test tools and clean existing tests

URPOSE

Prepare code cleaning and optimization in mail, mass_mailing and SMS by
cleaning models for readability and code complexity and footprint reduction.

SPECIFICATIONS

Add tool methods and asserts for link tracker tests.

Add tool methods and assets for mass mailing tests, notably about mailing
traces and their link with emails.

Merge existing and duplicated tests and rewrite them a bit.

Rename and improve test_mass_mailing models.

LINKS

Prepares task ID 2238597 (notification and trace models cleaning)
Task ID 1906925 (mass mailing tests cleaning)
PR #50169

Related: odoo/enterprise#10180
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Thibault Delavallée
2020-04-24 15:35:43 +00:00
parent 9721488817
commit 7946b42ef5
26 changed files with 732 additions and 706 deletions
+4
View File
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import common
+71
View File
@@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import werkzeug
from lxml import etree
from unittest.mock import patch
from odoo.tests import common
class MockLinkTracker(common.BaseCase):
def setUp(self):
super(MockLinkTracker, self).setUp()
def _get_title_from_url(url):
return "Test_TITLE"
link_tracker_title_patch = patch('odoo.addons.link_tracker.models.link_tracker.LinkTracker._get_title_from_url', wraps=_get_title_from_url)
link_tracker_title_patch.start()
self.addCleanup(link_tracker_title_patch.stop)
def _get_href_from_anchor_id(self, body, anchor_id):
html = etree.fromstring(body)
return html.xpath("*[@id='%s']" % anchor_id)[0].attrib.get('href')
def _get_tracker_from_short_url(self, short_url):
code = self.env['link.tracker.code'].sudo().search([
('code', '=', short_url.split('/r/')[-1])
])
return code.link_id
def assertLinkShortened(self, body, link_info, link_params=None):
""" Usage
self.assertLinkShortened(
message.body,
('url0', 'http://www.odoo.com', True),
{'utm_campaign': self.utm_c.name, 'utm_medium': self.utm_m.name}
)
"""
(anchor_id, url, is_shortened) = link_info
anchor_href = self._get_href_from_anchor_id(body, anchor_id)
if is_shortened:
self.assertTrue('/r/' in anchor_href, '%s should be shortened: %s' % (anchor_id, anchor_href))
link_tracker = self._get_tracker_from_short_url(anchor_href)
self.assertEqual(url, link_tracker.url)
self.assertLinkParams(url, link_tracker, link_params=link_params)
else:
self.assertTrue('/r/' not in anchor_href, '%s should not be shortened: %s' % (anchor_id, anchor_href))
self.assertEqual(anchor_href, url)
def assertLinkParams(self, url, link_tracker, link_params=None):
""" Usage
self.assertLinkTracker(
'http://www.example.com',
link_tracker,
{'utm_campaign': self.utm_c.name, 'utm_medium': self.utm_m.name}
)
"""
# check UTMS are correctly set on redirect URL
original_url = werkzeug.urls.url_parse(url)
redirect_url = werkzeug.urls.url_parse(link_tracker.redirected_url)
redirect_params = redirect_url.decode_query().to_dict(flat=True)
self.assertEqual(redirect_url.scheme, original_url.scheme)
self.assertEqual(redirect_url.decode_netloc(), original_url.decode_netloc())
self.assertEqual(redirect_url.path, original_url.path)
if link_params:
self.assertEqual(redirect_params, link_params)
+1 -2
View File
@@ -3,5 +3,4 @@
from . import common
from . import test_mailing_internals
from . import test_mass_mailing_list_merge
from . import test_mass_mailing_shortener
from . import test_mailing_list
+104 -5
View File
@@ -1,11 +1,106 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.link_tracker.tests.common import MockLinkTracker
from odoo.addons.mail.tests.common import MailCase, mail_new_test_user
from odoo.tests.common import SavepointCase
class TestMassMailCommon(SavepointCase, MailCase):
class MassMailCase(MailCase, MockLinkTracker):
def _find_mail_mail_wemail(self, email_to, state, author=None):
for mail in self._new_mails:
if author is not None and mail.author_id != author:
continue
if mail.state != state:
continue
if (mail.email_to == email_to and not mail.recipient_ids) or (not mail.email_to and mail.recipient_ids.email) == email_to:
break
else:
raise AssertionError('mail.mail not found for email_to %s / state %s in %s' % (email_to, state, repr([m.email_to for m in self._new_mails])))
return mail
def _find_mail_mail_wrecord(self, record):
for mail in self._new_mails:
if mail.model == record._name and mail.res_id == record.id:
break
else:
raise AssertionError('mail.mail not found for record %s in %s' % (record, repr([m.email_to for m in self._new_mails])))
return mail
def assertMailMailWEmails(self, emails, state, content, fields_values=None):
""" Will check in self._new_mails to find a sent mail.mail. To use with
mail gateway mock.
:param emails: list of emails;
:param state: state of mail.mail;
:param content: content to check for each email;
:param fields_values: specific value to check on the mail.mail record;
"""
for email_to in emails:
sent_mail = self._find_mail_mail_wemail(email_to, state)
if content:
self.assertIn(content, sent_mail.body_html)
for fname, fvalue in (fields_values or {}).items():
self.assertEqual(sent_mail[fname], fvalue)
def assertMailTraces(self, recipients_info, mailing, records, check_mail=True):
""" Check content of traces.
:param recipients_info: list[{
'partner': res.partner record (may be empty),
'email': email used when sending email (may be empty, computed based on partner),
'state': outgoing / sent / open / reply / error / cancel (sent by default),
'record: linked record,
'content': UDPATE ME
'failure_type': optional: UPDATE ME
}, { ... }]
"""
traces = self.env['mailing.trace'].search([
('mass_mailing_id', 'in', mailing.ids),
('res_id', 'in', records.ids)
])
# ensure trace coherency
self.assertTrue(all(s.model == records._name for s in traces))
self.assertEqual(set(s.res_id for s in traces), set(records.ids))
# check each traces
for recipient_info in recipients_info:
partner = recipient_info.get('partner', self.env['res.partner'])
email = recipient_info.get('email')
state = recipient_info.get('state', 'sent')
record = recipient_info.get('record')
content = recipient_info.get('content')
if email is None and partner:
email = partner.email_normalized
recipient_trace = traces.filtered(
lambda t: t.email == email and t.state == state and (t.res_id == record.id if record else True)
)
self.assertTrue(
len(recipient_trace) == 1,
'MailTrace: email %s (recipient %s, state: %s, record: %s): found %s records (1 expected)' % (email, partner, state, record, len(recipient_trace))
)
if check_mail:
fields_values = {'mailing_id': mailing}
if 'failure_type' in recipient_info:
fields_values['failure_type'] = recipient_info['failure_type']
if state == 'sent':
self.assertMailMailWEmails([email], 'sent', content, fields_values=fields_values)
elif state == 'ignored':
self.assertMailMailWEmails([email], 'cancel', content, fields_values=fields_values)
elif state == 'exception':
self.assertMailMailWEmails([email], 'exception', content, fields_values=fields_values)
elif state == 'canceled':
self.assertMailMailWEmails([email], 'canceled', content, fields_values=fields_values)
else:
raise NotImplementedError()
class TestMassMailCommon(SavepointCase, MassMailCase):
@classmethod
def setUpClass(cls):
@@ -16,7 +111,13 @@ class TestMassMailCommon(SavepointCase, MailCase):
groups='base.group_user,base.group_partner_manager,mass_mailing.group_mass_mailing_user',
name='Martial Marketing', signature='--\nMartial')
cls.mailing_list_1 = cls.env['mailing.list'].create({
cls.email_reply_to = 'MyCompany SomehowAlias <test.alias@test.mycompany.com>'
@classmethod
def _create_mailing_list(cls):
""" Shortcut to create mailing lists. Currently hardcoded, maybe evolve
in a near future. """
cls.mailing_list_1 = cls.env['mailing.list'].with_context(cls._test_context).create({
'name': 'List1',
'contact_ids': [
(0, 0, {'name': 'Déboulonneur', 'email': 'fleurus@example.com'}),
@@ -24,7 +125,7 @@ class TestMassMailCommon(SavepointCase, MailCase):
(0, 0, {'name': 'Ybrant', 'email': 'ybrant@example.com'}),
]
})
cls.mailing_list_2 = cls.env['mailing.list'].create({
cls.mailing_list_2 = cls.env['mailing.list'].with_context(cls._test_context).create({
'name': 'List2',
'contact_ids': [
(0, 0, {'name': 'Gilberte', 'email': 'gilberte@example.com'}),
@@ -33,5 +134,3 @@ class TestMassMailCommon(SavepointCase, MailCase):
(0, 0, {'name': 'Ybrant', 'email': 'ybrant@example.com'}),
]
})
cls.email_reply_to = 'MyCompany SomehowAlias <test.alias@test.mycompany.com>'
@@ -5,10 +5,48 @@ from ast import literal_eval
from odoo.addons.mass_mailing.tests.common import TestMassMailCommon
from odoo.tests.common import users, Form
from odoo.tools import formataddr, mute_logger
class TestMassMailValues(TestMassMailCommon):
@classmethod
def setUpClass(cls):
super(TestMassMailValues, cls).setUpClass()
cls._create_mailing_list()
@users('user_marketing')
def test_mailing_body_responsive(self):
""" Testing mail mailing responsive mail body """
recipient = self.env['res.partner'].create({
'name': 'Mass Mail Partner',
'email': 'Customer <test.customer@example.com>',
})
mailing = self.env['mailing.mailing'].create({
'name': 'Test',
'subject': 'Test',
'state': 'draft',
'mailing_model_id': self.env['ir.model']._get('res.partner').id,
})
composer = self.env['mail.compose.message'].with_user(self.user_marketing).with_context({
'default_composition_mode': 'mass_mail',
'default_model': 'res.partner',
'default_res_id': recipient.id,
}).create({
'subject': 'Mass Mail Responsive',
'body': 'I am Responsive body',
'mass_mailing_id': mailing.id
})
mail_values = composer.get_mail_values([recipient.id])
body_html = str(mail_values[recipient.id]['body_html'])
self.assertIn('<!DOCTYPE html>', body_html)
self.assertIn('<head>', body_html)
self.assertIn('viewport', body_html)
self.assertIn('@media', body_html)
self.assertIn('I am Responsive body', body_html)
@users('user_marketing')
def test_mailing_computed_fields(self):
# Create on res.partner, with default values for computed fields
@@ -82,3 +120,140 @@ class TestMassMailValues(TestMassMailCommon):
['&', ('is_blacklisted', '=', False), ('email', 'ilike', 'test.example.com')]
)
self.assertEqual(mailing_form.mailing_model_real, 'res.partner')
class TestMassMailFeatures(TestMassMailCommon):
@classmethod
def setUpClass(cls):
super(TestMassMailFeatures, cls).setUpClass()
cls._create_mailing_list()
@users('user_marketing')
@mute_logger('odoo.addons.mail.models.mail_mail')
def test_channel_blacklisted_recipients(self):
""" Posting a message on a channel should send one email to all recipients, except the blacklisted ones """
def _join_channel(channel, partners):
for partner in partners:
channel.write({'channel_last_seen_partner_ids': [(0, 0, {'partner_id': partner.id})]})
channel.invalidate_cache()
test_channel = self.env['mail.channel'].create({
'name': 'Test',
'description': 'Description',
'alias_name': 'test',
'public': 'public',
'email_send': True,
})
test_partner = self.env['res.partner'].create({
'name': 'Test Partner',
'email': 'test@example.com',
})
blacklisted_partner = self.env['res.partner'].create({
'name': 'Blacklisted Partner',
'email': 'test@black.list',
})
# Set Blacklist
self.env['mail.blacklist'].create({
'email': 'test@black.list',
})
_join_channel(test_channel, test_partner)
_join_channel(test_channel, blacklisted_partner)
with self.mock_mail_gateway():
test_channel.message_post(body="Test", message_type='comment', subtype_xmlid='mail.mt_comment')
self.assertEqual(len(self._mails), 1, 'Number of mail incorrect. Should be equal to 1.')
for email in self._mails:
self.assertEqual(
set(email['email_to']),
set([formataddr((test_partner.name, test_partner.email))]),
'email_to incorrect. Should be equal to "%s"' % (
formataddr((test_partner.name, test_partner.email))))
@users('user_marketing')
@mute_logger('odoo.addons.mail.models.mail_mail')
def test_mailing_on_res_partner(self):
""" Test mailing on res.partner model: ensure default recipients are
correctly computed """
partner_a = self.env['res.partner'].create({
'name': 'test email 1',
'email': 'test1@example.com',
})
partner_b = self.env['res.partner'].create({
'name': 'test email 2',
'email': 'test2@example.com',
})
self.env['mail.blacklist'].create({'email': 'Test2@example.com',})
mailing = self.env['mailing.mailing'].create({
'name': 'One',
'subject': 'One',
'mailing_model_id': self.env['ir.model']._get('res.partner').id,
'mailing_domain': [('id', 'in', (partner_a | partner_b).ids)],
'body_html': 'This is mass mail marketing demo'
})
mailing.action_put_in_queue()
with self.mock_mail_gateway(mail_unlink_sent=False):
mailing._process_mass_mailing_queue()
self.assertMailTraces(
[{'email': 'test1@example.com'},
{'email': 'test2@example.com', 'state': 'ignored'}],
mailing, partner_a | partner_b, check_mail=True
)
@users('user_marketing')
@mute_logger('odoo.addons.mail.models.mail_mail')
def test_mailing_shortener(self):
mailing = self.env['mailing.mailing'].create({
'name': 'TestSource',
'subject': 'TestShortener',
'body_html': """<div>
Hi,
% set url = "www.odoo.com"
% set httpurl = "https://www.odoo.eu"
Website0: <a id="url0" href="https://www.odoo.tz/my/${object.name}">https://www.odoo.tz/my/${object.name}</a>
Website1: <a id="url1" href="https://www.odoo.be">https://www.odoo.be</a>
Website2: <a id="url2" href="https://${url}">https://${url}</a>
Website3: <a id="url3" href="${httpurl}">${httpurl}</a>
External1: <a id="url4" href="https://www.example.com/foo/bar?baz=qux">Youpie</a>
Email: <a id="url5" href="mailto:test@odoo.com">test@odoo.com</a></div>""",
'mailing_model_id': self.env['ir.model']._get('mailing.list').id,
'reply_to_mode': 'email',
'reply_to': self.email_reply_to,
'contact_list_ids': [(6, 0, self.mailing_list_1.ids)],
'keep_archives': True,
})
mailing.action_put_in_queue()
with self.mock_mail_gateway(mail_unlink_sent=False):
mailing._process_mass_mailing_queue()
self.assertMailTraces(
[{'email': 'fleurus@example.com'},
{'email': 'gorramts@example.com'},
{'email': 'ybrant@example.com'}],
mailing, self.mailing_list_1.contact_ids, check_mail=True
)
for contact in self.mailing_list_1.contact_ids:
new_mail = self._find_mail_mail_wrecord(contact)
for link_info in [('url0', 'https://www.odoo.tz/my/%s' % contact.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),
('url5', 'mailto:test@odoo.com', False)]:
# TDE FIXME: why going to mail message id ? mail.body_html seems to fail, check
link_params = {'utm_medium': 'Email', 'utm_source': mailing.name}
if link_info[0] == 'url4':
link_params['baz'] = 'qux'
self.assertLinkShortened(
new_mail.mail_message_id.body,
link_info,
link_params=link_params,
)
@@ -1,47 +1,34 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests import common
from odoo.addons.mass_mailing.tests.common import TestMassMailCommon
from odoo.tests.common import users
class TestMailingListMerge(common.TransactionCase):
class TestMailingListMerge(TestMassMailCommon):
def test_00_test_mass_mailing_list_merge(self):
# Data set up
@classmethod
def setUpClass(cls):
super(TestMailingListMerge, cls).setUpClass()
cls._create_mailing_list()
mailing_list_A = self.env['mailing.list'].create({
'name': 'A',
'contact_ids': [
(0, 0, {'name': 'Noel Flantier', 'email': 'noel.flantier@example.com'}),
(0, 0, {'name': 'Gorramts', 'email': 'gorramts@example.com'}),
(0, 0, {'name': 'Ybrant', 'email': 'ybrant@example.com'}),
]
})
mailing_list_B = self.env['mailing.list'].create({
'name': 'B',
'contact_ids': [
(0, 0, {'name': 'Icallhimtest', 'email': 'icallhimtest@example.com'}),
(0, 0, {'name': 'Norbert', 'email': 'norbert@example.com'}),
(0, 0, {'name': 'Ybrant_Zoulou', 'email': 'ybrant@example.com'}),
]
})
mailing_list_C = self.env['mailing.list'].create({
'name': 'C',
cls.mailing_list_3 = cls.env['mailing.list'].with_context(cls._test_context).create({
'name': 'ListC',
'contact_ids': [
(0, 0, {'name': 'Norberto', 'email': 'norbert@example.com'}),
]
})
@users('user_marketing')
def test_mailing_list_merge(self):
# TEST CASE: Merge A,B into the existing mailing list C
# The mailing list C contains the same email address than 'Rorbert' in list B
# The mailing list C contains the same email address than 'Norbert' in list B
# This test ensure that the mailing lists are correctly merged and no
# duplicates are appearing in C
result_list = self.env['mailing.list.merge'].create({
'src_list_ids': [(4, list_id) for list_id in [mailing_list_A.id, mailing_list_B.id]],
'dest_list_id': mailing_list_C.id,
'src_list_ids': [(4, list_id) for list_id in [self.mailing_list_1.id, self.mailing_list_2.id]],
'dest_list_id': self.mailing_list_3.id,
'merge_options': 'existing',
'new_list_name': False,
'archive_src_lists': False,
@@ -1,122 +0,0 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests import common
from lxml import etree
from unittest.mock import patch
class TestMassMailingShortener(common.TransactionCase):
def getHrefFor(self, html, id):
return html.xpath("*[@id='%s']" % id)[0].attrib.get('href')
def shorturl_to_link(self, short_url):
return self.env['link.tracker.code'].search([('code', '=', short_url.split('/r/')[-1])]).link_id
def setUp(self):
super(TestMassMailingShortener, self).setUp()
def _get_title_from_url(u):
return "Hello"
patcher = patch('odoo.addons.link_tracker.models.link_tracker.LinkTracker._get_title_from_url', wraps=_get_title_from_url)
patcher.start()
self.addCleanup(patcher.stop)
def test_00_test_mass_mailing_shortener(self):
mailing_list_A = self.env['mailing.list'].create({
'name': 'A',
})
self.env['mailing.contact'].create({
'name': 'User 1', 'email': 'user1@example.com', 'list_ids': [(4, mailing_list_A.id)]
})
self.env['mailing.contact'].create({
'name': 'User 2', 'email': 'user2@example.com', 'list_ids': [(4, mailing_list_A.id)]
})
self.env['mailing.contact'].create({
'name': 'User 3', 'email': 'user3@example.com', 'list_ids': [(4, mailing_list_A.id)]
})
mass_mailing = self.env['mailing.mailing'].create({
"reply_to_mode": "email",
"reply_to": "Administrator <admin@yourcompany.example.com>",
"mailing_model_id": self.env.ref('mass_mailing.model_mailing_list').id,
"mailing_domain": "[('list_ids', 'in', [%d])]" % mailing_list_A.id,
"contact_list_ids": [[6, False, [mailing_list_A.id]]],
"campaign_id": False,
"name": "sdf",
"subject": "test_00_test_mass_mailing_shortener",
"body_html": """
Hi,
% set url = "www.odoo.com"
% set httpurl = "https://www.odoo.eu"
Website0: <a id="url0" href="https://www.odoo.tz/my/${object.name}">https://www.odoo.tz/my/${object.name}</h1>
Website1: <a id="url1" href="https://www.odoo.be">https://www.odoo.be</h1>
Website2: <a id="url2" href="https://${url}">https://${url}</h1>
Website3: <a id="url3" href="${httpurl}">${httpurl}</h1>
Email: <a id="url4" href="mailto:test@odoo.com">test@odoo.com</h1>
""",
"schedule_date": False,
"state": "draft",
"keep_archives": True,
})
mass_mailing.action_put_in_queue()
mass_mailing._process_mass_mailing_queue()
sent_mails = self.env['mail.mail'].sudo().search([('mailing_id', '=', mass_mailing.id)])
sent_messages = sent_mails.mapped('mail_message_id')
self.assertEqual(len(mailing_list_A.contact_ids), len(sent_messages),
'Some message has not been sent')
xbody = etree.fromstring(sent_messages[0].body)
after_url0 = self.getHrefFor(xbody, 'url0')
after_url1 = self.getHrefFor(xbody, 'url1')
after_url2 = self.getHrefFor(xbody, 'url2')
after_url3 = self.getHrefFor(xbody, 'url3')
after_url4 = self.getHrefFor(xbody, 'url4')
self.assertTrue('/r/' in after_url0, 'URL0 should be shortened: %s' % after_url0)
self.assertTrue('/r/' in after_url1, 'URL1 should be shortened: %s' % after_url1)
self.assertTrue('/r/' in after_url2, 'URL2 should be shortened: %s' % after_url2)
self.assertTrue('/r/' in after_url3, 'URL3 should be shortened: %s' % after_url3)
self.assertEqual(after_url4, "mailto:test@odoo.com", 'mailto: has been converted')
short0 = self.shorturl_to_link(after_url0)
short1 = self.shorturl_to_link(after_url1)
short2 = self.shorturl_to_link(after_url2)
short3 = self.shorturl_to_link(after_url3)
self.assertTrue("https://www.odoo.tz/my/User" in short0.url, 'URL mismatch')
self.assertEqual(short1.url, "https://www.odoo.be", 'URL mismatch')
self.assertEqual(short2.url, "https://www.odoo.com", 'URL mismatch')
self.assertEqual(short3.url, "https://www.odoo.eu", 'URL mismatch')
_xbody = etree.fromstring(sent_messages[1].body)
_after_url0 = self.getHrefFor(_xbody, 'url0')
_after_url1 = self.getHrefFor(_xbody, 'url1')
_after_url2 = self.getHrefFor(_xbody, 'url2')
_after_url3 = self.getHrefFor(_xbody, 'url3')
_after_url4 = self.getHrefFor(_xbody, 'url4')
self.assertTrue('/r/' in _after_url0, 'URL0 should be shortened: %s' % _after_url0)
self.assertTrue('/r/' in _after_url1, 'URL1 should be shortened: %s' % _after_url1)
self.assertTrue('/r/' in _after_url2, 'URL2 should be shortened: %s' % _after_url2)
self.assertTrue('/r/' in _after_url3, 'URL3 should be shortened: %s' % _after_url3)
self.assertEqual(_after_url4, "mailto:test@odoo.com", 'mailto: has been converted')
_short0 = self.shorturl_to_link(_after_url0)
_short1 = self.shorturl_to_link(_after_url1)
_short2 = self.shorturl_to_link(_after_url2)
_short3 = self.shorturl_to_link(_after_url3)
self.assertTrue("https://www.odoo.tz/my/User" in _short0.url, 'URL mismatch')
self.assertEqual(_short1.url, "https://www.odoo.be", 'URL mismatch')
self.assertEqual(_short2.url, "https://www.odoo.com", 'URL mismatch')
self.assertEqual(_short3.url, "https://www.odoo.eu", 'URL mismatch')
self.assertNotEqual(short0.url, _short0.url)
self.assertEqual(short1.url, _short1.url)
self.assertEqual(short2.url, _short2.url)
self.assertEqual(short3.url, _short3.url)
@@ -5,7 +5,6 @@ from ast import literal_eval
from odoo.addons.mass_mailing.tests.common import TestMassMailCommon
from odoo.tests.common import users
from odoo.tools import mute_logger
class TestMassMailValues(TestMassMailCommon):
@@ -14,6 +13,7 @@ class TestMassMailValues(TestMassMailCommon):
def setUpClass(cls):
super(TestMassMailValues, cls).setUpClass()
cls._create_mailing_list()
cls.sms_template_partner = cls.env['sms.template'].create({
'name': 'Test Template',
'model_id': cls.env['ir.model']._get('res.partner').id,
+1 -1
View File
@@ -6,7 +6,7 @@ from odoo.addons.test_mail.tests import common as test_mail_common
from odoo.addons.test_mass_mailing.tests import common as test_mass_mailing_common
class TestSMSCommon(test_mass_mailing_common.TestMailCommon, mass_mailing_sms_common.MockSMS):
class TestSMSCommon(test_mass_mailing_common.TestMassMailCommon, mass_mailing_sms_common.MockSMS):
@classmethod
def setUpClass(cls):
+4 -4
View File
@@ -58,7 +58,7 @@ class TestMassSMS(test_mail_full_common.TestSMSCommon):
})
def test_mass_sms_internals(self):
with self.with_user('marketing'):
with self.with_user('user_marketing'):
mailing = self.env['mailing.mailing'].create({
'name': 'Xmas Spam',
'subject': 'Xmas Spam',
@@ -105,7 +105,7 @@ class TestMassSMS(test_mail_full_common.TestSMSCommon):
})
records_numbers = self.records_numbers + ['+32456999999']
with self.with_user('marketing'):
with self.with_user('user_marketing'):
with self.mockSMSGateway():
self.mailing.action_send_sms()
@@ -119,7 +119,7 @@ class TestMassSMS(test_mail_full_common.TestSMSCommon):
)
def test_mass_sms_internals_done_ids(self):
with self.with_user('marketing'):
with self.with_user('user_marketing'):
with self.mockSMSGateway():
self.mailing.action_send_sms(res_ids=self.records[:5].ids)
@@ -131,7 +131,7 @@ class TestMassSMS(test_mail_full_common.TestSMSCommon):
self.mailing, self.records[:5], check_sms=True
)
with self.with_user('marketing'):
with self.with_user('user_marketing'):
with self.mockSMSGateway():
self.mailing.action_send_sms(res_ids=self.records.ids)
+2 -1
View File
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import mass_mail_test
from . import mailing_mailing
from . import mailing_models
@@ -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()
@@ -0,0 +1,71 @@
# -*- 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 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)
@@ -1,34 +0,0 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class MassMailTest(models.Model):
""" A very simple model only inheriting from mail.thread to test pure mass
mailing features and base performances. """
_description = 'Simple Mass Mailing Model'
_name = 'mass.mail.test'
_inherit = ['mail.thread.blacklist']
_primary_email = 'email_from'
name = fields.Char()
email_from = fields.Char()
class MassMailTestBlacklist(models.Model):
""" Model using blacklist mechanism for mass mailing. """
_description = 'Mass Mailing Model w Blacklist'
_name = 'mass.mail.test.bl'
_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)
@@ -1,5 +1,11 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_mass_mail_test_all,mass.mail.test.all,model_mass_mail_test,,0,0,0,0
access_mass_mail_test_user,mass.mail.test.user,model_mass_mail_test,base.group_user,1,1,1,1
access_mass_mail_test_bl_all,mass.mail.test.bl.all,model_mass_mail_test_bl,,0,0,0,0
access_mass_mail_test_bl_user,mass.mail.test.bl.user,model_mass_mail_test_bl,base.group_user,1,1,1,1
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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_mass_mail_test_all access_mailing_test_simple_all mass.mail.test.all access.mailing.test.simple.all model_mass_mail_test model_mailing_test_simple 0 0 0 0
3 access_mass_mail_test_user access_mailing_test_simple_user mass.mail.test.user access.mailing.test.simple.user model_mass_mail_test model_mailing_test_simple base.group_user 1 1 1 1
4 access_mass_mail_test_bl_all access_mailing_test_blacklist_all mass.mail.test.bl.all access.mailing.test.blacklist.all model_mass_mail_test_bl model_mailing_test_blacklist 0 0 0 0
5 access_mass_mail_test_bl_user access_mailing_test_blacklist_user mass.mail.test.bl.user access.mailing.test.blacklist.user model_mass_mail_test_bl model_mailing_test_blacklist base.group_user 1 1 1 1
6 access_mailing_test_optout_all access.mailing.test.optout.all model_mailing_test_optout 0 0 0 0
7 access_mailing_test_optout_user access.mailing.test.optout.user model_mailing_test_optout base.group_user 1 1 1 1
8 access_mailing_performance_all access.mailing.performance.all model_mailing_performance 0 0 0 0
9 access_mailing_performance_user access.mailing.performance.user model_mailing_performance base.group_user 1 1 1 1
10 access_mailing_performance_blacklist_all access.mailing.performance.blacklist.all model_mailing_performance_blacklist 0 0 0 0
11 access_mailing_performance_blacklist_user access.mailing.performance.blacklist.user model_mailing_performance_blacklist base.group_user 1 1 1 1
+2 -4
View File
@@ -2,10 +2,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_composer
from . import test_link
from . import test_mail_auto_blacklist
from . import test_mail_channel
from . import test_link_tracker
from . import test_mass_mailing
from . import test_performance
+44 -8
View File
@@ -1,17 +1,53 @@
# -*- 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.addons.test_mail.tests import common
import datetime
import random
from odoo.addons.mass_mailing.tests.common import TestMassMailCommon
from odoo.addons.test_mail.tests.common import TestMailCommon
class TestMailCommon(common.TestMailCommon):
class TestMassMailCommon(TestMassMailCommon, TestMailCommon):
@classmethod
def setUpClass(cls):
super(TestMailCommon, cls).setUpClass()
super(TestMassMailCommon, cls).setUpClass()
cls.user_marketing = mail_new_test_user(
cls.env, login='marketing',
groups='base.group_user,base.group_partner_manager,mass_mailing.group_mass_mailing_user',
name='Martial Marketing', signature='--\nMartial')
cls.mailing_bl = cls.env['mailing.mailing'].create({
'name': 'SourceName',
'subject': 'MailingSubject',
'body_html': '<p>Hello ${object.name}</p>',
'mailing_type': 'mail',
'mailing_model_id': cls.env['ir.model']._get('mailing.test.blacklist').id,
})
@classmethod
def _create_test_blacklist_records(cls, model='mailing.test.blacklist', count=1):
""" Helper to create data. Currently simple, to be improved. """
records = cls.env[model].create([{
'name': 'TestRecord_%02d' % x,
'email_from': '"TestCustomer %02d" <test.record.%02d@test.example.com>' % (x, x),
} for x in range(0, count)])
return records
@classmethod
def _create_bounce_trace(cls, record, dt=None):
if dt is None:
dt = datetime.datetime.now() - datetime.timedelta(days=1)
randomized = random.random()
if 'email_normalized' in record:
trace_email = record.email_normalized
elif 'email_from' in record:
trace_email = record.email_from
else:
trace_email = record.email
trace = cls.env['mailing.trace'].create({
'model': record._name,
'res_id': record.id,
'bounced': dt,
# TDE FIXME: improve this with a mail-enabled heuristics
'email': trace_email,
'message_id': '<%5f@gilbert.boitempomils>' % randomized,
})
return trace
@@ -6,7 +6,7 @@ from odoo.addons.test_mass_mailing.tests import common
from odoo.exceptions import AccessError
class TestBLAccessRights(common.TestMailCommon):
class TestBLAccessRights(common.TestMassMailCommon):
@classmethod
def setUpClass(cls):
@@ -46,7 +46,7 @@ class TestBLAccessRights(common.TestMailCommon):
with self.assertRaises(AccessError):
self.bl_rec.with_user(self.env.user).unlink()
@users('marketing')
@users('user_marketing')
def test_bl_crud_marketing(self):
self.env['mail.blacklist'].create([{'email': 'Arya.Stark@example.com'}])
@@ -59,7 +59,7 @@ class TestBLAccessRights(common.TestMailCommon):
self.bl_rec.with_user(self.env.user).unlink()
class TestBLConsistency(common.TestMailCommon):
class TestBLConsistency(common.TestMassMailCommon):
_base_list = ['Arya.Stark@example.com', 'ned.stark@example.com']
def setUp(self):
@@ -70,7 +70,7 @@ class TestBLConsistency(common.TestMailCommon):
self.bl_previous = self.env['mail.blacklist'].search([])
@users('marketing')
@users('user_marketing')
def test_bl_check_case_add(self):
""" Test emails case when adding through _add """
bl_sudo = self.env['mail.blacklist'].sudo()
@@ -83,7 +83,7 @@ class TestBLConsistency(common.TestMailCommon):
self.assertEqual(existing, added)
self.assertTrue(existing.active)
@users('marketing')
@users('user_marketing')
def test_bl_check_case_remove(self):
""" Test emails case when deactivating through _remove """
bl_sudo = self.env['mail.blacklist'].sudo()
@@ -96,7 +96,7 @@ class TestBLConsistency(common.TestMailCommon):
self.assertEqual(existing, added)
self.assertFalse(existing.active)
@users('marketing')
@users('user_marketing')
def test_bl_create_duplicate(self):
""" Test emails are inserted only once if duplicated """
bl_sudo = self.env['mail.blacklist'].sudo()
@@ -114,7 +114,7 @@ class TestBLConsistency(common.TestMailCommon):
set(v.lower() for v in new_bl.mapped('email'))
)
@users('marketing')
@users('user_marketing')
def test_bl_create_parsing(self):
""" Test email is correctly extracted from given entries """
bl_sudo = self.env['mail.blacklist'].sudo()
@@ -132,14 +132,15 @@ class TestBLConsistency(common.TestMailCommon):
set(v.lower() for v in new_bl.mapped('email'))
)
@users('marketing')
@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('marketing')
@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>')])
@@ -151,12 +152,12 @@ class TestBLConsistency(common.TestMailCommon):
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('marketing')
@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('marketing')
@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)
@@ -0,0 +1,63 @@
# -*- 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
class TestAutoBlacklist(common.TestMassMailCommon):
@users('user_marketing')
def test_mailing_bounce_w_auto_bl(self):
mailing = self.mailing_bl.with_user(self.env.user)
base_parsed_values = {
'email_from': 'toto@yaourth.com', 'to': 'tata@yaourth.com', 'message_id': '<123.321@yaourth.com>',
'bounced_partner': self.env['res.partner'].sudo(), 'bounced_message': self.env['mail.message'].sudo()
}
target = self._create_test_blacklist_records()[0]
# create bounced history of 4 statistics
for idx in range(4):
trace = self._create_bounce_trace(target, dt=datetime.datetime.now() - datetime.timedelta(weeks=idx+2))
base_parsed_values.update({
'bounced_email': target.email_normalized,
'bounced_msg_id': [trace.message_id],
})
self.env['mail.thread']._routing_handle_bounce(False, base_parsed_values)
# mass mail record: ok, not blacklisted yet
mailing.write({'mailing_domain': [('id', 'in', target.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'}],
mailing, target, check_mail=True
)
# call bounced
trace = self._create_bounce_trace(target, dt=datetime.datetime.now())
base_parsed_values.update({
'bounced_email': target.email_normalized,
'bounced_msg_id': [trace.message_id],
})
self.env['mail.thread']._routing_handle_bounce(False, base_parsed_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
)
@@ -1,13 +1,13 @@
# -*- 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.addons.test_mass_mailing.models.mass_mail_test import MassMailTestBlacklist
from odoo.exceptions import UserError
from odoo.tests.common import users
class TestBLMixin(common.TestMailCommon):
class TestBLMixin(common.TestMassMailCommon):
@classmethod
def setUpClass(cls):
@@ -23,49 +23,49 @@ class TestBLMixin(common.TestMailCommon):
@users('employee')
def test_bl_mixin_primary_field_consistency(self):
MassMailTestBlacklist._primary_email = 'not_a_field'
MailingBLacklist._primary_email = 'not_a_field'
with self.assertRaises(UserError):
self.env['mass.mail.test.bl'].search([('is_blacklisted', '=', False)])
self.env['mailing.test.blacklist'].search([('is_blacklisted', '=', False)])
MassMailTestBlacklist._primary_email = ['not_a_str']
MailingBLacklist._primary_email = ['not_a_str']
with self.assertRaises(UserError):
self.env['mass.mail.test.bl'].search([('is_blacklisted', '=', False)])
self.env['mailing.test.blacklist'].search([('is_blacklisted', '=', False)])
MassMailTestBlacklist._primary_email = 'email_from'
self.env['mass.mail.test.bl'].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['mass.mail.test.bl'].create({'email_from': 'arya.stark@example.com'})
record = self.env['mailing.test.blacklist'].create({'email_from': 'arya.stark@example.com'})
self.assertTrue(record.is_blacklisted)
record = self.env['mass.mail.test.bl'].create({'email_from': 'not.arya.stark@example.com'})
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['mass.mail.test.bl'].create({'email_from': 'arya.stark@example.com'})
record2 = self.env['mass.mail.test.bl'].create({'email_from': 'not.arya.stark@example.com'})
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['mass.mail.test.bl'].search([('is_blacklisted', '=', False)])
search_res = self.env['mailing.test.blacklist'].search([('is_blacklisted', '=', False)])
self.assertEqual(search_res, record2)
search_res = self.env['mass.mail.test.bl'].search([('is_blacklisted', '!=', True)])
search_res = self.env['mailing.test.blacklist'].search([('is_blacklisted', '!=', True)])
self.assertEqual(search_res, record2)
search_res = self.env['mass.mail.test.bl'].search([('is_blacklisted', '=', True)])
search_res = self.env['mailing.test.blacklist'].search([('is_blacklisted', '=', True)])
self.assertEqual(search_res, record1)
search_res = self.env['mass.mail.test.bl'].search([('is_blacklisted', '!=', False)])
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['mass.mail.test.bl'].create({'email_from': 'Arya Stark <arya.stark@example.com>'})
record1 = self.env['mailing.test.blacklist'].create({'email_from': 'Arya Stark <arya.stark@example.com>'})
self.assertTrue(record1.is_blacklisted)
search_res = self.env['mass.mail.test.bl'].search([('is_blacklisted', '=', True)])
search_res = self.env['mailing.test.blacklist'].search([('is_blacklisted', '=', True)])
self.assertEqual(search_res, record1)
@@ -1,36 +0,0 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.test_mass_mailing.tests import common
class TestComposer(common.TestMailCommon):
def test_body_responsive(self):
""" Testing mail mailing responsive mail body """
test_record = self.env['res.partner'].create({'name': 'Mass Mail Partner'})
mass_mail_record = self.env['mailing.mailing'].with_user(self.user_marketing).create({
'name': 'Test',
'subject': 'Test',
'state': 'draft',
'mailing_model_id': self.env.ref('base.model_res_partner').id,
})
composer = self.env['mail.compose.message'].with_user(self.user_marketing).with_context({
'default_composition_mode': 'mass_mail',
'default_model': 'res.partner',
'default_res_id': test_record.id,
}).create({
'subject': 'Mass Mail Responsive',
'body': 'I am Responsive body',
'mass_mailing_id': mass_mail_record.id
})
mail_values = composer.get_mail_values([test_record.id])
body_html = str(mail_values[test_record.id]['body_html'])
self.assertIn('<!DOCTYPE html>', body_html)
self.assertIn('<head>', body_html)
self.assertIn('viewport', body_html)
self.assertIn('@media', body_html)
self.assertIn('I am Responsive body', body_html)
@@ -5,7 +5,7 @@ from odoo.tests.common import users
from odoo.addons.test_mass_mailing.tests import common
class TestLinkTracker(common.TestMailCommon):
class TestLinkTracker(common.TestMassMailCommon):
def setUp(self):
super(TestLinkTracker, self).setUp()
@@ -43,7 +43,7 @@ class TestLinkTracker(common.TestMailCommon):
self.assertEqual(click, None)
self.assertEqual(self.link.count, 2)
@users('marketing')
@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
@@ -1,82 +0,0 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import datetime
from odoo import tools
from odoo.tests import common
class TestAutoBlacklist(common.TransactionCase):
def test_mail_bounced_auto_blacklist(self):
mass_mailing_contacts = self.env['mailing.contact']
mass_mailing = self.env['mailing.mailing']
mail_blacklist = self.env['mail.blacklist']
mail_statistics = self.env['mailing.trace']
# create mailing contact record
self.mailing_contact_1 = mass_mailing_contacts.create({'name': 'test email 1', 'email': 'Test1@email.com'})
base_parsed_values = {
'email_from': 'toto@yaourth.com', 'to': 'tata@yaourth.com', 'message_id': '<123.321@yaourth.com>',
'bounced_partner': self.env['res.partner'].sudo(), 'bounced_message': self.env['mail.message'].sudo()
}
# create bounced history of 4 statistics
for idx in range(4):
mail_statistics.create({
'model': 'mailing.contact',
'res_id': self.mailing_contact_1.id,
'bounced': datetime.datetime.now() - datetime.timedelta(weeks=idx+2),
'email': self.mailing_contact_1.email,
'message_id': '<123.00%s@iron.sky>' % idx,
})
base_parsed_values.update({
'bounced_email': tools.email_normalize(self.mailing_contact_1.email),
'bounced_msg_id': ['<123.00%s@iron.sky>' % idx]
})
self.env['mail.thread']._routing_handle_bounce(False, base_parsed_values)
# create mass mailing record
self.mass_mailing = mass_mailing.create({
'name': 'test',
'subject': 'Booooounce!',
'mailing_domain': [('id', 'in',
[self.mailing_contact_1.id])],
'body_html': 'This is a bounced mail for auto blacklist demo'})
self.mass_mailing.action_put_in_queue()
res_ids = self.mass_mailing._get_remaining_recipients()
composer_values = {
'body': self.mass_mailing.convert_links()[self.mass_mailing.id],
'subject': self.mass_mailing.name,
'model': self.mass_mailing.mailing_model_real,
'email_from': self.mass_mailing.email_from,
'composition_mode': 'mass_mail',
'mass_mailing_id': self.mass_mailing.id,
'mailing_list_ids': [(4, l.id) for l in self.mass_mailing.contact_list_ids],
}
composer = self.env['mail.compose.message'].with_context(
active_ids=res_ids,
mass_mailing_seen_list=self.mass_mailing._get_seen_list()
).create(composer_values)
composer.send_mail()
mail_statistics.create({
'model': 'mailing.contact',
'res_id': self.mailing_contact_1.id,
'bounced': datetime.datetime.now(),
'email': self.mailing_contact_1.email,
'message_id': '<123.004@iron.sky>',
})
base_parsed_values.update({
'bounced_email': tools.email_normalize(self.mailing_contact_1.email),
'bounced_msg_id': ['<123.004@iron.sky>']
})
# call bounced
self.env['mail.thread']._routing_handle_bounce(False, base_parsed_values)
# check blacklist
blacklist_record = mail_blacklist.search([('email', '=', self.mailing_contact_1.email)])
self.assertEqual(len(blacklist_record), 1,
'The email %s must be blacklisted' % self.mailing_contact_1.email)
@@ -1,51 +0,0 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.test_mail.tests import common
from odoo.tools import formataddr
class TestChannelPartnersNotification(common.TestMailCommon):
def _join_channel(self, channel, partners):
for partner in partners:
channel.write({'channel_last_seen_partner_ids': [(0, 0, {'partner_id': partner.id})]})
channel.invalidate_cache()
def test_channel_blacklisted_recipients(self):
""" Posting a message on a channel should send one email to all recipients, except the blacklisted ones """
self.test_channel = self.env['mail.channel'].create({
'name': 'Test',
'description': 'Description',
'alias_name': 'test',
'public': 'public',
})
self.test_partner = self.env['res.partner'].create({
'name': 'Test Partner',
'email': 'test@example.com',
})
self.blacklisted_partner = self.env['res.partner'].create({
'name': 'Blacklisted Partner',
'email': 'test@black.list',
})
# Set Blacklist
self.env['mail.blacklist'].create({
'email': 'test@black.list',
})
self.env['ir.config_parameter'].set_param('mail.catchall.domain', 'schlouby.fr')
self.test_channel.write({'email_send': True})
self._join_channel(self.test_channel, self.test_partner)
with self.mock_mail_gateway():
self.test_channel.message_post(body="Test", message_type='comment', subtype_xmlid='mail.mt_comment')
self.assertEqual(len(self._mails), 1, 'Number of mail incorrect. Should be equal to 1.')
for email in self._mails:
self.assertEqual(
set(email['email_to']),
set([formataddr((self.test_partner.name, self.test_partner.email))]),
'email_to incorrect. Should be equal to "%s"' % (
formataddr((self.test_partner.name, self.test_partner.email))))
@@ -1,313 +1,126 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from werkzeug import urls
from odoo.addons.test_mass_mailing.tests.common import TestMailCommon
from odoo.tests.common import TransactionCase, users
from odoo.addons.test_mass_mailing.tests.common import TestMassMailCommon
from odoo.tests.common import users
from odoo.tools import mute_logger
class TestMassMail(TestMailCommon):
class TestMassMailing(TestMassMailCommon):
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(TestMassMail, self).setUp()
values = [{
'name': 'Recipient %s' % x,
'email_from': 'Recipient <rec.%s@example.com>' % x,
} for x in range(0, 6)]
self.mm_recs = self.env['mass.mail.test.bl'].create(values)
@classmethod
def setUpClass(cls):
super(TestMassMailing, cls).setUpClass()
self.env['mail.blacklist'].create({
'email': 'rec.2@example.com'
@users('user_marketing')
@mute_logger('odoo.addons.mail.models.mail_mail')
def test_mailing_w_blacklist(self):
mailing = self.mailing_bl.with_user(self.env.user)
recipients = self._create_test_blacklist_records(count=5)
# blacklist records 3 and 4
self.env['mail.blacklist'].create({'email': recipients[3].email_normalized})
self.env['mail.blacklist'].create({'email': recipients[4].email_normalized})
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.mailing_bl.with_user(self.env.user)
recipients = self._create_test_blacklist_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.test_medium = self.env['utm.medium'].create({'name': 'TestMedium'})
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('marketing')
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
def test_link_tracker(self):
_url = 'https://www.example.com/foo/bar?baz=qux'
mailing = self.env['mailing.mailing'].create({
'name': 'TestMailing',
'subject': 'Test',
'medium_id': self.test_medium.id,
'body_html': '<p>Hello <a role="button" href="%s">${object.name}</a><a role="button" href="/unsubscribe_from_list">Unsubscribe</a></p>' % _url,
'reply_to_mode': 'email',
'mailing_model_id': self.ref('test_mass_mailing.model_mass_mail_test_bl'),
'mailing_domain': [('id', 'in', self.mm_recs.ids)],
})
mailing.action_send_mail()
# basic test emails are sent
self.assertEqual(mailing.sent, 5)
self.assertEqual(mailing.delivered, 5)
# link trackers
links = self.env['link.tracker'].sudo().search([('mass_mailing_id', '=', mailing.id)])
self.assertEqual(len(links), 1)
self.assertEqual(links.mapped('url'), [_url])
# check UTMS are correctly set on redirect URL
redirect_url = urls.url_parse(links.redirected_url)
redirect_params = redirect_url.decode_query().to_dict(flat=True)
self.assertEqual(redirect_url.scheme, 'https')
self.assertEqual(redirect_url.decode_netloc(), 'www.example.com')
self.assertEqual(redirect_url.path, '/foo/bar')
self.assertEqual(redirect_params, {
'utm_source': mailing.name,
'utm_medium': self.test_medium.name,
'baz': 'qux',
})
class TestAccessRights(TransactionCase):
def test_01_mass_mail_blacklist(self):
mass_mailing_contacts = self.env['mailing.contact']
mass_mailing = self.env['mailing.mailing']
mail_blacklist = self.env['mail.blacklist']
# create mailing contact record
self.mailing_contact_1 = mass_mailing_contacts.create({'name': 'test email 1', 'email': 'test1@email.com'})
self.mailing_contact_2 = mass_mailing_contacts.create({'name': 'test email 2', 'email': 'test2@email.com'})
self.mailing_contact_3 = mass_mailing_contacts.create({'name': 'test email 3', 'email': 'test3@email.com'})
self.mailing_contact_4 = mass_mailing_contacts.create({'name': 'test email 4', 'email': 'test4@email.com'})
self.mailing_contact_5 = mass_mailing_contacts.create({'name': 'test email 5', 'email': 'test5@email.com'})
# create blacklist record
mail_blacklist.create({'email': self.mailing_contact_3.email})
mail_blacklist.create({'email': self.mailing_contact_4.email})
# create mass mailing record
self.mass_mailing = mass_mailing.create({
'name': 'test',
'subject': 'Blacklisted',
'mailing_domain': [('id', 'in',
[self.mailing_contact_1.id, self.mailing_contact_2.id, self.mailing_contact_3.id,
self.mailing_contact_4.id, self.mailing_contact_5.id])],
'body_html': 'This is mass mail marketing demo'})
self.mass_mailing.action_put_in_queue()
res_ids = self.mass_mailing._get_remaining_recipients()
composer_values = {
'body': self.mass_mailing.convert_links()[self.mass_mailing.id],
'subject': self.mass_mailing.name,
'model': self.mass_mailing.mailing_model_real,
'email_from': self.mass_mailing.email_from,
'composition_mode': 'mass_mail',
'mass_mailing_id': self.mass_mailing.id,
'mailing_list_ids': [(4, l.id) for l in self.mass_mailing.contact_list_ids],
}
composer = self.env['mail.compose.message'].with_context(active_ids=res_ids,
mass_mailing_seen_list=self.mass_mailing._get_seen_list()).create(
composer_values)
composer.send_mail()
self.assertEqual(self.mass_mailing.ignored, 2,
'blacklist ignored email number incorrect, should be equals to 2')
def test_02_mass_mail_simple_opt_out(self):
mass_mailing_contacts = self.env['mailing.contact']
mass_mailing_lists = self.env['mailing.list']
mass_mailing_optout = self.env['mailing.contact.subscription']
mass_mailing = self.env['mailing.mailing']
# create mailing contact record
mailing_contact_1 = mass_mailing_contacts.create({'name': 'test email 1', 'email': 'test1@email.com'})
mailing_contact_2 = mass_mailing_contacts.create({'name': 'test email 2', 'email': 'test2@email.com'})
@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 = mass_mailing_lists.create({
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_2.id),
(4, mailing_contact_3.id),
(4, mailing_contact_5.id),
]
})
# Set Opt out
mass_mailing_optout.search([('contact_id', '=', mailing_contact_1.id), ('list_id', '=', mailing_list_1.id)]).write({
'opt_out': True,
})
# create mass mailing record
self.mass_mailing = mass_mailing.create({
'name': 'One',
'subject': 'One',
'mailing_model_id': self.env['ir.model']._get('mailing.contact').id,
'body_html': 'This is mass mail marketing demo'})
self.mass_mailing.contact_list_ids = [mailing_list_1.id]
self.mass_mailing.action_put_in_queue()
composer_values = {
'body': self.mass_mailing.convert_links()[self.mass_mailing.id],
'subject': self.mass_mailing.name,
'model': self.mass_mailing.mailing_model_real,
'email_from': self.mass_mailing.email_from,
'composition_mode': 'mass_mail',
'mass_mailing_id': self.mass_mailing.id,
'mailing_list_ids': [(4, l.id) for l in self.mass_mailing.contact_list_ids],
}
composer = self.env['mail.compose.message'].with_context(
active_ids=[mailing_contact_1.id, mailing_contact_2.id],
mass_mailing_seen_list=self.mass_mailing._get_seen_list(),
mass_mailing_opt_out_list=self.mass_mailing._get_opt_out_list()).create(composer_values)
composer.send_mail()
self.assertEqual(self.mass_mailing.ignored, 1,
'Opt Out ignored email number incorrect, should be equals to 1')
def test_03_mass_mail_multi_opt_out(self):
mass_mailing_contacts = self.env['mailing.contact']
mass_mailing_lists = self.env['mailing.list']
mass_mailing_optout = self.env['mailing.contact.subscription']
mass_mailing = self.env['mailing.mailing']
# create mailing contact record
mailing_contact_1 = mass_mailing_contacts.create({'name': 'test email 1', 'email': 'test1@email.com'})
mailing_contact_2 = mass_mailing_contacts.create({'name': 'test email 2', 'email': 'test2@email.com'})
# create mailing list record
mailing_list_1 = mass_mailing_lists.create({
'name': 'A',
'contact_ids': [
(4, mailing_contact_1.id),
(4, mailing_contact_2.id)
]
})
mailing_list_2 = mass_mailing_lists.create({
mailing_list_2 = self.env['mailing.list'].create({
'name': 'B',
'contact_ids': [
(4, mailing_contact_1.id),
(4, mailing_contact_2.id)
(4, mailing_contact_3.id),
(4, mailing_contact_4.id),
]
})
# Set Opt out
mass_mailing_optout.search([('contact_id', '=', mailing_contact_1.id), ('list_id', '=', mailing_list_1.id)]).write({
'opt_out': True,
})
# 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
self.mass_mailing = mass_mailing.create({
'name': 'One',
'subject': 'One',
'mailing_model_id': self.env['ir.model']._get('mailing.contact').id,
'body_html': 'This is mass mail marketing demo'})
self.mass_mailing.contact_list_ids = [mailing_list_1.id, mailing_list_2.id]
self.mass_mailing.action_put_in_queue()
composer_values = {
'body': self.mass_mailing.convert_links()[self.mass_mailing.id],
'subject': self.mass_mailing.name,
'model': self.mass_mailing.mailing_model_real,
'email_from': self.mass_mailing.email_from,
'composition_mode': 'mass_mail',
'mass_mailing_id': self.mass_mailing.id,
'mailing_list_ids': [(4, l.id) for l in self.mass_mailing.contact_list_ids],
}
composer = self.env['mail.compose.message'].with_context(
active_ids=[mailing_contact_1.id, mailing_contact_2.id],
mass_mailing_seen_list=self.mass_mailing._get_seen_list(),
mass_mailing_opt_out_list=self.mass_mailing._get_opt_out_list()).create(composer_values)
composer.send_mail()
# if user is opt_out on One list but not on another, send the mail anyway
self.assertEqual(self.mass_mailing.ignored, 0,
'Opt Out ignored email number incorrect, should be equals to 0')
def test_04_mass_mail_multi_users_different_opt_out(self):
mass_mailing_contacts = self.env['mailing.contact']
mass_mailing_lists = self.env['mailing.list']
mass_mailing_optout = self.env['mailing.contact.subscription']
mass_mailing = self.env['mailing.mailing']
# create mailing contact record
mailing_contact_1 = mass_mailing_contacts.create({'name': 'test email (A)', 'email': 'test@email.com'})
mailing_contact_2 = mass_mailing_contacts.create({'name': 'test email (B)', 'email': 'test@email.com'})
# create mailing list record
mailing_list_1 = mass_mailing_lists.create({
'name': 'A',
'contact_ids': [
(4, mailing_contact_1.id),
(4, mailing_contact_2.id)
]
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()
# Set Opt out
mass_mailing_optout.search([('contact_id', '=', mailing_contact_1.id), ('list_id', '=', mailing_list_1.id)]).write({
'opt_out': True,
})
# create mass mailing record
self.mass_mailing = mass_mailing.create({
'name': 'One',
'subject': 'One',
'mailing_model_id': self.env['ir.model']._get('mailing.contact').id,
'body_html': 'This is mass mail marketing demo'})
self.mass_mailing.contact_list_ids = [mailing_list_1.id]
self.mass_mailing.action_put_in_queue()
composer_values = {
'body': self.mass_mailing.convert_links()[self.mass_mailing.id],
'subject': self.mass_mailing.name,
'model': self.mass_mailing.mailing_model_real,
'email_from': self.mass_mailing.email_from,
'composition_mode': 'mass_mail',
'mass_mailing_id': self.mass_mailing.id,
'mailing_list_ids': [(4, l.id) for l in self.mass_mailing.contact_list_ids],
}
composer = self.env['mail.compose.message'].with_context(
active_ids=[mailing_contact_1.id, mailing_contact_2.id],
mass_mailing_seen_list=self.mass_mailing._get_seen_list(),
mass_mailing_opt_out_list=self.mass_mailing._get_opt_out_list()).create(composer_values)
composer.send_mail()
# if user A is opt_out on One list but user B is not opt_out on same list,
# send the mail anyway to the opt-in contact. Ignore (as normal behaviour) opted-out contact.
self.assertEqual(self.mass_mailing.ignored, 1,
'Opt Out ignored email number incorrect, should be equals to 1')
class TestOnResPartner(TransactionCase):
def test_mass_mail_on_res_partner(self):
partners = self.env['res.partner']
mass_mailing = self.env['mailing.mailing']
# create mailing contact record
partner_a = partners.create({
'name': 'test email 1',
'email': 'test1@email.com',
})
partner_b = partners.create({
'name': 'test email 2',
'email': 'test2@email.com',
})
# Set Blacklist
self.blacklist_contact_entry = self.env['mail.blacklist'].create({
'email': 'Test2@email.com',
})
# create mass mailing record
self.mass_mailing = mass_mailing.create({
'name': 'One',
'subject': 'One',
'mailing_domain': [('id', 'in', [partner_a.id, partner_b.id])],
'body_html': 'This is mass mail marketing demo'})
self.mass_mailing.mailing_model_real = 'res.partner'
self.mass_mailing.action_put_in_queue()
res_ids = self.mass_mailing._get_remaining_recipients()
composer_values = {
'body': self.mass_mailing.convert_links()[self.mass_mailing.id],
'subject': self.mass_mailing.name,
'model': self.mass_mailing.mailing_model_real,
'email_from': self.mass_mailing.email_from,
'composition_mode': 'mass_mail',
'mass_mailing_id': self.mass_mailing.id,
'mailing_list_ids': [(4, l.id) for l in self.mass_mailing.contact_list_ids],
}
composer = self.env['mail.compose.message'].with_context(
active_ids=res_ids,
mass_mailing_seen_list=self.mass_mailing._get_seen_list()).create(composer_values)
composer.send_mail()
# if user is opt_out on One list but not on another, send the mail anyway
self.assertEqual(self.mass_mailing.ignored, 1,
'Blacklisted ignored email number incorrect, should be equals to 1')
self.assertMailTraces(
[{'email': 'test@test.example.com', 'state': 'ignored'},
{'email': 'test@test.example.com', 'state': 'sent'},
{'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)
@@ -35,7 +35,7 @@ class TestMassMailPerformance(TestMassMailPerformanceBase):
'name': 'Recipient %s' % x,
'email_from': 'Recipient <rec.%s@example.com>' % x,
} for x in range(0, 50)]
self.mm_recs = self.env['mass.mail.test'].create(values)
self.mm_recs = self.env['mailing.performance'].create(values)
@users('__system__', 'marketing')
@warmup
@@ -46,7 +46,7 @@ class TestMassMailPerformance(TestMassMailPerformanceBase):
'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_mass_mail_test'),
'mailing_model_id': self.ref('test_mass_mailing.model_mailing_performance'),
'mailing_domain': [('id', 'in', self.mm_recs.ids)],
})
@@ -69,13 +69,13 @@ class TestMassMailBlPerformance(TestMassMailPerformanceBase):
'name': 'Recipient %s' % x,
'email_from': 'Recipient <rec.%s@example.com>' % x,
} for x in range(0, 62)]
self.mm_recs = self.env['mass.mail.test.bl'].create(values)
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['mass.mail.test.bl'].flush()
self.env['mailing.performance.blacklist'].flush()
@users('__system__', 'marketing')
@warmup
@@ -86,7 +86,7 @@ class TestMassMailBlPerformance(TestMassMailPerformanceBase):
'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_mass_mail_test_bl'),
'mailing_model_id': self.ref('test_mass_mailing.model_mailing_performance_blacklist'),
'mailing_domain': [('id', 'in', self.mm_recs.ids)],
})