summaryrefslogtreecommitdiff
path: root/addons/mail/tests
diff options
context:
space:
mode:
authorThibault Delavallée <tde@odoo.com>2017-11-21 13:34:51 +0100
committerThibault Delavallée <tde@odoo.com>2017-11-29 10:11:15 +0100
commitd040bfde89fca1c702e6e95c3b808e0b48c2267a (patch)
tree78f4d11e9d1194c878f89be61a4a4b8140b7e5da /addons/mail/tests
parent7a136d6acc3467504e7d6deed7482395e4d55bd8 (diff)
[MOV] (test_)mail: move tests into their dedicated module
Purpose: avoid having useless tables for test models in a production environment.
Diffstat (limited to 'addons/mail/tests')
-rw-r--r--addons/mail/tests/__init__.py15
-rw-r--r--addons/mail/tests/common.py222
-rw-r--r--addons/mail/tests/data/__init__.py3
-rw-r--r--addons/mail/tests/data/test_mail_data.py280
-rw-r--r--addons/mail/tests/models/__init__.py3
-rw-r--r--addons/mail/tests/models/test_mail_models.py97
-rw-r--r--addons/mail/tests/test_discuss.py153
-rw-r--r--addons/mail/tests/test_invite.py29
-rw-r--r--addons/mail/tests/test_ir_actions.py36
-rw-r--r--addons/mail/tests/test_mail_activity.py67
-rw-r--r--addons/mail/tests/test_mail_channel.py197
-rw-r--r--addons/mail/tests/test_mail_followers.py199
-rw-r--r--addons/mail/tests/test_mail_gateway.py512
-rw-r--r--addons/mail/tests/test_mail_mail.py45
-rw-r--r--addons/mail/tests/test_mail_message.py276
-rw-r--r--addons/mail/tests/test_mail_template.py203
-rw-r--r--addons/mail/tests/test_message_compose.py355
-rw-r--r--addons/mail/tests/test_message_track.py137
-rw-r--r--addons/mail/tests/test_update_notification.py11
19 files changed, 0 insertions, 2840 deletions
diff --git a/addons/mail/tests/__init__.py b/addons/mail/tests/__init__.py
deleted file mode 100644
index bf46d383f92..00000000000
--- a/addons/mail/tests/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from . import test_mail_activity
-from . import test_mail_followers
-from . import test_mail_message
-from . import test_mail_mail
-from . import test_mail_channel
-from . import test_mail_gateway
-from . import test_mail_template
-from . import test_message_compose
-from . import test_message_track
-from . import test_invite
-from . import test_ir_actions
-from . import test_update_notification
-from . import test_discuss
diff --git a/addons/mail/tests/common.py b/addons/mail/tests/common.py
deleted file mode 100644
index 5ff9f42954d..00000000000
--- a/addons/mail/tests/common.py
+++ /dev/null
@@ -1,222 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from contextlib import contextmanager
-from email.utils import formataddr
-
-from odoo import api
-from odoo.tests import common
-
-
-class BaseFunctionalTest(common.SavepointCase):
-
- @classmethod
- def setUpClass(cls):
- super(BaseFunctionalTest, cls).setUpClass()
- cls._quick_create_ctx = {
- 'mail_create_nolog': True,
- 'mail_create_nosubscribe': True,
- 'mail_notrack': True,
- }
- cls._quick_create_user_ctx = dict(cls._quick_create_ctx, no_reset_password=True)
-
- user_group_employee = cls.env.ref('base.group_user')
- cls.user_employee = cls.env['res.users'].with_context(cls._quick_create_user_ctx).create({
- 'name': 'Ernest Employee',
- 'login': 'ernest',
- 'email': 'e.e@example.com',
- 'signature': '--\nErnest',
- 'notification_type': 'email',
- 'groups_id': [(6, 0, [user_group_employee.id])]})
- cls.partner_employee = cls.user_employee.partner_id
- cls.user_admin = cls.env.user
- cls.partner_admin = cls.user_admin.partner_id
-
- cls.channel_listen = cls.env['mail.channel'].with_context(cls._quick_create_ctx).create({'name': 'Listener'})
-
- cls.test_record = cls.env['mail.test.simple'].with_context(cls._quick_create_ctx).create({'name': 'Test', 'email_from': 'ignasse@example.com'})
-
- @contextmanager
- def assertNotifications(self, **counters):
- """ Counters: 'partner_attribute': 'inbox' or 'email' """
- try:
- init_messages = self.test_record.message_ids
- init = {}
- partners = self.env['res.partner']
- for partner_attribute in counters.keys():
- partner = getattr(self, partner_attribute)
- partners |= partner
- if partner.user_ids:
- init[partner] = {
- 'na_counter': self.test_record.sudo(partner.user_ids[0]).message_needaction_counter,
- }
- yield
- finally:
- new_messages = self.test_record.sudo().message_ids - init_messages
- new_notifications = self.env['mail.notification'].search([
- ('res_partner_id', 'in', partners.ids),
- ('mail_message_id', 'in', new_messages.ids)
- ])
-
- for partner_attribute in counters.keys():
- counter, notif_type, notif_read = counters[partner_attribute]
- partner = getattr(self, partner_attribute)
- partner_notif = new_notifications.filtered(lambda n: n.res_partner_id == partner)
-
- self.assertEqual(len(partner_notif), counter)
-
- if partner.user_ids:
- expected = init[partner]['na_counter'] + counter if notif_read == 'unread' else init[partner]['na_counter']
- self.assertEqual(expected, self.test_record.sudo(partner.user_ids[0]).message_needaction_counter,
- 'Invalid number of notification for %s: %s instead of %s' %
- (partner.name, expected, self.test_record.sudo(partner.user_ids[0]).message_needaction_counter))
- if partner_notif:
- self.assertTrue(all(n.is_email == (notif_type == 'email') for n in partner_notif))
- self.assertTrue(all(n.is_read == (notif_read == 'read') for n in partner_notif),
- 'Invalid read status for %s' % partner.name)
-
- # for simplification, limitate to single message asserts
- if hasattr(self, 'assertEmails') and len(new_messages) == 1:
- self.assertEmails(new_messages.author_id, new_notifications.filtered(lambda n: n.is_email).mapped('res_partner_id'))
-
- @contextmanager
- def sudoAs(self, login):
- old_uid = self.uid
- try:
- user = self.env['res.users'].sudo().search([('login', '=', login)])
- self.test_record_old = self.test_record
- # switch user
- self.uid = user.id
- self.env = self.env(user=self.uid)
- self.test_record = self.test_record.sudo(self.uid)
- yield
- finally:
- # back
- self.uid = old_uid
- self.env = self.env(user=self.uid)
- self.test_record = self.test_record_old
-
-
-class TestRecipients(common.SavepointCase):
-
- @classmethod
- def setUpClass(cls):
- super(TestRecipients, cls).setUpClass()
- Partner = cls.env['res.partner'].with_context({
- 'mail_create_nolog': True,
- 'mail_create_nosubscribe': True,
- 'mail_notrack': True,
- 'no_reset_password': True,
- })
- cls.partner_1 = Partner.create({
- 'name': 'Valid Lelitre',
- 'email': 'valid.lelitre@agrolait.com'})
- cls.partner_2 = Partner.create({
- 'name': 'Valid Poilvache',
- 'email': 'valid.other@gmail.com'})
-
-
-class MockEmails(common.SingleTransactionCase):
-
- def setUp(self):
- super(MockEmails, self).setUp()
- self._mails_args[:] = []
- self._mails[:] = []
-
- @classmethod
- def setUpClass(cls):
- super(MockEmails, cls).setUpClass()
- cls._mails_args = []
- cls._mails = []
-
- def build_email(self, *args, **kwargs):
- cls._mails_args.append(args)
- cls._mails.append(kwargs)
- return build_email.origin(self, *args, **kwargs)
-
- @api.model
- def send_email(self, message, *args, **kwargs):
- return message['Message-Id']
-
- cls.env['ir.mail_server']._patch_method('build_email', build_email)
- cls.env['ir.mail_server']._patch_method('send_email', send_email)
-
- def assertEmails(self, partner_from, recipients, **values):
- """ Tools method to ease the check of send emails """
- expected_email_values = []
- for partners in recipients:
- expected = {
- 'email_from': formataddr((partner_from.name, partner_from.email)),
- 'email_to': [formataddr((partner.name, partner.email)) for partner in partners]
- }
- if 'reply_to' in values:
- expected['reply_to'] = values['reply_to']
- if 'subject' in values:
- expected['subject'] = values['subject']
- if 'attachments' in values:
- expected['attachments'] = values['attachments']
- if 'body' in values:
- expected['body'] = values['body']
- if 'body_content' in values:
- expected['body_content'] = values['body_content']
- if 'body_alt_content' in values:
- expected['body_alternative_content'] = values['body_alt_content']
- if 'references' in values:
- expected['references'] = values['references']
- if 'ref_content' in values:
- expected['references_content'] = values['ref_content']
- expected_email_values.append(expected)
-
- self.assertEqual(len(self._mails), len(expected_email_values))
- for expected in expected_email_values:
- sent_mail = next((mail for mail in self._mails if set(mail['email_to']) == set(expected['email_to'])), False)
- self.assertTrue(bool(sent_mail), 'Expected mail to %s not found' % expected['email_to'])
- for val in ['email_from', 'reply_to', 'subject', 'body', 'references', 'attachments']:
- if val in expected:
- self.assertEqual(expected[val], sent_mail[val], 'Value for %s: expected %s, received %s' % (val, expected[val], sent_mail[val]))
- for val in ['body_content', 'body_alternative', 'references_content']:
- 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]))
-
- def assertHtmlEqual(self, value, expected, message=None):
- from lxml import html
-
- tree = html.fragment_fromstring(value, parser=html.HTMLParser(encoding='utf-8'), create_parent='body')
-
- # mass mailing: add base tag we have to remove
- for base_node in tree.xpath('//base'):
- base_node.getparent().remove(base_node)
-
- # chatter: read more / read less TODO
-
- # mass mailing: add base tag we have to remove
- expected_node = html.fragment_fromstring(expected, create_parent='body')
-
- if message:
- self.assertEqual(tree, expected_node, message)
- else:
- self.assertEqual(tree, expected_node)
-
- @classmethod
- def tearDownClass(cls):
- # Remove mocks
- cls.env['ir.mail_server']._revert_method('build_email')
- cls.env['ir.mail_server']._revert_method('send_email')
- super(MockEmails, cls).tearDownClass()
-
- def _init_mock_build_email(self):
- self._mails_args[:] = []
- self._mails[:] = []
-
- def format(self, template, to='groups@example.com, other@gmail.com', subject='Frogs',
- extra='', email_from='Sylvie Lelitre <test.sylvie.lelitre@agrolait.com>',
- cc='', msg_id='<1198923581.41972151344608186760.JavaMail@agrolait.com>'):
- return template.format(to=to, subject=subject, cc=cc, extra=extra, email_from=email_from, msg_id=msg_id)
-
- def format_and_process(self, template, to='groups@example.com, other@gmail.com', subject='Frogs',
- extra='', email_from='Sylvie Lelitre <test.sylvie.lelitre@agrolait.com>',
- cc='', msg_id='<1198923581.41972151344608186760.JavaMail@agrolait.com>',
- model=None, target_model='mail.test.simple', target_field='name'):
- self.assertFalse(self.env[target_model].search([(target_field, '=', subject)]))
- mail = self.format(template, to=to, subject=subject, cc=cc, extra=extra, email_from=email_from, msg_id=msg_id)
- self.env['mail.thread'].with_context(mail_channel_noautofollow=True).message_process(model, mail)
- return self.env[target_model].search([(target_field, '=', subject)])
diff --git a/addons/mail/tests/data/__init__.py b/addons/mail/tests/data/__init__.py
deleted file mode 100644
index 3c2bb4e3324..00000000000
--- a/addons/mail/tests/data/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from . import test_mail_data
diff --git a/addons/mail/tests/data/test_mail_data.py b/addons/mail/tests/data/test_mail_data.py
deleted file mode 100644
index e516964dc3d..00000000000
--- a/addons/mail/tests/data/test_mail_data.py
+++ /dev/null
@@ -1,280 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-MAIL_TEMPLATE = """Return-Path: <whatever-2a840@postmaster.twitter.com>
-To: {to}
-cc: {cc}
-Received: by mail1.openerp.com (Postfix, from userid 10002)
- id 5DF9ABFB2A; Fri, 10 Aug 2012 16:16:39 +0200 (CEST)
-From: {email_from}
-Subject: {subject}
-MIME-Version: 1.0
-Content-Type: multipart/alternative;
- boundary="----=_Part_4200734_24778174.1344608186754"
-Date: Fri, 10 Aug 2012 14:16:26 +0000
-Message-ID: {msg_id}
-{extra}
-------=_Part_4200734_24778174.1344608186754
-Content-Type: text/plain; charset=utf-8
-Content-Transfer-Encoding: quoted-printable
-
-Please call me as soon as possible this afternoon!
-
---
-Sylvie
-------=_Part_4200734_24778174.1344608186754
-Content-Type: text/html; charset=utf-8
-Content-Transfer-Encoding: quoted-printable
-
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
- <head>=20
- <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8" />
- </head>=20
- <body style=3D"margin: 0; padding: 0; background: #ffffff;-webkit-text-size-adjust: 100%;">=20
-
- <p>Please call me as soon as possible this afternoon!</p>
-
- <p>--<br/>
- Sylvie
- <p>
- </body>
-</html>
-------=_Part_4200734_24778174.1344608186754--
-"""
-
-MAIL_TEMPLATE_PLAINTEXT = """Return-Path: <whatever-2a840@postmaster.twitter.com>
-To: {to}
-Received: by mail1.openerp.com (Postfix, from userid 10002)
- id 5DF9ABFB2A; Fri, 10 Aug 2012 16:16:39 +0200 (CEST)
-From: {email_from}
-Subject: {subject}
-MIME-Version: 1.0
-Content-Type: text/plain
-Date: Fri, 10 Aug 2012 14:16:26 +0000
-Message-ID: {msg_id}
-{extra}
-
-Please call me as soon as possible this afternoon!
-
---
-Sylvie
-"""
-
-MAIL_MULTIPART_MIXED = """Return-Path: <ignasse.carambar@gmail.com>
-X-Original-To: raoul@grosbedon.fr
-Delivered-To: raoul@grosbedon.fr
-Received: by mail1.grosbedon.com (Postfix, from userid 10002)
- id E8166BFACA; Fri, 23 Aug 2013 13:18:01 +0200 (CEST)
-X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail1.grosbedon.com
-X-Spam-Level:
-X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,FREEMAIL_FROM,
- HTML_MESSAGE,RCVD_IN_DNSWL_LOW autolearn=unavailable version=3.3.1
-Received: from mail-ie0-f173.google.com (mail-ie0-f173.google.com [209.85.223.173])
- by mail1.grosbedon.com (Postfix) with ESMTPS id 9BBD7BFAAA
- for <raoul@openerp.fr>; Fri, 23 Aug 2013 13:17:55 +0200 (CEST)
-Received: by mail-ie0-f173.google.com with SMTP id qd12so575130ieb.4
- for <raoul@grosbedon.fr>; Fri, 23 Aug 2013 04:17:54 -0700 (PDT)
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=gmail.com; s=20120113;
- h=mime-version:date:message-id:subject:from:to:content-type;
- bh=dMNHV52EC7GAa7+9a9tqwT9joy9z+1950J/3A6/M/hU=;
- b=DGuv0VjegdSrEe36ADC8XZ9Inrb3Iu+3/52Bm+caltddXFH9yewTr0JkCRQaJgMwG9
- qXTQgP8qu/VFEbCh6scu5ZgU1hknzlNCYr3LT+Ih7dAZVUEHUJdwjzUU1LFV95G2RaCd
- /Lwff6CibuUvrA+0CBO7IRKW0Sn5j0mukYu8dbaKsm6ou6HqS8Nuj85fcXJfHSHp6Y9u
- dmE8jBh3fHCHF/nAvU+8aBNSIzl1FGfiBYb2jCoapIuVFitKR4q5cuoodpkH9XqqtOdH
- DG+YjEyi8L7uvdOfN16eMr7hfUkQei1yQgvGu9/5kXoHg9+Gx6VsZIycn4zoaXTV3Nhn
- nu4g==
-MIME-Version: 1.0
-X-Received: by 10.50.124.65 with SMTP id mg1mr1144467igb.43.1377256674216;
- Fri, 23 Aug 2013 04:17:54 -0700 (PDT)
-Received: by 10.43.99.71 with HTTP; Fri, 23 Aug 2013 04:17:54 -0700 (PDT)
-Date: Fri, 23 Aug 2013 13:17:54 +0200
-Message-ID: <CAP76m_V4BY2F7DWHzwfjteyhW8L2LJswVshtmtVym+LUJ=rASQ@mail.gmail.com>
-Subject: Test mail multipart/mixed
-From: =?ISO-8859-1?Q?Raoul Grosbedon=E9e?= <ignasse.carambar@gmail.com>
-To: Followers of ASUSTeK-Joseph-Walters <raoul@grosbedon.fr>
-Content-Type: multipart/mixed; boundary=089e01536c4ed4d17204e49b8e96
-
---089e01536c4ed4d17204e49b8e96
-Content-Type: multipart/alternative; boundary=089e01536c4ed4d16d04e49b8e94
-
---089e01536c4ed4d16d04e49b8e94
-Content-Type: text/plain; charset=ISO-8859-1
-
-Should create a multipart/mixed: from gmail, *bold*, with attachment.
-
---
-Marcel Boitempoils.
-
---089e01536c4ed4d16d04e49b8e94
-Content-Type: text/html; charset=ISO-8859-1
-
-<div dir="ltr">Should create a multipart/mixed: from gmail, <b>bold</b>, with attachment.<br clear="all"><div><br></div>-- <br>Marcel Boitempoils.</div>
-
---089e01536c4ed4d16d04e49b8e94--
---089e01536c4ed4d17204e49b8e96
-Content-Type: text/plain; charset=US-ASCII; name="test.txt"
-Content-Disposition: attachment; filename="test.txt"
-Content-Transfer-Encoding: base64
-X-Attachment-Id: f_hkpb27k00
-
-dGVzdAo=
---089e01536c4ed4d17204e49b8e96--"""
-
-MAIL_MULTIPART_MIXED_TWO = """X-Original-To: raoul@grosbedon.fr
-Delivered-To: raoul@grosbedon.fr
-Received: by mail1.grosbedon.com (Postfix, from userid 10002)
- id E8166BFACA; Fri, 23 Aug 2013 13:18:01 +0200 (CEST)
-From: "Bruce Wayne" <bruce@wayneenterprises.com>
-Content-Type: multipart/alternative;
- boundary="Apple-Mail=_9331E12B-8BD2-4EC7-B53E-01F3FBEC9227"
-Message-Id: <6BB1FAB2-2104-438E-9447-07AE2C8C4A92@sexample.com>
-Mime-Version: 1.0 (Mac OS X Mail 7.3 \(1878.6\))
-
---Apple-Mail=_9331E12B-8BD2-4EC7-B53E-01F3FBEC9227
-Content-Transfer-Encoding: 7bit
-Content-Type: text/plain;
- charset=us-ascii
-
-First and second part
-
---Apple-Mail=_9331E12B-8BD2-4EC7-B53E-01F3FBEC9227
-Content-Type: multipart/mixed;
- boundary="Apple-Mail=_CA6C687E-6AA0-411E-B0FE-F0ABB4CFED1F"
-
---Apple-Mail=_CA6C687E-6AA0-411E-B0FE-F0ABB4CFED1F
-Content-Transfer-Encoding: 7bit
-Content-Type: text/html;
- charset=us-ascii
-
-<html><head></head><body>First part</body></html>
-
---Apple-Mail=_CA6C687E-6AA0-411E-B0FE-F0ABB4CFED1F
-Content-Disposition: inline;
- filename=thetruth.pdf
-Content-Type: application/pdf;
- name="thetruth.pdf"
-Content-Transfer-Encoding: base64
-
-SSBhbSB0aGUgQmF0TWFuCg==
-
---Apple-Mail=_CA6C687E-6AA0-411E-B0FE-F0ABB4CFED1F
-Content-Transfer-Encoding: 7bit
-Content-Type: text/html;
- charset=us-ascii
-
-<html><head></head><body>Second part</body></html>
---Apple-Mail=_CA6C687E-6AA0-411E-B0FE-F0ABB4CFED1F--
-
---Apple-Mail=_9331E12B-8BD2-4EC7-B53E-01F3FBEC9227--
-"""
-
-
-MAIL_MULTIPART_IMAGE = """X-Original-To: raoul@example.com
-Delivered-To: micheline@example.com
-Received: by mail1.example.com (Postfix, from userid 99999)
- id 9DFB7BF509; Thu, 17 Dec 2015 15:22:56 +0100 (CET)
-X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail1.example.com
-X-Spam-Level: *
-X-Spam-Status: No, score=1.1 required=5.0 tests=FREEMAIL_FROM,
- HTML_IMAGE_ONLY_08,HTML_MESSAGE,RCVD_IN_DNSWL_LOW,RCVD_IN_MSPIKE_H3,
- RCVD_IN_MSPIKE_WL,T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0
-Received: from mail-lf0-f44.example.com (mail-lf0-f44.example.com [209.85.215.44])
- by mail1.example.com (Postfix) with ESMTPS id 1D80DBF509
- for <micheline@example.com>; Thu, 17 Dec 2015 15:22:56 +0100 (CET)
-Authentication-Results: mail1.example.com; dkim=pass
- reason="2048-bit key; unprotected key"
- header.d=example.com header.i=@example.com header.b=kUkTIIlt;
- dkim-adsp=pass; dkim-atps=neutral
-Received: by mail-lf0-f44.example.com with SMTP id z124so47959461lfa.3
- for <micheline@example.com>; Thu, 17 Dec 2015 06:22:56 -0800 (PST)
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=example.com; s=20120113;
- h=mime-version:date:message-id:subject:from:to:content-type;
- bh=GdrEuMrz6vxo/Z/F+mJVho/1wSe6hbxLx2SsP8tihzw=;
- b=kUkTIIlt6fe4dftKHPNBkdHU2rO052o684R0e2bqH7roGUQFb78scYE+kqX0wo1zlk
- zhKPVBR1TqTsYlqcHu+D3aUzai7L/Q5m40sSGn7uYGkZJ6m1TwrWNqVIgTZibarqvy94
- NWhrjjK9gqd8segQdSjCgTipNSZME4bJCzPyBg/D5mqe07FPBJBGoF9SmIzEBhYeqLj1
- GrXjb/D8J11aOyzmVvyt+bT+oeLUJI8E7qO5g2eQkMncyu+TyIXaRofOOBA14NhQ+0nS
- w5O9rzzqkKuJEG4U2TJ2Vi2nl2tHJW2QPfTtFgcCzGxQ0+5n88OVlbGTLnhEIJ/SYpem
- O5EA==
-MIME-Version: 1.0
-X-Received: by 10.25.167.197 with SMTP id q188mr22222517lfe.129.1450362175493;
- Thu, 17 Dec 2015 06:22:55 -0800 (PST)
-Received: by 10.25.209.145 with HTTP; Thu, 17 Dec 2015 06:22:55 -0800 (PST)
-Date: Thu, 17 Dec 2015 15:22:55 +0100
-Message-ID: <CAP76m_UB=aLqWEFccnq86AhkpwRB3aZoGL9vMffX7co3YEro_A@mail.gmail.com>
-Subject: {subject}
-From: =?UTF-8?Q?Thibault_Delavall=C3=A9e?= <raoul@example.com>
-To: {to}
-Content-Type: multipart/related; boundary=001a11416b9e9b229a05272b7052
-
---001a11416b9e9b229a05272b7052
-Content-Type: multipart/alternative; boundary=001a11416b9e9b229805272b7051
-
---001a11416b9e9b229805272b7051
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: quoted-printable
-
-Premi=C3=A8re image, orang=C3=A9e.
-
-[image: Inline image 1]
-
-Seconde image, rosa=C3=A7=C3=A9e.
-
-[image: Inline image 2]
-
-Troisi=C3=A8me image, verte!=C2=B5
-
-[image: Inline image 3]
-
-J'esp=C3=A8re que tout se passera bien.
---=20
-Thibault Delavall=C3=A9e
-
---001a11416b9e9b229805272b7051
-Content-Type: text/html; charset=UTF-8
-Content-Transfer-Encoding: quoted-printable
-
-<div dir=3D"ltr"><div>Premi=C3=A8re image, orang=C3=A9e.</div><div><br></di=
-v><div><img src=3D"cid:ii_151b519fc025fdd3" alt=3D"Inline image 1" width=3D=
-"2" height=3D"2"><br></div><div><br></div><div>Seconde image, rosa=C3=A7=C3=
-=A9e.</div><div><br></div><div><img src=3D"cid:ii_151b51a290ed6a91" alt=3D"=
-Inline image 2" width=3D"2" height=3D"2"></div><div><br></div><div>Troisi=
-=C3=A8me image, verte!=C2=B5</div><div><br></div><div><img src=3D"cid:ii_15=
-1b51a37e5eb7a6" alt=3D"Inline image 3" width=3D"10" height=3D"10"><br></div=
-><div><br></div><div>J&#39;esp=C3=A8re que tout se passera bien.</div>-- <b=
-r><div class=3D"gmail_signature">Thibault Delavall=C3=A9e</div>
-</div>
-
---001a11416b9e9b229805272b7051--
---001a11416b9e9b229a05272b7052
-Content-Type: image/gif; name="=?UTF-8?B?b3JhbmfDqWUuZ2lm?="
-Content-Disposition: inline; filename="=?UTF-8?B?b3JhbmfDqWUuZ2lm?="
-Content-Transfer-Encoding: base64
-Content-ID: <ii_151b519fc025fdd3>
-X-Attachment-Id: ii_151b519fc025fdd3
-
-R0lGODdhAgACALMAAAAAAP///wAAAP//AP8AAP+AAAD/AAAAAAAA//8A/wAAAAAAAAAAAAAAAAAA
-AAAAACwAAAAAAgACAAAEA7DIEgA7
---001a11416b9e9b229a05272b7052
-Content-Type: image/gif; name="=?UTF-8?B?dmVydGUhwrUuZ2lm?="
-Content-Disposition: inline; filename="=?UTF-8?B?dmVydGUhwrUuZ2lm?="
-Content-Transfer-Encoding: base64
-Content-ID: <ii_151b51a37e5eb7a6>
-X-Attachment-Id: ii_151b51a37e5eb7a6
-
-R0lGODlhCgAKALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A/wD/
-/////ywAAAAACgAKAAAEClDJSau9OOvNe44AOw==
---001a11416b9e9b229a05272b7052
-Content-Type: image/gif; name="=?UTF-8?B?cm9zYcOnw6llLmdpZg==?="
-Content-Disposition: inline; filename="=?UTF-8?B?cm9zYcOnw6llLmdpZg==?="
-Content-Transfer-Encoding: base64
-Content-ID: <ii_151b51a290ed6a91>
-X-Attachment-Id: ii_151b51a290ed6a91
-
-R0lGODdhAgACALMAAAAAAP///wAAAP//AP8AAP+AAAD/AAAAAAAA//8A/wAAAP+AgAAAAAAAAAAA
-AAAAACwAAAAAAgACAAAEA3DJFQA7
---001a11416b9e9b229a05272b7052--
-""" \ No newline at end of file
diff --git a/addons/mail/tests/models/__init__.py b/addons/mail/tests/models/__init__.py
deleted file mode 100644
index 420d064776c..00000000000
--- a/addons/mail/tests/models/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from . import test_mail_models \ No newline at end of file
diff --git a/addons/mail/tests/models/test_mail_models.py b/addons/mail/tests/models/test_mail_models.py
deleted file mode 100644
index a45602bf6d5..00000000000
--- a/addons/mail/tests/models/test_mail_models.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from odoo import fields, models
-
-
-class MailTestSimple(models.Model):
- """ A very simple model only inheriting from mail.thread when only
- communication history is necessary. """
- _description = 'Simple Chatter Model'
- _name = 'mail.test.simple'
- _inherit = ['mail.thread']
-
- name = fields.Char()
- email_from = fields.Char()
-
-
-class MailTestStandard(models.Model):
- """ This model can be used in tests when automatic subscription and simple
- tracking is necessary. Most features are present in a simple way. """
- _description = 'Standard Chatter Model'
- _name = 'mail.test.track'
- _inherit = ['mail.thread']
-
- name = fields.Char()
- email_from = fields.Char()
- user_id = fields.Many2one('res.users', 'Responsible', track_visibility='onchange')
- umbrella_id = fields.Many2one('mail.test', track_visibility='onchange')
-
-
-class MailTestActivity(models.Model):
- """ This model can be used to test activities in addition to simple chatter
- features. """
- _description = 'Activity Model'
- _name = 'mail.test.activity'
- _inherit = ['mail.thread', 'mail.activity.mixin']
-
- name = fields.Char()
- email_from = fields.Char()
-
-
-class MailTestFull(models.Model):
- """ This model can be used in tests when complex chatter features are
- required like modeling tasks or tickets. """
- _description = 'Full Chatter Model'
- _name = 'mail.test.full'
- _inherit = ['mail.thread']
-
- name = fields.Char()
- email_from = fields.Char(track_visibility='always')
- count = fields.Integer(default=1)
- datetime = fields.Datetime(default=fields.Datetime.now)
- mail_template = fields.Many2one('mail.template', 'Template')
- customer_id = fields.Many2one('res.partner', 'Customer', track_visibility='onchange')
- user_id = fields.Many2one('res.users', 'Responsible', track_visibility='onchange')
- umbrella_id = fields.Many2one('mail.test', track_visibility='onchange')
-
- def _track_template(self, tracking):
- res = super(MailTestFull, self)._track_template(tracking)
- record = self[0]
- changes, tracking_value_ids = tracking[record.id]
- if 'customer_id' in changes and record.mail_template:
- res['customer_id'] = (record.mail_template, {'composition_mode': 'mass_mail'})
- elif 'datetime' in changes:
- res['datetime'] = ('mail.track_template', {'composition_mode': 'mass_mail'})
- return res
-
- def _track_subtype(self, init_values):
- self.ensure_one()
- if 'umbrella_id' in init_values and self.umbrella_id:
- return 'mail.track_subtype_umbrella'
- return super(MailTestFull, self)._track_subtype(init_values)
-
-
-class MailTestAlias(models.Model):
- """ This model can be used in tests when umbrella records like projects
- or teams are required. """
- _description = 'Alias Chatter Model'
- _name = 'mail.test'
- _mail_post_access = 'read'
- _inherit = ['mail.thread', 'mail.alias.mixin']
-
- name = fields.Char()
- description = fields.Text()
- alias_id = fields.Many2one(
- 'mail.alias', 'Alias',
- delegate=True)
-
- def get_alias_model_name(self, vals):
- return vals.get('alias_model', 'mail.test')
-
- def get_alias_values(self):
- self.ensure_one()
- res = super(MailTestAlias, self).get_alias_values()
- res['alias_force_thread_id'] = self.id
- res['alias_parent_thread_id'] = self.id
- return res
diff --git a/addons/mail/tests/test_discuss.py b/addons/mail/tests/test_discuss.py
deleted file mode 100644
index ea155bf3232..00000000000
--- a/addons/mail/tests/test_discuss.py
+++ /dev/null
@@ -1,153 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from odoo.addons.mail.tests.common import BaseFunctionalTest, TestRecipients, MockEmails
-
-
-class TestChatterTweaks(BaseFunctionalTest, TestRecipients):
-
- def test_post_no_subscribe_author(self):
- original = self.test_record.message_follower_ids
- self.test_record.sudo(self.user_employee).with_context({'mail_create_nosubscribe': True}).message_post(
- body='Test Body', message_type='comment', subtype='mt_comment')
- self.assertEqual(self.test_record.message_follower_ids.mapped('partner_id'), original.mapped('partner_id'))
- self.assertEqual(self.test_record.message_follower_ids.mapped('channel_id'), original.mapped('channel_id'))
-
- def test_post_no_subscribe_recipients(self):
- original = self.test_record.message_follower_ids
- self.test_record.sudo(self.user_employee).with_context({'mail_create_nosubscribe': True}).message_post(
- body='Test Body', message_type='comment', subtype='mt_comment', partner_ids=[(4, self.partner_1.id), (4, self.partner_2.id)])
- self.assertEqual(self.test_record.message_follower_ids.mapped('partner_id'), original.mapped('partner_id'))
- self.assertEqual(self.test_record.message_follower_ids.mapped('channel_id'), original.mapped('channel_id'))
-
- def test_post_subscribe_recipients(self):
- original = self.test_record.message_follower_ids
- self.test_record.sudo(self.user_employee).with_context({'mail_create_nosubscribe': True, 'mail_post_autofollow': True}).message_post(
- body='Test Body', message_type='comment', subtype='mt_comment', partner_ids=[(4, self.partner_1.id), (4, self.partner_2.id)])
- self.assertEqual(self.test_record.message_follower_ids.mapped('partner_id'), original.mapped('partner_id') | self.partner_1 | self.partner_2)
- self.assertEqual(self.test_record.message_follower_ids.mapped('channel_id'), original.mapped('channel_id'))
-
- def test_post_subscribe_recipients_partial(self):
- original = self.test_record.message_follower_ids
- self.test_record.sudo(self.user_employee).with_context({'mail_create_nosubscribe': True, 'mail_post_autofollow': True, 'mail_post_autofollow_partner_ids': [self.partner_2.id]}).message_post(
- body='Test Body', message_type='comment', subtype='mt_comment', partner_ids=[(4, self.partner_1.id), (4, self.partner_2.id)])
- self.assertEqual(self.test_record.message_follower_ids.mapped('partner_id'), original.mapped('partner_id') | self.partner_2)
- self.assertEqual(self.test_record.message_follower_ids.mapped('channel_id'), original.mapped('channel_id'))
-
- def test_chatter_mail_create_nolog(self):
- """ Test disable of automatic chatter message at create """
- rec = self.env['mail.test.simple'].sudo(self.user_employee).with_context({'mail_create_nolog': True}).create({'name': 'Test'})
- self.assertEqual(rec.message_ids, self.env['mail.message'])
-
- rec = self.env['mail.test.simple'].sudo(self.user_employee).with_context({'mail_create_nolog': False}).create({'name': 'Test'})
- self.assertEqual(len(rec.message_ids), 1)
-
- def test_chatter_mail_notrack(self):
- """ Test disable of automatic value tracking at create and write """
- rec = self.env['mail.test.track'].sudo(self.user_employee).with_context({'mail_notrack': False}).create({'name': 'Test', 'user_id': self.user_employee.id})
- self.assertEqual(len(rec.sudo().mapped('message_ids.tracking_value_ids')), 1)
-
- rec = self.env['mail.test.track'].sudo(self.user_employee).with_context({'mail_notrack': True}).create({'name': 'Test', 'user_id': self.user_employee.id})
- self.assertEqual(rec.sudo().mapped('message_ids.tracking_value_ids'), self.env['mail.tracking.value'])
-
- rec.write({'user_id': self.user_admin.id})
- self.assertEqual(rec.sudo().mapped('message_ids.tracking_value_ids'), self.env['mail.tracking.value'])
-
- rec.with_context({'mail_notrack': False}).write({'user_id': self.user_employee.id})
- self.assertEqual(len(rec.sudo().mapped('message_ids.tracking_value_ids')), 1)
-
- def test_chatter_tracking_disable(self):
- """ Test disable of all chatter features at create and write """
- rec = self.env['mail.test.track'].sudo(self.user_employee).with_context({'tracking_disable': True}).create({'name': 'Test', 'user_id': self.user_employee.id})
- self.assertEqual(rec.sudo().message_ids, self.env['mail.message'])
- self.assertEqual(rec.sudo().mapped('message_ids.tracking_value_ids'), self.env['mail.tracking.value'])
-
- rec.write({'user_id': self.user_admin.id})
- self.assertEqual(rec.sudo().mapped('message_ids.tracking_value_ids'), self.env['mail.tracking.value'])
-
- rec.with_context({'tracking_disable': False}).write({'user_id': self.user_employee.id})
- self.assertEqual(len(rec.sudo().mapped('message_ids.tracking_value_ids')), 1)
-
- rec = self.env['mail.test.track'].sudo(self.user_employee).with_context({'tracking_disable': False}).create({'name': 'Test', 'user_id': self.user_employee.id})
- self.assertEqual(len(rec.sudo().message_ids), 2)
- self.assertEqual(len(rec.sudo().mapped('message_ids.tracking_value_ids')), 1)
-
-
-class TestNotifications(BaseFunctionalTest, MockEmails):
-
- def setUp(self):
- super(TestNotifications, self).setUp()
- self.partner_1 = self.env['res.partner'].with_context(self._quick_create_ctx).create({
- 'name': 'Valid Lelitre',
- 'email': 'valid.lelitre@agrolait.com'})
-
- (self.user_employee | self.user_admin).write({'notification_type': 'inbox'})
-
- def test_needaction(self):
- with self.assertNotifications(partner_employee=(1, 'inbox', 'unread'), partner_admin=(0, '', '')):
- self.test_record.message_post(
- body='Test', message_type='comment', subtype='mail.mt_comment',
- partner_ids=[self.user_employee.partner_id.id])
-
- self.test_record.message_subscribe([self.partner_1.id])
- with self.assertNotifications(partner_employee=(1, 'inbox', 'unread'), partner_admin=(0, '', ''), partner_1=(1, 'email', 'read')):
- self.test_record.message_post(
- body='Test', message_type='comment', subtype='mail.mt_comment',
- partner_ids=[self.user_employee.partner_id.id])
-
- def test_set_message_done_user(self):
- with self.assertNotifications(partner_employee=(0, '', '')):
- message = self.test_record.message_post(
- body='Test', message_type='comment', subtype='mail.mt_comment',
- partner_ids=[self.user_employee.partner_id.id])
- message.sudo(self.user_employee).set_message_done()
-
- def test_set_message_done_portal(self):
- user_portal = self.env['res.users'].with_context(self._quick_create_user_ctx).create({
- 'name': 'Chell Gladys',
- 'login': 'chell',
- 'email': 'chell@gladys.portal',
- 'notification_type': 'inbox',
- 'groups_id': [(6, 0, [self.env.ref('base.group_portal').id])],
- })
- self.partner_portal = user_portal.partner_id
-
- with self.assertNotifications(partner_employee=(1, 'inbox', 'unread'), partner_portal=(1, 'inbox', 'read')):
- message = self.test_record.message_post(
- body='Test', message_type='comment', subtype='mail.mt_comment',
- partner_ids=[self.user_employee.partner_id.id, user_portal.partner_id.id])
- message.sudo(user_portal).set_message_done()
-
- def test_set_star(self):
- msg = self.test_record.message_post(body='My Body', subject='1')
- msg_emp = self.env['mail.message'].sudo(self.user_employee).browse(msg.id)
-
- # Admin set as starred
- msg.toggle_message_starred()
- self.assertTrue(msg.starred)
-
- # Employee set as starred
- msg_emp.toggle_message_starred()
- self.assertTrue(msg_emp.starred)
-
- # Do: Admin unstars msg
- msg.toggle_message_starred()
- self.assertFalse(msg.starred)
- self.assertTrue(msg_emp.starred)
-
-
-class TestChatterMisc(BaseFunctionalTest):
-
- def test_alias_setup(self):
- alias = self.env['mail.alias'].with_context(alias_model_name='mail.test').create({'alias_name': 'b4r+_#_R3wl$$'})
- self.assertEqual(alias.alias_name, 'b4r+_-_r3wl-', 'Disallowed chars should be replaced by hyphens')
-
- def test_cache_invalidation(self):
- """ Test that creating a mail-thread record does not invalidate the whole cache. """
- # make a new record in cache
- record = self.env['res.partner'].new({'name': 'Brave New Partner'})
- self.assertTrue(record.name)
-
- # creating a mail-thread record should not invalidate the whole cache
- self.env['res.partner'].create({'name': 'Actual Partner'})
- self.assertTrue(record.name)
diff --git a/addons/mail/tests/test_invite.py b/addons/mail/tests/test_invite.py
deleted file mode 100644
index bb50b3f1dc9..00000000000
--- a/addons/mail/tests/test_invite.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from odoo.addons.mail.tests import common
-from odoo.tools import mute_logger
-
-
-class TestInvite(common.BaseFunctionalTest, common.MockEmails):
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_invite_email(self):
- test_partner = self.env['res.partner'].with_context(self._quick_create_ctx).create({
- 'name': 'Valid Lelitre',
- 'email': 'valid.lelitre@agrolait.com'})
-
- mail_invite = self.env['mail.wizard.invite'].with_context({
- 'default_res_model': 'mail.test.simple',
- 'default_res_id': self.test_record.id
- }).sudo(self.user_employee.id).create({
- 'partner_ids': [(4, test_partner.id), (4, self.user_admin.partner_id.id)],
- 'send_mail': True})
- mail_invite.add_followers()
-
- # check added followers and that emails were sent
- self.assertEqual(self.test_record.message_partner_ids,
- test_partner | self.user_admin.partner_id)
- self.assertEqual(self.test_record.message_follower_ids.mapped('channel_id'),
- self.env['mail.channel'])
- self.assertEqual(len(self._mails), 2)
diff --git a/addons/mail/tests/test_ir_actions.py b/addons/mail/tests/test_ir_actions.py
deleted file mode 100644
index 543c27d4a21..00000000000
--- a/addons/mail/tests/test_ir_actions.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from odoo.addons.base.tests.test_ir_actions import TestServerActionsBase
-
-
-class TestServerActionsEmail(TestServerActionsBase):
-
- def test_action_email(self):
- email_template = self.env['mail.template'].create({
- 'name': 'TestTemplate',
- 'email_from': 'myself@example.com',
- 'email_to': 'brigitte@example.com',
- 'partner_to': '%s' % self.test_partner.id,
- 'model_id': self.res_partner_model.id,
- 'subject': 'About ${object.name}',
- 'body_html': '<p>Dear ${object.name}, your parent is ${object.parent_id and object.parent_id.name or "False"}</p>',
- })
- self.action.write({'state': 'email', 'template_id': email_template.id})
- self.action.with_context(self.context).run()
- # check an email is waiting for sending
- mail = self.env['mail.mail'].search([('subject', '=', 'About TestingPartner')])
- self.assertEqual(len(mail), 1)
- # check email content
- self.assertEqual(mail.body, '<p>Dear TestingPartner, your parent is False</p>')
-
- def test_action_followers(self):
- self.test_partner.message_unsubscribe(self.test_partner.message_partner_ids.ids)
- self.action.write({
- 'state': 'followers',
- 'partner_ids': [(4, self.env.ref('base.partner_root').id), (4, self.env.ref('base.partner_demo').id)],
- 'channel_ids': [(4, self.env.ref('mail.channel_all_employees').id)]
- })
- self.action.with_context(self.context).run()
- self.assertEqual(self.test_partner.message_partner_ids, self.env.ref('base.partner_root') | self.env.ref('base.partner_demo'))
- self.assertEqual(self.test_partner.message_channel_ids, self.env.ref('mail.channel_all_employees'))
diff --git a/addons/mail/tests/test_mail_activity.py b/addons/mail/tests/test_mail_activity.py
deleted file mode 100644
index 637bd05c021..00000000000
--- a/addons/mail/tests/test_mail_activity.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from datetime import date
-from dateutil.relativedelta import relativedelta
-
-from odoo import exceptions
-from odoo.addons.mail.tests.common import BaseFunctionalTest
-from odoo.tools import mute_logger
-
-
-class TestMailActivity(BaseFunctionalTest):
-
- @classmethod
- def setUpClass(cls):
- super(TestMailActivity, cls).setUpClass()
- cls.test_record = cls.env['mail.test.activity'].create({'name': 'Test'})
-
- def test_activity_flow_employee(self):
- with self.sudoAs('ernest'):
- test_record = self.env['mail.test.activity'].browse(self.test_record.id)
- self.assertEqual(test_record.activity_ids, self.env['mail.activity'])
-
- # employee record an activity and check the deadline
- self.env['mail.activity'].create({
- 'summary': 'Test Activity',
- 'date_deadline': date.today() + relativedelta(days=1),
- 'activity_type_id': self.env.ref('mail.mail_activity_data_email').id,
- 'res_model_id': self.env['ir.model']._get(test_record._name).id,
- 'res_id': test_record.id,
- })
- self.assertEqual(test_record.activity_summary, 'Test Activity')
- self.assertEqual(test_record.activity_state, 'planned')
-
- test_record.activity_ids.write({'date_deadline': date.today() - relativedelta(days=1)})
- test_record.invalidate_cache() # TDE note: should not have to do it I think
- self.assertEqual(test_record.activity_state, 'overdue')
-
- test_record.activity_ids.write({'date_deadline': date.today()})
- test_record.invalidate_cache() # TDE note: should not have to do it I think
- self.assertEqual(test_record.activity_state, 'today')
-
- # activity is done
- test_record.activity_ids.action_feedback(feedback='So much feedback')
- self.assertEqual(test_record.activity_ids, self.env['mail.activity'])
- self.assertEqual(test_record.message_ids[0].subtype_id, self.env.ref('mail.mt_activities'))
-
- def test_activity_flow_portal(self):
- portal_user = self.env['res.users'].with_context(self._quick_create_user_ctx).create({
- 'name': 'Chell Gladys',
- 'login': 'chell',
- 'email': 'chell@gladys.portal',
- 'groups_id': [(6, 0, [self.env.ref('base.group_portal').id])],
- })
-
- with self.sudoAs('chell'):
- test_record = self.env['mail.test.activity'].browse(self.test_record.id)
- # test_record.name
- # test_record.read()
- with self.assertRaises(exceptions.AccessError):
- self.env['mail.activity'].create({
- 'summary': 'Test Activity',
- 'activity_type_id': self.env.ref('mail.mail_activity_data_email').id,
- 'res_model_id': self.env['ir.model']._get(test_record._name).id,
- 'res_id': test_record.id,
- })
- # self.assertEqual(test_record.activity_ids, self.env['mail.activity'])
diff --git a/addons/mail/tests/test_mail_channel.py b/addons/mail/tests/test_mail_channel.py
deleted file mode 100644
index e06b10eeaa8..00000000000
--- a/addons/mail/tests/test_mail_channel.py
+++ /dev/null
@@ -1,197 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from email.utils import formataddr
-
-from odoo.addons.mail.tests import common
-from odoo.exceptions import AccessError, except_orm
-from odoo.tools import mute_logger
-
-
-class TestChannelAccessRights(common.BaseFunctionalTest, common.MockEmails):
-
- @classmethod
- def setUpClass(cls):
- super(TestChannelAccessRights, cls).setUpClass()
- Channel = cls.env['mail.channel'].with_context(cls._quick_create_ctx)
-
- Users = cls.env['res.users'].with_context(cls._quick_create_user_ctx)
- cls.user_public = Users.create({
- 'name': 'Bert Tartignole',
- 'login': 'bert',
- 'email': 'b.t@example.com',
- 'groups_id': [(6, 0, [cls.env.ref('base.group_public').id])]})
- cls.user_portal = Users.create({
- 'name': 'Chell Gladys',
- 'login': 'chell',
- 'email': 'chell@gladys.portal',
- 'groups_id': [(6, 0, [cls.env.ref('base.group_portal').id])]})
-
- # Pigs: base group for tests
- cls.group_pigs = Channel.create({
- 'name': 'Pigs',
- 'public': 'groups',
- 'group_public_id': cls.env.ref('base.group_user').id})
- # Jobs: public group
- cls.group_public = Channel.create({
- 'name': 'Jobs',
- 'description': 'NotFalse',
- 'public': 'public'})
- # Private: private group
- cls.group_private = Channel.create({
- 'name': 'Private',
- 'public': 'private'})
-
- @mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
- def test_access_rights_public(self):
- # Read public group -> ok
- self.group_public.sudo(self.user_public).read()
-
- # Read Pigs -> ko, restricted to employees
- # TODO: Change the except_orm to Warning ( Because here it's call check_access_rule
- # which still generate exception in except_orm.So we need to change all
- # except_orm to warning in mail module.)
- with self.assertRaises(except_orm):
- self.group_pigs.sudo(self.user_public).read()
-
- # Read a private group when being a member: ok
- self.group_private.write({'channel_partner_ids': [(4, self.user_public.partner_id.id)]})
- self.group_private.sudo(self.user_public).read()
-
- # Create group: ko, no access rights
- with self.assertRaises(AccessError):
- self.env['mail.channel'].sudo(self.user_public).create({'name': 'Test'})
-
- # Update group: ko, no access rights
- with self.assertRaises(AccessError):
- self.group_public.sudo(self.user_public).write({'name': 'Broutouschnouk'})
-
- # Unlink group: ko, no access rights
- with self.assertRaises(AccessError):
- self.group_public.sudo(self.user_public).unlink()
-
- @mute_logger('odoo.addons.base.models.ir_model', 'odoo.models', 'odoo.models.unlink')
- def test_access_rights_groups(self):
- # Employee read employee-based group: ok
- # TODO Change the except_orm to Warning
- self.group_pigs.sudo(self.user_employee).read()
-
- # Employee can create a group
- self.env['mail.channel'].sudo(self.user_employee).create({'name': 'Test'})
-
- # Employee update employee-based group: ok
- self.group_pigs.sudo(self.user_employee).write({'name': 'modified'})
-
- # Employee unlink employee-based group: ok
- self.group_pigs.sudo(self.user_employee).unlink()
-
- # Employee cannot read a private group
- with self.assertRaises(except_orm):
- self.group_private.sudo(self.user_employee).read()
-
- # Employee cannot write on private
- with self.assertRaises(AccessError):
- self.group_private.sudo(self.user_employee).write({'name': 're-modified'})
-
- @mute_logger('odoo.addons.base.ir.ir_model', 'odoo.models')
- def test_access_rights_followers_ko(self):
- with self.assertRaises(AccessError):
- self.group_private.sudo(self.user_portal).name
-
- def test_access_rights_followers_portal(self):
- # Do: Chell is added into Pigs members and browse it -> ok for messages, ko for partners (no read permission)
- self.group_private.write({'channel_partner_ids': [(4, self.user_portal.partner_id.id)]})
- chell_pigs = self.group_private.sudo(self.user_portal)
- trigger_read = chell_pigs.name
- for message in chell_pigs.message_ids:
- trigger_read = message.subject
- for partner in chell_pigs.message_partner_ids:
- if partner.id == self.user_portal.partner_id.id:
- # Chell can read her own partner record
- continue
- # TODO Change the except_orm to Warning
- with self.assertRaises(except_orm):
- trigger_read = partner.name
-
-
-class TestChannelFeatures(common.BaseFunctionalTest, common.MockEmails):
-
- @classmethod
- def setUpClass(cls):
- super(TestChannelFeatures, cls).setUpClass()
- cls.test_channel = cls.env['mail.channel'].with_context(cls._quick_create_ctx).create({
- 'name': 'Test',
- 'description': 'Description',
- 'alias_name': 'test',
- 'public': 'public',
- })
- cls.test_partner = cls.env['res.partner'].with_context(cls._quick_create_ctx).create({
- 'name': 'Test Partner',
- 'email': 'test@example.com',
- })
-
- 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 _leave_channel(self, channel, partners):
- for partner in partners:
- channel._action_unfollow(partner)
-
- def test_channel_listeners(self):
- self.assertEqual(self.test_channel.message_channel_ids, self.test_channel)
- self.assertEqual(self.test_channel.message_partner_ids, self.env['res.partner'])
- self.assertEqual(self.test_channel.channel_partner_ids, self.env['res.partner'])
-
- self._join_channel(self.test_channel, self.test_partner)
- self.assertEqual(self.test_channel.message_channel_ids, self.test_channel)
- self.assertEqual(self.test_channel.message_partner_ids, self.env['res.partner'])
- self.assertEqual(self.test_channel.channel_partner_ids, self.test_partner)
-
- self._leave_channel(self.test_channel, self.test_partner)
- self.assertEqual(self.test_channel.message_channel_ids, self.test_channel)
- self.assertEqual(self.test_channel.message_partner_ids, self.env['res.partner'])
- self.assertEqual(self.test_channel.channel_partner_ids, self.env['res.partner'])
-
- def test_channel_post_nofollow(self):
- self.test_channel.message_post(body='Test', message_type='comment', subtype='mt_comment')
- self.assertEqual(self.test_channel.message_channel_ids, self.test_channel)
- self.assertEqual(self.test_channel.message_partner_ids, self.env['res.partner'])
-
- @mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
- def test_channel_mailing_list_recipients(self):
- """ Posting a message on a mailing list should send one email to all recipients """
- 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.user_employee.partner_id | self.test_partner)
- self.test_channel.message_post(body="Test", message_type='comment', subtype='mt_comment')
-
- self.assertEqual(len(self._mails), 1)
- for email in self._mails:
- self.assertEqual(
- set(email['email_to']),
- set([formataddr((self.user_employee.name, self.user_employee.email)), formataddr((self.test_partner.name, self.test_partner.email))]))
-
- @mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
- def test_channel_chat_recipients(self):
- """ Posting a message on a chat should not send emails """
- self.env['ir.config_parameter'].set_param('mail.catchall.domain', 'schlouby.fr')
- self.test_channel.write({'email_send': False})
- self._join_channel(self.test_channel, self.user_employee.partner_id | self.test_partner)
- self.test_channel.message_post(body="Test", message_type='comment', subtype='mt_comment')
-
- self.assertEqual(len(self._mails), 0)
-
- @mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
- def test_channel_classic_recipients(self):
- """ Posting a message on a classic channel should work like classic post """
- self.test_channel.write({'alias_name': False})
- self.test_channel.message_subscribe([self.user_employee.partner_id.id, self.test_partner.id])
- self.test_channel.message_post(body="Test", message_type='comment', subtype='mt_comment')
-
- sent_emails = self._mails
- self.assertEqual(len(sent_emails), 2)
- for email in sent_emails:
- self.assertIn(
- email['email_to'][0],
- [formataddr((self.user_employee.name, self.user_employee.email)), formataddr((self.test_partner.name, self.test_partner.email))])
diff --git a/addons/mail/tests/test_mail_followers.py b/addons/mail/tests/test_mail_followers.py
deleted file mode 100644
index 887f9140c2b..00000000000
--- a/addons/mail/tests/test_mail_followers.py
+++ /dev/null
@@ -1,199 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from psycopg2 import IntegrityError
-
-from odoo.addons.mail.tests import common
-from odoo.tools.misc import mute_logger
-
-
-class BaseFollowersTest(common.BaseFunctionalTest):
-
- @classmethod
- def setUpClass(cls):
- super(BaseFollowersTest, cls).setUpClass()
- Subtype = cls.env['mail.message.subtype']
- cls.mt_mg_def = Subtype.create({'name': 'mt_mg_def', 'default': True, 'res_model': 'mail.test.simple'})
- cls.mt_cl_def = Subtype.create({'name': 'mt_cl_def', 'default': True, 'res_model': 'mail.test'})
- cls.mt_al_def = Subtype.create({'name': 'mt_al_def', 'default': True, 'res_model': False})
- cls.mt_mg_nodef = Subtype.create({'name': 'mt_mg_nodef', 'default': False, 'res_model': 'mail.test.simple'})
- cls.mt_al_nodef = Subtype.create({'name': 'mt_al_nodef', 'default': False, 'res_model': False})
- cls.mt_mg_def_int = cls.env['mail.message.subtype'].create({'name': 'mt_mg_def', 'default': True, 'res_model': 'mail.test.simple', 'internal': True})
- cls.default_group_subtypes = Subtype.search([('default', '=', True), '|', ('res_model', '=', 'mail.test.simple'), ('res_model', '=', False)])
- cls.default_group_subtypes_portal = Subtype.search([('internal', '=', False), ('default', '=', True), '|', ('res_model', '=', 'mail.test.simple'), ('res_model', '=', False)])
-
- def test_field_message_is_follower(self):
- test_record = self.test_record.sudo(self.user_employee)
- followed_before = test_record.search([('message_is_follower', '=', True)])
- self.assertFalse(test_record.message_is_follower)
- test_record.message_subscribe_users(user_ids=[self.user_employee.id])
- followed_after = test_record.search([('message_is_follower', '=', True)])
- self.assertTrue(test_record.message_is_follower)
- self.assertEqual(followed_before | test_record, followed_after)
-
- def test_field_followers(self):
- test_record = self.test_record.sudo(self.user_employee)
- test_record.message_subscribe(partner_ids=[self.user_employee.partner_id.id, self.user_admin.partner_id.id], channel_ids=[self.channel_listen.id])
- followers = self.env['mail.followers'].search([
- ('res_model', '=', 'mail.test.simple'),
- ('res_id', '=', test_record.id)])
- self.assertEqual(followers, test_record.message_follower_ids)
- self.assertEqual(test_record.message_partner_ids, self.user_employee.partner_id | self.user_admin.partner_id)
- self.assertEqual(test_record.message_channel_ids, self.channel_listen)
-
- def test_followers_subtypes_default(self):
- test_record = self.test_record.sudo(self.user_employee)
- test_record.message_subscribe(partner_ids=[self.user_employee.partner_id.id])
- self.assertEqual(test_record.message_partner_ids, self.user_employee.partner_id)
- follower = self.env['mail.followers'].search([
- ('res_model', '=', 'mail.test.simple'),
- ('res_id', '=', test_record.id),
- ('partner_id', '=', self.user_employee.partner_id.id)])
- self.assertEqual(follower, test_record.message_follower_ids)
- self.assertEqual(follower.subtype_ids, self.default_group_subtypes)
-
- def test_followers_subtypes_default_internal(self):
- user_portal = self.env['res.users'].with_context(self._quick_create_user_ctx).create({
- 'name': 'Chell Gladys',
- 'login': 'chell',
- 'email': 'chell@gladys.portal',
- 'groups_id': [(6, 0, [self.env.ref('base.group_portal').id])]
- })
-
- test_record = self.test_record.sudo(self.user_employee)
- test_record.message_subscribe(partner_ids=[user_portal.partner_id.id])
- self.assertEqual(test_record.message_partner_ids, user_portal.partner_id)
- follower = self.env['mail.followers'].search([
- ('res_model', '=', 'mail.test.simple'),
- ('res_id', '=', test_record.id),
- ('partner_id', '=', user_portal.partner_id.id)])
- self.assertEqual(follower.subtype_ids, self.default_group_subtypes_portal)
-
- def test_followers_subtypes_specified(self):
- test_record = self.test_record.sudo(self.user_employee)
- test_record.message_subscribe(partner_ids=[self.user_employee.partner_id.id], subtype_ids=[self.mt_mg_nodef.id])
- self.assertEqual(test_record.message_partner_ids, self.user_employee.partner_id)
- follower = self.env['mail.followers'].search([
- ('res_model', '=', 'mail.test.simple'),
- ('res_id', '=', test_record.id),
- ('partner_id', '=', self.user_employee.partner_id.id)])
- self.assertEqual(follower, test_record.message_follower_ids)
- self.assertEqual(follower.subtype_ids, self.mt_mg_nodef)
-
- def test_followers_multiple_subscription(self):
- test_record = self.test_record.sudo(self.user_employee)
-
- test_record.message_subscribe(partner_ids=[self.user_admin.partner_id.id], subtype_ids=[self.mt_mg_nodef.id])
- self.assertEqual(test_record.message_partner_ids, self.user_admin.partner_id)
- self.assertEqual(test_record.message_channel_ids, self.env['mail.channel'])
- self.assertEqual(test_record.message_follower_ids.subtype_ids, self.mt_mg_nodef)
-
- test_record.message_subscribe(partner_ids=[self.user_admin.partner_id.id], subtype_ids=[self.mt_mg_nodef.id, self.mt_al_nodef.id])
- self.assertEqual(test_record.message_partner_ids, self.user_admin.partner_id)
- self.assertEqual(test_record.message_channel_ids, self.env['mail.channel'])
- self.assertEqual(test_record.message_follower_ids.filtered(lambda fol: fol.partner_id == self.user_admin.partner_id).subtype_ids, self.mt_mg_nodef | self.mt_al_nodef)
-
- def test_followers_no_DID(self):
- """Test that a follower cannot suffer from dissociative identity disorder.
- It cannot be both a partner and a channel.
- """
- with self.assertRaises(IntegrityError), mute_logger('odoo.sql_db'):
- self.env['mail.followers'].create({
- 'res_model': self.test_record._name,
- 'res_id': self.test_record.id,
- 'partner_id': self.user_employee.partner_id.id,
- 'channel_id': self.channel_listen.id,
- })
-
-
-class AdvancedFollowersTest(common.BaseFunctionalTest):
- @classmethod
- def setUpClass(cls):
- super(AdvancedFollowersTest, cls).setUpClass()
-
- cls.user_portal = cls.env['res.users'].with_context(cls._quick_create_user_ctx).create({
- 'name': 'Chell Gladys',
- 'login': 'chell',
- 'email': 'chell@gladys.portal',
- 'groups_id': [(6, 0, [cls.env.ref('base.group_portal').id])],
- })
-
- cls.test_track = cls.env['mail.test.track'].sudo(cls.user_employee).create({
- 'name': 'Test',
- })
-
- Subtype = cls.env['mail.message.subtype']
- cls.sub_nodef = Subtype.create({'name': 'Sub NoDefault', 'default': False, 'res_model': 'mail.test'})
- cls.sub_umb1 = Subtype.create({'name': 'Sub Umbrella1', 'default': False, 'res_model': 'mail.test.track'})
- cls.sub_umb2 = Subtype.create({'name': 'Sub Umbrella2', 'default': False, 'res_model': 'mail.test.track'})
- cls.umb_def = Subtype.create({'name': 'Umbrella Default', 'default': True, 'res_model': 'mail.test'})
- # create subtypes for auto subscription from umbrella to sub records
- cls.umb_sub_def = Subtype.create({
- 'name': 'Umbrella Sub1', 'default': True, 'res_model': 'mail.test',
- 'parent_id': cls.sub_umb1.id, 'relation_field': 'umbrella_id'})
- cls.umb_sub_nodef = Subtype.create({
- 'name': 'Umbrella Sub2', 'default': False, 'res_model': 'mail.test',
- 'parent_id': cls.sub_umb2.id, 'relation_field': 'umbrella_id'})
-
- def test_auto_subscribe_create(self):
- """ Creator of records are automatically added as followers """
- self.assertEqual(self.test_track.message_partner_ids, self.user_employee.partner_id)
-
- def test_auto_subscribe_post(self):
- """ People posting a message are automatically added as followers """
- self.test_track.sudo(self.user_admin).message_post(body='Coucou hibou', message_type='comment')
- self.assertEqual(self.test_track.message_partner_ids, self.user_employee.partner_id | self.user_admin.partner_id)
-
- def test_auto_subscribe_post_email(self):
- """ People posting an email are automatically added as followers """
- self.test_track.sudo(self.user_admin).message_post(body='Coucou hibou', message_type='email')
- self.assertEqual(self.test_track.message_partner_ids, self.user_employee.partner_id | self.user_admin.partner_id)
-
- def test_auto_subscribe_not_on_notification(self):
- """ People posting an automatic notification are not subscribed """
- self.test_track.sudo(self.user_admin).message_post(body='Coucou hibou', message_type='notification')
- self.assertEqual(self.test_track.message_partner_ids, self.user_employee.partner_id)
-
- def test_auto_subscribe_responsible(self):
- """ Responsibles are tracked and added as followers """
- sub = self.env['mail.test.track'].sudo(self.user_employee).create({
- 'name': 'Test',
- 'user_id': self.user_admin.id,
- })
-
- self.assertEqual(sub.message_partner_ids, (self.user_employee.partner_id | self.user_admin.partner_id))
-
- def test_auto_subscribe_defaults(self):
- """ Test auto subscription based on an umbrella record. This mimics
- the behavior of addons like project and task where subscribing to
- some project's subtypes automatically subscribe the follower to its tasks.
-
- Functional rules applied here
-
- * subscribing to an umbrella subtype with parent_id / relation_field set
- automatically create subscription with matching subtypes
- * subscribing to a sub-record as creator applies default subtype values
- * portal user should not have access to internal subtypes
- """
- umbrella = self.env['mail.test'].with_context(self._quick_create_ctx).create({
- 'name': 'Project-Like',
- })
-
- umbrella.message_subscribe(partner_ids=[self.user_portal.partner_id.id])
- self.assertEqual(umbrella.message_partner_ids, self.user_portal.partner_id)
-
- sub1 = self.env['mail.test.track'].sudo(self.user_employee).create({
- 'name': 'Task-Like Test',
- 'umbrella_id': umbrella.id,
- })
-
- all_defaults = self.env['mail.message.subtype'].search([('default', '=', True), '|', ('res_model', '=', 'mail.test.full'), ('res_model', '=', False)])
- external_defaults = all_defaults.filtered(lambda subtype: not subtype.internal)
-
- self.assertEqual(sub1.message_partner_ids, self.user_portal.partner_id | self.user_employee.partner_id)
- self.assertEqual(
- sub1.message_follower_ids.filtered(lambda fol: fol.partner_id == self.user_portal.partner_id).subtype_ids,
- external_defaults | self.sub_umb1)
- self.assertEqual(
- sub1.message_follower_ids.filtered(lambda fol: fol.partner_id == self.user_employee.partner_id).subtype_ids,
- all_defaults)
diff --git a/addons/mail/tests/test_mail_gateway.py b/addons/mail/tests/test_mail_gateway.py
deleted file mode 100644
index 575972d4adf..00000000000
--- a/addons/mail/tests/test_mail_gateway.py
+++ /dev/null
@@ -1,512 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-import socket
-
-from email.utils import formataddr
-
-from odoo.addons.mail.tests.data.test_mail_data import MAIL_TEMPLATE, MAIL_TEMPLATE_PLAINTEXT, MAIL_MULTIPART_MIXED, MAIL_MULTIPART_MIXED_TWO, MAIL_MULTIPART_IMAGE
-from odoo.addons.mail.tests.common import BaseFunctionalTest, MockEmails
-from odoo.tools import mute_logger
-
-
-class TestEmailParsing(BaseFunctionalTest, MockEmails):
-
- @mute_logger('odoo.addons.mail.models.mail_thread')
- def test_message_parse(self):
- pass
-
- def test_message_parse_body(self):
- # test pure plaintext
- plaintext = self.format(MAIL_TEMPLATE_PLAINTEXT, email_from='Sylvie Lelitre <test.sylvie.lelitre@agrolait.com>')
- res = self.env['mail.thread'].message_parse(plaintext)
- self.assertIn('Please call me as soon as possible this afternoon!', res['body'])
-
- # test multipart / text and html -> html has priority
- multipart = self.format(MAIL_TEMPLATE, email_from='Sylvie Lelitre <test.sylvie.lelitre@agrolait.com>')
- res = self.env['mail.thread'].message_parse(multipart)
- self.assertIn('<p>Please call me as soon as possible this afternoon!</p>', res['body'])
-
- # test multipart / mixed
- res = self.env['mail.thread'].message_parse(MAIL_MULTIPART_MIXED)
- self.assertNotIn(
- 'Should create a multipart/mixed: from gmail, *bold*, with attachment', res['body'],
- 'message_parse: text version should not be in body after parsing multipart/mixed')
- self.assertIn(
- '<div dir="ltr">Should create a multipart/mixed: from gmail, <b>bold</b>, with attachment.<br clear="all"><div><br></div>', res['body'],
- 'message_parse: html version should be in body after parsing multipart/mixed')
-
- res = self.env['mail.thread'].message_parse(MAIL_MULTIPART_MIXED_TWO)
- self.assertNotIn('First and second part', res['body'],
- 'message_parse: text version should not be in body after parsing multipart/mixed')
- self.assertIn('First part', res['body'],
- 'message_parse: first part of the html version should be in body after parsing multipart/mixed')
- self.assertIn('Second part', res['body'],
- 'message_parse: second part of the html version should be in body after parsing multipart/mixed')
-
-
-class TestMailgateway(BaseFunctionalTest, MockEmails):
-
- @classmethod
- def setUpClass(cls):
- super(TestMailgateway, cls).setUpClass()
- mail_test_simple_model = cls.env['ir.model']._get('mail.test.simple')
-
- cls.partner_1 = cls.env['res.partner'].with_context(cls._quick_create_ctx).create({
- 'name': 'Valid Lelitre',
- 'email': 'valid.lelitre@agrolait.com',
- })
- # groups@.. will cause the creation of new mail.test.simple
- cls.alias = cls.env['mail.alias'].create({
- 'alias_name': 'groups',
- 'alias_user_id': False,
- 'alias_model_id': mail_test_simple_model.id,
- 'alias_contact': 'everyone'})
-
- # Set a first message on public group to test update and hierarchy
- cls.fake_email = cls.env['mail.message'].create({
- 'model': 'mail.test.simple',
- 'res_id': cls.test_record.id,
- 'subject': 'Public Discussion',
- 'message_type': 'email',
- 'author_id': cls.partner_1.id,
- 'message_id': '<123456-openerp-%s-mail.test.simple@%s>' % (cls.test_record.id, socket.gethostname()),
- })
-
- @mute_logger('odoo.addons.mail.models.mail_thread')
- def test_message_process_cid(self):
- record = self.format_and_process(MAIL_MULTIPART_IMAGE, to='groups@example.com')
- message = record.message_ids[0]
- for attachment in message.attachment_ids:
- self.assertIn('/web/image/%s' % attachment.id, message.body)
-
- def test_message_process_followers(self):
- pass
- # TODO : the author of a message post should be added as follower
- # currently it is not the case as otherwise Administrator would be follower of a lot of stuff
- # this is a bug with mail_create_nosubscribe -> should be changed in master
- # self.assertEqual(record.message_partner_ids, self.partner_1,
- # 'message_process: recognized email -> added as follower')
-
- # TODO : the author of a message post on mail.test should not be added as follower
- # Test: author (and not recipient) added as follower
- # self.assertEqual(self.test_public.message_partner_ids, self.partner_1 | self.partner_2,
- # 'message_process: after reply, group should have 2 followers')
- # self.assertEqual(self.test_public.message_channel_ids, self.env['mail.test'],
- # 'message_process: after reply, group should have 2 followers (0 channels)')
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_alias_basic(self):
- """ Test details of created message going through mailgateway """
- record = self.format_and_process(MAIL_TEMPLATE, subject='Specific')
-
- # Test: one group created by mailgateway administrator as user_id is not set
- self.assertEqual(len(record), 1, 'message_process: a new mail.test should have been created')
- res = record.get_metadata()[0].get('create_uid') or [None]
- self.assertEqual(res[0], self.env.uid)
-
- # Test: one message that is the incoming email
- self.assertEqual(len(record.message_ids), 1)
- msg = record.message_ids[0]
- self.assertEqual(msg.subject, 'Specific')
- self.assertIn('Please call me as soon as possible this afternoon!', msg.body)
- self.assertEqual(msg.message_type, 'email')
- self.assertEqual(msg.subtype_id, self.env.ref('mail.mt_comment'))
-
- # --------------------------------------------------
- # Author recognition
- # --------------------------------------------------
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_email_email_from(self):
- """ Incoming email: not recognized author: email_from, no author_id, no followers """
- email_from = 'Sylvie Lelitre <test.sylvie.lelitre@agrolait.com>'
-
- record = self.format_and_process(MAIL_TEMPLATE, email_from=email_from)
- self.assertFalse(record.message_ids[0].author_id, 'message_process: unrecognized email -> no author_id')
- self.assertEqual(record.message_ids[0].email_from, email_from)
- self.assertEqual(len(record.message_partner_ids), 0,
- 'message_process: newly create group should not have any follower')
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_email_author(self):
- """ Incoming email: recognized author: email_from, author_id, added as follower """
- record = self.format_and_process(MAIL_TEMPLATE, email_from=formataddr((self.partner_1.name, self.partner_1.email)))
-
- self.assertEqual(record.message_ids[0].author_id, self.partner_1,
- 'message_process: recognized email -> author_id')
- self.assertEqual(record.message_ids[0].email_from, formataddr((self.partner_1.name, self.partner_1.email)))
- self.assertEqual(len(self._mails), 0, 'No notification / bounce should be sent')
-
- # --------------------------------------------------
- # Alias configuration
- # --------------------------------------------------
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_alias_user_id(self):
- """ Test alias ownership """
- self.alias.write({'alias_user_id': self.user_employee.id})
-
- record = self.format_and_process(MAIL_TEMPLATE)
- self.assertEqual(len(record), 1)
- res = record.get_metadata()[0].get('create_uid') or [None]
- self.assertEqual(res[0], self.user_employee.id)
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_alias_everyone(self):
- """ Incoming email: everyone: new record + message_new """
- self.alias.write({'alias_contact': 'everyone'})
-
- record = self.format_and_process(MAIL_TEMPLATE, subject='Specific')
- self.assertEqual(len(record), 1)
- self.assertEqual(len(record.message_ids), 1)
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
- def test_message_process_alias_partners_bounce(self):
- """ Incoming email from an unknown partner on a Partners only alias -> bounce + test bounce email """
- self.env['ir.config_parameter'].set_param('mail.bounce.alias', 'bounce.test')
- self.env['ir.config_parameter'].set_param('mail.catchall.domain', 'test.com')
- self.alias.write({'alias_contact': 'partners'})
-
- # Test: no group created, email bounced
- record = self.format_and_process(MAIL_TEMPLATE, subject='Should Bounce')
- self.assertTrue(len(record) == 0)
- self.assertEqual(len(self._mails), 1,
- 'message_process: incoming email on Partners alias should send a bounce email')
- # Test bounce email
- self.assertEqual(self._mails[0].get('subject'), 'Re: Should Bounce')
- self.assertEqual(self._mails[0].get('email_to')[0], 'whatever-2a840@postmaster.twitter.com')
- self.assertEqual(self._mails[0].get('email_from'), formataddr(('MAILER-DAEMON', 'bounce.test@test.com')))
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
- def test_message_process_alias_followers_bounce(self):
- """ Incoming email from unknown partner / not follower partner on a Followers only alias -> bounce """
- self.alias.write({
- 'alias_contact': 'followers',
- 'alias_parent_model_id': self.env['ir.model']._get('mail.test.simple').id,
- 'alias_parent_thread_id': self.test_record.id,
- })
-
- # Test: unknown on followers alias -> bounce
- record = self.format_and_process(MAIL_TEMPLATE, to='groups@example.com, other@gmail.com')
- self.assertEqual(len(record), 0, 'message_process: should have bounced')
- self.assertEqual(len(self._mails), 1,
- 'message_process: incoming email on Followers alias should send a bounce email')
-
- # Test: partner on followers alias -> bounce
- self._init_mock_build_email()
- record = self.format_and_process(MAIL_TEMPLATE, email_from=formataddr((self.partner_1.name, self.partner_1.email)))
- self.assertTrue(len(record) == 0, 'message_process: should have bounced')
- self.assertEqual(len(self._mails), 1,
- 'message_process: incoming email on Followers alias should send a bounce email')
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_alias_partner(self):
- """ Incoming email from a known partner on a Partners alias -> ok (+ test on alias.user_id) """
- self.alias.write({'alias_contact': 'partners'})
- record = self.format_and_process(MAIL_TEMPLATE, email_from=formataddr((self.partner_1.name, self.partner_1.email)))
-
- # Test: one group created by alias user
- self.assertEqual(len(record), 1)
- self.assertEqual(len(record.message_ids), 1)
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_alias_followers(self):
- """ Incoming email from a parent document follower on a Followers only alias -> ok """
- self.alias.write({
- 'alias_contact': 'followers',
- 'alias_parent_model_id': self.env['ir.model']._get('mail.test.simple').id,
- 'alias_parent_thread_id': self.test_record.id,
- })
- self.test_record.message_subscribe(partner_ids=[self.partner_1.id])
- record = self.format_and_process(MAIL_TEMPLATE, email_from=formataddr((self.partner_1.name, self.partner_1.email)))
-
- # Test: one group created by Raoul (or Sylvie maybe, if we implement it)
- self.assertEqual(len(record), 1)
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models.unlink', 'odoo.addons.mail.models.mail_mail')
- def test_message_process_alias_update(self):
- """ Incoming email update discussion + notification email """
- self.alias.write({'alias_force_thread_id': self.test_record.id})
-
- self.test_record.message_subscribe(partner_ids=[self.partner_1.id])
- record = self.format_and_process(
- MAIL_TEMPLATE, email_from='valid.other@gmail.com',
- msg_id='<1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>',
- to='groups@example.com>', subject='Re: cats')
-
- # Test: no new group + new message
- self.assertEqual(len(record), 0, 'message_process: alias update should not create new records')
- self.assertEqual(len(self.test_record.message_ids), 2)
- # Test: sent emails: 1 (Sylvie copy of the incoming email)
- self.assertEqual(len(self._mails), 1,
- 'message_process: one email should have been generated')
- self.assertEqual(formataddr((self.partner_1.name, self.partner_1.email)), self._mails[0].get('email_to')[0],
- 'message_process: email should be sent to Sylvie')
-
- # --------------------------------------------------
- # Thread formation
- # --------------------------------------------------
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_in_reply_to(self):
- """ Incoming email using in-rely-to should go into the right destination even with a wrong destination """
- self.format_and_process(
- MAIL_TEMPLATE, email_from='valid.other@gmail.com',
- msg_id='<1198923581.41972151344608186800.JavaMail.diff1@agrolait.com>',
- to='erroneous@example.com>', subject='Re: news',
- extra='In-Reply-To:\r\n\t%s\n' % self.fake_email.message_id)
-
- self.assertEqual(len(self.test_record.message_ids), 2, 'message_process: group should contain one new message')
- self.assertEqual(len(self.fake_email.child_ids), 1, 'message_process: new message should be children of the existing one')
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_references(self):
- """ Incoming email using references should go into the right destination even with a wrong destination """
- init_msg_count = len(self.test_record.message_ids)
- self.format_and_process(
- MAIL_TEMPLATE, to='erroneous@example.com',
- extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % self.fake_email.message_id,
- msg_id='<1198923581.41972151344608186800.JavaMail.4@agrolait.com>')
-
- self.assertEqual(len(self.test_record.message_ids), init_msg_count + 1)
- self.assertEqual(len(self.fake_email.child_ids), 1)
-
- @mute_logger('odoo.addons.mail.models.mail_thread')
- def test_message_process_references_external(self):
- """ Incoming email being a reply to an external email processed by odoo should update thread accordingly """
- new_message_id = '<ThisIsTooMuchFake.MonsterEmail.789@agrolait.com>'
- self.fake_email.write({
- 'message_id': new_message_id
- })
- init_msg_count = len(self.test_record.message_ids)
- self.format_and_process(
- MAIL_TEMPLATE, to='erroneous@example.com',
- extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % self.fake_email.message_id,
- msg_id='<1198923581.41972151344608186800.JavaMail.4@agrolait.com>')
-
- self.assertEqual(len(self.test_record.message_ids), init_msg_count + 1)
- self.assertEqual(len(self.fake_email.child_ids), 1)
-
- @mute_logger('odoo.addons.mail.models.mail_thread')
- def test_message_process_references_forward(self):
- """ Incoming email using references but with alias forward should not go into references destination """
- new_alias_2 = self.env['mail.alias'].create({
- 'alias_name': 'test',
- 'alias_user_id': False,
- 'alias_model_id': self.env['ir.model']._get('mail.test').id,
- 'alias_contact': 'everyone',
- })
- init_msg_count = len(self.test_record.message_ids)
- res_test = self.format_and_process(
- MAIL_TEMPLATE, to='test@example.com',
- subject='My Dear Forward',
- extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % self.fake_email.message_id,
- msg_id='<1198923581.41972151344608186800.JavaMail.4@agrolait.com>',
- target_model='mail.test')
-
- self.assertEqual(len(self.test_record.message_ids), init_msg_count)
- self.assertEqual(len(self.fake_email.child_ids), 0)
- self.assertEqual(res_test.name, 'My Dear Forward')
- self.assertEqual(len(res_test.message_ids), 1)
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_references_forward_cc(self):
- """ Incoming email using references but with alias forward should not go into references destination """
- self.format_and_process(
- MAIL_TEMPLATE, to='erroneous@example.com', cc='test@example.com',
- subject='My Dear Forward',
- extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % self.fake_email.message_id,
- msg_id='<1198923581.41972151344608186800.JavaMail.4@agrolait.com>',
- target_model='mail.test.simple')
-
- self.assertEqual(len(self.test_record.message_ids), 2, 'message_process: group should contain one new message')
- self.assertEqual(len(self.fake_email.child_ids), 1, 'message_process: new message should be children of the existing one')
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_model_res_id(self):
- """ Incoming email with ref holding model / res_id but that does not match any message in the thread: must raise since OpenERP saas-3 """
- self.assertRaises(ValueError,
- self.format_and_process, MAIL_TEMPLATE,
- email_from=formataddr((self.partner_1.name, self.partner_1.email)),
- to='noone@example.com', subject='spam',
- extra='In-Reply-To: <12321321-openerp-%d-mail.test.simple@%s>' % (self.test_record.id, socket.gethostname()),
- msg_id='<1198923581.41972151344608186802.JavaMail.diff1@agrolait.com>')
-
- # when 6.1 messages are present, compat mode is available
- # Odoo 10 update: compat mode has been removed and should not work anymore
- self.fake_email.write({'message_id': False})
- # Do: compat mode accepts partial-matching emails
- self.assertRaises(
- ValueError,
- self.format_and_process,
- MAIL_TEMPLATE, email_from=formataddr((self.partner_1.name, self.partner_1.email)),
- msg_id='<1.2.JavaMail.new@agrolait.com>',
- to='noone@example.com>', subject='spam',
- extra='In-Reply-To: <12321321-openerp-%d-mail.test.simple@%s>' % (self.test_record.id, socket.gethostname()))
-
- # 3''. 6.1 compat mode should not work if hostname does not match!
- # Odoo 10 update: compat mode has been removed and should not work anymore and does not depend from hostname
- self.assertRaises(ValueError,
- self.format_and_process,
- MAIL_TEMPLATE, email_from=formataddr((self.partner_1.name, self.partner_1.email)),
- msg_id='<1.3.JavaMail.new@agrolait.com>',
- to='noone@example.com>', subject='spam',
- extra='In-Reply-To: <12321321-openerp-%d-mail.test@neighbor.com>' % self.test_record.id)
-
- # Test created messages
- self.assertEqual(len(self.test_record.message_ids), 1)
- self.assertEqual(len(self.test_record.message_ids[0].child_ids), 0)
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_duplicate(self):
- """ Duplicate emails (same message_id) are not processed """
- self.alias.write({'alias_force_thread_id': self.test_record.id,})
-
- # Post a base message
- record = self.format_and_process(
- MAIL_TEMPLATE, email_from='valid.other@gmail.com', subject='Re: super cats',
- msg_id='<1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>')
-
- # Do: due to some issue, same email goes back into the mailgateway
- record = self.format_and_process(
- MAIL_TEMPLATE, email_from='other4@gmail.com', subject='Re: news',
- msg_id='<1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>',
- extra='In-Reply-To: <1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>\n')
-
- # Test: no group 'Re: news' created, still only 1 Frogs group
- self.assertEqual(len(record), 0)
-
- # Test: no new message
- self.assertEqual(len(self.test_record.message_ids), 2, 'message_process: message with already existing message_id should not have been duplicated')
- # Test: message_id is still unique
- no_of_msg = self.env['mail.message'].search_count([('message_id', 'ilike', '<1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>')])
- self.assertEqual(no_of_msg, 1,
- 'message_process: message with already existing message_id should not have been duplicated')
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_partner_find(self):
- """ Finding the partner based on email, based on partner / user / follower """
- self.alias.write({'alias_force_thread_id': self.test_record.id})
- from_1 = self.env['res.partner'].create({'name': 'Brice Denisse', 'email': 'from.test@example.com'})
-
- self.format_and_process(MAIL_TEMPLATE, msg_id='<1>', email_from='Brice Denisse <from.test@example.com>')
- self.assertEqual(self.test_record.message_ids[0].author_id, from_1)
- self.test_record.message_unsubscribe([from_1.id])
-
- from_2 = self.env['res.users'].with_context(self._quick_create_user_ctx).create({'name': 'Brice Denisse', 'login': 'B', 'email': 'from.test@example.com'})
-
- self.format_and_process(MAIL_TEMPLATE, msg_id='<2>', email_from='Brice Denisse <from.test@example.com>')
- self.assertEqual(self.test_record.message_ids[0].author_id, from_2.partner_id)
- self.test_record.message_unsubscribe([from_2.partner_id.id])
-
- from_3 = self.env['res.partner'].create({'name': 'Brice Denisse', 'email': 'from.test@example.com'})
- self.test_record.message_subscribe([from_3.id])
-
- self.format_and_process(MAIL_TEMPLATE, msg_id='<3>', email_from='Brice Denisse <from.test@example.com>')
- self.assertEqual(self.test_record.message_ids[0].author_id, from_3)
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_crash_wrong_model(self):
- """ Incoming email with model that does not accepts incoming emails must raise """
- self.assertRaises(ValueError,
- self.format_and_process,
- MAIL_TEMPLATE,
- to='noone@example.com', subject='spam', extra='', model='res.country',
- msg_id='<1198923581.41972151344608186760.JavaMail.new4@agrolait.com>')
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_crash_no_data(self):
- """ Incoming email without model and without alias must raise """
- self.assertRaises(ValueError,
- self.format_and_process,
- MAIL_TEMPLATE,
- to='noone@example.com', subject='spam', extra='',
- msg_id='<1198923581.41972151344608186760.JavaMail.new5@agrolait.com>')
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_fallback(self):
- """ Incoming email with model that accepting incoming emails as fallback """
- record = self.format_and_process(
- MAIL_TEMPLATE, to='noone@example.com', subject='Spammy', extra='', model='mail.test.simple',
- msg_id='<1198923581.41972151344608186760.JavaMail.new6@agrolait.com>')
- self.assertEqual(len(record), 1)
- self.assertEqual(record._name, 'mail.test.simple')
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models')
- def test_message_process_plain_text(self):
- """ Incoming email in plaintext should be stored as html """
- record = self.format_and_process(
- MAIL_TEMPLATE_PLAINTEXT, to='groups@example.com', subject='Frogs Return', extra='',
- msg_id='<deadcafe.1337@smtp.agrolait.com>')
- self.assertEqual(len(record), 1, 'message_process: a new mail.test should have been created')
- msg = record.message_ids[0]
- # signature recognition -> Sylvie should be in a span
- self.assertIn('<pre>\nPlease call me as soon as possible this afternoon!\n<span data-o-mail-quote="1">\n--\nSylvie\n</span></pre>', msg.body,
- 'message_process: plaintext incoming email incorrectly parsed')
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models', 'odoo.addons.mail.models.mail_mail')
- def test_private_discussion(self):
- """ Testing private discussion between partners. """
- msg1_pids = [self.env.user.partner_id.id, self.partner_1.id]
-
- # Do: Raoul writes to Bert and Administrator, with a thread_model in context that should not be taken into account
- msg1 = self.env['mail.thread'].with_context({
- 'thread_model': 'mail.test'
- }).sudo(self.user_employee).message_post(partner_ids=msg1_pids, subtype='mail.mt_comment')
-
- # Test: message recipients
- msg = self.env['mail.message'].browse(msg1.id)
- self.assertEqual(msg.partner_ids, self.env.user.partner_id | self.partner_1,
- 'message_post: private discussion: incorrect recipients')
- self.assertEqual(msg.model, False,
- 'message_post: private discussion: context key "thread_model" not correctly ignored when having no res_id')
- # Test: message-id
- self.assertIn('openerp-private', msg.message_id, 'message_post: private discussion: message-id should contain the private keyword')
-
- # Do: Bert replies through mailgateway (is a customer)
- self.format_and_process(
- MAIL_TEMPLATE, to='not_important@mydomain.com', email_from='valid.lelitre@agrolait.com',
- extra='In-Reply-To: %s' % msg.message_id, msg_id='<test30.JavaMail.0@agrolait.com>')
-
- # Test: last mail_message created
- msg2 = self.env['mail.message'].search([], limit=1)
- # Test: message recipients
- self.assertEqual(msg2.author_id, self.partner_1,
- 'message_post: private discussion: wrong author through mailgateway based on email')
- self.assertEqual(msg2.partner_ids, self.user_employee.partner_id | self.env.user.partner_id,
- 'message_post: private discussion: incorrect recipients when replying')
-
- # Do: Bert replies through chatter (is a customer)
- msg3 = self.env['mail.thread'].message_post(author_id=self.partner_1.id, parent_id=msg1.id, subtype='mail.mt_comment')
-
- # Test: message recipients
- msg = self.env['mail.message'].browse(msg3.id)
- self.assertEqual(msg.partner_ids, self.user_employee.partner_id | self.env.user.partner_id,
- 'message_post: private discussion: incorrect recipients when replying')
- self.assertEqual(msg.needaction_partner_ids, self.user_employee.partner_id | self.env.user.partner_id,
- 'message_post: private discussion: incorrect notified recipients when replying')
-
- @mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.models', 'odoo.addons.mail.models.mail_mail')
- def test_forward_parent_id(self):
- msg = self.test_record.sudo(self.user_employee).message_post(no_auto_thread=True, subtype='mail.mt_comment')
- self.assertNotIn(msg.model, msg.message_id)
- self.assertNotIn('-%d-' % msg.res_id, msg.message_id)
- self.assertIn('reply_to', msg.message_id)
-
- # forward it to a new thread AND an existing thread
- fw_msg_id = '<THIS.IS.A.FW.MESSAGE.1@bert.fr>'
- fw_message = MAIL_TEMPLATE.format(to='groups@example.com',
- cc='',
- subject='FW: Re: 1',
- email_from='b.t@example.com',
- extra='In-Reply-To: %s' % msg.message_id,
- msg_id=fw_msg_id)
- self.env['mail.thread'].message_process(None, fw_message)
- msg_fw = self.env['mail.message'].search([('message_id', '=', fw_msg_id)])
- self.assertEqual(len(msg_fw), 1)
- new_record = self.env['mail.test.simple'].search([('name', "=", msg_fw.subject)])
- self.assertEqual(len(new_record), 1)
- self.assertEqual(msg_fw.model, 'mail.test.simple')
- self.assertFalse(msg_fw.parent_id)
- self.assertTrue(msg_fw.res_id == new_record.id)
diff --git a/addons/mail/tests/test_mail_mail.py b/addons/mail/tests/test_mail_mail.py
deleted file mode 100644
index 862178c0c7c..00000000000
--- a/addons/mail/tests/test_mail_mail.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-import itertools
-
-from odoo.addons.mail.tests import common as mail_common
-from odoo.tests import common
-from odoo.tools import mute_logger
-
-
-class TestMail(common.SavepointCase, mail_common.MockEmails):
-
- @classmethod
- def setUpClass(cls):
- super(TestMail, cls).setUpClass()
-
- cls.user_employee = cls.env['res.users'].with_context({
- 'no_reset_password': True,
- 'mail_create_nolog': True,
- 'mail_create_nosubscribe': True,
- 'mail_notrack': True,
- }).create({
- 'name': 'Ernest Employee',
- 'login': 'ernest',
- 'email': 'e.e@example.com',
- 'signature': '--\nErnest',
- 'notification_type': 'email',
- 'groups_id': [(6, 0, [cls.env.ref('base.group_user').id])]
- })
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_mail_message_notify_from_mail_mail(self):
- # Due ot post-commit hooks, store send emails in every step
- self.email_to_list = []
- mail = self.env['mail.mail'].create({
- 'body_html': '<p>Test</p>',
- 'email_to': 'test@example.com',
- 'partner_ids': [(4, self.user_employee.partner_id.id)]
- })
- self.email_to_list.extend(itertools.chain.from_iterable(sent_email['email_to'] for sent_email in self._mails if sent_email.get('email_to')))
- self.assertNotIn(u'Ernest Employee <e.e@example.com>', self.email_to_list)
- mail.send()
- self.email_to_list.extend(itertools.chain.from_iterable(sent_email['email_to'] for sent_email in self._mails if sent_email.get('email_to')))
- self.assertNotIn(u'Ernest Employee <e.e@example.com>', self.email_to_list)
- self.assertIn(u'test@example.com', self.email_to_list)
diff --git a/addons/mail/tests/test_mail_message.py b/addons/mail/tests/test_mail_message.py
deleted file mode 100644
index 779b8d4f526..00000000000
--- a/addons/mail/tests/test_mail_message.py
+++ /dev/null
@@ -1,276 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-import base64
-
-from odoo.addons.mail.tests import common
-from odoo.exceptions import AccessError, except_orm
-from odoo.tools import mute_logger
-
-
-class TestMessageValues(common.BaseFunctionalTest, common.MockEmails):
-
- @classmethod
- def setUpClass(cls):
- super(TestMessageValues, cls).setUpClass()
-
- cls.alias_record = cls.env['mail.test'].with_context(cls._quick_create_ctx).create({
- 'name': 'Pigs',
- 'alias_name': 'pigs',
- 'alias_contact': 'followers',
- })
-
- cls.Message = cls.env['mail.message'].sudo(cls.user_employee)
-
- def test_mail_message_values_basic(self):
- self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.domain')]).unlink()
-
- msg = self.Message.create({
- 'reply_to': 'test.reply@example.com',
- 'email_from': 'test.from@example.com',
- })
- self.assertIn('-private', msg.message_id, 'mail_message: message_id for a void message should be a "private" one')
- self.assertEqual(msg.reply_to, 'test.reply@example.com')
- self.assertEqual(msg.email_from, 'test.from@example.com')
-
- def test_mail_message_values_default(self):
- self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.domain')]).unlink()
-
- msg = self.Message.create({})
- self.assertIn('-private', msg.message_id, 'mail_message: message_id for a void message should be a "private" one')
- self.assertEqual(msg.reply_to, '%s <%s>' % (self.user_employee.name, self.user_employee.email))
- self.assertEqual(msg.email_from, '%s <%s>' % (self.user_employee.name, self.user_employee.email))
-
- @mute_logger('odoo.models.unlink')
- def test_mail_message_values_alias(self):
- alias_domain = 'example.com'
- self.env['ir.config_parameter'].set_param('mail.catchall.domain', alias_domain)
- self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.alias')]).unlink()
-
- msg = self.Message.create({})
- self.assertIn('-private', msg.message_id, 'mail_message: message_id for a void message should be a "private" one')
- self.assertEqual(msg.reply_to, '%s <%s>' % (self.user_employee.name, self.user_employee.email))
- self.assertEqual(msg.email_from, '%s <%s>' % (self.user_employee.name, self.user_employee.email))
-
- def test_mail_message_values_alias_catchall(self):
- alias_domain = 'example.com'
- alias_catchall = 'pokemon'
- self.env['ir.config_parameter'].set_param('mail.catchall.domain', alias_domain)
- self.env['ir.config_parameter'].set_param('mail.catchall.alias', alias_catchall)
-
- msg = self.Message.create({})
- self.assertIn('-private', msg.message_id, 'mail_message: message_id for a void message should be a "private" one')
- self.assertEqual(msg.reply_to, '%s <%s@%s>' % (self.env.user.company_id.name, alias_catchall, alias_domain))
- self.assertEqual(msg.email_from, '%s <%s>' % (self.user_employee.name, self.user_employee.email))
-
- def test_mail_message_values_document_no_alias(self):
- self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.domain')]).unlink()
-
- msg = self.Message.create({
- 'model': 'mail.test',
- 'res_id': self.alias_record.id
- })
- self.assertIn('-openerp-%d-mail.test' % self.alias_record.id, msg.message_id)
- self.assertEqual(msg.reply_to, '%s <%s>' % (self.user_employee.name, self.user_employee.email))
- self.assertEqual(msg.email_from, '%s <%s>' % (self.user_employee.name, self.user_employee.email))
-
- @mute_logger('odoo.models.unlink')
- def test_mail_message_values_document_alias(self):
- alias_domain = 'example.com'
- self.env['ir.config_parameter'].set_param('mail.catchall.domain', alias_domain)
- self.env['ir.config_parameter'].search([('key', '=', 'mail.catchall.alias')]).unlink()
-
- msg = self.Message.create({
- 'model': 'mail.test',
- 'res_id': self.alias_record.id
- })
- self.assertIn('-openerp-%d-mail.test' % self.alias_record.id, msg.message_id)
- self.assertEqual(msg.reply_to, '%s %s <%s@%s>' % (self.env.user.company_id.name, self.alias_record.name, self.alias_record.alias_name, alias_domain))
- self.assertEqual(msg.email_from, '%s <%s>' % (self.user_employee.name, self.user_employee.email))
-
- def test_mail_message_values_document_alias_catchall(self):
- alias_domain = 'example.com'
- alias_catchall = 'pokemon'
- self.env['ir.config_parameter'].set_param('mail.catchall.domain', alias_domain)
- self.env['ir.config_parameter'].set_param('mail.catchall.alias', alias_catchall)
-
- msg = self.Message.create({
- 'model': 'mail.test',
- 'res_id': self.alias_record.id
- })
- self.assertIn('-openerp-%d-mail.test' % self.alias_record.id, msg.message_id)
- self.assertEqual(msg.reply_to, '%s %s <%s@%s>' % (self.env.user.company_id.name, self.alias_record.name, self.alias_record.alias_name, alias_domain))
- self.assertEqual(msg.email_from, '%s <%s>' % (self.user_employee.name, self.user_employee.email))
-
- def test_mail_message_values_no_auto_thread(self):
- msg = self.Message.create({
- 'model': 'mail.test',
- 'res_id': self.alias_record.id,
- 'no_auto_thread': True,
- })
- self.assertIn('reply_to', msg.message_id)
- self.assertNotIn('mail.test', msg.message_id)
- self.assertNotIn('-%d-' % self.alias_record.id, msg.message_id)
-
-
-class TestMessageAccess(common.BaseFunctionalTest, common.MockEmails):
-
- @classmethod
- def setUpClass(cls):
- super(TestMessageAccess, cls).setUpClass()
-
- Users = cls.env['res.users'].with_context(cls._quick_create_user_ctx)
- cls.user_public = Users.create({
- 'name': 'Bert Tartignole',
- 'login': 'bert',
- 'email': 'b.t@example.com',
- 'groups_id': [(6, 0, [cls.env.ref('base.group_public').id])]})
- cls.user_portal = Users.create({
- 'name': 'Chell Gladys',
- 'login': 'chell',
- 'email': 'chell@gladys.portal',
- 'groups_id': [(6, 0, [cls.env.ref('base.group_portal').id])]})
-
- Channel = cls.env['mail.channel'].with_context(cls._quick_create_ctx)
- # Pigs: base group for tests
- cls.group_pigs = Channel.create({
- 'name': 'Pigs',
- 'public': 'groups',
- 'group_public_id': cls.env.ref('base.group_user').id})
- # Jobs: public group
- cls.group_public = Channel.create({
- 'name': 'Jobs',
- 'description': 'NotFalse',
- 'public': 'public'})
- # Private: private gtroup
- cls.group_private = Channel.create({
- 'name': 'Private',
- 'public': 'private'})
- cls.message = cls.env['mail.message'].create({
- 'body': 'My Body',
- 'model': 'mail.channel',
- 'res_id': cls.group_private.id,
- })
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_mail_message_access_search(self):
- # Data: various author_ids, partner_ids, documents
- msg1 = self.env['mail.message'].create({
- 'subject': '_Test', 'body': 'A', 'subtype_id': self.ref('mail.mt_comment')})
- msg2 = self.env['mail.message'].create({
- 'subject': '_Test', 'body': 'A+B', 'subtype_id': self.ref('mail.mt_comment'),
- 'partner_ids': [(6, 0, [self.user_public.partner_id.id])]})
- msg3 = self.env['mail.message'].create({
- 'subject': '_Test', 'body': 'A Pigs', 'subtype_id': False,
- 'model': 'mail.channel', 'res_id': self.group_pigs.id})
- msg4 = self.env['mail.message'].create({
- 'subject': '_Test', 'body': 'A+P Pigs', 'subtype_id': self.ref('mail.mt_comment'),
- 'model': 'mail.channel', 'res_id': self.group_pigs.id,
- 'partner_ids': [(6, 0, [self.user_public.partner_id.id])]})
- msg5 = self.env['mail.message'].create({
- 'subject': '_Test', 'body': 'A+E Pigs', 'subtype_id': self.ref('mail.mt_comment'),
- 'model': 'mail.channel', 'res_id': self.group_pigs.id,
- 'partner_ids': [(6, 0, [self.user_employee.partner_id.id])]})
- msg6 = self.env['mail.message'].create({
- 'subject': '_Test', 'body': 'A Birds', 'subtype_id': self.ref('mail.mt_comment'),
- 'model': 'mail.channel', 'res_id': self.group_private.id})
- msg7 = self.env['mail.message'].sudo(self.user_employee).create({
- 'subject': '_Test', 'body': 'B', 'subtype_id': self.ref('mail.mt_comment')})
- msg8 = self.env['mail.message'].sudo(self.user_employee).create({
- 'subject': '_Test', 'body': 'B+E', 'subtype_id': self.ref('mail.mt_comment'),
- 'partner_ids': [(6, 0, [self.user_employee.partner_id.id])]})
-
- # Test: Public: 2 messages (recipient)
- messages = self.env['mail.message'].sudo(self.user_public).search([('subject', 'like', '_Test')])
- self.assertEqual(messages, msg2 | msg4)
-
- # Test: Employee: 3 messages on Pigs Raoul can read (employee can read group with default values)
- messages = self.env['mail.message'].sudo(self.user_employee).search([('subject', 'like', '_Test'), ('body', 'ilike', 'A')])
- self.assertEqual(messages, msg3 | msg4 | msg5)
-
- # Test: Raoul: 3 messages on Pigs Raoul can read (employee can read group with default values), 0 on Birds (private group) + 2 messages as author
- messages = self.env['mail.message'].sudo(self.user_employee).search([('subject', 'like', '_Test')])
- self.assertEqual(messages, msg3 | msg4 | msg5 | msg7 | msg8)
-
- # Test: Admin: all messages
- messages = self.env['mail.message'].search([('subject', 'like', '_Test')])
- self.assertEqual(messages, msg1 | msg2 | msg3 | msg4 | msg5 | msg6 | msg7 | msg8)
-
- # Test: Portal: 0 (no access to groups, not recipient)
- messages = self.env['mail.message'].sudo(self.user_portal).search([('subject', 'like', '_Test')])
- self.assertFalse(messages)
-
- # Test: Portal: 2 messages (public group with a subtype)
- self.group_pigs.write({'public': 'public'})
- messages = self.env['mail.message'].sudo(self.user_portal).search([('subject', 'like', '_Test')])
- self.assertEqual(messages, msg4 | msg5)
-
- @mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
- def test_mail_message_access_read_crash(self):
- # TODO: Change the except_orm to Warning ( Because here it's call check_access_rule
- # which still generate exception in except_orm.So we need to change all
- # except_orm to warning in mail module.)
- with self.assertRaises(except_orm):
- self.message.sudo(self.user_employee).read()
-
- @mute_logger('odoo.models')
- def test_mail_message_access_read_crash_portal(self):
- with self.assertRaises(except_orm):
- self.message.sudo(self.user_portal).read(['body', 'message_type', 'subtype_id'])
-
- def test_mail_message_access_read_ok_portal(self):
- self.message.write({'subtype_id': self.ref('mail.mt_comment'), 'res_id': self.group_public.id})
- self.message.sudo(self.user_portal).read(['body', 'message_type', 'subtype_id'])
-
- def test_mail_message_access_read_notification(self):
- attachment = self.env['ir.attachment'].create({
- 'datas': base64.b64encode(b'My attachment'),
- 'name': 'doc.txt',
- 'datas_fname': 'doc.txt'})
- # attach the attachment to the message
- self.message.write({'attachment_ids': [(4, attachment.id)]})
- self.message.write({'partner_ids': [(4, self.user_employee.partner_id.id)]})
- self.message.sudo(self.user_employee).read()
- # Test: Bert has access to attachment, ok because he can read message
- attachment.sudo(self.user_employee).read(['name', 'datas'])
-
- def test_mail_message_access_read_author(self):
- self.message.write({'author_id': self.user_employee.partner_id.id})
- self.message.sudo(self.user_employee).read()
-
- def test_mail_message_access_read_doc(self):
- self.message.write({'model': 'mail.channel', 'res_id': self.group_public.id})
- # Test: Bert reads the message, ok because linked to a doc he is allowed to read
- self.message.sudo(self.user_employee).read()
-
- @mute_logger('odoo.addons.base.models.ir_model')
- def test_mail_message_access_create_crash_public(self):
- # Do: Bert creates a message on Pigs -> ko, no creation rights
- with self.assertRaises(AccessError):
- self.env['mail.message'].sudo(self.user_public).create({'model': 'mail.channel', 'res_id': self.group_pigs.id, 'body': 'Test'})
-
- # Do: Bert create a message on Jobs -> ko, no creation rights
- with self.assertRaises(AccessError):
- self.env['mail.message'].sudo(self.user_public).create({'model': 'mail.channel', 'res_id': self.group_public.id, 'body': 'Test'})
-
- @mute_logger('odoo.models')
- def test_mail_message_access_create_crash(self):
- # Do: Bert create a private message -> ko, no creation rights
- with self.assertRaises(except_orm):
- self.env['mail.message'].sudo(self.user_employee).create({'model': 'mail.channel', 'res_id': self.group_private.id, 'body': 'Test'})
-
- @mute_logger('odoo.models')
- def test_mail_message_access_create_doc(self):
- # TODO Change the except_orm to Warning
- Message = self.env['mail.message'].sudo(self.user_employee)
- # Do: Raoul creates a message on Jobs -> ok, write access to the related document
- Message.create({'model': 'mail.channel', 'res_id': self.group_public.id, 'body': 'Test'})
- # Do: Raoul creates a message on Priv -> ko, no write access to the related document
- with self.assertRaises(except_orm):
- Message.create({'model': 'mail.channel', 'res_id': self.group_private.id, 'body': 'Test'})
-
- def test_mail_message_access_create_private(self):
- self.env['mail.message'].sudo(self.user_employee).create({'body': 'Test'})
-
- def test_mail_message_access_create_reply(self):
- self.message.write({'partner_ids': [(4, self.user_employee.partner_id.id)]})
- self.env['mail.message'].sudo(self.user_employee).create({'model': 'mail.channel', 'res_id': self.group_private.id, 'body': 'Test', 'parent_id': self.message.id})
diff --git a/addons/mail/tests/test_mail_template.py b/addons/mail/tests/test_mail_template.py
deleted file mode 100644
index 5705ac3ad4e..00000000000
--- a/addons/mail/tests/test_mail_template.py
+++ /dev/null
@@ -1,203 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-import base64
-from datetime import datetime, timedelta
-
-from odoo.addons.mail.tests.common import BaseFunctionalTest, MockEmails, TestRecipients
-from odoo.tools import mute_logger, DEFAULT_SERVER_DATETIME_FORMAT
-
-
-class TestMailTemplate(BaseFunctionalTest, MockEmails, TestRecipients):
-
- def setUp(self):
- super(TestMailTemplate, self).setUp()
-
- self.user_employee.write({
- 'groups_id': [(4, self.env.ref('base.group_partner_manager').id)],
- })
-
- self._attachments = [{
- 'name': '_Test_First',
- 'datas_fname': 'first.txt',
- 'datas': base64.b64encode(b'My first attachment'),
- 'res_model': 'res.partner',
- 'res_id': self.user_admin.partner_id.id
- }, {
- 'name': '_Test_Second',
- 'datas_fname': 'second.txt',
- 'datas': base64.b64encode(b'My second attachment'),
- 'res_model': 'res.partner',
- 'res_id': self.user_admin.partner_id.id
- }]
-
- self.email_1 = 'test1@example.com'
- self.email_2 = 'test2@example.com'
- self.email_3 = self.partner_1.email
- self.email_template = self.env['mail.template'].create({
- 'model_id': self.env['ir.model']._get('mail.test.simple').id,
- 'name': 'Pigs Template',
- 'subject': '${object.name}',
- 'body_html': '${object.email_from}',
- 'user_signature': False,
- 'attachment_ids': [(0, 0, self._attachments[0]), (0, 0, self._attachments[1])],
- 'partner_to': '%s,%s' % (self.partner_2.id, self.user_admin.partner_id.id),
- 'email_to': '%s, %s' % (self.email_1, self.email_2),
- 'email_cc': '%s' % self.email_3})
-
- # admin should receive emails
- self.user_admin.write({'notification_type': 'email'})
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_composer_w_template(self):
- composer = self.env['mail.compose.message'].sudo(self.user_employee).with_context({
- 'default_composition_mode': 'comment',
- 'default_model': 'mail.test.simple',
- 'default_res_id': self.test_record.id,
- 'default_template_id': self.email_template.id,
- }).create({'subject': 'Forget me subject', 'body': 'Dummy body'})
-
- # perform onchange and send emails
- values = composer.onchange_template_id(self.email_template.id, 'comment', self.test_record._name, self.test_record.id)['value']
- composer.write(values)
- composer.send_mail()
-
- new_partners = self.env['res.partner'].search([('email', 'in', [self.email_1, self.email_2])])
- self.assertEmails(
- self.user_employee.partner_id,
- [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]],
- subject=self.test_record.name,
- body_content=self.test_record.email_from,
- attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')])
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_post_post_w_template(self):
- self.test_record.sudo(self.user_employee).message_post_with_template(self.email_template.id, composition_mode='comment')
-
- new_partners = self.env['res.partner'].search([('email', 'in', [self.email_1, self.email_2])])
- self.assertEmails(
- self.user_employee.partner_id,
- [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]],
- subject=self.test_record.name,
- body_content=self.test_record.email_from,
- attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')])
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_composer_w_template_mass_mailing(self):
- test_record_2 = self.env['mail.test.simple'].with_context(self._quick_create_ctx).create({'name': 'Test2', 'email_from': 'laurie.poiret@example.com'})
-
- composer = self.env['mail.compose.message'].sudo(self.user_employee).with_context({
- 'default_composition_mode': 'mass_mail',
- # 'default_notify': True,
- 'default_notify': False,
- 'default_model': 'mail.test.simple',
- 'default_res_id': self.test_record.id,
- 'default_template_id': self.email_template.id,
- 'active_ids': [self.test_record.id, test_record_2.id]
- }).create({})
- values = composer.onchange_template_id(self.email_template.id, 'mass_mail', 'mail.test.simple', self.test_record.id)['value']
- composer.write(values)
- composer.send_mail()
-
- new_partners = self.env['res.partner'].search([('email', 'in', [self.email_1, self.email_2])])
- # hack to use assertEmails
- self._mails_record1 = [dict(mail) for mail in self._mails if '%s-%s' % (self.test_record.id, self.test_record._name) in mail['message_id']]
- self._mails_record2 = [dict(mail) for mail in self._mails if '%s-%s' % (test_record_2.id, test_record_2._name) in mail['message_id']]
-
- self._mails = self._mails_record1
- self.assertEmails(
- self.user_employee.partner_id,
- [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]],
- subject=self.test_record.name,
- body_content=self.test_record.email_from,
- attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')])
-
- self._mails = self._mails_record2
- self.assertEmails(
- self.user_employee.partner_id,
- [[self.partner_1], [self.partner_2], [new_partners[0]], [new_partners[1]], [self.partner_admin]],
- subject=test_record_2.name,
- body_content=test_record_2.email_from,
- attachments=[('first.txt', b'My first attachment', 'text/plain'), ('second.txt', b'My second attachment', 'text/plain')])
-
- message_1 = self.test_record.message_ids[0]
- message_2 = test_record_2.message_ids[0]
-
- # messages effectively posted
- self.assertEqual(message_1.subject, self.test_record.name)
- self.assertEqual(message_2.subject, test_record_2.name)
- self.assertIn(self.test_record.email_from, message_1.body)
- self.assertIn(test_record_2.email_from, message_2.body)
-
- def test_composer_template_save(self):
- self.env['mail.compose.message'].with_context({
- 'default_composition_mode': 'comment',
- 'default_model': 'mail.test.simple',
- 'default_res_id': self.test_record.id,
- }).create({
- 'subject': 'Forget me subject',
- 'body': '<p>Dummy body</p>'
- }).save_as_template()
- # Test: email_template subject, body_html, model
- last_template = self.env['mail.template'].search([('model', '=', 'mail.test.simple'), ('subject', '=', 'Forget me subject')], limit=1)
- self.assertEqual(last_template.body_html, '<p>Dummy body</p>', 'email_template incorrect body_html')
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_template_send_email(self):
- mail_id = self.email_template.send_mail(self.test_record.id)
- mail = self.env['mail.mail'].browse(mail_id)
- self.assertEqual(mail.subject, self.test_record.name)
- self.assertEqual(mail.email_to, self.email_template.email_to)
- self.assertEqual(mail.email_cc, self.email_template.email_cc)
- self.assertEqual(mail.recipient_ids, self.partner_2 | self.user_admin.partner_id)
-
- def test_template_add_context_action(self):
- self.email_template.create_action()
-
- # check template act_window has been updated
- self.assertTrue(bool(self.email_template.ref_ir_act_window))
-
- # check those records
- action = self.email_template.ref_ir_act_window
- self.assertEqual(action.name, 'Send Mail (%s)' % self.email_template.name)
- self.assertEqual(action.binding_model_id.model, 'mail.test.simple')
-
- # def test_template_scheduled_date(self):
- # from unittest.mock import patch
-
- # self.email_template_in_2_days = self.email_template.copy()
-
- # with patch('odoo.addons.mail.tests.test_mail_template.datetime', wraps=datetime) as mock_datetime:
- # mock_datetime.now.return_value = datetime(2017, 11, 15, 11, 30, 28)
- # mock_datetime.side_effect = lambda *args, **kw: datetime(*args, **kw)
-
- # self.email_template_in_2_days.write({
- # 'scheduled_date': "${(datetime.datetime.now() + relativedelta(days=2)).strftime('%s')}" % DEFAULT_SERVER_DATETIME_FORMAT,
- # })
-
- # mail_now_id = self.email_template.send_mail(self.test_record.id)
- # mail_in_2_days_id = self.email_template_in_2_days.send_mail(self.test_record.id)
-
- # mail_now = self.env['mail.mail'].browse(mail_now_id)
- # mail_in_2_days = self.env['mail.mail'].browse(mail_in_2_days_id)
-
- # # mail preparation
- # self.assertEqual(mail_now.exists() | mail_in_2_days.exists(), mail_now | mail_in_2_days)
- # self.assertEqual(bool(mail_now.scheduled_date), False)
- # self.assertEqual(mail_now.state, 'outgoing')
- # self.assertEqual(mail_in_2_days.state, 'outgoing')
- # scheduled_date = datetime.strptime(mail_in_2_days.scheduled_date, DEFAULT_SERVER_DATETIME_FORMAT)
- # date_in_2_days = datetime.now() + timedelta(days = 2)
- # self.assertEqual(scheduled_date, date_in_2_days)
- # # self.assertEqual(scheduled_date.month, date_in_2_days.month)
- # # self.assertEqual(scheduled_date.year, date_in_2_days.year)
-
- # # Launch the scheduler on the first mail, it should be reported in self.mails
- # # and the mail_mail is now deleted
- # self.env['mail.mail'].process_email_queue()
- # self.assertEqual(mail_now.exists() | mail_in_2_days.exists(), mail_in_2_days)
-
- # # Launch the scheduler on the first mail, it's still in 'outgoing' state
- # self.env['mail.mail'].process_email_queue(ids=[mail_in_2_days.id])
- # self.assertEqual(mail_in_2_days.state, 'outgoing')
- # self.assertEqual(mail_now.exists() | mail_in_2_days.exists(), mail_in_2_days)
diff --git a/addons/mail/tests/test_message_compose.py b/addons/mail/tests/test_message_compose.py
deleted file mode 100644
index 043f458e33f..00000000000
--- a/addons/mail/tests/test_message_compose.py
+++ /dev/null
@@ -1,355 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-import base64
-
-from unittest.mock import patch
-
-from odoo.addons.mail.tests.common import BaseFunctionalTest, MockEmails, TestRecipients
-from odoo.addons.mail.tests.data.test_mail_data import MAIL_TEMPLATE_PLAINTEXT
-from odoo.addons.mail.tests.models.test_mail_models import MailTestSimple
-from odoo.exceptions import AccessError
-from odoo.tools import mute_logger
-
-
-class TestMessagePost(BaseFunctionalTest, MockEmails, TestRecipients):
-
- def setUp(self):
- super(TestMessagePost, self).setUp()
-
- # configure mailing
- self.alias_domain = 'schlouby.fr'
- self.alias_catchall = 'test+catchall'
- self.env['ir.config_parameter'].set_param('mail.catchall.domain', self.alias_domain)
- self.env['ir.config_parameter'].set_param('mail.catchall.alias', self.alias_catchall)
-
- # admin should not receive emails
- self.user_admin.write({'notification_type': 'email'})
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_post_notifications(self):
- _body, _body_alt, _subject = '<p>Test Body</p>', 'Test Body', 'Test Subject'
-
- # subscribe second employee to the group to test notifications
- self.test_record.message_subscribe_users(user_ids=[self.user_admin.id])
-
- msg = self.test_record.sudo(self.user_employee).message_post(
- body=_body, subject=_subject,
- message_type='comment', subtype='mt_comment',
- partner_ids=[self.partner_1.id, self.partner_2.id]
- )
-
- # message content
- self.assertEqual(msg.subject, _subject)
- self.assertEqual(msg.body, _body)
- self.assertEqual(msg.partner_ids, self.partner_1 | self.partner_2)
- self.assertEqual(msg.needaction_partner_ids, self.user_admin.partner_id | self.partner_1 | self.partner_2)
- self.assertEqual(msg.channel_ids, self.env['mail.channel'])
-
- # notifications emails should have been deleted
- self.assertFalse(self.env['mail.mail'].search([('mail_message_id', '=', msg.id)]),
- 'message_post: mail.mail notifications should have been auto-deleted')
-
- # notification emails
- self.assertEmails(
- self.user_employee.partner_id,
- [[self.partner_1], [self.partner_2], [self.user_admin.partner_id]],
- reply_to=msg.reply_to, subject=_subject,
- body_content=_body, body_alt_content=_body_alt,
- references=False)
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_post_notifications_keep_emails(self):
- self.test_record.message_subscribe_users(user_ids=[self.user_admin.id])
-
- msg = self.test_record.sudo(self.user_employee).with_context(mail_auto_delete=False).message_post(
- body='Test', subject='Test',
- message_type='comment', subtype='mt_comment',
- partner_ids=[self.partner_1.id, self.partner_2.id]
- )
-
- # notifications emails should not have been deleted: one for customers, one for user
- self.assertEqual(len(self.env['mail.mail'].search([('mail_message_id', '=', msg.id)])), 2)
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_post_notifications_emails_tweak(self):
- pass
- # we should check _notification_groups behavior, for emails and buttons
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_post_attachments(self):
- _attachments = [
- ('List1', b'My first attachment'),
- ('List2', b'My second attachment')
- ]
- _attach_1 = self.env['ir.attachment'].sudo(self.user_employee).create({
- 'name': 'Attach1', 'datas_fname': 'Attach1',
- 'datas': 'bWlncmF0aW9uIHRlc3Q=',
- 'res_model': 'mail.compose.message', 'res_id': 0})
- _attach_2 = self.env['ir.attachment'].sudo(self.user_employee).create({
- 'name': 'Attach2', 'datas_fname': 'Attach2',
- 'datas': 'bWlncmF0aW9uIHRlc3Q=',
- 'res_model': 'mail.compose.message', 'res_id': 0})
-
- msg = self.test_record.sudo(self.user_employee).message_post(
- body='Test', subject='Test',
- message_type='comment', subtype='mt_comment',
- attachment_ids=[_attach_1.id, _attach_2.id],
- partner_ids=[self.partner_1.id],
- attachments=_attachments,
- )
-
- # message attachments
- self.assertEqual(len(msg.attachment_ids), 4)
- self.assertEqual(set(msg.attachment_ids.mapped('res_model')), set([self.test_record._name]))
- self.assertEqual(set(msg.attachment_ids.mapped('res_id')), set([self.test_record.id]))
- self.assertEqual(set([base64.b64decode(x) for x in msg.attachment_ids.mapped('datas')]),
- set([b'migration test', _attachments[0][1], _attachments[1][1]]))
- self.assertTrue(set([_attach_1.id, _attach_2.id]).issubset(msg.attachment_ids.ids),
- 'message_post: mail.message attachments duplicated')
-
- # notification email attachments
- self.assertEmails(self.user_employee.partner_id, [[self.partner_1]])
- # self.assertEqual(len(self._mails), 1)
- self.assertEqual(len(self._mails[0]['attachments']), 4)
- self.assertIn(('List1', b'My first attachment', 'application/octet-stream'), self._mails[0]['attachments'])
- self.assertIn(('List2', b'My second attachment', 'application/octet-stream'), self._mails[0]['attachments'])
- self.assertIn(('Attach1', b'migration test', 'application/octet-stream'), self._mails[0]['attachments'])
- self.assertIn(('Attach2', b'migration test', 'application/octet-stream'), self._mails[0]['attachments'])
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_post_answer(self):
- parent_msg = self.test_record.sudo(self.user_employee).message_post(
- body='<p>Test</p>', subject='Test Subject',
- message_type='comment', subtype='mt_comment')
-
- self.assertEqual(parent_msg.partner_ids, self.env['res.partner'])
- self.assertEmails(self.user_employee.partner_id, [])
-
- msg = self.test_record.sudo(self.user_employee).message_post(
- body='<p>Test Answer</p>',
- message_type='comment', subtype='mt_comment',
- partner_ids=[self.partner_1.id],
- parent_id=parent_msg.id)
-
- self.assertEqual(msg.parent_id.id, parent_msg.id)
- self.assertEqual(msg.partner_ids, self.partner_1)
- self.assertEqual(parent_msg.partner_ids, self.env['res.partner'])
-
- # check notification emails: references
- self.assertEmails(self.user_employee.partner_id, [[self.partner_1]], ref_content='openerp-%d-mail.test.simple' % self.test_record.id)
- # self.assertTrue(all('openerp-%d-mail.test.simple' % self.test_record.id in m['references'] for m in self._mails))
-
- new_msg = self.test_record.sudo(self.user_employee).message_post(
- body='<p>Test Answer Bis</p>',
- message_type='comment', subtype='mt_comment',
- parent_id=msg.id)
-
- self.assertEqual(new_msg.parent_id.id, parent_msg.id, 'message_post: flatten error')
- self.assertEqual(new_msg.partner_ids, self.env['res.partner'])
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_post_portal_ok(self):
- portal_user = self.env['res.users'].with_context(self._quick_create_user_ctx).create({
- 'name': 'Chell Gladys',
- 'login': 'chell',
- 'email': 'chell@gladys.portal',
- 'groups_id': [(6, 0, [self.env.ref('base.group_portal').id])],
- })
-
- with patch.object(MailTestSimple, 'check_access_rights', return_value=True):
- self.test_record.message_subscribe((self.partner_1 | self.user_employee.partner_id).ids)
- new_msg = self.test_record.sudo(portal_user).message_post(
- body='<p>Test</p>', subject='Subject',
- message_type='comment', subtype='mt_comment')
-
- self.assertEqual(new_msg.sudo().needaction_partner_ids, (self.partner_1 | self.user_employee.partner_id))
- self.assertEmails(portal_user.partner_id, [[self.partner_1], [self.user_employee.partner_id]])
-
- def test_post_portal_crash(self):
- portal_user = self.env['res.users'].with_context(self._quick_create_user_ctx).create({
- 'name': 'Chell Gladys',
- 'login': 'chell',
- 'email': 'chell@gladys.portal',
- 'groups_id': [(6, 0, [self.env.ref('base.group_portal').id])],
- })
-
- with self.assertRaises(AccessError):
- self.test_record.sudo(portal_user).message_post(
- body='<p>Test</p>', subject='Subject',
- message_type='comment', subtype='mt_comment')
-
- @mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.addons.mail.models.mail_thread')
- def test_post_internal(self):
- self.test_record.message_subscribe([self.user_admin.partner_id.id])
- msg = self.test_record.sudo(self.user_employee).message_post(
- body='My Body', subject='My Subject',
- message_type='comment', subtype='mt_note')
- self.assertEqual(msg.partner_ids, self.env['res.partner'])
- self.assertEqual(msg.needaction_partner_ids, self.env['res.partner'])
-
- self.format_and_process(
- MAIL_TEMPLATE_PLAINTEXT,
- email_from=self.user_admin.email,
- msg_id='<1198923581.41972151344608186800.JavaMail.diff1@agrolait.com>',
- to='not_my_businesss@example.com',
- extra='In-Reply-To:\r\n\t%s\n' % msg.message_id)
- reply = self.test_record.message_ids - msg
- self.assertTrue(reply)
- self.assertEqual(reply.subtype_id, self.env.ref('mail.mt_note'))
- self.assertEqual(reply.needaction_partner_ids, self.user_employee.partner_id)
- self.assertEqual(reply.parent_id, msg)
-
-
-class TestComposer(BaseFunctionalTest, MockEmails, TestRecipients):
-
- def setUp(self):
- super(TestComposer, self).setUp()
-
- # configure mailing
- self.alias_domain = 'schlouby.fr'
- self.alias_catchall = 'test+catchall'
- self.env['ir.config_parameter'].set_param('mail.catchall.domain', self.alias_domain)
- self.env['ir.config_parameter'].set_param('mail.catchall.alias', self.alias_catchall)
-
- # admin should not receive emails
- self.user_admin.write({'notification_type': 'email'})
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_composer_comment(self):
- composer = self.env['mail.compose.message'].with_context({
- 'default_composition_mode': 'comment',
- 'default_model': self.test_record._name,
- 'default_res_id': self.test_record.id,
- }).sudo(self.user_employee).create({
- 'body': '<p>Test Body</p>',
- 'partner_ids': [(4, self.partner_1.id), (4, self.partner_2.id)]
- })
- composer.send_mail()
-
- message = self.test_record.message_ids[0]
- self.assertEqual(message.body, '<p>Test Body</p>')
- self.assertEqual(message.author_id, self.user_employee.partner_id)
- self.assertEqual(message.subject, 'Re: %s' % self.test_record.name)
- self.assertEqual(message.subtype_id, self.env.ref('mail.mt_comment'))
- self.assertEqual(message.partner_ids, self.partner_1 | self.partner_2)
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_composer_comment_parent(self):
- parent = self.test_record.message_post(body='Test')
-
- self.env['mail.compose.message'].with_context({
- 'default_composition_mode': 'comment',
- 'default_parent_id': parent.id
- }).sudo(self.user_employee).create({
- 'body': '<p>Mega</p>',
- }).send_mail()
-
- message = self.test_record.message_ids[0]
- self.assertEqual(message.body, '<p>Mega</p>')
- self.assertEqual(message.parent_id, parent)
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_composer_mass_mail(self):
- test_record_2 = self.env['mail.test.simple'].with_context(self._quick_create_ctx).create({'name': 'Test2'})
-
- composer = self.env['mail.compose.message'].with_context({
- 'default_composition_mode': 'mass_mail',
- 'default_model': self.test_record._name,
- 'default_res_id': False,
- 'active_ids': [self.test_record.id, test_record_2.id]
- }).sudo(self.user_employee).create({
- 'subject': 'Testing ${object.name}',
- 'body': '<p>${object.name}</p>',
- 'partner_ids': [(4, self.partner_1.id), (4, self.partner_2.id)]
- })
- composer.with_context({
- 'default_res_id': -1,
- 'active_ids': [self.test_record.id, test_record_2.id]
- }).send_mail()
-
- # check mail_mail
- mails = self.env['mail.mail'].search([('subject', 'ilike', 'Testing')])
- for mail in mails:
- self.assertEqual(mail.recipient_ids, self.partner_1 | self.partner_2,
- 'compose wizard: mail_mail mass mailing: mail.mail in mass mail incorrect recipients')
-
- # check message on test_record
- message1 = self.test_record.message_ids[0]
- self.assertEqual(message1.subject, 'Testing %s' % self.test_record.name)
- self.assertEqual(message1.body, '<p>%s</p>' % self.test_record.name)
-
- # check message on test_record_2
- message1 = test_record_2.message_ids[0]
- self.assertEqual(message1.subject, 'Testing %s' % test_record_2.name)
- self.assertEqual(message1.body, '<p>%s</p>' % test_record_2.name)
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_composer_mass_mail_active_domain(self):
- test_record_2 = self.env['mail.test.simple'].with_context(self._quick_create_ctx).create({'name': 'Test2'})
-
- self.env['mail.compose.message'].with_context({
- 'default_composition_mode': 'mass_mail',
- 'default_model': self.test_record._name,
- 'default_use_active_domain': True,
- 'active_ids': [self.test_record.id],
- 'active_domain': [('name', 'in', ['%s' % self.test_record.name, '%s' % test_record_2.name])],
- }).sudo(self.user_employee).create({
- 'subject': 'From Composer Test',
- 'body': '${object.name}',
- }).send_mail()
-
- self.assertEqual(self.test_record.message_ids[0].subject, 'From Composer Test')
- self.assertEqual(test_record_2.message_ids[0].subject, 'From Composer Test')
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_message_compose_mass_mail_no_active_domain(self):
- test_record_2 = self.env['mail.test.simple'].with_context(self._quick_create_ctx).create({'name': 'Test2'})
-
- self.env['mail.compose.message'].with_context({
- 'default_composition_mode': 'mass_mail',
- 'default_model': self.test_record._name,
- 'default_use_active_domain': False,
- 'active_ids': [self.test_record.id],
- 'active_domain': [('name', 'in', ['%s' % self.test_record.name, '%s' % test_record_2.name])],
- }).sudo(self.user_employee).create({
- 'subject': 'From Composer Test',
- 'body': '${object.name}',
- }).send_mail()
-
- self.assertEqual(self.test_record.message_ids[0].subject, 'From Composer Test')
- self.assertFalse(test_record_2.message_ids.ids)
-
- @mute_logger('odoo.addons.mail.models.mail_mail')
- def test_message_compose_portal_ok(self):
- portal_user = self.env['res.users'].with_context(self._quick_create_ctx).create({
- 'name': 'Chell Gladys',
- 'login': 'chell',
- 'email': 'chell@gladys.portal',
- 'groups_id': [(6, 0, [self.env.ref('base.group_portal').id])],
- })
-
- with patch.object(MailTestSimple, 'check_access_rights', return_value=True):
- ComposerPortal = self.env['mail.compose.message'].sudo(portal_user)
-
- ComposerPortal.with_context({
- 'default_composition_mode': 'comment',
- 'default_model': self.test_record._name,
- 'default_res_id': self.test_record.id,
- }).create({
- 'subject': 'Subject',
- 'body': '<p>Body text</p>',
- 'partner_ids': []}).send_mail()
-
- self.assertEqual(self.test_record.message_ids[0].body, '<p>Body text</p>')
- self.assertEqual(self.test_record.message_ids[0].author_id, portal_user.partner_id)
-
- ComposerPortal.with_context({
- 'default_composition_mode': 'comment',
- 'default_parent_id': self.test_record.message_ids.ids[0],
- }).create({
- 'subject': 'Subject',
- 'body': '<p>Body text 2</p>'}).send_mail()
-
- self.assertEqual(self.test_record.message_ids[0].body, '<p>Body text 2</p>')
- self.assertEqual(self.test_record.message_ids[0].author_id, portal_user.partner_id)
diff --git a/addons/mail/tests/test_message_track.py b/addons/mail/tests/test_message_track.py
deleted file mode 100644
index abb7bdf0fae..00000000000
--- a/addons/mail/tests/test_message_track.py
+++ /dev/null
@@ -1,137 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from email.utils import formataddr
-
-from odoo.addons.mail.tests import common
-
-
-class TestTracking(common.BaseFunctionalTest, common.MockEmails):
-
- def assertTracking(self, message, data):
- tracking_values = message.sudo().tracking_value_ids
- for field_name, value_type, old_value, new_value in data:
- tracking = tracking_values.filtered(lambda track: track.field == field_name)
- self.assertEqual(len(tracking), 1)
- if value_type in ('char', 'integer'):
- self.assertEqual(tracking.old_value_char, old_value)
- self.assertEqual(tracking.new_value_char, new_value)
- elif value_type in ('many2one'):
- self.assertEqual(tracking.old_value_integer, old_value and old_value.id or False)
- self.assertEqual(tracking.new_value_integer, new_value and new_value.id or False)
- self.assertEqual(tracking.old_value_char, old_value and old_value.name_get()[0][1] or '')
- self.assertEqual(tracking.new_value_char, new_value and new_value.name_get()[0][1] or '')
- else:
- self.assertEqual(1, 0)
-
- def setUp(self):
- super(TestTracking, self).setUp()
-
- self.track_subtype_umbrella = self.env['mail.message.subtype'].create({
- 'name': 'Umbrella',
- 'description': 'Umbrella Changed',
- })
- self.env['ir.model.data'].create({
- 'name': 'track_subtype_umbrella',
- 'model': 'mail.message.subtype',
- 'module': 'mail',
- 'res_id': self.track_subtype_umbrella.id
- })
-
- record = self.env['mail.test.full'].sudo(self.user_employee).with_context(self._quick_create_ctx).create({
- 'name': 'Test',
- })
- self.record = record.with_context(mail_notrack=False)
-
- def test_message_track_no_tracking(self):
- """ Update a set of non tracked fields -> no message, no tracking """
- self.record.write({
- 'name': 'Tracking or not',
- 'count': 32,
- })
- self.assertEqual(self.record.message_ids, self.env['mail.message'])
-
- def test_message_track_no_subtype(self):
- """ Update some tracked fields not linked to some subtype -> message with onchange + always tracked values """
- customer = self.env['res.partner'].create({'name': 'Customer', 'email': 'cust@example.com'})
- self.record.write({
- 'name': 'Test2',
- 'customer_id': customer.id,
- })
-
- # one new message containing tracking; without subtype linked to tracking, a note is generated
- self.assertEqual(len(self.record.message_ids), 1)
- self.assertEqual(self.record.message_ids.subtype_id, self.env.ref('mail.mt_note'))
-
- # no specific recipients except those following notes, no email
- self.assertEqual(self.record.message_ids.partner_ids, self.env['res.partner'])
- self.assertEqual(self.record.message_ids.needaction_partner_ids, self.env['res.partner'])
- self.assertEqual(self._mails, [])
-
- # verify tracked value
- self.assertTracking(
- self.record.message_ids,
- [('email_from', 'char', False, False), # always tracked field
- ('customer_id', 'many2one', False, customer) # onchange tracked field
- ])
-
- def test_message_track_subtype(self):
- """ Update some tracked fields linked to some subtype -> message with onchange + always tracked values """
- self.record.message_subscribe(
- partner_ids=[self.user_admin.partner_id.id],
- subtype_ids=[self.track_subtype_umbrella.id]
- )
-
- umbrella = self.env['mail.test'].create({'name': 'Umbrella'})
- self.record.write({
- 'name': 'Test2',
- 'email_from': 'noone@example.com',
- 'umbrella_id': umbrella.id,
- })
- # one new message containing tracking; subtype linked to tracking
- self.assertEqual(len(self.record.message_ids), 1)
- self.assertEqual(self.record.message_ids.subtype_id, self.track_subtype_umbrella)
-
- # no specific recipients except those following umbrella
- self.assertEqual(self.record.message_ids.partner_ids, self.env['res.partner'])
- self.assertEqual(self.record.message_ids.needaction_partner_ids, self.user_admin.partner_id)
-
- # verify tracked value
- self.assertTracking(
- self.record.message_ids,
- [('email_from', 'char', False, 'noone@example.com'), # always tracked field
- ('umbrella_id', 'many2one', False, umbrella) # onchange tracked field
- ])
-
- def test_message_track_template(self):
- """ Update some tracked fields linked to some template -> message with onchange + always tracked values """
- mail_template = self.env['mail.template'].create({
- 'model_id': self.env.ref('mail.model_mail_test_full').id,
- 'body_html': '<p>Hello ${object.name}</p>',
- 'subject': 'Test Template',
- 'partner_to': '${object.customer_id.id | safe}',
- })
- self.record.write({'mail_template': mail_template.id})
- self.assertEqual(self.record.message_ids, self.env['mail.message'])
-
- self.record.write({
- 'name': 'Test2',
- 'customer_id': self.user_admin.partner_id.id,
- })
-
- self.assertEqual(len(self.record.message_ids), 2, 'should have 2 new messages: one for tracking, one for template')
-
- # one new message containing the template linked to tracking
- self.assertEqual(self.record.message_ids[0].subject, 'Test Template')
- self.assertEqual(self.record.message_ids[0].body, '<p>Hello Test2</p>')
-
- # one email send due to template
- self.assertEqual(len(self._mails), 1)
- self.assertEqual(set(self._mails[0]['email_to']), set([formataddr((self.user_admin.name, self.user_admin.email))]))
- self.assertHtmlEqual(self._mails[0]['body'], '<p>Hello Test2</p>')
-
- # one new message containing tracking; without subtype linked to tracking
- self.assertEqual(self.record.message_ids[1].subtype_id, self.env.ref('mail.mt_note'))
- self.assertTracking(
- self.record.message_ids[1],
- [('customer_id', 'many2one', False, self.user_admin.partner_id) # onchange tracked field
- ])
diff --git a/addons/mail/tests/test_update_notification.py b/addons/mail/tests/test_update_notification.py
deleted file mode 100644
index 7621e4056a1..00000000000
--- a/addons/mail/tests/test_update_notification.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- coding: utf-8 -*-
-from odoo.tests.common import TransactionCase
-
-
-class TestUpdateNotification(TransactionCase):
- def test_user_count(self):
- ping_msg = self.env['publisher_warranty.contract'].with_context(active_test=False)._get_message()
- user_count = self.env['res.users'].search_count([('active', '=', True)])
- self.assertEqual(ping_msg.get('nbr_users'), user_count, 'Update Notification: Users count is badly computed in ping message')
- share_user_count = self.env['res.users'].search_count([('active', '=', True), ('share', '=', True)])
- self.assertEqual(ping_msg.get('nbr_share_users'), share_user_count, 'Update Notification: Portal Users count is badly computed in ping message')