You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

284 lines
12 KiB

import odoo
from odoo.tests import TransactionCase
from email.message import EmailMessage
from ..models.mail import encode_msg_id
from ..models.mail import encode_msg_id_legacy
from ..models.mail import MESSAGE_PREFIX
import mock
from odoo import SUPERUSER_ID
from odoo.addons.base.models.ir_mail_server import IrMailServer
from ..models.mail import random_string
@odoo.tests.tagged('post_install', '-at_install')
class TestEmail(TransactionCase):
def setUp(self):
super(TestEmail, self).setUp()
self.partner = self.env['res.partner'].create({'name': 'Test Dude'})
self.partner2 = self.env['res.partner'].create({'name': 'Dudette'})
self.demo_user = self.env.ref('base.user_demo')
self.subtype_comment = self.env.ref('mail.mt_comment')
self.subtype_note = self.env.ref('mail.mt_note')
self.MailMessage = self.env['mail.message']
self.ConfigParam = self.env['ir.config_parameter']
# Create server configuration
self.outgoing_server = self.env['ir.mail_server'].create({
'name': 'Outgoing SMTP Server for Unit Tests',
'sequence': 1,
'smtp_host': 'localhost',
'smtp_port': '9999',
'smtp_encryption': 'none',
'smtp_user': 'doesnt',
'smtp_pass': 'exist',
'reply_to_method': 'msg_id',
'force_email_reply_to_domain': 'example.com',
'force_email_from': 'odoo@example.com',
})
@staticmethod
def create_email_message():
message = EmailMessage()
message['Content-Type'] = 'multipart/mixed; boundary="===============2590914155756834027=="'
message['MIME-Version'] = '1.0'
message['Message-Id'] = '<CAD-eYi=a264_3DcrYSDU5yc_fwYoHonZ3H+{}@mail.gmail.com>'.format(random_string(6))
message['Subject'] = '1'
message['From'] = 'Miku Laitinen <miku@avoin.systems>'
message['Reply-To'] = 'YourCompany Eurooppa <sales@avoin.onmicrosoft.com>'
message['To'] = '"Erik N. French" <ErikNFrench@armyspy.com>'
message['Date'] = 'Mon, 06 May 2019 14:16:38 -0000'
return message
def test_reply_to_method_msg_id(self):
# Make administrator follow the partner
self.partner.message_subscribe([self.env.user.partner_id.id])
# Send a message to the followers of the partner
thread_msg = self.partner.with_user(self.demo_user).message_post(
body='dummy message.',
message_type='comment',
subtype='mail.mt_comment'
)
# Make sure the message headers look right.. or not
# mail_msg = thread_msg.notification_ids[0]
# Get the encoded message address
encoded_msg_id = encode_msg_id(thread_msg.id, self.env)
# Try to read an incoming email
message = self.create_email_message()
del message['To']
message['To'] = '"Erik N. French" <ErikNFrench+{}{}@armyspy.com>'.format(MESSAGE_PREFIX, encoded_msg_id)
thread_id = self.env['mail.thread'].message_process(model=False, message=message.as_string())
self.assertEqual(thread_msg.res_id, thread_id,
"The incoming email wasn't connected to the correct thread")
# Make sure the message is a comment
incoming_msg1 = self.MailMessage.search([('message_id', '=', message['Message-Id'])])
self.assertEqual(
incoming_msg1.message_type,
'email',
"The incoming message was created as a type {} instead of a email.".format(incoming_msg1.message_type)
)
self.assertEqual(
incoming_msg1.subtype_id,
self.subtype_comment,
"The incoming message was created as a subtype {} instead of a comment.".format(incoming_msg1.subtype_id)
)
# Try to read another incoming email
message = self.create_email_message()
del message['To']
message['To'] = '"Erik N. French" <ErikNFrench+{}HURDURLUR@armyspy.com>'.format(MESSAGE_PREFIX)
message['In-Reply-To'] = thread_msg.message_id
thread_id = self.env['mail.thread'].message_process(model=False, message=message.as_string())
self.assertEqual(thread_msg.res_id, thread_id,
"The incoming email wasn't connected to the correct thread")
# Make sure the message is a comment
incoming_msg2 = self.MailMessage.search([('message_id', '=', message['Message-Id'])])
self.assertEqual(
incoming_msg2.message_type,
'email',
"The incoming message was created as a type {} instead of a email.".format(incoming_msg2.message_type)
)
self.assertEqual(
incoming_msg2.subtype_id,
self.subtype_comment,
"The incoming message was created as a subtype {} instead of a comment.".format(incoming_msg2.subtype_id)
)
def test_reply_to_method_msg_id_priority(self):
"""
In this test we will inject the wrong Message-Id to the incoming
email messages References-header and see if Odoo will prioritize
the custom Reply-To address over the References-header. It should.
:return:
"""
# Make administrator follow the partner
self.partner.message_subscribe([self.env.user.partner_id.id])
# Send a message to the followers of the partner
thread_msg = self.partner.with_user(self.demo_user).message_post(
body='dummy message X.',
message_type='comment',
subtype='mail.mt_comment'
)
# Get the encoded message address
encoded_msg_id = encode_msg_id(thread_msg.id, self.env)
# Send another message to the followers of the partner
thread_msg2 = self.partner2.with_user(self.demo_user).message_post(
body='dummy message X.',
message_type='comment',
subtype='mail.mt_comment'
)
# Try to read an incoming email
message = self.create_email_message()
del message['To']
del message['References']
message['To'] = '"Erik N. French" <ErikNFrench+{}{}@armyspy.com>'.format(MESSAGE_PREFIX, encoded_msg_id)
# Inject the wrong References
message['References'] = thread_msg2.message_id
thread_id = self.env['mail.thread'].message_process(model=False, message=message.as_string())
self.assertEqual(thread_msg.res_id, thread_id,
"The incoming email wasn't connected to the correct thread")
def test_reply_to_method_msg_id_notification(self):
# Make administrator follow the partner
self.partner2.message_subscribe([self.env.user.partner_id.id])
# Send a message to the followers of the partner
thread_msg = self.partner2.with_user(self.demo_user).message_post(
body='dummy message 2.',
message_type='comment',
subtype='mail.mt_note'
)
# Get the encoded message address
encoded_msg_id = encode_msg_id(thread_msg.id, self.env)
# Try to read an incoming email
message = self.create_email_message()
del message['To']
message['To'] = '"Erik N. French" <ErikNFrench+{}{}@armyspy.com>'.format(MESSAGE_PREFIX, encoded_msg_id)
thread_id = self.env['mail.thread'].message_process(model=False, message=message.as_string())
self.assertEqual(thread_msg.res_id, thread_id,
"The incoming email wasn't connected to the correct thread")
# Make sure the message is a note
incoming_msg1 = self.MailMessage.search([('message_id', '=', message['Message-Id'])])
self.assertEqual(
incoming_msg1.message_type,
'email',
"The incoming message was created as a type {} instead of a email.".format(incoming_msg1.message_type)
)
self.assertEqual(
incoming_msg1.subtype_id,
self.subtype_note,
"The incoming message was created as a subtype {} instead of a note.".format(incoming_msg1.subtype_id)
)
def test_reply_to_method_msg_id_legacy(self):
# REMOVE this test when porting to Odoo 14
# Make administrator follow the partner
self.partner2.message_subscribe([self.env.user.partner_id.id])
# Send a message to the followers of the partner
thread_msg = self.partner2.with_user(self.demo_user).message_post(
body='dummy message 2.',
message_type='comment',
subtype='mail.mt_note'
)
# Get the encoded message address
encoded_msg_id = encode_msg_id_legacy(thread_msg.id, self.env)
# Try to read an incoming email
message = self.create_email_message()
del message['To']
message['To'] = '"Erik N. French" <ErikNFrench+{}{}@armyspy.com>'.format(MESSAGE_PREFIX, encoded_msg_id)
thread_id = self.env['mail.thread'].message_process(model=False, message=message.as_string())
self.assertEqual(thread_msg.res_id, thread_id,
"The incoming email wasn't connected to the correct thread")
def test_reply_to_method_msg_id_lowercase(self):
# Make administrator follow the partner
self.partner2.message_subscribe([self.env.user.partner_id.id])
# Send a message to the followers of the partner
thread_msg = self.partner2.with_user(self.demo_user).message_post(
body='dummy message 2.',
message_type='comment',
subtype='mail.mt_note'
)
# Get the encoded message address
encoded_msg_id = encode_msg_id(thread_msg.id, self.env).lower()
# Try to read an incoming email
message = self.create_email_message()
del message['To']
message['To'] = '"Erik N. French" <ErikNFrench+{}{}@armyspy.com>'.format(MESSAGE_PREFIX, encoded_msg_id)
thread_id = self.env['mail.thread'].message_process(model=False, message=message.as_string())
self.assertEqual(thread_msg.res_id, thread_id,
"The incoming email wasn't connected to the correct thread")
def test_outgoing_msg_id(self):
# Make administrator follow the partner
self.partner2.message_subscribe([SUPERUSER_ID])
with mock.patch.object(IrMailServer, 'send_email') as send_email:
# Send a message to the followers of the partner
thread_msg = self.partner2.with_user(self.demo_user).message_post(
body='dummy message 3.',
message_type='comment',
subtype='mail.mt_comment'
)
# Get the encoded message address
encoded_msg_id = encode_msg_id(thread_msg.id, self.env)
self.assertTrue(
send_email.called,
"IrMailServer.send_email wasn't called when sending outgoing email"
)
message = send_email.call_args[0][0]
reply_to_address = '{}{}@{}'.format(
MESSAGE_PREFIX,
encoded_msg_id,
self.outgoing_server.force_email_reply_to_domain
)
# Make sure the subaddress is correct in the Reply-To field
self.assertIn(reply_to_address,
message['Reply-To'],
"Reply-To address didn't contain the correct subaddress")
# Make sure the author name is in the Reply-To field
self.assertIn(thread_msg.author_id.name,
message['Reply-To'],
"Reply-To address didn't contain the author name")
self.assertIn(self.outgoing_server.force_email_from,
message['From'],
"From address didn't contain the configure From-address")