[REF] mail: add 'force_send' field on composer to control email queue usage
Currently when using the composer to create a mass mailing emails are sent
directly, unless scheduled date is in the future.
With this commit it is now controllable through a field like what has been
done on SMS composer. Its default behavior is the same as before
* posting on a monorecord: force send notification emails;
* posting on multirecords: use the queue (force_send=False parameter given
to message_post and propagated to _notify_thread);
* mass mailing: use force send to send emails directly;
Usage of mail_notify_force_send context key is also removed when possible
as it is a standard parameter of posting API.
Task-3132710 (Mail: Configurable composer)
Part-of: odoo/odoo#99482
This commit is contained in:
@@ -183,7 +183,6 @@ class AlarmManager(models.AbstractModel):
|
||||
for alarm in alarms:
|
||||
alarm_attendees = attendees.filtered(lambda attendee: attendee.event_id.id in events_by_alarm[alarm.id])
|
||||
alarm_attendees.with_context(
|
||||
mail_notify_force_send=True,
|
||||
calendar_template_ignore_recurrence=True
|
||||
)._send_mail_to_attendees(
|
||||
alarm.mail_template_id,
|
||||
|
||||
@@ -104,6 +104,12 @@ class MailComposer(models.TransientModel):
|
||||
# comment mode by default removes emails
|
||||
if 'auto_delete' in fields_list and 'auto_delete' not in result and result.get('composition_mode') == 'comment':
|
||||
result['auto_delete'] = True
|
||||
# batch post mode by default use queues for notifications
|
||||
if 'force_send' in fields_list and 'force_send' not in result:
|
||||
result['force_send'] = (
|
||||
result.get('composition_mode') != 'comment' or
|
||||
len(self._parse_res_ids(result.get('res_ids') or [])) <= 1
|
||||
)
|
||||
|
||||
return {
|
||||
fname: result[fname]
|
||||
@@ -181,6 +187,8 @@ class MailComposer(models.TransientModel):
|
||||
auto_delete_keep_log = fields.Boolean(
|
||||
'Keep Message Copy', default=True,
|
||||
help='Keep a copy of the email content if emails are removed (mass mailing only)')
|
||||
force_send = fields.Boolean(
|
||||
'Send mailing or notifications directly')
|
||||
mail_server_id = fields.Many2one('ir.mail_server', 'Outgoing mail server')
|
||||
scheduled_date = fields.Char(
|
||||
'Scheduled Date',
|
||||
@@ -463,10 +471,8 @@ class MailComposer(models.TransientModel):
|
||||
post_values_all = self._prepare_mail_values(res_ids)
|
||||
ActiveModel = self.env[self.model] if self.model and hasattr(self.env[self.model], 'message_post') else self.env['mail.thread']
|
||||
if self.composition_batch:
|
||||
# do not send emails directly but use the queue instead
|
||||
# add context key to avoid subscribing the author
|
||||
ActiveModel = ActiveModel.with_context(
|
||||
mail_notify_force_send=False,
|
||||
mail_create_nosubscribe=True,
|
||||
)
|
||||
|
||||
@@ -510,6 +516,8 @@ class MailComposer(models.TransientModel):
|
||||
|
||||
# as 'send' does not filter out scheduled mails (only 'process_email_queue'
|
||||
# does) we need to do it manually
|
||||
if not self.force_send:
|
||||
continue
|
||||
iter_mails_sudo_tosend = iter_mails_sudo.filtered(
|
||||
lambda mail: (
|
||||
not mail.scheduled_date or
|
||||
@@ -563,6 +571,7 @@ class MailComposer(models.TransientModel):
|
||||
MAIL
|
||||
STA - 'auto_delete',
|
||||
DYN - 'body_html',
|
||||
STA - 'force_send', (notify parameter)
|
||||
STA - 'model',
|
||||
DYN - 'recipient_ids', (from partner_ids)
|
||||
DYN - 'res_id',
|
||||
@@ -667,6 +676,7 @@ class MailComposer(models.TransientModel):
|
||||
values.update(
|
||||
email_add_signature=not bool(self.template_id) and self.email_add_signature,
|
||||
email_layout_xmlid=self.email_layout_xmlid,
|
||||
force_send=self.force_send,
|
||||
mail_auto_delete=self.auto_delete,
|
||||
model_description=model_description,
|
||||
)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<field name="composition_batch" invisible="1"/>
|
||||
<field name="composition_mode" invisible="1"/>
|
||||
<field name="email_layout_xmlid" invisible="1"/>
|
||||
<field name="force_send" invisible="1"/>
|
||||
<field name="lang" invisible="1"/>
|
||||
<field name="mail_server_id" invisible="1"/>
|
||||
<field name="model" invisible="1"/>
|
||||
|
||||
@@ -184,6 +184,7 @@ class RatingMixin(models.AbstractModel):
|
||||
self.with_context(mail_notify_force_send=force_send).message_post_with_source(
|
||||
template,
|
||||
email_layout_xmlid='mail.mail_notification_light',
|
||||
force_send=force_send,
|
||||
subtype_xmlid='mail.mt_note',
|
||||
)
|
||||
|
||||
|
||||
@@ -134,6 +134,7 @@ class TestComposerForm(TestMailComposer):
|
||||
self.assertFalse(composer_form.composition_batch)
|
||||
self.assertEqual(composer_form.composition_mode, 'comment')
|
||||
self.assertEqual(composer_form.email_from, self.env.user.email_formatted)
|
||||
self.assertTrue(composer_form.force_send, 'MailComposer: single record post send notifications right away')
|
||||
self.assertFalse(composer_form.mail_server_id)
|
||||
self.assertEqual(composer_form.model, self.test_record._name)
|
||||
self.assertFalse(composer_form.partner_ids)
|
||||
@@ -207,10 +208,11 @@ class TestComposerForm(TestMailComposer):
|
||||
self.assertTrue(composer_form.auto_delete, 'Should take template value')
|
||||
self.assertTrue(composer_form.auto_delete_keep_log)
|
||||
self.assertEqual(composer_form.author_id, self.env.user.partner_id)
|
||||
self.assertEqual(composer_form.body, '<p>TemplateBody %s</p>' % self.test_record.name)
|
||||
self.assertEqual(composer_form.body, f'<p>TemplateBody {self.test_record.name}</p>')
|
||||
self.assertFalse(composer_form.composition_batch)
|
||||
self.assertEqual(composer_form.composition_mode, 'comment')
|
||||
self.assertEqual(composer_form.email_from, self.user_employee_2.email_formatted)
|
||||
self.assertTrue(composer_form.force_send, 'MailComposer: single record post send notifications right away')
|
||||
self.assertEqual(composer_form.mail_server_id, self.mail_server_domain)
|
||||
self.assertEqual(composer_form.model, self.test_record._name)
|
||||
self.assertEqual(composer_form.partner_ids[:], self.partner_1)
|
||||
@@ -219,7 +221,7 @@ class TestComposerForm(TestMailComposer):
|
||||
self.assertFalse(composer_form.reply_to_force_new)
|
||||
self.assertEqual(literal_eval(composer_form.res_ids), self.test_record.ids)
|
||||
self.assertEqual(composer_form.scheduled_date, FieldDatetime.to_string(self.reference_now + timedelta(days=2)))
|
||||
self.assertEqual(composer_form.subject, 'TemplateSubject %s' % self.test_record.name)
|
||||
self.assertEqual(composer_form.subject, f'TemplateSubject {self.test_record.name}')
|
||||
self.assertEqual(composer_form.subtype_id, self.env.ref('mail.mt_comment'))
|
||||
self.assertFalse(composer_form.subtype_is_log)
|
||||
|
||||
@@ -242,6 +244,7 @@ class TestComposerForm(TestMailComposer):
|
||||
self.assertEqual(composer_form.composition_mode, 'comment')
|
||||
self.assertEqual(composer_form.email_from, self.template.email_from,
|
||||
'MailComposer: comment in batch mode should have template raw email_from if template')
|
||||
self.assertFalse(composer_form.force_send, 'MailComposer: batch record post use email queue for notifications')
|
||||
self.assertEqual(composer_form.mail_server_id, self.mail_server_domain)
|
||||
self.assertEqual(composer_form.model, self.test_record._name)
|
||||
self.assertFalse(composer_form.record_name, 'MailComposer: comment in batch mode should have void record name')
|
||||
@@ -270,6 +273,7 @@ class TestComposerForm(TestMailComposer):
|
||||
self.assertFalse(composer_form.composition_batch)
|
||||
self.assertEqual(composer_form.composition_mode, 'comment')
|
||||
self.assertEqual(composer_form.email_from, self.env.user.partner_id.email_formatted)
|
||||
self.assertTrue(composer_form.force_send)
|
||||
self.assertEqual(composer_form.mail_server_id, self.mail_server_domain)
|
||||
self.assertEqual(composer_form.model, self.test_record._name)
|
||||
self.assertFalse(composer_form.partner_ids[:])
|
||||
@@ -296,6 +300,7 @@ class TestComposerForm(TestMailComposer):
|
||||
self.assertTrue(composer_form.composition_batch)
|
||||
self.assertEqual(composer_form.composition_mode, 'mass_mail')
|
||||
self.assertEqual(composer_form.email_from, self.env.user.email_formatted)
|
||||
self.assertTrue(composer_form.force_send, 'MailComposer: mass mode sends emails right away')
|
||||
self.assertFalse(composer_form.mail_server_id)
|
||||
self.assertEqual(composer_form.model, self.test_records._name)
|
||||
self.assertFalse(composer_form.record_name, 'MailComposer: mass mode should have void record name')
|
||||
@@ -321,6 +326,7 @@ class TestComposerForm(TestMailComposer):
|
||||
self.assertEqual(composer_form.composition_mode, 'mass_mail')
|
||||
self.assertEqual(composer_form.email_from, self.template.email_from,
|
||||
'MailComposer: mass mode should have template raw email_from if template')
|
||||
self.assertTrue(composer_form.force_send, 'MailComposer: mass mode sends emails right away')
|
||||
self.assertEqual(composer_form.mail_server_id, self.mail_server_domain)
|
||||
self.assertEqual(composer_form.model, self.test_records._name)
|
||||
self.assertFalse(composer_form.record_name, 'MailComposer: mass mode should have void record name')
|
||||
@@ -351,6 +357,7 @@ class TestComposerForm(TestMailComposer):
|
||||
self.assertEqual(composer_form.composition_mode, 'mass_mail')
|
||||
self.assertEqual(composer_form.email_from, self.template.email_from,
|
||||
'MailComposer: mass mode should have template raw email_from if template')
|
||||
self.assertTrue(composer_form.force_send, 'MailComposer: mass mode sends emails right away')
|
||||
self.assertEqual(composer_form.mail_server_id, self.mail_server_domain)
|
||||
self.assertEqual(composer_form.model, self.test_records._name)
|
||||
self.assertFalse(composer_form.record_name, 'MailComposer: mass mode should have void record name')
|
||||
@@ -1347,9 +1354,16 @@ class TestComposerResultsComment(TestMailComposer, CronMixinCase):
|
||||
# and 5 emails, and 1 inbox notification (admin)
|
||||
self.assertEqual(len(self._new_mails), 2 * len(test_records),
|
||||
'Should have created 1 mail.mail per group per record')
|
||||
self.assertEqual(self._new_mails.mapped('state'), ['sent'] * len(self._new_mails))
|
||||
self.assertEqual(len(self._mails), 5 * len(test_records),
|
||||
'Should have sent 5 emails, one per recipient per record')
|
||||
if not batch:
|
||||
self.assertEqual(self._new_mails.mapped('state'), ['sent'] * len(self._new_mails))
|
||||
self.assertEqual(len(self._mails), 5,
|
||||
'Should have sent 5 emails, one per recipient per record')
|
||||
else:
|
||||
self.assertEqual(self._new_mails.mapped('state'), ['outgoing'] * len(self._new_mails))
|
||||
self.assertEqual(len(self._mails), 0,
|
||||
'Should have kept force_send False parameter, and not sent any email')
|
||||
# simulate cron sending emails
|
||||
self.env['mail.mail'].sudo().process_email_queue()
|
||||
|
||||
# template is sent only to partners (email_to are transformed)
|
||||
for test_record in test_records:
|
||||
|
||||
Reference in New Issue
Block a user