1 parent
2ae89396c3
commit
3cc0bb6c15
22 files changed
+150
-117
No files matched your search
@@ -8,7 +8,7 @@ from trytond.model import fields
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.pyson import Bool, Eval
|
||||
from trytond.report import get_email
|
||||
from trytond.sendmail import SMTPDataManager, sendmail_transactional
|
||||
from trytond.sendmail import SMTPDataManager, send_message_transactional
|
||||
from trytond.tools.email_ import convert_ascii_email, set_from_header
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.wizard import StateTransition
|
||||
@@ -143,15 +143,14 @@ class Dunning(metaclass=PoolMeta):
|
||||
languages.add(lang)
|
||||
|
||||
msg, title = self._email(from_, to, cc, bcc, languages)
|
||||
to_addrs = [e for _, e in getaddresses(to + cc + bcc)]
|
||||
addr_fields = filter(None, (msg['To'], msg['Cc'], msg['Bcc']))
|
||||
to_addrs = [e for _, e in getaddresses(addr_fields)]
|
||||
if to_addrs:
|
||||
if not pool.test:
|
||||
sendmail_transactional(
|
||||
from_, to_addrs, msg, datamanager=datamanager)
|
||||
send_message_transactional(msg, datamanager=datamanager)
|
||||
return Email(
|
||||
recipients=', '.join(to),
|
||||
recipients_secondary=', '.join(cc),
|
||||
recipients_hidden=', '.join(bcc),
|
||||
recipients=msg['To'],
|
||||
recipients_secondary=msg['Cc'],
|
||||
recipients_hidden=msg['Bcc'],
|
||||
addresses=[{'address': a} for a in to_addrs],
|
||||
subject=title,
|
||||
resource=self,
|
||||
|
||||
@@ -6,13 +6,22 @@ Imports::
|
||||
|
||||
>>> import datetime
|
||||
>>> from decimal import Decimal
|
||||
>>> from unittest.mock import patch
|
||||
|
||||
>>> from proteus import Model, Wizard
|
||||
>>> from trytond.modules.account.tests.tools import (
|
||||
... create_chart, create_fiscalyear, get_accounts)
|
||||
>>> from trytond.modules.account_dunning_email import account
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
Patch send_message_transactional::
|
||||
|
||||
>>> smtp_calls = patch.object(
|
||||
... account, 'send_message_transactional').start()
|
||||
>>> manager = patch.object(
|
||||
... account, 'SMTPDataManager').start()
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('account_dunning_email')
|
||||
|
||||
@@ -26,7 +26,7 @@ from trytond.pool import Pool, PoolMeta
|
||||
from trytond.pyson import Eval, TimeDelta
|
||||
from trytond.report import Report, get_email
|
||||
from trytond.rpc import RPC
|
||||
from trytond.sendmail import sendmail_transactional
|
||||
from trytond.sendmail import send_message_transactional
|
||||
from trytond.tools import sql_pairing
|
||||
from trytond.tools.email_ import set_from_header
|
||||
from trytond.transaction import Transaction
|
||||
@@ -391,7 +391,7 @@ class Payment(StripeCustomerMethodMixin, CheckoutMixin, metaclass=PoolMeta):
|
||||
set_from_header(msg, from_cfg, from_ or from_cfg)
|
||||
msg['To'] = ','.join(emails)
|
||||
msg['Subject'] = title
|
||||
sendmail_transactional(from_cfg, emails, msg)
|
||||
send_message_transactional(msg)
|
||||
|
||||
def _emails_checkout(self):
|
||||
emails = []
|
||||
|
||||
@@ -37,7 +37,7 @@ from trytond.model import (
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval, If, PYSONDecoder, TimeDelta
|
||||
from trytond.report import Report
|
||||
from trytond.sendmail import SMTPDataManager, sendmail_transactional
|
||||
from trytond.sendmail import SMTPDataManager, send_message_transactional
|
||||
from trytond.tools import grouped_slice, pairwise_longest, reduce_ids
|
||||
from trytond.tools.email_ import convert_ascii_email, set_from_header
|
||||
from trytond.transaction import Transaction
|
||||
@@ -741,11 +741,12 @@ class Activity(
|
||||
|
||||
to_addrs = [convert_ascii_email(a) for _, a in getaddresses([str(to)])]
|
||||
if to_addrs:
|
||||
sendmail_transactional(
|
||||
from_, to_addrs, msg, datamanager=smtpd_datamanager)
|
||||
send_message_transactional(msg, datamanager=smtpd_datamanager)
|
||||
|
||||
email = Email(
|
||||
recipients=to,
|
||||
recipients=msg['To'],
|
||||
recipients_secondary=msg['Cc'],
|
||||
recipients_hidden=msg['Bcc'],
|
||||
addresses=[{'address': a} for a in to_addrs],
|
||||
subject=title,
|
||||
resource=record.record,
|
||||
|
||||
@@ -14,10 +14,10 @@ Imports::
|
||||
... activate_modules, assertEqual, assertIn, assertTrue)
|
||||
>>> from trytond.tools import file_open
|
||||
|
||||
Patch sendmail_transactional::
|
||||
Patch send_message_transactional::
|
||||
|
||||
>>> smtp_calls = patch.object(
|
||||
... marketing_automation, 'sendmail_transactional').start()
|
||||
... marketing_automation, 'send_message_transactional').start()
|
||||
>>> manager = patch.object(
|
||||
... marketing_automation, 'SMTPDataManager').start()
|
||||
|
||||
@@ -149,10 +149,9 @@ Check email sent::
|
||||
|
||||
>>> smtp_calls.call_count
|
||||
1
|
||||
>>> from_, to, msg = smtp_calls.call_args[0]
|
||||
>>> msg, = smtp_calls.call_args[0]
|
||||
>>> smtp_calls.reset_mock()
|
||||
>>> msg = msg.get_body().get_content()
|
||||
>>> assertEqual(to, [contact.value])
|
||||
>>> assertEqual(re.search(r'Hello, (.*)!', msg).group(1), party.name)
|
||||
>>> open_url.shortened_url in msg
|
||||
True
|
||||
|
||||
@@ -12,10 +12,10 @@ Imports::
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
>>> from trytond.tools import file_open
|
||||
|
||||
Patch sendmail_transactional::
|
||||
Patch send_message_transactional::
|
||||
|
||||
>>> smtp_calls = patch.object(
|
||||
... marketing_automation, 'sendmail_transactional').start()
|
||||
... marketing_automation, 'send_message_transactional').start()
|
||||
>>> manager = patch.object(
|
||||
... marketing_automation, 'SMTPDataManager').start()
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import time
|
||||
from collections import defaultdict
|
||||
from email.headerregistry import Address
|
||||
from email.message import EmailMessage
|
||||
from email.utils import getaddresses
|
||||
from functools import lru_cache, partial
|
||||
from urllib.parse import (
|
||||
parse_qs, parse_qsl, urlencode, urljoin, urlsplit, urlunsplit)
|
||||
@@ -28,11 +27,10 @@ from trytond.model import (
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval
|
||||
from trytond.report import Report, get_email
|
||||
from trytond.sendmail import SMTPDataManager, sendmail_transactional
|
||||
from trytond.sendmail import SMTPDataManager, send_message_transactional
|
||||
from trytond.tools import grouped_slice, reduce_ids
|
||||
from trytond.tools.email_ import (
|
||||
EmailNotValidError, convert_ascii_email, normalize_email, set_from_header,
|
||||
validate_email)
|
||||
EmailNotValidError, normalize_email, set_from_header, validate_email)
|
||||
from trytond.transaction import Transaction, inactive_records
|
||||
from trytond.url import http_host
|
||||
from trytond.wizard import Button, StateTransition, StateView, Wizard
|
||||
@@ -317,8 +315,7 @@ class EmailList(DeactivableMixin, ModelSQL, ModelView):
|
||||
set_from_header(msg, from_cfg, from_ or from_cfg)
|
||||
msg['To'] = record.email
|
||||
msg['Subject'] = title
|
||||
sendmail_transactional(
|
||||
from_cfg, [convert_ascii_email(record.email)], msg)
|
||||
send_message_transactional(msg)
|
||||
|
||||
def request_unsubscribe(self, email, from_=None):
|
||||
pool = Pool()
|
||||
@@ -343,8 +340,7 @@ class EmailList(DeactivableMixin, ModelSQL, ModelView):
|
||||
set_from_header(msg, from_cfg, from_ or from_cfg)
|
||||
msg['To'] = record.email
|
||||
msg['Subject'] = title
|
||||
sendmail_transactional(
|
||||
from_cfg, [convert_ascii_email(record.email)], msg)
|
||||
send_message_transactional(msg)
|
||||
|
||||
|
||||
class Message(Workflow, ModelSQL, ModelView):
|
||||
@@ -522,9 +518,7 @@ class Message(Workflow, ModelSQL, ModelView):
|
||||
content_text = converter.handle(content)
|
||||
msg.add_alternative(content_text, subtype='plain')
|
||||
|
||||
sendmail_transactional(
|
||||
from_cfg, getaddresses([str(to)]), msg,
|
||||
datamanager=smtpd_datamanager)
|
||||
send_message_transactional(msg, datamanager=smtpd_datamanager)
|
||||
if not emails:
|
||||
cls.sent(messages)
|
||||
|
||||
|
||||
@@ -53,9 +53,10 @@ class MarketingEmailTestCase(ModuleTestCase):
|
||||
email_list.save()
|
||||
|
||||
with patch.object(
|
||||
marketing_module, 'sendmail_transactional') as sendmail:
|
||||
marketing_module,
|
||||
'send_message_transactional') as send_message:
|
||||
email_list.request_subscribe('user@example.com')
|
||||
sendmail.assert_called_once_with(FROM, ['user@example.com'], ANY)
|
||||
send_message.assert_called_once()
|
||||
|
||||
with inactive_records():
|
||||
email, = Email.search([
|
||||
@@ -98,9 +99,10 @@ class MarketingEmailTestCase(ModuleTestCase):
|
||||
self.assertTrue(email.active)
|
||||
|
||||
with patch.object(
|
||||
marketing_module, 'sendmail_transactional') as sendmail:
|
||||
marketing_module,
|
||||
'send_message_transactional') as send_message:
|
||||
email_list.request_unsubscribe('user@example.com')
|
||||
sendmail.assert_called_once_with(FROM, ['user@example.com'], ANY)
|
||||
send_message.assert_called_once()
|
||||
|
||||
self.assertEqual(
|
||||
email.get_email_unsubscribe_url(),
|
||||
@@ -142,13 +144,12 @@ class MarketingEmailTestCase(ModuleTestCase):
|
||||
|
||||
with patch.object(
|
||||
marketing_module,
|
||||
'sendmail_transactional') as sendmail:
|
||||
'send_message_transactional') as send_message:
|
||||
smtpd_datamanager = Mock()
|
||||
Message.process(smtpd_datamanager=smtpd_datamanager)
|
||||
|
||||
sendmail.assert_called_once_with(
|
||||
FROM, [('', 'user@example.com')], ANY,
|
||||
datamanager=smtpd_datamanager)
|
||||
send_message.assert_called_once_with(
|
||||
ANY, datamanager=smtpd_datamanager)
|
||||
urls = ShortenedURL.search([
|
||||
('record', '=', str(message)),
|
||||
])
|
||||
|
||||
@@ -12,8 +12,8 @@ from trytond.model import ModelSQL, ModelView, fields
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval, TimeDelta
|
||||
from trytond.report import get_email
|
||||
from trytond.sendmail import SMTPDataManager, sendmail_transactional
|
||||
from trytond.tools.email_ import convert_ascii_email, set_from_header
|
||||
from trytond.sendmail import SMTPDataManager, send_message_transactional
|
||||
from trytond.tools.email_ import set_from_header
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
from .exceptions import TemplateError
|
||||
@@ -171,9 +171,12 @@ class Email(ModelSQL, ModelView):
|
||||
|
||||
# TODO order languages to get default as last one for title
|
||||
msg, title = get_email(self.content, record, languages)
|
||||
language = list(languages)[-1]
|
||||
if languages:
|
||||
language = list(languages)[-1].code
|
||||
else:
|
||||
language = None
|
||||
from_ = sender
|
||||
with Transaction().set_context(language=language.code):
|
||||
with Transaction().set_context(language=language):
|
||||
notification = self.__class__(self.id)
|
||||
if notification.from_:
|
||||
from_ = notification.from_
|
||||
@@ -184,7 +187,7 @@ class Email(ModelSQL, ModelView):
|
||||
|
||||
if self.attachments:
|
||||
for report in self.attachments:
|
||||
name, data = Attachment.get(report, record, language.code)
|
||||
name, data = Attachment.get(report, record, language)
|
||||
ctype, _ = mimetypes.guess_type(name)
|
||||
if not ctype:
|
||||
ctype = 'application/octet-stream'
|
||||
@@ -198,6 +201,7 @@ class Email(ModelSQL, ModelView):
|
||||
set_from_header(msg, sender, from_)
|
||||
msg['To'] = [Address(n, addr_spec=a) for n, a in getaddresses(to)]
|
||||
msg['Cc'] = [Address(n, addr_spec=a) for n, a in getaddresses(cc)]
|
||||
msg['Bcc'] = [Address(n, addr_spec=a) for n, a in getaddresses(bcc)]
|
||||
msg['Subject'] = title
|
||||
msg['Auto-Submitted'] = 'auto-generated'
|
||||
return msg, title
|
||||
@@ -239,17 +243,15 @@ class Email(ModelSQL, ModelView):
|
||||
cc, cc_languages = self._get_cc(record)
|
||||
bcc, bcc_languages = self._get_bcc(record)
|
||||
languages = to_languages | cc_languages | bcc_languages
|
||||
to_addrs = [
|
||||
convert_ascii_email(e) for _, e in getaddresses(to + cc + bcc)]
|
||||
msg, title = self.get_email(record, from_, to, cc, bcc, languages)
|
||||
to_addrs = [e for _, e in getaddresses(
|
||||
filter(None, (msg['To'], msg['Cc'], msg['Bcc'])))]
|
||||
if to_addrs:
|
||||
msg, title = self.get_email(
|
||||
record, from_, to, cc, bcc, languages)
|
||||
sendmail_transactional(
|
||||
from_, to_addrs, msg, datamanager=datamanager)
|
||||
send_message_transactional(msg, datamanager=datamanager)
|
||||
emails.append(Email(
|
||||
recipients=', '.join(to),
|
||||
recipients_secondary=', '.join(cc),
|
||||
recipients_hidden=', '.join(bcc),
|
||||
recipients=msg['To'],
|
||||
recipients_secondary=msg['Cc'],
|
||||
recipients_hidden=msg['Bcc'],
|
||||
addresses=[{'address': a} for a in to_addrs],
|
||||
subject=title,
|
||||
resource=record,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import datetime as dt
|
||||
import sys
|
||||
import unittest
|
||||
from unittest.mock import ANY, patch
|
||||
from unittest.mock import patch
|
||||
|
||||
from trytond.config import config
|
||||
|
||||
@@ -104,14 +104,13 @@ class NotificationEmailTestCase(CompanyTestMixin, ModuleTestCase):
|
||||
}])
|
||||
|
||||
with patch.object(
|
||||
notification_module, 'sendmail_transactional') as sendmail, \
|
||||
notification_module,
|
||||
'send_message_transactional') as send_message, \
|
||||
patch.object(notification_module, 'SMTPDataManager'):
|
||||
user, = User.create([{'name': "Michael Scott", 'login': "msc"}])
|
||||
self.run_tasks()
|
||||
sendmail.assert_called_once_with(
|
||||
FROM, ['user@example.com'], ANY,
|
||||
datamanager=ANY)
|
||||
_, _, msg = sendmail.call_args[0]
|
||||
send_message.assert_called_once()
|
||||
msg, = send_message.call_args[0]
|
||||
self.assertEqual(msg['From'], FROM)
|
||||
self.assertEqual(msg['Subject'], 'Notification Email')
|
||||
self.assertEqual(msg['To'], 'Administrator <user@example.com>')
|
||||
@@ -156,16 +155,15 @@ class NotificationEmailTestCase(CompanyTestMixin, ModuleTestCase):
|
||||
}])
|
||||
|
||||
with patch.object(
|
||||
notification_module, 'sendmail_transactional') as sendmail, \
|
||||
notification_module,
|
||||
'send_message_transactional') as send_message, \
|
||||
patch.object(notification_module, 'SMTPDataManager'):
|
||||
user, = User.create([{
|
||||
'name': "Michael Scott",
|
||||
'login': "msc",
|
||||
'email': 'msc@example.com'}])
|
||||
self.run_tasks()
|
||||
sendmail.assert_called_once_with(
|
||||
FROM, ['msc@example.com'], ANY,
|
||||
datamanager=ANY)
|
||||
send_message.assert_called_once()
|
||||
|
||||
email, = Email.search([])
|
||||
self.assertEqual(email.recipients, 'Michael Scott <msc@example.com>')
|
||||
@@ -200,14 +198,14 @@ class NotificationEmailTestCase(CompanyTestMixin, ModuleTestCase):
|
||||
}])
|
||||
|
||||
with patch.object(
|
||||
notification_module, 'sendmail_transactional') as sendmail, \
|
||||
notification_module,
|
||||
'send_message_transactional') as send_message, \
|
||||
patch.object(notification_module, 'SMTPDataManager'):
|
||||
User.create([{'name': "Michael Scott", 'login': "msc"}])
|
||||
self.run_tasks(1)
|
||||
sendmail.assert_not_called()
|
||||
send_message.assert_not_called()
|
||||
self.run_tasks()
|
||||
sendmail.assert_called_once_with(
|
||||
FROM, ['user@example.com'], ANY, datamanager=ANY)
|
||||
send_message.assert_called_once()
|
||||
|
||||
@with_transaction()
|
||||
def test_notification_email_attachment(self):
|
||||
@@ -355,14 +353,13 @@ class NotificationEmailTestCase(CompanyTestMixin, ModuleTestCase):
|
||||
}])
|
||||
|
||||
with patch.object(
|
||||
notification_module, 'sendmail_transactional') as sendmail, \
|
||||
notification_module,
|
||||
'send_message_transactional') as send_message, \
|
||||
patch.object(notification_module, 'SMTPDataManager'):
|
||||
User.create([{'name': "Michael Scott", 'login': "msc"}])
|
||||
self.run_tasks()
|
||||
sendmail.assert_called_once_with(
|
||||
FROM, ['fallback@example.com'], ANY,
|
||||
datamanager=ANY)
|
||||
_, _, msg = sendmail.call_args[0]
|
||||
send_message.assert_called_once()
|
||||
msg, = send_message.call_args[0]
|
||||
self.assertEqual(msg['To'], 'Fallback <fallback@example.com>')
|
||||
|
||||
@with_transaction()
|
||||
@@ -393,11 +390,12 @@ class NotificationEmailTestCase(CompanyTestMixin, ModuleTestCase):
|
||||
}])
|
||||
|
||||
with patch.object(
|
||||
notification_module, 'get_email') as get_email, \
|
||||
notification_module,
|
||||
'send_message_transactional') as send_message_transactional, \
|
||||
patch.object(notification_module, 'SMTPDataManager'):
|
||||
User.create([{'name': "Michael Scott", 'login': "msc"}])
|
||||
self.run_tasks()
|
||||
get_email.assert_not_called()
|
||||
send_message_transactional.assert_not_called()
|
||||
|
||||
|
||||
del ModuleTestCase
|
||||
@@ -13,7 +13,7 @@ from trytond.modules.currency.fields import Monetary
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.pyson import Bool, Eval, Id
|
||||
from trytond.report import Report, get_email
|
||||
from trytond.sendmail import sendmail_transactional
|
||||
from trytond.sendmail import send_message_transactional
|
||||
from trytond.tools.email_ import (
|
||||
EmailNotValidError, set_from_header, validate_email)
|
||||
from trytond.transaction import Transaction
|
||||
@@ -198,7 +198,7 @@ class GiftCard(ModelSQL, ModelView):
|
||||
set_from_header(msg, from_cfg, from_ or from_cfg)
|
||||
msg['To'] = email
|
||||
msg['Subject'] = title
|
||||
sendmail_transactional(from_cfg, [email], msg, strict=True)
|
||||
send_message_transactional(msg, strict=True)
|
||||
|
||||
|
||||
class GiftCardReport(Report):
|
||||
|
||||
@@ -13,10 +13,10 @@ Imports::
|
||||
>>> from trytond.modules.sale_gift_card import sale
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
Patch sendmail_transactional::
|
||||
Patch send_message_transactional::
|
||||
|
||||
>>> smtp_calls = patch.object(
|
||||
... sale, 'sendmail_transactional').start()
|
||||
... sale, 'send_message_transactional').start()
|
||||
|
||||
Activate modules::
|
||||
|
||||
@@ -136,9 +136,7 @@ Check gift cards::
|
||||
False
|
||||
>>> smtp_calls.call_count
|
||||
2
|
||||
>>> from_, to, msg = smtp_calls.call_args[0]
|
||||
>>> to
|
||||
['customer@example.com']
|
||||
>>> msg, = smtp_calls.call_args[0]
|
||||
>>> card.number in msg.get_body().get_content()
|
||||
True
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
from unittest.mock import ANY, patch
|
||||
from unittest.mock import patch
|
||||
|
||||
from trytond.config import config
|
||||
from trytond.modules.party.tests import PartyCheckEraseMixin
|
||||
@@ -101,9 +101,10 @@ class WebUserTestCase(PartyCheckEraseMixin, ModuleTestCase):
|
||||
self.assertFalse(user.email_valid)
|
||||
self.assertFalse(user.email_token)
|
||||
|
||||
with patch.object(user_module, 'sendmail_transactional') as sendmail:
|
||||
with patch.object(
|
||||
user_module, 'send_message_transactional') as send_message:
|
||||
User.validate_email([user])
|
||||
sendmail.assert_called_once_with(FROM, ['user@example.com'], ANY)
|
||||
send_message.assert_called_once()
|
||||
|
||||
token = user.email_token
|
||||
self.assertTrue(token)
|
||||
@@ -133,9 +134,10 @@ class WebUserTestCase(PartyCheckEraseMixin, ModuleTestCase):
|
||||
user.save()
|
||||
self.assertFalse(user.password_hash)
|
||||
|
||||
with patch.object(user_module, 'sendmail_transactional') as sendmail:
|
||||
with patch.object(
|
||||
user_module, 'send_message_transactional') as send_message:
|
||||
User.reset_password([user])
|
||||
sendmail.assert_called_once_with(FROM, ['user@example.com'], ANY)
|
||||
send_message.assert_called_once()
|
||||
|
||||
token = user.reset_password_token
|
||||
self.assertTrue(token)
|
||||
|
||||
@@ -33,7 +33,7 @@ from trytond.pool import Pool
|
||||
from trytond.pyson import Eval
|
||||
from trytond.report import Report, get_email
|
||||
from trytond.res.user import CRYPT_CONTEXT, LoginAttempt
|
||||
from trytond.sendmail import sendmail_transactional
|
||||
from trytond.sendmail import send_message_transactional
|
||||
from trytond.tools.email_ import (
|
||||
EmailNotValidError, normalize_email, set_from_header, validate_email)
|
||||
from trytond.transaction import Transaction, without_check_access
|
||||
@@ -50,7 +50,7 @@ def _send_email(from_, users, email_func):
|
||||
set_from_header(msg, from_cfg, from_ or from_cfg)
|
||||
msg['To'] = user.email
|
||||
msg['Subject'] = title
|
||||
sendmail_transactional(from_cfg, [user.email], msg)
|
||||
send_message_transactional(msg)
|
||||
|
||||
|
||||
def _add_params(url, **params):
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
* Add send_message methods
|
||||
* Store model on ir.rule.group
|
||||
* Store model on ir.model.button
|
||||
* Store model and field name on ir.model.field.access
|
||||
|
||||
@@ -10,7 +10,7 @@ Sendmail
|
||||
|
||||
The required arguments are an :rfc:`5322` from-address string, a list of
|
||||
:rfc:`5322` to-address strings (a bare string is treated as a list with 1
|
||||
address), and an email message.
|
||||
address), and an :py:class:`email.message.Message`.
|
||||
The caller may pass a :class:`~trytond.transaction.Transaction` instance to
|
||||
join otherwise the current one is joined.
|
||||
A specific data manager can be specified otherwise the default
|
||||
@@ -21,6 +21,12 @@ Sendmail
|
||||
|
||||
An SMTP failure is only logged without raising any exception.
|
||||
|
||||
.. function:: send_message_transactional(msg[, from_addr[, to_addrs[, transaction[, datamanager[, strict]]]]])
|
||||
|
||||
It is a convenience method for calling :func:`sendmail_transactional`.
|
||||
If ``from_addr`` is ``None`` or ``to_addrs`` is ``None``, if fills those
|
||||
arguments with addresses extracted from the headers of ``msg``.
|
||||
|
||||
.. function:: sendmail(from_addr, to_addrs, msg[, server[, strict]])
|
||||
|
||||
Send email message like :meth:`sendmail_transactional` but directly without
|
||||
@@ -32,6 +38,11 @@ Sendmail
|
||||
If strict is ``True``, an exception is raised if it is not possible to
|
||||
connect to the server.
|
||||
|
||||
.. function:: send_message(msg[, from_addr[, to_addrs[, server[, strict]]]])
|
||||
|
||||
Same convenience method as :func:`send_message_transactional` but for
|
||||
calling :func:`sendmail`.
|
||||
|
||||
.. function:: get_smtp_server([uri[, strict]])
|
||||
|
||||
Return a SMTP instance from `smtplib`_ using the ``uri`` or the one defined
|
||||
|
||||
@@ -20,7 +20,7 @@ from trytond.pool import Pool
|
||||
from trytond.pyson import Bool, Eval, PYSONDecoder
|
||||
from trytond.report import Report
|
||||
from trytond.rpc import RPC
|
||||
from trytond.sendmail import sendmail_transactional
|
||||
from trytond.sendmail import send_message_transactional
|
||||
from trytond.tools import escape_wildcard
|
||||
from trytond.tools.email_ import convert_ascii_email, set_from_header
|
||||
from trytond.tools.string_ import StringMatcher
|
||||
@@ -161,17 +161,20 @@ class Email(ResourceAccessMixin, ModelSQL, ModelView):
|
||||
msg['Cc'] = ', '.join(
|
||||
formataddr((n, convert_ascii_email(a)))
|
||||
for n, a in getaddresses([cc]))
|
||||
msg['Bcc'] = ', '.join(
|
||||
formataddr((n, convert_ascii_email(a)))
|
||||
for n, a in getaddresses([bcc]))
|
||||
msg['Subject'] = subject
|
||||
|
||||
to_addrs = list(filter(None, map(
|
||||
str.strip,
|
||||
_get_emails(to) + _get_emails(cc) + _get_emails(bcc))))
|
||||
sendmail_transactional(from_, to_addrs, msg, strict=True)
|
||||
send_message_transactional(msg, strict=True)
|
||||
|
||||
email = cls(
|
||||
recipients=to,
|
||||
recipients_secondary=cc,
|
||||
recipients_hidden=bcc,
|
||||
recipients=msg['To'],
|
||||
recipients_secondary=msg['Cc'],
|
||||
recipients_hidden=msg['Bcc'],
|
||||
addresses=[{'address': a} for a in to_addrs],
|
||||
subject=subject,
|
||||
body=body,
|
||||
|
||||
@@ -51,7 +51,7 @@ from trytond.pool import Pool
|
||||
from trytond.pyson import Bool, Eval, PYSONEncoder
|
||||
from trytond.report import Report, get_email
|
||||
from trytond.rpc import RPC
|
||||
from trytond.sendmail import sendmail_transactional
|
||||
from trytond.sendmail import send_message_transactional
|
||||
from trytond.tools import grouped_slice
|
||||
from trytond.tools.email_ import (
|
||||
EmailNotValidError, normalize_email, set_from_header, validate_email)
|
||||
@@ -96,7 +96,7 @@ def _send_email(from_, users, email_func):
|
||||
set_from_header(msg, from_cfg, from_ or from_cfg)
|
||||
msg['To'] = user.email
|
||||
msg['Subject'] = title
|
||||
sendmail_transactional(from_cfg, [user.email], msg)
|
||||
send_message_transactional(msg)
|
||||
|
||||
|
||||
class PasswordError(UserError):
|
||||
|
||||
@@ -11,7 +11,10 @@ from urllib.parse import parse_qs, unquote_plus
|
||||
from trytond.config import config, parse_uri
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
__all__ = ['sendmail_transactional', 'sendmail', 'SMTPDataManager']
|
||||
__all__ = [
|
||||
'sendmail_transactional', 'sendmail',
|
||||
'send_message_transactional', 'send_message',
|
||||
'SMTPDataManager']
|
||||
logger = logging.getLogger(__name__)
|
||||
retry = config.getint('email', 'retry', default=5)
|
||||
|
||||
@@ -19,6 +22,13 @@ retry = config.getint('email', 'retry', default=5)
|
||||
def sendmail_transactional(
|
||||
from_addr, to_addrs, msg, transaction=None, datamanager=None,
|
||||
strict=False):
|
||||
send_message_transactional(
|
||||
msg, from_addr, to_addrs, transaction, datamanager, strict)
|
||||
|
||||
|
||||
def send_message_transactional(
|
||||
msg, from_addr=None, to_addrs=None, transaction=None, datamanager=None,
|
||||
strict=False):
|
||||
if transaction is None:
|
||||
transaction = Transaction()
|
||||
assert isinstance(transaction, Transaction), transaction
|
||||
@@ -29,6 +39,11 @@ def sendmail_transactional(
|
||||
|
||||
|
||||
def sendmail(from_addr, to_addrs, msg, server=None, strict=False):
|
||||
return send_message(msg, from_addr, to_addrs, server, strict)
|
||||
|
||||
|
||||
def send_message(
|
||||
msg, from_addr=None, to_addrs=None, server=None, strict=False):
|
||||
if server is None:
|
||||
server = get_smtp_server(strict=strict)
|
||||
if not server:
|
||||
@@ -43,7 +58,7 @@ def sendmail(from_addr, to_addrs, msg, server=None, strict=False):
|
||||
if count != retry:
|
||||
time.sleep(0.02 * (retry - count))
|
||||
try:
|
||||
senderrs = server.sendmail(from_addr, to_addrs, msg.as_string())
|
||||
senderrs = server.send_message(msg, from_addr, to_addrs)
|
||||
except smtplib.SMTPServerDisconnected:
|
||||
if count:
|
||||
server = get_smtp_server(strict=strict)
|
||||
@@ -82,8 +97,7 @@ def send_test_email(to_addrs, server=None):
|
||||
msg['From'] = from_
|
||||
msg['To'] = to_addrs
|
||||
msg['Subject'] = 'Tryton test email'
|
||||
sendmail(
|
||||
config.get('email', 'from'), to_addrs, msg, server=server, strict=True)
|
||||
send_message(msg, server=server, strict=True)
|
||||
|
||||
|
||||
def get_smtp_server(uri=None, strict=False):
|
||||
@@ -153,8 +167,8 @@ class SMTPDataManager(object):
|
||||
def tpc_finish(self, trans):
|
||||
if self._server is not None:
|
||||
for from_addr, to_addrs, msg in self.queue:
|
||||
new_server = sendmail(
|
||||
from_addr, to_addrs, msg, server=self._server)
|
||||
new_server = send_message(
|
||||
msg, from_addr, to_addrs, server=self._server)
|
||||
if new_server:
|
||||
self._server = new_server
|
||||
self._server.quit()
|
||||
|
||||
@@ -17,7 +17,6 @@ except ImportError:
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from trytond.config import config
|
||||
from trytond.ir.exceptions import SequenceAffixError
|
||||
from trytond.ir.lang import _replace
|
||||
from trytond.pool import Pool
|
||||
@@ -339,7 +338,9 @@ class IrTestCase(ModuleTestCase):
|
||||
)
|
||||
report.save()
|
||||
|
||||
with patch('trytond.ir.email_.sendmail_transactional') as sendmail:
|
||||
with patch(
|
||||
'trytond.ir.email_.send_message_transactional'
|
||||
) as send_message:
|
||||
email = Email.send(
|
||||
to='"John Doe" <john@example.com>, Jane <jane@example.com>',
|
||||
cc='User <user@example.com>',
|
||||
@@ -359,11 +360,10 @@ class IrTestCase(ModuleTestCase):
|
||||
'jane@example.com',
|
||||
'user@example.com',
|
||||
'me@example.com']
|
||||
sendmail.assert_called_once_with(
|
||||
config.get('email', 'from'), addresses, ANY, strict=True)
|
||||
send_message.assert_called_once_with(ANY, strict=True)
|
||||
self.assertEqual(
|
||||
email.recipients,
|
||||
'"John Doe" <john@example.com>, Jane <jane@example.com>')
|
||||
'John Doe <john@example.com>, Jane <jane@example.com>')
|
||||
self.assertEqual(email.recipients_secondary, 'User <user@example.com>')
|
||||
self.assertEqual(email.recipients_hidden, 'me@example.com')
|
||||
self.assertEqual(
|
||||
|
||||
@@ -37,8 +37,8 @@ class SendmailTestCase(unittest.TestCase):
|
||||
server = Mock()
|
||||
sendmail(
|
||||
'tryton@example.com', 'foo@example.com', message, server=server)
|
||||
server.sendmail.assert_called_with(
|
||||
'tryton@example.com', 'foo@example.com', message.as_string())
|
||||
server.send_message.assert_called_with(
|
||||
message, 'tryton@example.com', 'foo@example.com')
|
||||
server.quit.assert_not_called()
|
||||
|
||||
def test_get_smtp_server(self):
|
||||
@@ -97,9 +97,9 @@ class SendmailTestCase(unittest.TestCase):
|
||||
|
||||
transaction.commit()
|
||||
|
||||
server.sendmail.assert_has_calls([
|
||||
call('foo@example.com', 'bar@example.com', msg1.as_string()),
|
||||
call('bar@example.com', 'foo@example.com', msg2.as_string()),
|
||||
server.send_message.assert_has_calls([
|
||||
call(msg1, 'foo@example.com', 'bar@example.com'),
|
||||
call(msg2, 'bar@example.com', 'foo@example.com'),
|
||||
])
|
||||
server.quit.assert_called_once_with()
|
||||
self.assertFalse(datamanager.queue)
|
||||
@@ -110,5 +110,5 @@ class SendmailTestCase(unittest.TestCase):
|
||||
'foo@example.com', 'bar@example.com', MagicMock(Message))
|
||||
transaction.rollback()
|
||||
|
||||
server.sendmail.assert_not_called()
|
||||
server.send_message.assert_not_called()
|
||||
self.assertFalse(datamanager.queue)
|
||||
@@ -4,7 +4,7 @@ import datetime
|
||||
import os
|
||||
import unittest
|
||||
from contextlib import contextmanager
|
||||
from unittest.mock import ANY, Mock, patch
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from trytond.config import config
|
||||
from trytond.pool import Pool
|
||||
@@ -151,9 +151,10 @@ class UserTestCase(unittest.TestCase):
|
||||
|
||||
user = self.create_user('user', '12345', email='user@example.com')
|
||||
|
||||
with patch.object(user_module, 'sendmail_transactional') as sendmail:
|
||||
with patch.object(
|
||||
user_module, 'send_message_transactional') as send_message:
|
||||
User.reset_password([user], length=8)
|
||||
sendmail.assert_called_once_with(FROM, ['user@example.com'], ANY)
|
||||
send_message.assert_called_once()
|
||||
|
||||
cursor.execute(*user_table.select(
|
||||
user_table.password_hash,
|
||||
@@ -174,7 +175,7 @@ class UserTestCase(unittest.TestCase):
|
||||
user = User(login='user', email='user@example.com')
|
||||
user.save()
|
||||
|
||||
with patch.object(user_module, 'sendmail_transactional'):
|
||||
with patch.object(user_module, 'send_message_transactional'):
|
||||
User.reset_password([user], length=8)
|
||||
|
||||
user.password_reset_expire = (
|
||||
|
||||
Reference in new issue
Block a user