gh-151454: Accept Header values in email.message.Message.add_header#151458
Open
harjothkhara wants to merge 1 commit into
Open
gh-151454: Accept Header values in email.message.Message.add_header#151458harjothkhara wants to merge 1 commit into
harjothkhara wants to merge 1 commit into
Conversation
…ader Message.items() can yield (name, Header) pairs under the compat32 policy (for a header carrying 8-bit data), and Message[name] = value accepts such Header values, but add_header() raised "TypeError: sequence item 0: expected str instance, Header found" because it assembled the value with SEMISPACE.join(). When no extra parameters are given, add_header() now mirrors __setitem__ and stores the value (Header or str) unmodified, fixing the reported header-copy loop. None is still coerced to '' to preserve add_header()'s historical behavior. The parameterized branch is unchanged: it still builds the header as a string and so continues to require a str value. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Documentation build overview
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
email.message.Message.items()returns(name, Header)pairs under thecompat32policy when a header carries 8-bit data (for example a multi-lineSpamAssassin
X-Ham-Report). Assigning such a value back withmsg[name] = valueworks, but the documented-as-equivalentmsg.add_header(name, value)raised:add_header()always assembled the header withSEMISPACE.join(parts), andstr.joinrejects a non-strelement such as aHeader. So the common"copy every header into a new message" loop from the bug report broke on any
message carrying a
Header-typed value:Fix
When no extra parameters are given,
add_header()now stores the value thesame way
__setitem__does, so aHeader(orstr) is stored unmodified —matching the documented equivalence with
msg[name] = value.Noneis stillcoerced to
''to preserveadd_header()'s historical behavior.The parameterized branch is intentionally left unchanged: it must assemble the
header as a string, so it continues to require a
strvalue. (Passing aHeaderthere still raises, as before — and stringifying anunknown-8bitHeaderwould silently corrupt its bytes toU+FFFD, so quietly accepting itwould be worse than the existing error.)
Verification
New regression test
test_add_header_copies_Header_returned_by_itemsreproduces the bug from the real
email.message_from_bytes(...).items()producer path, and asserts the
Headeris stored unmodified (raw_items()identity) and that
add_headermatches the__setitem__path byte-for-byte(
as_bytes()). Theadd_headerdocs gain a note and a.. versionchanged::describing the no-parameter
Headeracceptance, as the issue requested.Real behavior proof
Behavior addressed:
Message.add_header(name, value)raisedTypeError: sequence item 0: expected str instance, Header foundwhenvaluewas an
email.header.Header— the typeMessage.items()yields under thecompat32policy for 8-bit headers — whereas the documented-equivalentmsg[name] = valueaccepted it.Real environment tested: locally-built CPython
main(Python 3.16.0a0),arm64 macOS, run via
./python.exe. The same interpreter binary is used forboth BEFORE and AFTER; only
Lib/email/message.pyis swapped (origin/main vs.this PR), since the change is pure Python and loaded at runtime.
Exact steps or command run after this patch:
Evidence after fix:
Observed result after fix: the reporter's copy loop completes without
error, the
X-Ham-Reportvalue is preserved as aHeader(not stringified),and the resulting message serializes byte-for-byte identically to the
msg[h] = vworkaround.What was not tested:
add_header(name, Header(...), **params)— leftunchanged on purpose; it still raises
TypeErroras onmain.compat32policies (email.policy.default/EmailMessage): theremsg[name] = Header(...)itself raises, andadd_headernow delegates tothe same
__setitem__, so behavior is unchanged and consistent.sslmodule is not built in this environment (no OpenSSL); unrelated toemailand does not affecttest_email.