Update to 3.3.8
This commit is contained in:
parent
2a884b1225
commit
858d271b8b
@ -1,112 +0,0 @@
|
||||
From 3b8f0a3c4981f61d2f9b759b27a1e4b3c1d504aa Mon Sep 17 00:00:00 2001
|
||||
From: baizg1107 <preloyalwhite@163.com>
|
||||
Date: Mon, 20 Jun 2022 11:33:30 +0800
|
||||
Subject: [PATCH] fix tests assertion error
|
||||
|
||||
---
|
||||
src/mailman/commands/tests/test_cli_addmembers.py | 1 +
|
||||
src/mailman/commands/tests/test_cli_delmembers.py | 1 +
|
||||
src/mailman/commands/tests/test_cli_notify.py | 7 +++----
|
||||
src/mailman/commands/tests/test_cli_syncmembers.py | 12 ++++++------
|
||||
src/mailman/model/tests/test_listmanager.py | 12 ++++++------
|
||||
5 files changed, 17 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/src/mailman/commands/tests/test_cli_addmembers.py b/src/mailman/commands/tests/test_cli_addmembers.py
|
||||
index 13f6ff7..6c87b9d 100644
|
||||
--- a/src/mailman/commands/tests/test_cli_addmembers.py
|
||||
+++ b/src/mailman/commands/tests/test_cli_addmembers.py
|
||||
@@ -253,6 +253,7 @@ class TestCLIAddMembers(unittest.TestCase):
|
||||
print('Anne Person <aperson@example.com>', file=infp)
|
||||
result = self._command.invoke(addmembers, (
|
||||
'-i', infp.name, 'ant.example.com'))
|
||||
+ self.maxDiff = None
|
||||
self.assertEqual(result.output, '')
|
||||
self.assertEqual(result.exit_code, 0)
|
||||
members = list(self._mlist.members.members)
|
||||
diff --git a/src/mailman/commands/tests/test_cli_delmembers.py b/src/mailman/commands/tests/test_cli_delmembers.py
|
||||
index 297e0bf..091c134 100644
|
||||
--- a/src/mailman/commands/tests/test_cli_delmembers.py
|
||||
+++ b/src/mailman/commands/tests/test_cli_delmembers.py
|
||||
@@ -143,6 +143,7 @@ class TestCLIDelMembers(unittest.TestCase):
|
||||
print('Bart Person <bperson@example.com>', file=infp)
|
||||
result = self._command.invoke(delmembers, (
|
||||
'--fromall', '-f', infp.name))
|
||||
+ self.maxDiff = None
|
||||
self.assertEqual(result.output, '')
|
||||
members = list(self._mlist.members.members)
|
||||
self.assertEqual(len(members), 1)
|
||||
diff --git a/src/mailman/commands/tests/test_cli_notify.py b/src/mailman/commands/tests/test_cli_notify.py
|
||||
index 8b37922..30b4518 100644
|
||||
--- a/src/mailman/commands/tests/test_cli_notify.py
|
||||
+++ b/src/mailman/commands/tests/test_cli_notify.py
|
||||
@@ -134,10 +134,9 @@ No such list found: bogus@example.com
|
||||
# Clear messages from setup.
|
||||
get_queue_messages('virgin')
|
||||
result = self._command.invoke(notify, ('-v',))
|
||||
- self.assertMultiLineEqual(result.output, """\
|
||||
-The ant@example.com list has 4 moderation requests waiting.
|
||||
-The bee@example.com list has 0 moderation requests waiting.
|
||||
-""")
|
||||
+ self.maxDiff = None
|
||||
+ equaldiff = result.output
|
||||
+ self.assertMultiLineEqual(result.output, equaldiff)
|
||||
msg = get_queue_messages('virgin', expected_count=1)[0].msg
|
||||
self.assertMultiLineEqual(msg.get_payload(), """\
|
||||
The ant@example.com list has 4 moderation requests waiting.
|
||||
diff --git a/src/mailman/commands/tests/test_cli_syncmembers.py b/src/mailman/commands/tests/test_cli_syncmembers.py
|
||||
index 3a30bbf..6dc46b0 100644
|
||||
--- a/src/mailman/commands/tests/test_cli_syncmembers.py
|
||||
+++ b/src/mailman/commands/tests/test_cli_syncmembers.py
|
||||
@@ -106,11 +106,10 @@ class TestCLISyncMembers(unittest.TestCase):
|
||||
print('Anne Person <aperson@example.com>', file=infp)
|
||||
result = self._command.invoke(syncmembers, (
|
||||
infp.name, 'ant.example.com'))
|
||||
+ self.maxDiff = None
|
||||
+ equaldiff = result.output
|
||||
self.assertEqual(
|
||||
- result.output,
|
||||
- '[ADD] Anne Person <aperson@example.com>\n'
|
||||
- 'Membership is banned (skipping): '
|
||||
- 'Anne Person <aperson@example.com>\n'
|
||||
+ result.output, equaldiff
|
||||
)
|
||||
self.assertEqual(len(list(self._mlist.members.members)), 0)
|
||||
|
||||
@@ -413,8 +412,9 @@ class TestCLISyncMembers(unittest.TestCase):
|
||||
print('Anne Person <aperson@example.com>', file=infp)
|
||||
result = self._command.invoke(syncmembers, (
|
||||
infp.name, 'ant.example.com'))
|
||||
- self.assertEqual(result.output,
|
||||
- '[ADD] Anne Person <aperson@example.com>\n')
|
||||
+ self.assertEqual(result.exit_code, 0)
|
||||
+ equaldiff = result.output
|
||||
+ self.assertEqual(result.output, equaldiff)
|
||||
self.assertEqual(result.exit_code, 0)
|
||||
members = list(self._mlist.members.members)
|
||||
self.assertEqual(len(members), 1)
|
||||
diff --git a/src/mailman/model/tests/test_listmanager.py b/src/mailman/model/tests/test_listmanager.py
|
||||
index 8e0ba03..82f8427 100644
|
||||
--- a/src/mailman/model/tests/test_listmanager.py
|
||||
+++ b/src/mailman/model/tests/test_listmanager.py
|
||||
@@ -81,12 +81,12 @@ class TestListManager(unittest.TestCase):
|
||||
|
||||
def test_list_manager_list_ids(self):
|
||||
# You can get all the list ids for all the existing mailing lists.
|
||||
- create_list('ant@example.com')
|
||||
- create_list('bee@example.com')
|
||||
- create_list('cat@example.com')
|
||||
- self.assertEqual(
|
||||
- sorted(getUtility(IListManager).list_ids),
|
||||
- ['ant.example.com', 'bee.example.com', 'cat.example.com'])
|
||||
+ ant = create_list('ant@example.com')
|
||||
+ bee = create_list('bee@example.com')
|
||||
+ cat = create_list('cat@example.com')
|
||||
+ self.assertEqual(ant.list_id, 'ant.example.com')
|
||||
+ self.assertEqual(bee.list_id, 'bee.example.com')
|
||||
+ self.assertEqual(cat.list_id, 'cat.example.com')
|
||||
|
||||
def test_delete_list_with_list_archiver_set(self):
|
||||
# Ensure that mailing lists with archiver sets can be deleted. In
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -1,120 +0,0 @@
|
||||
From 38c794d9ed71f25ee138760461f66abc29dfa81c Mon Sep 17 00:00:00 2001
|
||||
From: Abhilash Raj <maxking@asynchronous.in>
|
||||
Date: Sun, 20 Dec 2020 05:26:18 +0000
|
||||
Subject: [PATCH] Remove old style coroutines and use async def instead.
|
||||
|
||||
---
|
||||
src/mailman/testing/mta.py | 39 ++++++++++++++++----------------------
|
||||
1 file changed, 16 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/src/mailman/testing/mta.py b/src/mailman/testing/mta.py
|
||||
index aede4a24da..aa6543056d 100644
|
||||
--- a/src/mailman/testing/mta.py
|
||||
+++ b/src/mailman/testing/mta.py
|
||||
@@ -18,7 +18,6 @@
|
||||
"""Fake MTA for testing purposes."""
|
||||
from __future__ import generator_stop
|
||||
|
||||
-import asyncio
|
||||
import smtplib
|
||||
|
||||
from aiosmtpd.controller import Controller
|
||||
@@ -54,14 +53,12 @@ class ConnectionCountingHandler(MessageHandler):
|
||||
def handle_message(self, message):
|
||||
self._msg_queue.put(message)
|
||||
|
||||
- @asyncio.coroutine
|
||||
- def handle_EHLO(self, server, session, envelope, hostname):
|
||||
+ async def handle_EHLO(self, server, session, envelope, hostname):
|
||||
session.host_name = hostname
|
||||
- yield from server.push('250-AUTH PLAIN')
|
||||
+ await server.push('250-AUTH PLAIN')
|
||||
return '250 HELP'
|
||||
|
||||
- @asyncio.coroutine
|
||||
- def handle_RSET(self, server, session, envelope):
|
||||
+ async def handle_RSET(self, server, session, envelope):
|
||||
self.connection_count = 0
|
||||
return '250 OK'
|
||||
|
||||
@@ -83,8 +80,7 @@ class ConnectionCountingSMTP(SMTP):
|
||||
# same though, so it's fine to stash this value away there.
|
||||
self.event_handler.connection_count += 1
|
||||
|
||||
- @asyncio.coroutine
|
||||
- def smtp_AUTH(self, arg):
|
||||
+ async def smtp_AUTH(self, arg):
|
||||
"""Record that the AUTH occurred."""
|
||||
args = arg.split()
|
||||
if args[0].lower() == 'plain':
|
||||
@@ -94,25 +90,24 @@ class ConnectionCountingSMTP(SMTP):
|
||||
# which must be equal to the base 64 equivalent of the
|
||||
# expected login string "testuser:testpass".
|
||||
if response == 'AHRlc3R1c2VyAHRlc3RwYXNz':
|
||||
- yield from self.push('235 Ok')
|
||||
+ await self.push('235 Ok')
|
||||
self._oob_queue.put(response)
|
||||
else:
|
||||
- yield from self.push('571 Bad authentication')
|
||||
+ await self.push('571 Bad authentication')
|
||||
else:
|
||||
assert len(args) == 1, args
|
||||
# Send a challenge and set us up to wait for the response.
|
||||
- yield from self.push('334 ')
|
||||
+ await self.push('334 ')
|
||||
self._waiting_for_auth_response = True
|
||||
else:
|
||||
- yield from self.push('571 Bad authentication')
|
||||
+ await self.push('571 Bad authentication')
|
||||
|
||||
- @asyncio.coroutine
|
||||
- def smtp_STAT(self, arg):
|
||||
+ async def smtp_STAT(self, arg):
|
||||
"""Cause the server to send statistics to its controller."""
|
||||
# Do not count the connection caused by the STAT connect.
|
||||
self.event_handler.connection_count -= 1
|
||||
self._oob_queue.put(self.event_handler.connection_count)
|
||||
- yield from self.push('250 Ok')
|
||||
+ await self.push('250 Ok')
|
||||
|
||||
def _next_error(self, command):
|
||||
"""Return the next error for the SMTP command, if there is one.
|
||||
@@ -139,29 +134,27 @@ class ConnectionCountingSMTP(SMTP):
|
||||
return code
|
||||
return None
|
||||
|
||||
- @asyncio.coroutine
|
||||
- def smtp_RCPT(self, arg):
|
||||
+ async def smtp_RCPT(self, arg):
|
||||
"""For testing, sometimes cause a non-25x response."""
|
||||
code = self._next_error('rcpt')
|
||||
if code is None:
|
||||
# Everything's cool.
|
||||
- yield from super().smtp_RCPT(arg)
|
||||
+ await super().smtp_RCPT(arg)
|
||||
else:
|
||||
# The test suite wants this to fail. The message corresponds to
|
||||
# the exception we expect smtplib.SMTP to raise.
|
||||
- yield from self.push('%d Error: SMTPRecipientsRefused' % code)
|
||||
+ await self.push('%d Error: SMTPRecipientsRefused' % code)
|
||||
|
||||
- @asyncio.coroutine
|
||||
- def smtp_MAIL(self, arg):
|
||||
+ async def smtp_MAIL(self, arg):
|
||||
"""For testing, sometimes cause a non-25x response."""
|
||||
code = self._next_error('mail')
|
||||
if code is None:
|
||||
# Everything's cool.
|
||||
- yield from super().smtp_MAIL(arg)
|
||||
+ await super().smtp_MAIL(arg)
|
||||
else:
|
||||
# The test suite wants this to fail. The message corresponds to
|
||||
# the exception we expect smtplib.SMTP to raise.
|
||||
- yield from self.push('%d Error: SMTPResponseException' % code)
|
||||
+ await self.push('%d Error: SMTPResponseException' % code)
|
||||
|
||||
|
||||
class ConnectionCountingController(Controller):
|
||||
--
|
||||
GitLab
|
||||
|
||||
@ -1,64 +0,0 @@
|
||||
From 6eada072194037049e5875edc4fda914d9c67f83 Mon Sep 17 00:00:00 2001
|
||||
From: starlet-dx <15929766099@163.com>
|
||||
Date: Thu, 19 Jan 2023 15:08:54 +0800
|
||||
Subject: [PATCH 1/1] Require authheaders >=0.14.0 and adjust tests accordingly.
|
||||
|
||||
---
|
||||
setup.py | 2 +-
|
||||
src/mailman/handlers/tests/test_arc_validate.py | 13 ++++++++-----
|
||||
2 files changed, 9 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/setup.py b/setup.py
|
||||
index 5eceac2..5171d0e 100644
|
||||
--- a/setup.py
|
||||
+++ b/setup.py
|
||||
@@ -113,7 +113,7 @@ case second 'm'. Any other spelling is incorrect.""",
|
||||
'aiosmtpd>=1.1',
|
||||
'alembic',
|
||||
'atpublic',
|
||||
- 'authheaders>=0.9.2',
|
||||
+ 'authheaders>=0.14.0',
|
||||
'authres>=1.0.1',
|
||||
'click>=8.0.0',
|
||||
'dnspython>=1.14.0',
|
||||
diff --git a/src/mailman/handlers/tests/test_arc_validate.py b/src/mailman/handlers/tests/test_arc_validate.py
|
||||
index 6eb2f57..2103b08 100644
|
||||
--- a/src/mailman/handlers/tests/test_arc_validate.py
|
||||
+++ b/src/mailman/handlers/tests/test_arc_validate.py
|
||||
@@ -190,8 +190,9 @@ This is a test message.
|
||||
""")
|
||||
|
||||
ValidateAuthenticity().process(lst, msg, msgdata)
|
||||
- res = ["lists.example.org; spf=pass smtp.mfrom=jqd@d1.example"
|
||||
- "; dkim=pass header.i=@d1.example; dmarc=pass; arc=fail"]
|
||||
+ res = ['lists.example.org; spf=pass smtp.mfrom=jqd@d1.example',
|
||||
+ '; dkim=pass header.i=@d1.example; dmarc=pass; arc=fail ',
|
||||
+ '(Most recent ARC-Message-Signature did not validate)']
|
||||
self.assertEqual(msg["Authentication-Results"], ''.join(res))
|
||||
|
||||
def test_authentication_whitelist_hit(self):
|
||||
@@ -233,8 +234,9 @@ This is a test!
|
||||
|
||||
ValidateAuthenticity().process(lst, msg, msgdata)
|
||||
|
||||
- res = ["example.com; spf=pass smtp.mailfrom=gmail.com"
|
||||
- "; dkim=pass header.d=valimail.com; arc=none"]
|
||||
+ res = ['example.com; spf=pass smtp.mailfrom=gmail.com',
|
||||
+ '; dkim=pass header.d=valimail.com; arc=none ',
|
||||
+ '(Message is not ARC signed)']
|
||||
self.assertEqual(msg["Authentication-Results"], ''.join(res))
|
||||
|
||||
def test_authentication_whitelist_miss(self):
|
||||
@@ -277,7 +279,8 @@ This is a test!
|
||||
|
||||
ValidateAuthenticity().process(lst, msg, msgdata)
|
||||
self.assertEqual(msg["Authentication-Results"],
|
||||
- "test.com; dkim=pass header.d=valimail.com; arc=none")
|
||||
+ 'test.com; dkim=pass header.d=valimail.com; arc=none '
|
||||
+ '(Message is not ARC signed)')
|
||||
|
||||
|
||||
class TestTimeout(unittest.TestCase):
|
||||
--
|
||||
2.30.0
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
From 1f2b19c8ad7235f5632a170c91e766462884813e Mon Sep 17 00:00:00 2001
|
||||
From: starlet-dx <15929766099@163.com>
|
||||
Date: Sun, 23 Jul 2023 15:19:02 +0800
|
||||
Subject: [PATCH 1/1] Support Python 3.11
|
||||
|
||||
Refer:
|
||||
https://gitlab.com/mailman/mailman/-/commit/1954815f32fea4d9d920cdc74f63bcc24d3b6c49
|
||||
---
|
||||
src/mailman/runners/lmtp.py | 17 ++++++++++++-----
|
||||
1 file changed, 12 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/mailman/runners/lmtp.py b/src/mailman/runners/lmtp.py
|
||||
index a653275..0fc45bf 100644
|
||||
--- a/src/mailman/runners/lmtp.py
|
||||
+++ b/src/mailman/runners/lmtp.py
|
||||
@@ -35,7 +35,6 @@ so that the peer mail server can provide better diagnostics.
|
||||
"""
|
||||
|
||||
import email
|
||||
-import asyncio
|
||||
import logging
|
||||
|
||||
from aiosmtpd.controller import Controller
|
||||
@@ -126,9 +125,13 @@ def split_recipient(address):
|
||||
|
||||
|
||||
class LMTPHandler:
|
||||
- @asyncio.coroutine
|
||||
+ async def handle_RCPT(self, server, session, envelope, to, rcpt_options):
|
||||
+ # Use a helper function to use the transactional wrapper on since it
|
||||
+ # doesn't yet work on awaitables (async def funcs.)
|
||||
+ return self._handle_RCPT(server, session, envelope, to, rcpt_options)
|
||||
+
|
||||
@transactional
|
||||
- def handle_RCPT(self, server, session, envelope, to, rcpt_options):
|
||||
+ def _handle_RCPT(self, server, session, envelope, to, rcpt_options):
|
||||
listnames = set(getUtility(IListManager).names)
|
||||
try:
|
||||
to = parseaddr(to)[1].lower()
|
||||
@@ -164,9 +167,13 @@ class LMTPHandler:
|
||||
config.db.abort()
|
||||
return ERR_550
|
||||
|
||||
- @asyncio.coroutine
|
||||
+ async def handle_DATA(self, server, session, envelope):
|
||||
+ # Use a helper function to use the transactional wrapper on since it
|
||||
+ # doesn't yet work on awaitables (async def funcs.)
|
||||
+ return self._handle_DATA(server, session, envelope)
|
||||
+
|
||||
@transactional
|
||||
- def handle_DATA(self, server, session, envelope):
|
||||
+ def _handle_DATA(self, server, session, envelope):
|
||||
try:
|
||||
# Refresh the list of list names every time we process a message
|
||||
# since the set of mailing lists could have changed.
|
||||
--
|
||||
2.30.0
|
||||
|
||||
@ -1,217 +0,0 @@
|
||||
From b9387743835821e8327e73aa502cb01f2f83dc97 Mon Sep 17 00:00:00 2001
|
||||
From: Patrick Cernko <errror+gitlab.com@errror.org>
|
||||
Date: Wed, 19 Oct 2022 23:27:10 +0000
|
||||
Subject: [PATCH] Verify recipient validity at RCPT command in LMTP runner (2nd
|
||||
try)
|
||||
|
||||
Verify recipient validity at RCPT command in LMTP runner (reviewed merge request c2ddff05a4f405fa46fb792cc69912829c1cbf83, rejected 2 years ago)
|
||||
* returning '250 ok' to correctly accept valid recipients
|
||||
* reorganized code a bit to better match existing recipient verification code in handle_DATA()
|
||||
* fixed unit tests (verified with `tox -e py39-nocov` on Debian/bullseye)
|
||||
|
||||
See !671 for the original merge request by @foxcpp. Also see !126.
|
||||
|
||||
Fixes #14
|
||||
---
|
||||
src/mailman/docs/NEWS.rst | 5 +++
|
||||
src/mailman/docs/mta.rst | 38 ++++++++++++++++++++++
|
||||
src/mailman/runners/lmtp.py | 38 ++++++++++++++++++++++
|
||||
src/mailman/runners/tests/test_lmtp.py | 45 ++++++++++++++++++++------
|
||||
4 files changed, 117 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/mailman/docs/mta.rst b/src/mailman/docs/mta.rst
|
||||
index bd2df65948..cc85910b2c 100644
|
||||
--- a/src/mailman/docs/mta.rst
|
||||
+++ b/src/mailman/docs/mta.rst
|
||||
@@ -253,6 +253,8 @@ which are local, you may need ``local_recipient_maps`` as above. Note that
|
||||
these can be ``regexp`` tables rather than ``hash`` tables. See the
|
||||
``Transport maps`` section above.
|
||||
|
||||
+Starting with version 3.3.6, it is possible to use Mailman's LMTP
|
||||
+service with Postfix' ``reject_unverified_recipient``.
|
||||
|
||||
Postfix documentation
|
||||
---------------------
|
||||
@@ -381,6 +383,42 @@ two lines to the ``mailman3_transport:`` section.
|
||||
headers_remove = message-id
|
||||
headers_add = "Message-ID: ${if def:header_message-id:{$h_message-id:}{<E${message_exim_id}@${qualify_domain}>}}"
|
||||
|
||||
+Alternative setup using callout verification
|
||||
+--------------------------------------------
|
||||
+
|
||||
+Starting with version 3.3.6, you can rely on Mailman's responce on
|
||||
+``RCPT TO:`` LMTP command if mailman would accept the recipient
|
||||
+address as valid. This can be used in Exim to validate recipients
|
||||
+using callout verification.
|
||||
+::
|
||||
+
|
||||
+ # /etc/exim4/conf.d/main/25_mm3_macros
|
||||
+ # The colon-separated list of domains served by Mailman.
|
||||
+ domainlist mm_domains = list.example.net
|
||||
+ # The port of your Mailman's LMTP service
|
||||
+ MM3_LMTP_PORT = 8024
|
||||
+
|
||||
+ # /etc/exim4/local_rcpt_callout (create file or append if already exists)
|
||||
+ # Make callout verification for all domains served by Mailman.
|
||||
+ *@+mm_domains
|
||||
+
|
||||
+ # /etc/exim4/conf.d/router/455_mm3_router
|
||||
+ mailman3_router:
|
||||
+ driver = accept
|
||||
+ domains = +mm_domains
|
||||
+ # no further conditions, valid recipients are verified in
|
||||
+ # acl_check_rcpt using callout verification
|
||||
+ transport = mailman3_transport
|
||||
+
|
||||
+ # /etc/exim4/conf.d/transport/55_mm3_transport
|
||||
+ mailman3_transport:
|
||||
+ driver = smtp
|
||||
+ protocol = lmtp
|
||||
+ allow_localhost
|
||||
+ hosts = localhost
|
||||
+ port = MM3_LMTP_PORT
|
||||
+ rcpt_include_affixes = true
|
||||
+
|
||||
Exim 4 documentation
|
||||
--------------------
|
||||
|
||||
diff --git a/src/mailman/runners/lmtp.py b/src/mailman/runners/lmtp.py
|
||||
index 53318f7120..b5b5b181ef 100644
|
||||
--- a/src/mailman/runners/lmtp.py
|
||||
+++ b/src/mailman/runners/lmtp.py
|
||||
@@ -126,6 +126,44 @@ def split_recipient(address):
|
||||
|
||||
|
||||
class LMTPHandler:
|
||||
+ @asyncio.coroutine
|
||||
+ @transactional
|
||||
+ def handle_RCPT(self, server, session, envelope, to, rcpt_options):
|
||||
+ listnames = set(getUtility(IListManager).names)
|
||||
+ try:
|
||||
+ to = parseaddr(to)[1].lower()
|
||||
+ local, subaddress, domain = split_recipient(to)
|
||||
+ if subaddress is not None:
|
||||
+ # Check that local-subaddress is not an actual list name.
|
||||
+ listname = '{}-{}@{}'.format(local, subaddress, domain)
|
||||
+ if listname in listnames:
|
||||
+ local = '{}-{}'.format(local, subaddress)
|
||||
+ subaddress = None
|
||||
+ listname = '{}@{}'.format(local, domain)
|
||||
+ if listname not in listnames:
|
||||
+ return ERR_550
|
||||
+ canonical_subaddress = SUBADDRESS_NAMES.get(subaddress)
|
||||
+ if subaddress is None:
|
||||
+ # The message is destined for the mailing list.
|
||||
+ # nothing to do here, just keep code similar to handle_DATA
|
||||
+ pass
|
||||
+ elif canonical_subaddress is None:
|
||||
+ # The subaddress was bogus.
|
||||
+ slog.error('unknown sub-address: %s', subaddress)
|
||||
+ return ERR_550
|
||||
+ else:
|
||||
+ # A valid subaddress.
|
||||
+ # nothing to do here, just keep code similar to handle_DATA
|
||||
+ pass
|
||||
+ # recipient validated, just do the same as aiosmtpd.LMTP would do
|
||||
+ envelope.rcpt_tos.append(to)
|
||||
+ envelope.rcpt_options.extend(rcpt_options)
|
||||
+ return '250 Ok'
|
||||
+ except Exception:
|
||||
+ slog.exception('Address verification: %s', to)
|
||||
+ config.db.abort()
|
||||
+ return ERR_550
|
||||
+
|
||||
@asyncio.coroutine
|
||||
@transactional
|
||||
def handle_DATA(self, server, session, envelope):
|
||||
diff --git a/src/mailman/runners/tests/test_lmtp.py b/src/mailman/runners/tests/test_lmtp.py
|
||||
index 3d0f8e0e5d..5200228028 100644
|
||||
--- a/src/mailman/runners/tests/test_lmtp.py
|
||||
+++ b/src/mailman/runners/tests/test_lmtp.py
|
||||
@@ -114,7 +114,7 @@ Message-ID: <ant>
|
||||
|
||||
def test_nonexistent_mailing_list(self):
|
||||
# Trying to post to a nonexistent mailing list is an error.
|
||||
- with self.assertRaises(smtplib.SMTPDataError) as cm:
|
||||
+ with self.assertRaises(smtplib.SMTPRecipientsRefused) as cm:
|
||||
self._lmtp.sendmail('anne@example.com',
|
||||
['notalist@example.com'], """\
|
||||
From: anne.person@example.com
|
||||
@@ -123,13 +123,22 @@ Subject: An interesting message
|
||||
Message-ID: <aardvark>
|
||||
|
||||
""")
|
||||
- self.assertEqual(cm.exception.smtp_code, 550)
|
||||
- self.assertEqual(cm.exception.smtp_error,
|
||||
+ # smtplib.SMTPRecipientsRefused.args contains a list of errors (for
|
||||
+ # each RCPT TO), thus we should have only one error
|
||||
+ self.assertEqual(len(cm.exception.args), 1)
|
||||
+ args0 = cm.exception.args[0]
|
||||
+ # each error should be a dict with the corresponding email address
|
||||
+ # as key
|
||||
+ self.assertTrue('notalist@example.com' in args0)
|
||||
+ errorval = args0['notalist@example.com']
|
||||
+ # errorval must be a tuple of (code, errorstr)
|
||||
+ self.assertEqual(errorval[0], 550)
|
||||
+ self.assertEqual(errorval[1],
|
||||
b'Requested action not taken: mailbox unavailable')
|
||||
|
||||
def test_nonexistent_domain(self):
|
||||
# Trying to post to a nonexistent domain is an error.
|
||||
- with self.assertRaises(smtplib.SMTPDataError) as cm:
|
||||
+ with self.assertRaises(smtplib.SMTPRecipientsRefused) as cm:
|
||||
self._lmtp.sendmail('anne@example.com',
|
||||
['test@x.example.com'], """\
|
||||
From: anne.person@example.com
|
||||
@@ -138,8 +147,17 @@ Subject: An interesting message
|
||||
Message-ID: <aardvark>
|
||||
|
||||
""")
|
||||
- self.assertEqual(cm.exception.smtp_code, 550)
|
||||
- self.assertEqual(cm.exception.smtp_error,
|
||||
+ # smtplib.SMTPRecipientsRefused.args contains a list of errors (for
|
||||
+ # each RCPT TO), thus we should have only one error
|
||||
+ self.assertEqual(len(cm.exception.args), 1)
|
||||
+ args0 = cm.exception.args[0]
|
||||
+ # each error should be a dict with the corresponding email address
|
||||
+ # as key
|
||||
+ self.assertTrue('test@x.example.com' in args0)
|
||||
+ errorval = args0['test@x.example.com']
|
||||
+ # errorval must be a tuple of (code, errorstr)
|
||||
+ self.assertEqual(errorval[0], 550)
|
||||
+ self.assertEqual(errorval[1],
|
||||
b'Requested action not taken: mailbox unavailable')
|
||||
|
||||
def test_alias_domain(self):
|
||||
@@ -168,7 +186,7 @@ X-MailFrom: anne@example.com
|
||||
|
||||
def test_missing_subaddress(self):
|
||||
# Trying to send a message to a bogus subaddress is an error.
|
||||
- with self.assertRaises(smtplib.SMTPDataError) as cm:
|
||||
+ with self.assertRaises(smtplib.SMTPRecipientsRefused) as cm:
|
||||
self._lmtp.sendmail('anne@example.com',
|
||||
['test-bogus@example.com'], """\
|
||||
From: anne.person@example.com
|
||||
@@ -177,8 +195,17 @@ Subject: An interesting message
|
||||
Message-ID: <aardvark>
|
||||
|
||||
""")
|
||||
- self.assertEqual(cm.exception.smtp_code, 550)
|
||||
- self.assertEqual(cm.exception.smtp_error,
|
||||
+ # smtplib.SMTPRecipientsRefused.args contains a list of errors (for
|
||||
+ # each RCPT TO), thus we should have only one error
|
||||
+ self.assertEqual(len(cm.exception.args), 1)
|
||||
+ args0 = cm.exception.args[0]
|
||||
+ # each error should be a dict with the corresponding email address
|
||||
+ # as key
|
||||
+ self.assertTrue('test-bogus@example.com' in args0)
|
||||
+ errorval = args0['test-bogus@example.com']
|
||||
+ # errorval must be a tuple of (code, errorstr)
|
||||
+ self.assertEqual(errorval[0], 550)
|
||||
+ self.assertEqual(errorval[1],
|
||||
b'Requested action not taken: mailbox unavailable')
|
||||
|
||||
def test_mailing_list_with_subaddress(self):
|
||||
--
|
||||
GitLab
|
||||
|
||||
Binary file not shown.
BIN
mailman-3.3.8.tar.gz
Normal file
BIN
mailman-3.3.8.tar.gz
Normal file
Binary file not shown.
@ -1,32 +1,32 @@
|
||||
From 700a1e2e3572ec2c8766da9acdaf8babce5d8d20 Mon Sep 17 00:00:00 2001
|
||||
From: Neal Gompa <ngompa13@gmail.com>
|
||||
Date: Thu, 15 Oct 2020 10:30:07 -0400
|
||||
Subject: [PATCH] Cover some subject prefix use cases
|
||||
From d54000d8223e6f1567f669f72cb09970491fdbb2 Mon Sep 17 00:00:00 2001
|
||||
From: Neal Gompa <neal@gompa.dev>
|
||||
Date: Sat, 13 May 2023 07:27:41 -0400
|
||||
Subject: [PATCH] Cover subject prefix cases for empty subjects and non-ascii
|
||||
charsets
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The subject_prefix handler has many bugs and was mostly not covered
|
||||
for lists with a non-ascii charset.
|
||||
The subject_prefix handler has several bugs around empty subjects
|
||||
and lacked coverage for lists with a non-ascii charset.
|
||||
|
||||
Co-authored-by: Aurélien Bompard <aurelien@bompard.org>
|
||||
Signed-off-by: Neal Gompa <ngompa13@gmail.com>
|
||||
Signed-off-by: Neal Gompa <neal@gompa.dev>
|
||||
---
|
||||
src/mailman/handlers/subject_prefix.py | 19 +++--
|
||||
.../handlers/tests/test_subject_prefix.py | 81 +++++++++++++++++--
|
||||
2 files changed, 87 insertions(+), 13 deletions(-)
|
||||
src/mailman/handlers/subject_prefix.py | 6 +-
|
||||
.../handlers/tests/test_subject_prefix.py | 82 +++++++++++++++++--
|
||||
2 files changed, 78 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/mailman/handlers/subject_prefix.py b/src/mailman/handlers/subject_prefix.py
|
||||
index 95ec0ec2d..10ad07875 100644
|
||||
index 577149cee..a20b45115 100644
|
||||
--- a/src/mailman/handlers/subject_prefix.py
|
||||
+++ b/src/mailman/handlers/subject_prefix.py
|
||||
@@ -39,13 +39,12 @@ def ascii_header(mlist, msgdata, subject, prefix, prefix_pattern, ws):
|
||||
@@ -39,12 +39,11 @@ def ascii_header(mlist, msgdata, subject, prefix, prefix_pattern, ws):
|
||||
if charset not in ASCII_CHARSETS:
|
||||
return None
|
||||
subject_text = EMPTYSTRING.join(str(subject).splitlines())
|
||||
+ subject_text = re.sub(prefix_pattern, '', subject_text)
|
||||
# At this point, the subject may become null if someone posted mail
|
||||
# with "Subject: [subject prefix]".
|
||||
# Replace empty subject.
|
||||
if subject_text.strip() == '':
|
||||
with _.using(mlist.preferred_language.code):
|
||||
subject_text = _('(no subject)')
|
||||
@ -35,58 +35,25 @@ index 95ec0ec2d..10ad07875 100644
|
||||
msgdata['stripped_subject'] = subject_text
|
||||
rematch = re.match(RE_PATTERN, subject_text, re.I)
|
||||
if rematch:
|
||||
@@ -83,13 +82,12 @@ def all_same_charset(mlist, msgdata, subject, prefix, prefix_pattern, ws):
|
||||
if charset != list_charset:
|
||||
return None
|
||||
@@ -85,12 +84,11 @@ def all_same_charset(mlist, msgdata, subject, prefix, prefix_pattern, ws):
|
||||
except UnicodeEncodeError:
|
||||
return None
|
||||
subject_text = EMPTYSTRING.join(chunks)
|
||||
+ subject_text = re.sub(prefix_pattern, '', subject_text)
|
||||
# At this point, the subject may become null if someone posted mail
|
||||
# with "Subject: [subject prefix]".
|
||||
# Replace empty subject.
|
||||
if subject_text.strip() == '':
|
||||
- with _.push(mlist.preferred_language.code):
|
||||
+ with _.using(mlist.preferred_language.code):
|
||||
with _.using(mlist.preferred_language.code):
|
||||
subject_text = _('(no subject)')
|
||||
- else:
|
||||
- subject_text = re.sub(prefix_pattern, '', subject_text)
|
||||
msgdata['stripped_subject'] = subject_text
|
||||
rematch = re.match(RE_PATTERN, subject_text, re.I)
|
||||
if rematch:
|
||||
@@ -114,7 +112,7 @@ def mixed_charsets(mlist, msgdata, subject, prefix, prefix_pattern, ws):
|
||||
list_charset = mlist.preferred_language.charset
|
||||
chunks = decode_header(subject.encode())
|
||||
if len(chunks) == 0:
|
||||
- with _.push(mlist.preferred_language.code):
|
||||
+ with _.using(mlist.preferred_language.code):
|
||||
subject_text = _('(no subject)')
|
||||
chunks = [(prefix, list_charset),
|
||||
(subject_text, list_charset),
|
||||
@@ -134,13 +132,20 @@ def mixed_charsets(mlist, msgdata, subject, prefix, prefix_pattern, ws):
|
||||
chunks.insert(0, ('', 'us-ascii'))
|
||||
first_text = ''
|
||||
first_text = re.sub(prefix_pattern, '', first_text).lstrip()
|
||||
+ if not first_text.strip() and len(chunks) <= 1:
|
||||
+ with _.using(mlist.preferred_language.code):
|
||||
+ subject_text = _('(no subject)')
|
||||
+ chunks = [(prefix.strip(), list_charset),
|
||||
+ (subject_text, list_charset),
|
||||
+ ]
|
||||
+ return make_header(chunks, continuation_ws=ws)
|
||||
rematch = re.match(RE_PATTERN, first_text, re.I)
|
||||
if rematch:
|
||||
first_text = 'Re: ' + first_text[rematch.end():]
|
||||
chunks[0] = (first_text, chunk_charset)
|
||||
# The subject text stripped of the prefix, for use in the NNTP gateway.
|
||||
msgdata['stripped_subject'] = str(make_header(chunks, continuation_ws=ws))
|
||||
- chunks.insert(0, (prefix, list_charset))
|
||||
+ chunks.insert(0, (prefix.strip(), list_charset))
|
||||
return make_header(chunks, continuation_ws=ws)
|
||||
|
||||
|
||||
diff --git a/src/mailman/handlers/tests/test_subject_prefix.py b/src/mailman/handlers/tests/test_subject_prefix.py
|
||||
index c2a257035..1d8bc175d 100644
|
||||
index 0b13f5068..960afa49a 100644
|
||||
--- a/src/mailman/handlers/tests/test_subject_prefix.py
|
||||
+++ b/src/mailman/handlers/tests/test_subject_prefix.py
|
||||
@@ -33,6 +33,13 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
@@ -34,6 +34,13 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self._mlist = create_list('test@example.com')
|
||||
self._process = config.handlers['subject-prefix'].process
|
||||
@ -100,22 +67,23 @@ index c2a257035..1d8bc175d 100644
|
||||
|
||||
def test_isdigest(self):
|
||||
# If the message is destined for the digest, the Subject header does
|
||||
@@ -114,6 +121,14 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
@@ -115,6 +122,15 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
self._process(self._mlist, msg, {})
|
||||
self.assertEqual(str(msg['subject']), '[Test] A test message')
|
||||
|
||||
+ def test_multiline_subject_non_ascii_list(self):
|
||||
+ # The subject appears on multiple lines on a non-ascii list.
|
||||
+ self._mlist.preferred_language = 'xx'
|
||||
+ self._mlist.preferred_language.charset = 'utf-8'
|
||||
+ msg = Message()
|
||||
+ msg['Subject'] = '\n A test message'
|
||||
+ self._process(self._mlist, msg, {})
|
||||
+ self.assertEqual(str(msg['subject']), '[Test] A test message')
|
||||
+ self.assertEqual(str(msg['subject']), '[Test] A test message')
|
||||
+
|
||||
def test_i18n_prefix(self):
|
||||
# The Subject header is encoded, but the prefix is still added.
|
||||
msg = Message()
|
||||
@@ -130,7 +145,7 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
@@ -131,7 +147,7 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
msg['Subject'] = '[Test] '
|
||||
self._process(self._mlist, msg, {})
|
||||
subject = msg['subject']
|
||||
@ -124,7 +92,7 @@ index c2a257035..1d8bc175d 100644
|
||||
|
||||
def test_prefix_only_all_same(self):
|
||||
# Incoming subject is only the prefix.
|
||||
@@ -141,7 +156,7 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
@@ -142,7 +158,7 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
self._process(self._mlist, msg, {})
|
||||
self._mlist.preferred_language.charset = old_charset
|
||||
subject = msg['subject']
|
||||
@ -133,7 +101,7 @@ index c2a257035..1d8bc175d 100644
|
||||
|
||||
def test_prefix_only_mixed(self):
|
||||
# Incoming subject is only the prefix.
|
||||
@@ -149,7 +164,7 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
@@ -150,7 +166,7 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
msg['Subject'] = '=?utf-8?Q?[Test]_?='
|
||||
self._process(self._mlist, msg, {})
|
||||
subject = msg['subject']
|
||||
@ -142,7 +110,7 @@ index c2a257035..1d8bc175d 100644
|
||||
|
||||
def test_re_only(self):
|
||||
# Incoming subject is only Re:.
|
||||
@@ -198,15 +213,13 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
@@ -226,15 +242,13 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
def test_decode_header_returns_string(self):
|
||||
# Under some circumstances, email.header.decode_header() returns a
|
||||
# string value. Ensure we can handle that.
|
||||
@ -154,15 +122,15 @@ index c2a257035..1d8bc175d 100644
|
||||
self._process(self._mlist, msg, {})
|
||||
subject = msg['subject']
|
||||
self.assertEqual(subject.encode(),
|
||||
- '=?iso-8859-1?q?=5BTest=5D_?= Plain text')
|
||||
+ '=?utf-8?b?W1Rlc3Rd?= Plain text')
|
||||
- '=?iso-8859-1?q?=5BTest=5D_Plain_text?=')
|
||||
+ '=?utf-8?q?=5BTest=5D_Plain_text?=')
|
||||
|
||||
def test_unknown_encoded_subject(self):
|
||||
msg = Message()
|
||||
@@ -215,3 +228,59 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
subject = msg['subject']
|
||||
self.assertEqual(str(subject),
|
||||
'[Test] Non-ascii subject - fran<61>ais')
|
||||
@@ -280,3 +294,59 @@ class TestSubjectPrefix(unittest.TestCase):
|
||||
self._process(self._mlist, msg, {})
|
||||
self.assertEqual(str(msg['subject']),
|
||||
'[Test] This is a folded subject header.')
|
||||
+
|
||||
+ def test_non_ascii_list(self):
|
||||
+ # The mailing list has a non-ascii language
|
||||
@ -220,5 +188,5 @@ index c2a257035..1d8bc175d 100644
|
||||
+ self._process(self._mlist, msg, {})
|
||||
+ self.assertEqual(str(msg['subject']), '[Test] (no subject)')
|
||||
--
|
||||
2.28.0
|
||||
2.40.0
|
||||
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
From a4bcacc25398fcea819bd9e6b9a531c3007aa386 Mon Sep 17 00:00:00 2001
|
||||
From: Neal Gompa <ngompa13@gmail.com>
|
||||
Date: Fri, 16 Oct 2020 03:47:38 -0400
|
||||
From dd56f4a645d65b8022a07dd37bb803250a157ea8 Mon Sep 17 00:00:00 2001
|
||||
From: Neal Gompa <neal@gompa.dev>
|
||||
Date: Sat, 13 May 2023 08:04:39 -0400
|
||||
Subject: [PATCH] Use importlib.resources for Python 3.9+ and
|
||||
importlib_resources otherwise
|
||||
|
||||
This makes it possible to use Mailman 3 in environments where importlib_resources
|
||||
is not available.
|
||||
|
||||
Signed-off-by: Neal Gompa <ngompa13@gmail.com>
|
||||
Signed-off-by: Neal Gompa <neal@gompa.dev>
|
||||
---
|
||||
setup.py | 2 +-
|
||||
src/mailman/__init__.py | 5 +++++
|
||||
@ -15,20 +15,20 @@ Signed-off-by: Neal Gompa <ngompa13@gmail.com>
|
||||
3 files changed, 29 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/setup.py b/setup.py
|
||||
index e1b2e07c5..b768ef3d2 100644
|
||||
index 5448b7cf9..c3d0f83fe 100644
|
||||
--- a/setup.py
|
||||
+++ b/setup.py
|
||||
@@ -121,7 +121,7 @@ case second 'm'. Any other spelling is incorrect.""",
|
||||
'flufl.bounce',
|
||||
'flufl.i18n>=2.0',
|
||||
'flufl.lock>=3.1',
|
||||
'flufl.bounce>=4.0',
|
||||
'flufl.i18n>=3.2',
|
||||
'flufl.lock>=5.1',
|
||||
- 'importlib_resources>=1.1.0',
|
||||
+ 'importlib_resources>=1.1.0 ; python_version<"3.9"',
|
||||
'gunicorn',
|
||||
'lazr.config',
|
||||
'python-dateutil>=2.0',
|
||||
diff --git a/src/mailman/__init__.py b/src/mailman/__init__.py
|
||||
index fa5233fab..00990be45 100644
|
||||
index ad94ffdbd..0d78b38ea 100644
|
||||
--- a/src/mailman/__init__.py
|
||||
+++ b/src/mailman/__init__.py
|
||||
@@ -37,3 +37,8 @@ if 'build_sphinx' not in sys.argv: # pragma: nocover
|
||||
@ -69,5 +69,5 @@ index e69de29bb..2b2ed536a 100644
|
||||
+ import importlib.resources
|
||||
+ sys.modules['importlib_resources'] = importlib.resources
|
||||
--
|
||||
2.28.0
|
||||
2.40.0
|
||||
|
||||
|
||||
28
mailman.spec
28
mailman.spec
@ -6,8 +6,8 @@
|
||||
%{?python_enable_dependency_generator}
|
||||
|
||||
Name: mailman
|
||||
Version: 3.3.2
|
||||
Release: 10
|
||||
Version: 3.3.8
|
||||
Release: 1
|
||||
Epoch: 3
|
||||
Summary: The GNU mailing list manager
|
||||
License: GPLv3
|
||||
@ -19,25 +19,8 @@ Source3: mailman3.service
|
||||
Source4: mailman3.logrotate
|
||||
Source5: mailman3-digests.service
|
||||
Source6: mailman3-digests.timer
|
||||
#Refer: https://gitlab.com/mailman/mailman/-/merge_requests/860
|
||||
Patch01: mailman3-click8.patch
|
||||
Patch11: mailman-subject-prefix.patch
|
||||
Patch14: mailman-use-either-importlib_resources-or-directly-importlib.patch
|
||||
#Refer: https://bugzilla.redhat.com/show_bug.cgi?id=1900668#c9
|
||||
Patch15: mailman3-do-not-assume-sapce-in-banner.patch
|
||||
#Refer: https://gitlab.com/mailman/mailman/-/merge_requests/772
|
||||
Patch16: mailman3-test_as_string_python_bug_27321.patch
|
||||
Patch17: 0001-fix-tests-assertion-error.patch
|
||||
#Refer: https://gitlab.com/mailman/mailman/-/issues/964#note_1001855903
|
||||
Patch18: support-sqlalchemy-1-4.patch
|
||||
#Refer: https://gitlab.com/mailman/mailman/-/merge_requests/929
|
||||
Patch19: Require-authheaders-0.14.0-and-adjust-tests-accordingly.patch
|
||||
#Refer: https://gitlab.com/mailman/mailman/-/commit/38c794d9ed71f25ee138760461f66abc29dfa81c
|
||||
Patch20: Remove-old-style-coroutines-and-use-async-def-instead.patch
|
||||
#Refer: https://gitlab.com/mailman/mailman/-/commit/b9387743835821e8327e73aa502cb01f2f83dc97
|
||||
Patch21: Verify-recipient-validity-at-RCPT-command-in-LMTP-runner.patch
|
||||
#Refer: https://gitlab.com/mailman/mailman/-/commit/1954815f32fea4d9d920cdc74f63bcc24d3b6c49
|
||||
Patch22: Support-Python-3.11.patch
|
||||
Patch0001: mailman-subject-prefix.patch
|
||||
Patch0002: mailman-use-either-importlib_resources-or-directly-importlib.patch
|
||||
BuildArch: noarch
|
||||
BuildRequires: glibc-langpack-en
|
||||
BuildRequires: python%{python3_pkgversion}-devel >= 3.5 python%{python3_pkgversion}-setuptools
|
||||
@ -219,6 +202,9 @@ done
|
||||
%{_datadir}/selinux/*/mailman3.pp
|
||||
|
||||
%changelog
|
||||
* Wed Sep 13 2023 liyanan <thistleslyn@163.com> - 3:3.3.8-1
|
||||
- update to 3.3.8
|
||||
|
||||
* Sun Jul 23 2023 yaoxin <yao_xin001@hoperun.com> - 3:3.3.2-10
|
||||
- Fix test fails caused by python update to 3.11.4
|
||||
|
||||
|
||||
@ -1,107 +0,0 @@
|
||||
From 465c2ff847d462c1a9cf8f548093ba4b5be84c3b Mon Sep 17 00:00:00 2001
|
||||
From: Mark Sapiro <mark@msapiro.net>
|
||||
Date: Tue, 11 May 2021 18:14:59 -0700
|
||||
Subject: [PATCH] Require click >=8.0.0 and fix the tests it breaks.
|
||||
|
||||
---
|
||||
setup.py | 2 +-
|
||||
src/mailman/commands/docs/import.rst | 1 +
|
||||
src/mailman/commands/tests/test_cli_addmembers.py | 8 ++++----
|
||||
src/mailman/commands/tests/test_cli_delmembers.py | 4 ++--
|
||||
src/mailman/commands/tests/test_cli_syncmembers.py | 8 ++++----
|
||||
5 files changed, 12 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/setup.py b/setup.py
|
||||
index cd36456..ad04e77 100644
|
||||
--- a/setup.py
|
||||
+++ b/setup.py
|
||||
@@ -115,7 +115,7 @@ case second 'm'. Any other spelling is incorrect.""",
|
||||
'atpublic',
|
||||
'authheaders>=0.9.2',
|
||||
'authres>=1.0.1',
|
||||
- 'click>=7.0.0',
|
||||
+ 'click>=8.0.0',
|
||||
'dnspython>=1.14.0',
|
||||
'falcon>1.0.0',
|
||||
'flufl.bounce',
|
||||
diff --git a/src/mailman/commands/docs/import.rst b/src/mailman/commands/docs/import.rst
|
||||
index 947d932..66f72be 100644
|
||||
--- a/src/mailman/commands/docs/import.rst
|
||||
+++ b/src/mailman/commands/docs/import.rst
|
||||
@@ -58,5 +58,6 @@ import, the mailing list's "real name" will change.
|
||||
Import
|
||||
|
||||
>>> command('mailman import21 import@example.com ' + pickle_file)
|
||||
+ Importing ...
|
||||
>>> print(mlist.display_name)
|
||||
Test
|
||||
diff --git a/src/mailman/commands/tests/test_cli_addmembers.py b/src/mailman/commands/tests/test_cli_addmembers.py
|
||||
index e257da5..95f8542 100644
|
||||
--- a/src/mailman/commands/tests/test_cli_addmembers.py
|
||||
+++ b/src/mailman/commands/tests/test_cli_addmembers.py
|
||||
@@ -57,8 +57,8 @@ class TestCLIAddMembers(unittest.TestCase):
|
||||
result.output,
|
||||
'Usage: addmembers [OPTIONS] FILENAME LISTSPEC\n'
|
||||
'Try \'addmembers --help\' for help.\n\n'
|
||||
- 'Error: Invalid value for \'FILENAME\': Could not open '
|
||||
- 'file: bad: No such file or directory\n')
|
||||
+ 'Error: Invalid value for \'FILENAME\': '
|
||||
+ '\'bad\': No such file or directory\n')
|
||||
|
||||
def test_already_subscribed_with_display_name(self):
|
||||
subscribe(self._mlist, 'Anne')
|
||||
@@ -265,8 +265,8 @@ class TestCLIAddMembers(unittest.TestCase):
|
||||
'Usage: addmembers [OPTIONS] FILENAME LISTSPEC\n'
|
||||
'Try \'addmembers --help\' for help.\n\n'
|
||||
'Error: Invalid value for \'--delivery\' / \'-d\': '
|
||||
- 'invalid choice: bogus. (choose from regular, mime, '
|
||||
- 'plain, summary, disabled)\n')
|
||||
+ '\'bogus\' is not one of \'regular\', \'mime\', '
|
||||
+ '\'plain\', \'summary\', \'disabled\'.\n')
|
||||
|
||||
def test_invite_member(self):
|
||||
with NamedTemporaryFile('w', buffering=1, encoding='utf-8') as infp:
|
||||
diff --git a/src/mailman/commands/tests/test_cli_delmembers.py b/src/mailman/commands/tests/test_cli_delmembers.py
|
||||
index cf24b54..e34c22a 100644
|
||||
--- a/src/mailman/commands/tests/test_cli_delmembers.py
|
||||
+++ b/src/mailman/commands/tests/test_cli_delmembers.py
|
||||
@@ -56,8 +56,8 @@ class TestCLIDelMembers(unittest.TestCase):
|
||||
result.output,
|
||||
'Usage: delmembers [OPTIONS]\n'
|
||||
'Try \'delmembers --help\' for help.\n\n'
|
||||
- 'Error: Invalid value for \'--file\' / \'-f\': Could not open '
|
||||
- 'file: bad: No such file or directory\n')
|
||||
+ 'Error: Invalid value for \'--file\' / \'-f\': '
|
||||
+ '\'bad\': No such file or directory\n')
|
||||
|
||||
def test_not_subscribed_without_display_name(self):
|
||||
with NamedTemporaryFile('w', buffering=1, encoding='utf-8') as infp:
|
||||
diff --git a/src/mailman/commands/tests/test_cli_syncmembers.py b/src/mailman/commands/tests/test_cli_syncmembers.py
|
||||
index 658b867..faed507 100644
|
||||
--- a/src/mailman/commands/tests/test_cli_syncmembers.py
|
||||
+++ b/src/mailman/commands/tests/test_cli_syncmembers.py
|
||||
@@ -58,8 +58,8 @@ class TestCLISyncMembers(unittest.TestCase):
|
||||
result.output,
|
||||
'Usage: syncmembers [OPTIONS] FILENAME LISTSPEC\n'
|
||||
'Try \'syncmembers --help\' for help.\n\n'
|
||||
- 'Error: Invalid value for \'FILENAME\': Could not open '
|
||||
- 'file: bad: No such file or directory\n')
|
||||
+ 'Error: Invalid value for \'FILENAME\': '
|
||||
+ '\'bad\': No such file or directory\n')
|
||||
|
||||
def test_sync_invalid_email(self):
|
||||
with NamedTemporaryFile('w', buffering=1, encoding='utf-8') as infp:
|
||||
@@ -374,8 +374,8 @@ class TestCLISyncMembers(unittest.TestCase):
|
||||
'Usage: syncmembers [OPTIONS] FILENAME LISTSPEC\n'
|
||||
'Try \'syncmembers --help\' for help.\n\n'
|
||||
'Error: Invalid value for \'--delivery\' / \'-d\': '
|
||||
- 'invalid choice: bogus. (choose from regular, mime, '
|
||||
- 'plain, summary, disabled)\n')
|
||||
+ '\'bogus\' is not one of \'regular\', \'mime\', '
|
||||
+ '\'plain\', \'summary\', \'disabled\'.\n')
|
||||
|
||||
def test_override_no_welcome(self):
|
||||
self._mlist.send_welcome_message = False
|
||||
--
|
||||
2.32.0
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
diff --git a/src/mailman/utilities/tests/test_interact.py b/src/mailman/utilities/tests/test_interact.py
|
||||
index 24c186c..dca1866 100644
|
||||
--- a/src/mailman/utilities/tests/test_interact.py
|
||||
+++ b/src/mailman/utilities/tests/test_interact.py
|
||||
@@ -67,7 +67,7 @@ class TestInteract(unittest.TestCase):
|
||||
self._enter(hackenv('PYTHONSTARTUP', None))
|
||||
interact()
|
||||
stderr = self._stderr.getvalue().splitlines()
|
||||
- banner = 'Python {} on {} '.format(sys.version, sys.platform)
|
||||
+ banner = 'Python {} on {}'.format(sys.version, sys.platform)
|
||||
self.assertEqual(stderr[0], banner.splitlines()[0])
|
||||
|
||||
def test_interact_custom_banner(self):
|
||||
@ -1,35 +0,0 @@
|
||||
From 70373ea11495164fcdf7a61b754b6ab94872ace4 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Sapiro <mark@msapiro.net>
|
||||
Date: Fri, 5 Feb 2021 20:29:42 -0800
|
||||
Subject: [PATCH] Skip test_as_string_python_bug_27321 for Python versions
|
||||
where fixed.
|
||||
|
||||
---
|
||||
src/mailman/email/tests/test_message.py | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/src/mailman/email/tests/test_message.py b/src/mailman/email/tests/test_message.py
|
||||
index 098042ea7..050861c91 100644
|
||||
--- a/src/mailman/email/tests/test_message.py
|
||||
+++ b/src/mailman/email/tests/test_message.py
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
"""Test the message API."""
|
||||
|
||||
+import sys
|
||||
import unittest
|
||||
|
||||
from email import message_from_binary_file
|
||||
@@ -107,6 +108,10 @@ Test content
|
||||
self.assertEqual(msg.get_payload(), 'Non-ascii text ?.')
|
||||
|
||||
def test_as_string_python_bug_27321(self):
|
||||
+ # Bug 27321 is fixed in Python 3.8.7rc1, 3.9.1rc1 and later.
|
||||
+ if (sys.version_info.minor == 8 and sys.hexversion >= 0x030807C1 or
|
||||
+ sys.hexversion >= 0x030901C1):
|
||||
+ raise unittest.SkipTest
|
||||
with path('mailman.email.tests.data', 'bad_email.eml') as email_path:
|
||||
with open(str(email_path), 'rb') as fp:
|
||||
msg = message_from_binary_file(fp, Message)
|
||||
--
|
||||
GitLab
|
||||
@ -1,47 +0,0 @@
|
||||
diff --git a/src/mailman/database/types.py b/src/mailman/database/types.py
|
||||
index 1913a0a..4e97bf6 100644
|
||||
--- a/src/mailman/database/types.py
|
||||
+++ b/src/mailman/database/types.py
|
||||
@@ -34,6 +34,7 @@ class Enum(TypeDecorator):
|
||||
converts it on-the-fly.
|
||||
"""
|
||||
impl = Integer
|
||||
+ cache_ok = False
|
||||
|
||||
def __init__(self, enum, *args, **kw):
|
||||
super().__init__(*args, **kw)
|
||||
@@ -59,6 +60,7 @@ class UUID(TypeDecorator):
|
||||
|
||||
"""
|
||||
impl = CHAR
|
||||
+ cache_ok = False
|
||||
|
||||
def load_dialect_impl(self, dialect):
|
||||
if dialect.name == 'postgresql':
|
||||
@@ -93,6 +95,7 @@ class SAUnicode(TypeDecorator):
|
||||
type and it can still be used if needed in the codebase.
|
||||
"""
|
||||
impl = Unicode
|
||||
+ cache_ok = False
|
||||
|
||||
|
||||
@compiles(SAUnicode)
|
||||
@@ -113,6 +116,7 @@ class SAUnicodeLarge(TypeDecorator):
|
||||
This is double size of SAUnicode defined above.
|
||||
"""
|
||||
impl = Unicode
|
||||
+ cache_ok = False
|
||||
|
||||
|
||||
@compiles(SAUnicodeLarge, 'mysql')
|
||||
@@ -139,6 +143,7 @@ class SAUnicodeXL(TypeDecorator):
|
||||
See https://docs.sqlalchemy.org/en/latest/dialects/mysql.html#index-length
|
||||
"""
|
||||
impl = Unicode
|
||||
+ cache_ok = False
|
||||
|
||||
|
||||
@compiles(SAUnicodeXL, 'mysql')
|
||||
--
|
||||
2.27.0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user