email: a header value that is itself a well-formed RFC 2047 encoded word is decoded or written verbatim, never encoded
Mantenedores costumam responder em até 1 dia
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 5/5
- Tempo estimado
- Mais de uma semana
- Facilidade para iniciantes
- 35/100
Direção de pesquisa
Start with Lib/email/policy.py and Lib/email/_header_value_parser.py, which the issue identifies as the folding and parsing paths, then inspect the email policy tests, especially test_policy.py. Reproduce the shown fold and message assignment examples and review the proposed round-trip test. Done means the project has chosen and implemented behavior that preserves literal encoded-word lookalikes through parsing and folding, with tests and documentation matching that decision.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Bug description
With the modern (email.policy.default) API there is no way to send a Subject whose literal text is =?utf-8?q?x?=. Setting it on a message decodes it on the spot, and folding it as a string writes it out unchanged, where any RFC 2047 reader will decode it:
>>> import email.message, email.policy
>>> m = email.message.EmailMessage()
>>> m['Subject'] = '=?utf-8?q?x?='
>>> m['Subject']
'x'
>>> m.as_string()
'Subject: x\n\n'
>>> email.policy.default.fold('Subject', '=?utf-8?q?x?=')
'Subject: =?utf-8?q?x?=\n' # a reader decodes this to 'x' as well
>>> email.policy.default.fold('Subject', '=?utf-8?q?x?=\xe9')
'Subject: x=?utf-8?q?=C3=A9?=\n'
The legacy API gets this right:
>>> import email.header
>>> email.header.Header('=?utf-8?q?x?=', 'utf-8').encode()
'=?utf-8?b?PT91dGYtOD9xP3g/PQ==?='
RFC 2047 §7 says that a composer "MUST ensure that any string of non-white-space printable ASCII characters within a *text or *ctext that begins with =? and ends with ?= be a valid encoded-word", and §5 anticipates the case: "In rare cases it may be necessary to encode ordinary text that looks like an encoded-word." The only compliant output for the literal text above is an encoded word whose decoded value is =?utf-8?q?x?=, as the legacy API produces.
Apparently both behaviors follow the current documentation, so I guess this needs some discussion. UnstructuredHeader is documented to decode encoded words in whatever string it is given, which is what happens in __setitem__ via header_factory (get_unstructured treats every =? as a possible encoded word). And EmailPolicy.fold is documented to treat a plain string as a "source value", so with refold_source='long' a short value is emitted unchanged, and when it is refolded it goes through the same parser (policy.py), which is where the x=?utf-8?q?=C3=A9?= output comes from. The gap is that the API has no way to say "this string is the decoded text, not wire source", so any text supplied to the program is interpreted as the wire source.
Possible directions, none of which I have a strong opinion on:
- Treat strings set by a program as decoded text (and encode look-alikes on output, per RFC 2047 §7). This would change the documented decoding on
__setitem__, which some code may rely on to round-trip raw header text. - Keep the current behavior and document the limitation, possibly with an escape hatch (a header object constructed from decoded text).
This came out of the Hypothesis round-trip test in #159771, which originally carried it as an expectedFailure; it was taken out of that PR at the reviewer's request so that the question can be discussed separately. The test, for reference (a fold round trip, written against test_policy.py):
@hypothesis.given(
word=hypothesis.strategies.text(alphabet='abc', min_size=1, max_size=5),
trailer=hypothesis.strategies.sampled_from(['', ')', ' word']),
)
@hypothesis.example(word='x', trailer='')
@hypothesis.example(word='x', trailer=')')
def test_fold_encoded_word_lookalike_round_trip(self, word, trailer):
subject = f'=?utf-8?q?{word}?={trailer}'
folded = email.policy.default.fold('Subject', subject)
reparsed = email.message_from_string(
folded, policy=email.policy.default)['Subject']
self.assertEqual(reparsed, subject)
Possibly related: #85725 (an encoded word produced by folding that violates RFC 2047), though that is about the generator's output rather than user text.
CPython versions tested on
CPython main (6e1bd24e4d8)
Operating systems tested on
Linux
- Linguagem predominante
- Python
- Estrelas
- 77.7k
- Forks
- 38.3k
- Merge médio
- 14h 29min
- PRs com merge (30d)
- 699
Preparar o ambiente
Inicia o contêiner de desenvolvimento do projeto no navegador, com a sua própria conta do GitHub.
- Sem Dockerfile nem arquivo Docker Compose
- Tem um modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de python/cpython
-
topic-socket type-bug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 72/100
python/cpython#160561 · 7 comentários ·
Mantenedores costumam responder em até 1 dia
-
tests topic-profiling type-bug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 78/100
python/cpython#160334 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
extension-modules type-bug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 84/100
Mantenedores costumam responder em até 1 dia
-
Remove unused FVS_* macrosAbertainterpreter-core type-feature
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 78/100
python/cpython#160109 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
extension-modules type-bug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 72/100
python/cpython#160001 · 3 comentários ·
Mantenedores costumam responder em até 1 dia
Todas as issues de python/cpython
Issues semelhantes
-
request-theme
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 66/100
LizardByte/ThemerrDB#9575 ·
Mantenedores costumam responder em até 1 dia
-
Author Page: noshin-nawalAbertaauthor-page correction
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 62/100
acl-org/acl-anthology#10599 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 78/100
zilliztech/memsearch#818 ·
Mantenedores costumam responder em até 1 dia
-
[FAQ] Commit ID for ProjectsTalvez já em andamento @github-actions assumiu hoje. Abertafaq-proposal
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 84/100
DataTalksClub/faq#503 · 1 comentário ·
Mantenedores costumam responder em até 2 dias
-
README.zh-CN/ja/es still hard-code 501 test counts after README.md went count-freeTalvez já em andamento @Aaqibhafeezkhan assumiu hoje. Abertabeginner documentation good first issue
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
BistaDinesh03/critique#164 · 1 comentário ·
Mantenedores costumam responder em até 1 dia