The ISO-2022 encoders took the ASCII fast path for every code point below 0x80, so U+001B came out as a bare ESC byte, and in iso2022_kr U+000E and U+000F as bare SO and SI. Decoders read those bytes as the start of an escape sequence or as shifts. This makes them unencodable, so strict raises UnicodeEncodeError and the error handlers work as usual (replace gives ?, backslashreplace gives \x1b). SO and SI are left alone in the iso2022_jp* codecs, where they aren't shifts.
This broke one caller in the stdlib. For euc-jp and shift_jis, which email sends as iso-2022-jp, Message.set_payload() encoded the text and set_charset() then encoded the result again, which only worked because the encoder let ESC through. set_payload() now leaves that conversion to set_charset(), so the payload is encoded once and comes out the same.
Tested on a debug build: test_codecencodings_iso2022, test_multibytecodec, test_codecs, the other CJK codec tests, test_email, test_mailbox, test_smtplib, test_imaplib and test_mimetypes pass, -R 3:3 shows no leaks for the codec tests, and the new test cases fail on main.
gh-160155 pins this as xfail in test_encode_decode and keeps these characters out of the generated text, so whichever of the two lands second has to drop that.