mirror of
https://gitlab.com/flectra-hq/flectra.git
synced 2025-02-25 18:55:21 -06:00
[PATCH] Upstream patch - 27072023
This commit is contained in:
@@ -271,6 +271,7 @@ class Channel(models.Model):
|
||||
all_emp_group = None
|
||||
if all_emp_group and all_emp_group in self and not self._context.get(MODULE_UNINSTALL_FLAG):
|
||||
raise UserError(_('You cannot delete those groups, as the Whole Company group is required by other modules.'))
|
||||
self.env['bus.bus'].sendmany([[(self._cr.dbname, 'mail.channel', channel.id), {'info': 'delete'}] for channel in self])
|
||||
return super(Channel, self).unlink()
|
||||
|
||||
def write(self, vals):
|
||||
|
||||
@@ -120,6 +120,8 @@ function factory(dependencies) {
|
||||
last_message_id,
|
||||
partner_id,
|
||||
});
|
||||
case 'delete':
|
||||
return this._handleNotificationChannelDelete(channelId);
|
||||
case 'typing_status':
|
||||
return this._handleNotificationChannelTypingStatus(channelId, data);
|
||||
default:
|
||||
@@ -127,6 +129,24 @@ function factory(dependencies) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {integer} channelId
|
||||
* @param {Object} param1
|
||||
* @param {integer} param1.partner_id
|
||||
* @param {string} param1.partner_name
|
||||
*/
|
||||
async _handleNotificationChannelDelete(channelId) {
|
||||
const channel = this.env.models['mail.thread'].findFromIdentifyingData({
|
||||
id: channelId,
|
||||
model: 'mail.channel',
|
||||
});
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
channel.delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {integer} channelId
|
||||
|
||||
@@ -161,16 +161,16 @@ function factory(dependencies) {
|
||||
* @private
|
||||
*/
|
||||
_onThreadCacheChanged() {
|
||||
// clear obsolete hints
|
||||
this.update({ componentHintList: clear() });
|
||||
this.addComponentHint('change-of-thread-cache');
|
||||
if (this.threadCache) {
|
||||
// clear obsolete hints
|
||||
this.update({ componentHintList: clear() });
|
||||
this.addComponentHint('change-of-thread-cache');
|
||||
this.threadCache.update({
|
||||
isCacheRefreshRequested: true,
|
||||
isMarkAllAsReadRequested: true,
|
||||
});
|
||||
this.update({ lastVisibleMessage: [['unlink']] });
|
||||
}
|
||||
this.update({ lastVisibleMessage: [['unlink']] });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,7 +194,9 @@ function factory(dependencies) {
|
||||
return;
|
||||
}
|
||||
this.env.browser.clearTimeout(this._loaderTimeout);
|
||||
this.update({ isLoading: false, isPreparingLoading: false });
|
||||
if (this.thread) {
|
||||
this.update({ isLoading: false, isPreparingLoading: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -257,7 +257,13 @@ class MockEmail(common.BaseCase):
|
||||
if mail.id == mail_id:
|
||||
break
|
||||
else:
|
||||
raise AssertionError('mail.mail not found for ID %s' % (mail_id))
|
||||
debug_info = '\n'.join(
|
||||
f'From: {mail.author_id} ({mail.email_from}) - ID {mail.id} (State: {mail.state})'
|
||||
for mail in filtered
|
||||
)
|
||||
raise AssertionError(
|
||||
f'mail.mail not found for ID {mail_id} / message {mail_message} / status {status} / author {author}\n{debug_info}'
|
||||
)
|
||||
return mail
|
||||
|
||||
def _find_mail_mail_wpartners(self, recipients, status, mail_message=None, author=None):
|
||||
@@ -275,7 +281,14 @@ class MockEmail(common.BaseCase):
|
||||
if all(p in mail.recipient_ids for p in recipients):
|
||||
break
|
||||
else:
|
||||
raise AssertionError('mail.mail not found for message %s / status %s / recipients %s / author %s' % (mail_message, status, recipients.ids, author))
|
||||
debug_info = '\n'.join(
|
||||
f'From: {mail.author_id} ({mail.email_from}) - To: {sorted(mail.recipient_ids.ids)} (State: {mail.state})'
|
||||
for mail in filtered
|
||||
)
|
||||
recipients_info = f'Missing: {[r.name for r in recipients if r.id not in filtered.recipient_ids.ids]}'
|
||||
raise AssertionError(
|
||||
f'mail.mail not found for message {mail_message} / status {status} / recipients {sorted(recipients.ids)} / author {author}\n{recipients_info}\n{debug_info}'
|
||||
)
|
||||
return mail
|
||||
|
||||
def _find_mail_mail_wemail(self, email_to, status, mail_message=None, author=None):
|
||||
@@ -293,7 +306,13 @@ class MockEmail(common.BaseCase):
|
||||
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 / status %s in %s' % (email_to, status, repr([m.email_to for m in self._new_mails])))
|
||||
debug_info = '\n'.join(
|
||||
f'From: {mail.author_id} ({mail.email_from}) - To: {mail.email_to} / {sorted(mail.recipient_ids.mapped("email"))} (State: {mail.state})'
|
||||
for mail in filtered
|
||||
)
|
||||
raise AssertionError(
|
||||
f'mail.mail not found for message {mail_message} / status {status} / email_to {email_to} / author {author}\n{debug_info}'
|
||||
)
|
||||
return mail
|
||||
|
||||
def _find_mail_mail_wrecord(self, record, status=None, mail_message=None, author=None):
|
||||
@@ -306,25 +325,52 @@ class MockEmail(common.BaseCase):
|
||||
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])))
|
||||
debug_info = '\n'.join(
|
||||
f'From: {mail.author_id} ({mail.email_from}) - Model{mail.model} / ResId {mail.res_id} (State: {mail.state})'
|
||||
for mail in filtered
|
||||
)
|
||||
raise AssertionError(
|
||||
f'mail.mail not found for message {mail_message} / status {status} / record {record.model}, {record.id} / author {author}\n{debug_info}'
|
||||
)
|
||||
return mail
|
||||
|
||||
def _find_sent_email(self, email_from, emails_to, subject=None):
|
||||
""" Find an outgoing email based on from / to and optional subject when
|
||||
having a conflict.
|
||||
|
||||
:return sent_email: an outgoing email generated during the mock;
|
||||
"""
|
||||
sent_emails = [
|
||||
mail for mail in self._mails
|
||||
if set(mail['email_to']) == set(emails_to) and mail['email_from'] == email_from
|
||||
]
|
||||
if len(sent_emails) > 1 and subject:
|
||||
# try to better filter
|
||||
sent_email = next((mail for mail in sent_emails if mail['subject'] == subject), False)
|
||||
else:
|
||||
sent_email = sent_emails[0] if sent_emails else False
|
||||
return sent_email
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# GATEWAY ASSERTS
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def assertMailMail(self, recipients, status,
|
||||
check_mail_mail=True, mail_message=None, author=None,
|
||||
content=None, fields_values=None, email_values=None):
|
||||
""" Assert mail.mail records are created and maybe sent as emails. Allow
|
||||
def _assertMailMail(self, mail, recipients_list, status,
|
||||
email_to_recipients=None, author=None,
|
||||
content=None, fields_values=None, email_values=None):
|
||||
""" Assert mail.mail record values and maybe related emails. Allow
|
||||
asserting their content. Records to check are the one generated when
|
||||
using mock (mail.mail and outgoing emails). This method takes partners
|
||||
as source of record fetch and assert.
|
||||
using mock (mail.mail and outgoing emails).
|
||||
|
||||
:param recipients: a ``res.partner`` recordset. See ``_find_mail_mail_wpartners``;
|
||||
:param mail: a ``mail.mail`` record;
|
||||
:param recipients_list: an ``res.partner`` recordset or a list of
|
||||
emails (both are supported, see ``_find_mail_mail_wpartners`` and
|
||||
``_find_mail_mail_wemail``);
|
||||
:param status: mail.mail state used to filter mails. If ``sent`` this method
|
||||
also check that emails have been sent trough gateway;
|
||||
:param mail_message: see ``_find_mail_mail_wpartners``;
|
||||
:param email_to_recipients: used for assertSentEmail to find email based
|
||||
on 'email_to' when doing the match directly based on recipients_list
|
||||
being partners it nos easy (e.g. multi emails, ...);
|
||||
:param author: see ``_find_mail_mail_wpartners``;
|
||||
:param content: if given, check it is contained within mail html body;
|
||||
:param fields_values: if given, should be a dictionary of field names /
|
||||
@@ -336,54 +382,104 @@ class MockEmail(common.BaseCase):
|
||||
|
||||
:param check_mail_mail: deprecated, use ``assertSentEmail`` if False
|
||||
"""
|
||||
self.assertTrue(bool(mail))
|
||||
if content:
|
||||
self.assertIn(content, mail.body_html)
|
||||
for fname, fvalue in (fields_values or {}).items():
|
||||
with self.subTest(fname=fname, fvalue=fvalue):
|
||||
self.assertEqual(
|
||||
mail[fname], fvalue,
|
||||
'Mail: expected %s for %s, got %s' % (fvalue, fname, mail[fname])
|
||||
)
|
||||
if status == 'sent':
|
||||
if email_to_recipients:
|
||||
recipients = email_to_recipients # already formatted
|
||||
else:
|
||||
recipients = [[r] for r in recipients_list] # one partner -> list of a single email
|
||||
for recipient in recipients:
|
||||
with self.subTest(recipient=recipient):
|
||||
self.assertSentEmail(
|
||||
email_values['email_from'] if email_values and email_values.get('email_from') else author,
|
||||
recipient,
|
||||
**(email_values or {})
|
||||
)
|
||||
|
||||
def assertMailMail(self, recipients, status,
|
||||
email_to_recipients=None,
|
||||
check_mail_mail=True, mail_message=None, author=None,
|
||||
content=None, fields_values=None, email_values=None):
|
||||
""" Assert mail.mail records are created and maybe sent as emails. This
|
||||
method takes partners as source to find mails and check their content.
|
||||
See '_assertMailMail' for more details.
|
||||
|
||||
:param recipients: a ``res.partner`` recordset. See
|
||||
``_find_mail_mail_wpartners``;
|
||||
:param mail_message: used to find the related email;
|
||||
|
||||
See '_assertMailMail' for more details about other parameters.
|
||||
"""
|
||||
found_mail = self._find_mail_mail_wpartners(recipients, status, mail_message=mail_message, author=author)
|
||||
self.assertTrue(bool(found_mail))
|
||||
if content:
|
||||
self.assertIn(content, found_mail.body_html)
|
||||
for fname, fvalue in (fields_values or {}).items():
|
||||
self.assertEqual(
|
||||
found_mail[fname], fvalue,
|
||||
'Mail: expected %s for %s, got %s' % (fvalue, fname, found_mail[fname]))
|
||||
if status == 'sent':
|
||||
for recipient in recipients:
|
||||
self.assertSentEmail(email_values['email_from'] if email_values and email_values.get('email_from') else author, [recipient], **(email_values or {}))
|
||||
self._assertMailMail(
|
||||
found_mail, recipients, status,
|
||||
email_to_recipients=email_to_recipients,
|
||||
author=author, content=content,
|
||||
fields_values=fields_values, email_values=email_values,
|
||||
)
|
||||
return found_mail
|
||||
|
||||
def assertMailMailWEmails(self, emails, status,
|
||||
email_to_recipients=None,
|
||||
mail_message=None, author=None,
|
||||
content=None, fields_values=None, email_values=None):
|
||||
""" Assert mail.mail records are created and maybe sent as emails. Allow
|
||||
asserting their content. Records to check are the one generated when
|
||||
using mock (mail.mail and outgoing emails). This method takes emails
|
||||
as source of record fetch and assert.
|
||||
""" Assert mail.mail records are created and maybe sent as emails. This
|
||||
method takes emails as source to find mails and check their content.
|
||||
See '_assertMailMail' for more details.
|
||||
|
||||
:param emails: a list of emails. See ``_find_mail_mail_wemail``;
|
||||
:param status: mail.mail state used to filter mails. If ``sent`` this method
|
||||
also check that emails have been sent trough gateway;
|
||||
:param mail_message: see ``_find_mail_mail_wemail``;
|
||||
:param author: see ``_find_mail_mail_wemail``;;
|
||||
:param content: if given, check it is contained within mail html body;
|
||||
:param fields_values: if given, should be a dictionary of field names /
|
||||
values allowing to check ``mail.mail`` additional values (subject,
|
||||
reply_to, ...);
|
||||
:param email_values: if given, should be a dictionary of keys / values
|
||||
allowing to check sent email additional values (if any).
|
||||
See ``assertSentEmail``;
|
||||
:param mail_message: used to find the related email;
|
||||
|
||||
:param check_mail_mail: deprecated, use ``assertSentEmail`` if False
|
||||
See '_assertMailMail' for more details about other parameters.
|
||||
"""
|
||||
found_mail = False
|
||||
for email_to in emails:
|
||||
found_mail = self._find_mail_mail_wemail(email_to, status, mail_message=mail_message, author=author)
|
||||
if content:
|
||||
self.assertIn(content, found_mail.body_html)
|
||||
for fname, fvalue in (fields_values or {}).items():
|
||||
self.assertEqual(
|
||||
found_mail[fname], fvalue,
|
||||
'Mail: expected %s for %s, got %s' % (fvalue, fname, found_mail[fname]))
|
||||
if status == 'sent':
|
||||
for email_to in emails:
|
||||
self.assertSentEmail(email_values['email_from'] if email_values and email_values.get('email_from') else author, [email_to], **(email_values or {}))
|
||||
self.assertTrue(bool(found_mail))
|
||||
self._assertMailMail(
|
||||
found_mail, [email_to], status,
|
||||
email_to_recipients=email_to_recipients,
|
||||
author=author, content=content,
|
||||
fields_values=fields_values, email_values=email_values,
|
||||
)
|
||||
return found_mail
|
||||
|
||||
def assertMailMailWRecord(self, record, recipients, status,
|
||||
email_to_recipients=None,
|
||||
mail_message=None, author=None,
|
||||
content=None, fields_values=None, email_values=None):
|
||||
""" Assert mail.mail records are created and maybe sent as emails. This
|
||||
method takes a record as source to find mails and check their content
|
||||
using model / res_id. See '_assertMailMail' for more details.
|
||||
|
||||
:param record: a record used to find emails sent related on it.
|
||||
See ``_find_mail_mail_wrecord``;
|
||||
:param mail_message: used to find the related email;
|
||||
|
||||
See '_assertMailMail' for more details about other parameters.
|
||||
"""
|
||||
found_mail = self._find_mail_mail_wrecord(record, mail_message=mail_message, author=author)
|
||||
self.assertTrue(bool(found_mail))
|
||||
self._assertMailMail(
|
||||
found_mail, recipients, status,
|
||||
email_to_recipients=email_to_recipients,
|
||||
author=author, content=content,
|
||||
fields_values=fields_values, email_values=email_values,
|
||||
)
|
||||
return found_mail
|
||||
|
||||
def assertMailMailWId(self, mail_id, status,
|
||||
email_to_recipients=None,
|
||||
author=None,
|
||||
content=None, fields_values=None):
|
||||
""" Assert mail.mail records are created and maybe sent as emails. Allow
|
||||
asserting their content. Records to check are the one generated when
|
||||
@@ -391,22 +487,19 @@ class MockEmail(common.BaseCase):
|
||||
as source of record fetch and assert.
|
||||
|
||||
:param mail_id: a ``mail.mail`` DB ID. See ``_find_mail_mail_wid``;
|
||||
:param status: mail.mail state to check upon found mail;
|
||||
:param content: if given, check it is contained within mail html body;
|
||||
:param fields_values: if given, should be a dictionary of field names /
|
||||
values allowing to check ``mail.mail`` additional values (subject,
|
||||
reply_to, ...);
|
||||
|
||||
For other parameters, see ``_assertMailMail``.
|
||||
"""
|
||||
found_mail = self._find_mail_mail_wid(mail_id)
|
||||
self.assertTrue(bool(found_mail))
|
||||
if status:
|
||||
self.assertEqual(found_mail.state, status)
|
||||
if content:
|
||||
self.assertIn(content, found_mail.body_html)
|
||||
for fname, fvalue in (fields_values or {}).items():
|
||||
self.assertEqual(
|
||||
found_mail[fname], fvalue,
|
||||
'Mail: expected %s for %s, got %s' % (fvalue, fname, found_mail[fname]))
|
||||
self._assertMailMail(
|
||||
found_mail, [], # generally used when recipients are Falsy
|
||||
status,
|
||||
email_to_recipients=email_to_recipients,
|
||||
author=author, content=content,
|
||||
fields_values=fields_values,
|
||||
)
|
||||
return found_mail
|
||||
|
||||
def assertNoMail(self, recipients, mail_message=None, author=None):
|
||||
""" Check no mail.mail and email was generated during gateway mock. """
|
||||
@@ -455,7 +548,7 @@ class MockEmail(common.BaseCase):
|
||||
"""
|
||||
direct_check = ['attachments', 'body_alternative', 'email_from', 'references', 'reply_to', 'subject']
|
||||
content_check = ['body_alternative_content', 'body_content', 'references_content']
|
||||
other_check = ['body', 'attachments_info']
|
||||
other_check = ['body', 'attachments_info', 'email_to']
|
||||
|
||||
expected = {}
|
||||
for fname in direct_check + content_check + other_check:
|
||||
@@ -470,20 +563,30 @@ class MockEmail(common.BaseCase):
|
||||
else:
|
||||
expected['email_from'] = author
|
||||
|
||||
email_to_list = []
|
||||
for email_to in recipients:
|
||||
if isinstance(email_to, self.env['res.partner'].__class__):
|
||||
email_to_list.append(formataddr((email_to.name, email_to.email)))
|
||||
else:
|
||||
email_to_list.append(email_to)
|
||||
if 'email_to' in values:
|
||||
email_to_list = values['email_to']
|
||||
else:
|
||||
email_to_list = []
|
||||
for email_to in recipients:
|
||||
if isinstance(email_to, self.env['res.partner'].__class__):
|
||||
email_to_list.append(formataddr((email_to.name, email_to.email or 'False')))
|
||||
else:
|
||||
email_to_list.append(email_to)
|
||||
expected['email_to'] = email_to_list
|
||||
|
||||
sent_mail = next(
|
||||
(mail for mail in self._mails
|
||||
if set(mail['email_to']) == set(expected['email_to']) and mail['email_from'] == expected['email_from']
|
||||
), False)
|
||||
debug_info = '-'.join('From: %s-To: %s' % (mail['email_from'], mail['email_to']) for mail in self._mails) if not bool(sent_mail) else ''
|
||||
self.assertTrue(bool(sent_mail), 'Expected mail from %s to %s not found in %s' % (expected['email_from'], expected['email_to'], debug_info))
|
||||
# fetch mail
|
||||
sent_mail = self._find_sent_email(
|
||||
expected['email_from'],
|
||||
expected['email_to'],
|
||||
values.get('subject'),
|
||||
)
|
||||
debug_info = ''
|
||||
if not sent_mail:
|
||||
debug_info = '-'.join('From: %s-To: %s' % (mail['email_from'], mail['email_to']) for mail in self._mails)
|
||||
self.assertTrue(
|
||||
bool(sent_mail),
|
||||
'Expected mail from %s to %s not found in %s' % (expected['email_from'], expected['email_to'], debug_info)
|
||||
)
|
||||
|
||||
for val in direct_check:
|
||||
if val in expected:
|
||||
@@ -491,7 +594,11 @@ class MockEmail(common.BaseCase):
|
||||
if 'attachments_info' in expected:
|
||||
attachments = sent_mail['attachments']
|
||||
for attachment_info in expected['attachments_info']:
|
||||
attachment = next(attach for attach in attachments if attach[0] == attachment_info['name'])
|
||||
attachment = next((attach for attach in attachments if attach[0] == attachment_info['name']), False)
|
||||
self.assertTrue(
|
||||
bool(attachment),
|
||||
f'Attachment {attachment_info["name"]} not found in attachments',
|
||||
)
|
||||
if attachment_info.get('raw'):
|
||||
self.assertEqual(attachment[1], attachment_info['raw'])
|
||||
if attachment_info.get('type'):
|
||||
@@ -503,6 +610,8 @@ class MockEmail(common.BaseCase):
|
||||
if val in expected:
|
||||
self.assertIn(expected[val], sent_mail[val[:-8]], 'Value for %s: %s does not contain %s' % (val, sent_mail[val[:-8]], expected[val]))
|
||||
|
||||
return sent_mail
|
||||
|
||||
|
||||
class MailCase(MockEmail):
|
||||
""" Tools, helpers and asserts for mail-related tests, including mail
|
||||
@@ -803,9 +912,10 @@ class MailCase(MockEmail):
|
||||
if not self.mail_unlink_sent:
|
||||
self.assertMailMail(
|
||||
partners, mail_status,
|
||||
author=message.author_id if message.author_id else message.email_from,
|
||||
author=message_info.get('fields_values', {}).get('author_id') or message.author_id or message.email_from,
|
||||
mail_message=message,
|
||||
email_values=email_values,
|
||||
fields_values=message_info.get('fields_values'),
|
||||
)
|
||||
else:
|
||||
for recipient in partners:
|
||||
|
||||
@@ -32,8 +32,8 @@ class MassMailCase(MailCase, MockLinkTracker):
|
||||
)
|
||||
|
||||
def assertMailTraces(self, recipients_info, mailing, records,
|
||||
check_mail=True, sent_unlink=False, author=None,
|
||||
mail_links_info=None):
|
||||
check_mail=True, sent_unlink=False,
|
||||
author=None, mail_links_info=None):
|
||||
""" Check content of traces. Traces are fetched based on a given mailing
|
||||
and records. Their content is compared to recipients_info structure that
|
||||
holds expected information. Links content may be checked, notably to
|
||||
@@ -48,6 +48,7 @@ class MassMailCase(MailCase, MockLinkTracker):
|
||||
'record: linked record,
|
||||
# MAIL.MAIL
|
||||
'content': optional content that should be present in mail.mail body_html;
|
||||
'email_to_recipients': optional, see '_assertMailMail';
|
||||
'failure_type': optional failure reason;
|
||||
}, { ... }]
|
||||
|
||||
@@ -79,6 +80,12 @@ class MassMailCase(MailCase, MockLinkTracker):
|
||||
('mass_mailing_id', 'in', mailing.ids),
|
||||
('res_id', 'in', records.ids)
|
||||
])
|
||||
debug_info = '\n'.join(
|
||||
(
|
||||
f'Trace: to {t.email} - state {t.state}'
|
||||
for t in traces
|
||||
)
|
||||
)
|
||||
|
||||
# ensure trace coherency
|
||||
self.assertTrue(all(s.model == records._name for s in traces))
|
||||
@@ -90,6 +97,7 @@ class MassMailCase(MailCase, MockLinkTracker):
|
||||
for recipient_info, link_info, record in zip(recipients_info, mail_links_info, records):
|
||||
partner = recipient_info.get('partner', self.env['res.partner'])
|
||||
email = recipient_info.get('email')
|
||||
email_to_recipients = recipient_info.get('email_to_recipients')
|
||||
state = recipient_info.get('state', 'sent')
|
||||
record = record or recipient_info.get('record')
|
||||
content = recipient_info.get('content')
|
||||
@@ -97,33 +105,57 @@ class MassMailCase(MailCase, MockLinkTracker):
|
||||
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)
|
||||
lambda t: (t.email == email or (not email and not t.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))
|
||||
'MailTrace: email %s (recipient %s, state: %s, record: %s): found %s records (1 expected)\n%s' % (
|
||||
email, partner, state, record,
|
||||
len(recipient_trace), debug_info)
|
||||
)
|
||||
self.assertTrue(bool(recipient_trace.mail_mail_id_int))
|
||||
if 'failure_type' in recipient_info or state in ('ignored', 'exception', 'canceled', 'bounced'):
|
||||
self.assertEqual(recipient_trace.failure_type, recipient_info['failure_type'])
|
||||
|
||||
if check_mail:
|
||||
if author is None:
|
||||
author = self.env.user.partner_id
|
||||
|
||||
fields_values = {'mailing_id': mailing}
|
||||
if 'failure_type' in recipient_info:
|
||||
fields_values['failure_type'] = recipient_info['failure_type']
|
||||
if 'failure_reason' in recipient_info:
|
||||
fields_values['failure_reason'] = recipient_info['failure_reason']
|
||||
|
||||
# specific for partner: email_formatted is used
|
||||
if partner:
|
||||
if state == 'sent' and sent_unlink:
|
||||
self.assertSentEmail(author, [partner])
|
||||
else:
|
||||
self.assertMailMail(partner, state_mapping[state], author=author, content=content, fields_values=fields_values)
|
||||
self.assertMailMail(
|
||||
partner, state_mapping[state],
|
||||
author=author,
|
||||
content=content,
|
||||
email_to_recipients=email_to_recipients,
|
||||
fields_values=fields_values,
|
||||
)
|
||||
# specific if email is False -> could have troubles finding it if several falsy traces
|
||||
elif not email and state in ('ignored', 'canceled', 'bounced'):
|
||||
self.assertMailMailWId(recipient_trace.mail_mail_id_int, state_mapping[state], content=content, fields_values=fields_values)
|
||||
self.assertMailMailWId(
|
||||
recipient_trace.mail_mail_id_int, state_mapping[state],
|
||||
author=author,
|
||||
content=content,
|
||||
email_to_recipients=email_to_recipients,
|
||||
fields_values=fields_values,
|
||||
)
|
||||
else:
|
||||
self.assertMailMailWEmails([email], state_mapping[state], author=author, content=content, fields_values=fields_values)
|
||||
self.assertMailMailWEmails(
|
||||
[email], state_mapping[state],
|
||||
author=author,
|
||||
content=content,
|
||||
email_to_recipients=email_to_recipients,
|
||||
fields_values=fields_values,
|
||||
)
|
||||
|
||||
if link_info:
|
||||
trace_mail = self._find_mail_mail_wrecord(record)
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
from ast import literal_eval
|
||||
|
||||
from flectra.addons.mass_mailing.tests.common import MassMailCommon
|
||||
from flectra.tests.common import users, Form
|
||||
from flectra.tests.common import users, Form, tagged
|
||||
from flectra.tools import formataddr, mute_logger
|
||||
|
||||
|
||||
@tagged('mass_mailing')
|
||||
class TestMassMailValues(MassMailCommon):
|
||||
|
||||
@classmethod
|
||||
@@ -122,6 +124,7 @@ class TestMassMailValues(MassMailCommon):
|
||||
self.assertEqual(mailing_form.mailing_model_real, 'res.partner')
|
||||
|
||||
|
||||
@tagged('mass_mailing')
|
||||
class TestMassMailFeatures(MassMailCommon):
|
||||
|
||||
@classmethod
|
||||
@@ -274,7 +277,7 @@ class TestMassMailFeatures(MassMailCommon):
|
||||
|
||||
self.assertMailTraces(
|
||||
[{'partner': partner_a},
|
||||
{'partner': partner_b, 'state': 'ignored'}],
|
||||
{'partner': partner_b, 'state': 'ignored', 'failure_type': False}],
|
||||
mailing, partner_a + partner_b, check_mail=True
|
||||
)
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ class PhoneBlackList(models.Model):
|
||||
|
||||
def phone_action_blacklist_remove(self):
|
||||
return {
|
||||
'name': 'Are you sure you want to unblacklist this Phone Number?',
|
||||
'name': _('Are you sure you want to unblacklist this Phone Number?'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'phone.blacklist.remove',
|
||||
|
||||
@@ -695,21 +695,10 @@ class TestComposerResultsMass(TestMailComposer):
|
||||
self.assertEqual(len(self._new_mails), 2, 'Should have created 1 mail.mail per record')
|
||||
self.assertEqual(len(self._mails), 10, 'Should have sent 5 emails per record')
|
||||
|
||||
# hack to use assertEmails: filtering on from/to only is not sufficient to distinguish emails
|
||||
_mails_records = [
|
||||
[mail for mail in self._mails if '%s-%s' % (record.id, record._name) in mail['message_id']]
|
||||
for record in self.test_records
|
||||
]
|
||||
|
||||
for record, _mails in zip(self.test_records, _mails_records):
|
||||
# message copy is kept
|
||||
message = record.message_ids[0]
|
||||
|
||||
for record in self.test_records:
|
||||
# template is sent only to partners (email_to are transformed)
|
||||
self._mails = _mails
|
||||
self.assertMailMail(record.customer_id + new_partners + self.partner_admin,
|
||||
'sent',
|
||||
mail_message=message,
|
||||
author=self.partner_employee,
|
||||
email_values={
|
||||
'attachments_info': [
|
||||
@@ -732,6 +721,7 @@ class TestComposerResultsMass(TestMailComposer):
|
||||
f'{self.alias_catchall}@{self.alias_domain}'
|
||||
)),
|
||||
},
|
||||
mail_message=record.message_ids[0], # message copy is kept
|
||||
)
|
||||
|
||||
# test without catchall filling reply-to
|
||||
@@ -745,15 +735,8 @@ class TestComposerResultsMass(TestMailComposer):
|
||||
self.env['ir.config_parameter'].sudo().set_param("mail.catchall.domain", None)
|
||||
composer.send_mail()
|
||||
|
||||
# hack to use assertEmails: filtering on from/to only is not sufficient to distinguish emails
|
||||
_mails_records = [
|
||||
[mail for mail in self._mails if '%s-%s' % (record.id, record._name) in mail['message_id']]
|
||||
for record in self.test_records
|
||||
]
|
||||
|
||||
for record, _mails in zip(self.test_records, _mails_records):
|
||||
for record in self.test_records:
|
||||
# template is sent only to partners (email_to are transformed)
|
||||
self._mails = _mails
|
||||
self.assertMailMail(record.customer_id + new_partners + self.partner_admin,
|
||||
'sent',
|
||||
mail_message=record.message_ids[0],
|
||||
|
||||
@@ -51,18 +51,23 @@ class TestMassMailing(TestMailFullCommon):
|
||||
'content': 'Hello %s' % recipient.name}
|
||||
# opt-out: ignored (cancel mail)
|
||||
if recipient in recipients[1] | recipients[2]:
|
||||
recipient_info['failure_type'] = False
|
||||
recipient_info['state'] = 'ignored'
|
||||
# blacklisted: ignored (cancel mail)
|
||||
elif recipient in recipients[3] | recipients[4]:
|
||||
recipient_info['failure_type'] = False
|
||||
recipient_info['state'] = 'ignored'
|
||||
# duplicates: ignored (cancel mail)
|
||||
elif recipient == recipient_dup_1:
|
||||
recipient_info['failure_type'] = False
|
||||
recipient_info['state'] = 'ignored'
|
||||
# void: ignored (cancel mail)
|
||||
elif recipient == recipient_void_1:
|
||||
recipient_info['failure_type'] = False
|
||||
recipient_info['state'] = 'ignored'
|
||||
# falsy: ignored (cancel mail)
|
||||
elif recipient == recipient_falsy_1:
|
||||
recipient_info['failure_type'] = False
|
||||
recipient_info['state'] = 'ignored'
|
||||
recipient_info['email'] = recipient.email_from # normalized is False but email should be falsymail
|
||||
else:
|
||||
|
||||
@@ -78,6 +78,6 @@ class TestAutoBlacklist(common.TestMassMailCommon):
|
||||
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'}],
|
||||
[{'email': 'test.record.00@test.example.com', 'state': 'ignored', 'failure_type': False}],
|
||||
new_mailing, target, check_mail=True
|
||||
)
|
||||
|
||||
@@ -245,8 +245,8 @@ class TestMassMailing(TestMassMailCommon):
|
||||
[{'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'}],
|
||||
{'email': 'test.record.03@test.example.com', 'state': 'ignored', 'failure_type': False},
|
||||
{'email': 'test.record.04@test.example.com', 'state': 'ignored', 'failure_type': False}],
|
||||
mailing, recipients, check_mail=True
|
||||
)
|
||||
self.assertEqual(mailing.ignored, 2)
|
||||
@@ -271,11 +271,11 @@ class TestMassMailing(TestMassMailCommon):
|
||||
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.00@test.example.com', 'state': 'ignored', 'failure_type': False},
|
||||
{'email': 'test.record.01@test.example.com', 'state': 'ignored', 'failure_type': False},
|
||||
{'email': 'test.record.02@test.example.com'},
|
||||
{'email': 'test.record.03@test.example.com'},
|
||||
{'email': 'test.record.04@test.example.com', 'state': 'ignored'}],
|
||||
{'email': 'test.record.04@test.example.com', 'state': 'ignored', 'failure_type': False}],
|
||||
mailing, recipients, check_mail=True
|
||||
)
|
||||
self.assertEqual(mailing.ignored, 3)
|
||||
@@ -369,10 +369,10 @@ class TestMassMailing(TestMassMailCommon):
|
||||
|
||||
self.assertMailTraces(
|
||||
[{'email': 'test@test.example.com', 'state': 'sent'},
|
||||
{'email': 'test@test.example.com', 'state': 'ignored'},
|
||||
{'email': 'test@test.example.com', 'state': 'ignored', 'failure_type': False},
|
||||
{'email': 'test3@test.example.com'},
|
||||
{'email': 'test4@test.example.com'},
|
||||
{'email': 'test5@test.example.com', 'state': 'ignored'}],
|
||||
{'email': 'test5@test.example.com', 'state': 'ignored', 'failure_type': False}],
|
||||
mailing,
|
||||
mailing_contact_1 + mailing_contact_2 + mailing_contact_3 + mailing_contact_4 + mailing_contact_5,
|
||||
check_mail=True
|
||||
|
||||
Reference in New Issue
Block a user