Files
odoo_source/addons/test_mail/tests/test_mail_resend.py
T
XavierDo 133eeb1bbf [ADD] mail, mass_mailing: allow a user to resend a mail with failures
When a mail is in failure state, a red envelope appears next to the message
in a thread but it was difficult to send the mail again.
This tasks will allow users to send mail again easily, or mark notification
as cancelled if the user want to ignore this failure.
A notification will appear in sender systray while mail are in failure.

Task: #46158
PR: #24628
2018-06-07 11:46:28 +02:00

142 lines
7.6 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import itertools
from unittest.mock import patch
from odoo.addons.test_mail.tests import common
from odoo.tests import tagged
from odoo.tools import mute_logger
from odoo import api
from odoo.addons.base.models.ir_mail_server import IrMailServer
@tagged('resend_test')
class TestMailResend(common.BaseFunctionalTest, common.MockEmails):
@classmethod
def setUpClass(cls):
super(TestMailResend, cls).setUpClass()
#Two users
cls.user1 = cls.env['res.users'].with_context(cls._quick_create_user_ctx).create({
'name': 'Employee 1',
'login': 'e1',
'email': 'e1', # invalid email
'notification_type': 'email',
'groups_id': [(6, 0, [cls.env.ref('base.group_user').id])]
})
cls.user2 = cls.env['res.users'].with_context(cls._quick_create_user_ctx).create({
'name': 'Employee 2',
'login': 'e2',
'email': 'e2@example.com',
'notification_type': 'email',
'groups_id': [(6, 0, [cls.env.ref('base.group_user').id])]
})
#Two partner
cls.partner1 = cls.env['res.partner'].with_context(cls._quick_create_user_ctx).create({
'name': 'Partner 1',
'email': 'p1' # invalid email
})
cls.partner2 = cls.env['res.partner'].with_context(cls._quick_create_user_ctx).create({
'name': 'Partner 2',
'email': 'p2@example.com'
})
@api.model
def send_email(self, message, *args, **kwargs):
assert '@' in message['To'], self.NO_VALID_RECIPIENT
return message['Message-Id']
cls.bus_update_failure = []
def sendone(self, channel, message):
if 'type' in message and message['type'] == 'mail_failure':
cls.bus_update_failure.append((channel, message))
cls.env['ir.mail_server']._patch_method('send_email', send_email)
cls.env['bus.bus']._patch_method('sendone', sendone)
cls.partners = cls.env['res.partner'].concat(cls.user1.partner_id, cls.user2.partner_id, cls.partner1, cls.partner2)
cls.invalid_email_partners = cls.env['res.partner'].concat(cls.user1.partner_id, cls.partner1)
def setUp(self):
super(TestMailResend, self).setUp()
TestMailResend.bus_update_failure = []
def assertNotifStates(self, states, message):
notif = self.env['mail.notification'].search([('mail_message_id', '=', message.id)], order="res_partner_id asc")
self.assertEquals(tuple(notif.mapped('email_status')), states)
return notif
def assertBusMessage(self, partners):
partner_ids = [elem[0][2] for elem in self.bus_update_failure]
self.assertEquals(partner_ids, [partner.id for partner in partners])
self.bus_update_failure.clear()
@classmethod
def tearDownClass(cls):
# Remove mocks
cls.env['ir.mail_server']._revert_method('send_email')
cls.env['bus.bus']._revert_method('sendone')
super(TestMailResend, cls).tearDownClass()
def assertEmails(self, *args, **kwargs):
res = super(TestMailResend, self).assertEmails(*args, **kwargs)
self._mails.clear()
@mute_logger('odoo.addons.mail.models.mail_mail')
def test_mail_resend_workflow(self):
cls = TestMailResend
#missconfigured server
@api.model
def connect_failure(**kwargs):
raise Exception
with patch.object(IrMailServer, 'connect', side_effect=connect_failure):
message = self.test_record.sudo().message_post(partner_ids=self.partners.ids, subtype='mail.mt_comment', message_type='notification')
self.assertBusMessage([self.partner_admin])
self.assertEmails(self.partner_admin, [])
self.assertNotifStates(('exception', 'exception', 'exception', 'exception'), message)
wizard = self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({})
self.assertEqual(wizard.notification_ids.mapped('res_partner_id'), self.partners, "wizard should manage notifications for each failed partner")
wizard.resend_mail_action()
self.assertBusMessage([self.partner_admin] * 3) # three more failure sent on bus, one for each mail in failure and one for resend
self.assertEmails(self.partner_admin, self.partners)
self.assertNotifStates(('exception', 'sent', 'exception', 'sent'), message)
self.user1.write({"email": 'u1@example.com'})
self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({}).resend_mail_action()
self.assertBusMessage([self.partner_admin] * 2) # two more failure update sent on bus, one for failed mail and one for resend
self.assertEmails(self.partner_admin, self.invalid_email_partners)
self.assertNotifStates(('sent', 'sent', 'exception', 'sent'), message)
self.partner1.write({"email": 'p1@example.com'})
self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({}).resend_mail_action()
self.assertBusMessage([self.partner_admin]) # A success update should be sent on bus once the email has no more failure
self.assertEmails(self.partner_admin, self.partner1)
self.assertNotifStates(('sent', 'sent', 'sent', 'sent'), message)
@mute_logger('odoo.addons.mail.models.mail_mail')
def test_mail_send_no_failure(self):
self.user1.write({"email": 'u1@example.com'})
self.partner1.write({"email": 'p1@example.com'})
message = self.test_record.sudo().message_post(partner_ids=self.partners.ids, subtype='mail.mt_comment', message_type='notification')
self.assertBusMessage([]) # one update for cancell
@mute_logger('odoo.addons.mail.models.mail_mail')
def test_remove_mail_become_canceled(self):
message = self.test_record.sudo().message_post(partner_ids=self.partners.ids, subtype='mail.mt_comment', message_type='notification')
self.assertEmails(self.partner_admin, self.partners)
self.assertBusMessage([self.partner_admin] * 2) # two failure sent on bus, one for each mail
wizard = self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({})
partners = wizard.partner_ids.mapped("partner_id")
self.assertEqual(self.invalid_email_partners, partners)
wizard.partner_ids.filtered(lambda p: p.partner_id == self.partner1).write({"resend": False})
wizard.resend_mail_action()
self.assertEmails(self.partner_admin, self.user1)
self.assertBusMessage([self.partner_admin] * 2) # two more failure sent on bus, one for failure, one for resend
self.assertNotifStates(('exception', 'sent', 'canceled', 'sent'), message)
@mute_logger('odoo.addons.mail.models.mail_mail')
def test_cancel_all(self):
message = self.test_record.sudo().message_post(partner_ids=self.partners.ids, subtype='mail.mt_comment', message_type='notification')
self.assertNotifStates(('exception', 'sent', 'exception', 'sent'), message)
self.assertBusMessage([self.partner_admin] * 2)
wizard = self.env['mail.resend.message'].with_context({'mail_message_to_resend': message.id}).create({})
wizard.cancel_mail_action()
self.assertNotifStates(('canceled', 'sent', 'canceled', 'sent'), message)
self.assertBusMessage([self.partner_admin]) # one update for cancell