@@ -1,3 +1,4 @@
|
||||
* Set Message-Id to email sent
|
||||
* Add pair/unpair in tools
|
||||
|
||||
Version 7.6.0 - 2025-04-28
|
||||
|
||||
@@ -69,6 +69,7 @@ class Email(ResourceAccessMixin, ModelSQL, ModelView):
|
||||
'ir.email.address', 'email', "Addresses", readonly=True)
|
||||
subject = fields.Char("Subject", readonly=True)
|
||||
body = fields.Text("Body", readonly=True)
|
||||
message_id = fields.Char("Message-ID", readonly=True)
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
@@ -228,6 +229,7 @@ class Email(ResourceAccessMixin, ModelSQL, ModelView):
|
||||
recipients_hidden=msg['Bcc'],
|
||||
addresses=[{'address': a} for a in to_addrs],
|
||||
subject=msg['Subject'],
|
||||
message_id=msg['Message-ID'],
|
||||
**values)
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="user"/>
|
||||
<label name="at"/>
|
||||
<field name="at"/>
|
||||
|
||||
<label name="message_id"/>
|
||||
<field name="message_id" colspan="3"/>
|
||||
|
||||
<label name="recipients"/>
|
||||
<field name="recipients" colspan="3"/>
|
||||
<label name="recipients_secondary"/>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tree>
|
||||
<field name="resource" expand="2"/>
|
||||
<field name="message_id" optional="1"/>
|
||||
<field name="user"/>
|
||||
<field name="at" widget="date"/>
|
||||
<field name="at" widget="time"/>
|
||||
|
||||
@@ -5,11 +5,12 @@ import smtplib
|
||||
import ssl
|
||||
import time
|
||||
from email.message import EmailMessage, Message
|
||||
from email.utils import formatdate
|
||||
from email.utils import formatdate, make_msgid
|
||||
from urllib.parse import parse_qs, unquote_plus
|
||||
|
||||
from trytond.config import config, parse_uri
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.url import host
|
||||
|
||||
__all__ = [
|
||||
'sendmail_transactional', 'sendmail',
|
||||
@@ -29,6 +30,8 @@ def sendmail_transactional(
|
||||
def send_message_transactional(
|
||||
msg, from_addr=None, to_addrs=None, transaction=None, datamanager=None,
|
||||
strict=False):
|
||||
if not msg['Message-ID']:
|
||||
msg['Message-ID'] = make_msgid(domain=host())
|
||||
if transaction is None:
|
||||
transaction = Transaction()
|
||||
assert isinstance(transaction, Transaction), transaction
|
||||
@@ -44,6 +47,8 @@ def sendmail(from_addr, to_addrs, msg, server=None, strict=False):
|
||||
|
||||
def send_message(
|
||||
msg, from_addr=None, to_addrs=None, server=None, strict=False):
|
||||
if not msg['Message-ID']:
|
||||
msg['Message-ID'] = make_msgid(domain=host())
|
||||
if server is None:
|
||||
server = get_smtp_server(strict=strict)
|
||||
if not server:
|
||||
|
||||
@@ -520,9 +520,13 @@ class IrTestCase(ModuleTestCase):
|
||||
)
|
||||
report.save()
|
||||
|
||||
def set_message_id(msg, *args, **kwargs):
|
||||
msg['Message-ID'] = 'test'
|
||||
|
||||
with patch(
|
||||
'trytond.ir.email_.send_message_transactional'
|
||||
) as send_message:
|
||||
send_message.side_effect = set_message_id
|
||||
email = Email.send(
|
||||
to='"John Doe" <john@example.com>, Jane <jane@example.com>',
|
||||
cc='User <user@example.com>',
|
||||
@@ -551,6 +555,7 @@ class IrTestCase(ModuleTestCase):
|
||||
self.assertEqual(
|
||||
[a.address for a in email.addresses],
|
||||
addresses)
|
||||
self.assertEqual(email.message_id, 'test')
|
||||
self.assertEqual(email.subject, "Email subject")
|
||||
self.assertEqual(email.body, '<p>Hello</p>')
|
||||
self.assertEqual(len(attachments), 2)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
import smtplib
|
||||
from email.message import Message
|
||||
from email.message import EmailMessage, Message
|
||||
from unittest.mock import ANY, MagicMock, Mock, call, patch
|
||||
|
||||
from trytond.sendmail import (
|
||||
@@ -22,7 +22,7 @@ class SendmailTestCase(TestCase):
|
||||
@with_transaction()
|
||||
def test_sendmail_transactional(self):
|
||||
'Test sendmail_transactional'
|
||||
message = MagicMock()
|
||||
message = EmailMessage()
|
||||
datamanager = Mock()
|
||||
sendmail_transactional(
|
||||
'tryton@example.com', 'foo@example.com', message,
|
||||
@@ -30,16 +30,42 @@ class SendmailTestCase(TestCase):
|
||||
|
||||
datamanager.put.assert_called_once_with(
|
||||
'tryton@example.com', 'foo@example.com', message)
|
||||
self.assertTrue(message['Message-ID'])
|
||||
|
||||
@with_transaction()
|
||||
def test_sendmail_transactional_keeps_message_id(self):
|
||||
"Test sendmail_transactional keeps Message-ID"
|
||||
message = EmailMessage()
|
||||
message['Message-ID'] = 'test'
|
||||
|
||||
datamanager = Mock()
|
||||
sendmail_transactional(
|
||||
'tryton@example.com', 'foo@example.com', message,
|
||||
datamanager=datamanager)
|
||||
|
||||
self.assertEqual(message['Message-ID'], 'test')
|
||||
|
||||
def test_sendmail(self):
|
||||
'Test sendmail'
|
||||
message = MagicMock()
|
||||
message = EmailMessage()
|
||||
server = Mock()
|
||||
sendmail(
|
||||
'tryton@example.com', 'foo@example.com', message, server=server)
|
||||
server.send_message.assert_called_with(
|
||||
message, 'tryton@example.com', 'foo@example.com')
|
||||
server.quit.assert_not_called()
|
||||
self.assertTrue(message['Message-ID'])
|
||||
|
||||
def test_sendmail_keeps_message_id(self):
|
||||
"Test sendmail keeps Message-ID"
|
||||
message = EmailMessage()
|
||||
message['Message-ID'] = 'test'
|
||||
|
||||
server = Mock()
|
||||
sendmail(
|
||||
'tryton@example.com', 'foo@example.com', message, server=server)
|
||||
|
||||
self.assertEqual(message['Message-ID'], 'test')
|
||||
|
||||
def test_get_smtp_server(self):
|
||||
'Test get_smtp_server'
|
||||
|
||||
Reference in New Issue
Block a user