python / cpython

The Python programming language
https://www.python.org
Other
63.42k stars 30.37k forks source link

email.contentmanager raises error when policy.max_line_length==None or 0 #78981

Open 10838133-1050-4ab6-b425-d6f08f328d32 opened 6 years ago

10838133-1050-4ab6-b425-d6f08f328d32 commented 6 years ago
BPO 34800
Nosy @warsaw, @bitdancer, @tirkarthi, @silane
PRs
  • python/cpython#9578
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields: ```python assignee = None closed_at = None created_at = labels = ['3.8', 'type-bug', '3.7', 'expert-email'] title = 'email.contentmanager raises error when policy.max_line_length==None or 0' updated_at = user = 'https://github.com/silane' ``` bugs.python.org fields: ```python activity = actor = 'silane' assignee = 'none' closed = False closed_date = None closer = None components = ['email'] creation = creator = 'silane' dependencies = [] files = [] hgrepos = [] issue_num = 34800 keywords = ['patch'] message_count = 4.0 messages = ['326364', '326384', '326399', '326403'] nosy_count = 4.0 nosy_names = ['barry', 'r.david.murray', 'xtreak', 'silane'] pr_nums = ['9578'] priority = 'normal' resolution = None stage = 'patch review' status = 'open' superseder = None type = 'behavior' url = 'https://bugs.python.org/issue34800' versions = ['Python 3.7', 'Python 3.8'] ```

    Linked PRs

    10838133-1050-4ab6-b425-d6f08f328d32 commented 6 years ago

    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.

    tirkarthi commented 6 years ago

    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 bpo-33524. 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!

    bitdancer commented 6 years ago

    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.

    10838133-1050-4ab6-b425-d6f08f328d32 commented 6 years ago

    I've made a pull request. Please look at it. And this is my first pull request, so please let me know if something wrong.

    https://github.com/python/cpython/pull/9578