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
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")
|