The document of the email.policy.Policy says max_line_length=0 or None indicates that no line wrapping should be done at all. But email.contentmanager doesn't handle this properly and raises error when calling set_content() with bytes or non-ascii str. ---Code to reproduce the bug--- from email.message import EmailMessage from email.policy import default msg=EmailMessage(default.clone(max_line_length=None)) # or max_line_length=0 msg.set_content('あ') # raise error # or msg.set_content(b'a',maintype='application',subtype='octet-stream') # raise error --- This bug is caused by contentmanager._encode_text() and contentmanager.set_bytes_content(). These don't assume policy.max_line_length to be None or 0. I tested this on python3.7 3.6 3.5, but probably 3.4 has the same bug.
Thanks silane for the report and script. The case where max_line_length=0 causing ValueError was introduced with b938c8c25316b69f1d5df2c7880a9f6b87e7c2fa and the code at [0] has some comments regarding the minimum value to be 4 characters. There was another case where policy can have max_line_length=0 but it's with respect to folding . Maybe this behavior can be documented better for set_content method with respect to the minimum value ? [0] https://github.com/tirkarthi/cpython/blob/f6c8007a29b95b3ea3ca687a9b4924769a696328/Lib/email/quoprimime.py#L171 """ Each line will be wrapped at, at most, maxlinelen characters before the eol string (maxlinelen defaults to 76 characters, the maximum value permitted by RFC 2045). Long lines will have the 'soft line break' quoted-printable character "=" appended to them, so the decoded text will be identical to the original text. The minimum maxlinelen is 4 to have room for a quoted character ("=XX") followed by a soft line break. Smaller values will generate a ValueError. """ Hope this helps!
An unlimited line length would certainly satisfy the required minimum. As silane indicates, if max_line_length is 0 or None, the serializer is not supposed to wrap lines. (In fact one would like to have the option to control this separately for the headers and the body, but currently the policy does not have knobs for that.) So, this is a bug.