Skip to content

Fix body_line_iterator(decode=True) returning no lines in Python 3.11#31

Open
thegushi wants to merge 13 commits into
jaredmauch:mainfrom
thegushi:fix/body-line-iterator-decode
Open

Fix body_line_iterator(decode=True) returning no lines in Python 3.11#31
thegushi wants to merge 13 commits into
jaredmauch:mainfrom
thegushi:fix/body-line-iterator-decode

Conversation

@thegushi
Copy link
Copy Markdown
Collaborator

Python 3.11's email.iterators.body_line_iterator only yields str payloads. When called with decode=True, get_payload() returns bytes, which the iterator silently drops — leaving SimpleMatch, SimpleWarning, and Tagger with an empty line set and therefore finding nothing.

Removing decode=True (reverting to the default False) causes get_payload() to return str, which the iterator handles correctly. Bounce detection and topic tagging now work under Python 3.

Affected:

  • Mailman/Bouncers/SimpleMatch.py
  • Mailman/Bouncers/SimpleWarning.py
  • Mailman/Handlers/Tagger.py

This was caught by the test suite (test_bounces.BounceTest.test_bounce failing for the SimpleMatch/sendmail case, and the Tagger tests failing in test_handlers).

thegushi added 13 commits May 11, 2026 23:04
iconv -o is a GNU iconv extension not supported on BSD. Replace the
subprocess call with Python's own open() encoding support, which is
portable and removes the iconv dependency entirely.
Replace file -bi encoding detection with a Python-native UTF-8 open
attempt. If the file opens cleanly as UTF-8, skip it; otherwise
convert from the known locale encoding. No external tools needed.
Detects legacy SHA1 hex digest passwords that need upgrading to
the PBKDF2 format introduced by hash_password().
sha_new() requires bytes in Python 3 but was receiving a str.
Switch to hash_password() so new lists get PBKDF2 hashes from
the start rather than legacy SHA1. Fixes jaredmauch#24.
'Hit enter to notify %(listname)s owner...' was never interpolated.
Replace print()+readline() with input() which handles both the prompt
and waiting for Enter in one call.
check_perms and Mailman/MTA/Postfix.py both had Python 2-style
print C_('...') % locals(), statements where the migration to Python 3
dropped the % locals() substitution, leaving literal %(varname)s in
error output. Also fix two bare print -> print() in Postfix.py.
BSD make does not have a wildcard function -- it treats the argument
as a variable name with spaces, generating warnings. Use $(POFILES)
in messages/ (already defined) and drop the dependency list in
templates/ (stamp file is sufficient for a clean build).
distutils was removed in Python 3.12. The configure check was using
distutils.sysconfig solely to verify Python development headers exist.
Replace with the sysconfig stdlib module (available since Python 3.2)
using sysconfig.get_path('include') in place of get_python_inc().
Python 3.11's body_line_iterator only yields str payloads. When decode=True,
get_payload() returns bytes, which the iterator silently drops — leaving
SimpleMatch, SimpleWarning, and Tagger with nothing to scan.

Remove decode=True (defaulting to False) so get_payload() returns str as
expected. Bounce detection and topic tagging now work correctly under Python 3.
The previous fix (removing decode=True) stopped the crash but left
quoted-printable and base64 bodies undecoded, causing e.g. QP soft
line breaks (=20) to appear literally in addresses and break pattern
matching.

Add _body_line_iterator() to SimpleMatch which uses get_payload(decode=True)
to get CTE-decoded bytes, then decodes to str using the part's charset.
SimpleWarning imports and uses the same helper. Tagger likewise imports it
so topic matching works correctly on encoded message bodies.
In Python 3, get_payload(decode=True) always returns bytes. AOL.py was
iterating over those bytes with string regex patterns, causing TypeError.
Decode to str before iterating.
@thegushi thegushi mentioned this pull request May 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant