Index: Doc/library/email.message.rst =================================================================== --- Doc/library/email.message.rst (revision 85191) +++ Doc/library/email.message.rst (working copy) @@ -257,7 +257,12 @@ taken as the parameter name, with underscores converted to dashes (since dashes are illegal in Python identifiers). Normally, the parameter will be added as ``key="value"`` unless the value is ``None``, in which case - only the key will be added. + only the key will be added. If the value contains non-ASCII characters, + it must be specified as a three tuple in the format + ``(CHARSET, LANGUAGE, VALUE)``, where ``CHARSET`` is a string naming the + charset to be used to encode the value, ``LANGUAGE`` can usually be set + to ``None`` or the empty string (see :RFC:`2231` for other possibilities), + and ``VALUE`` is the string value containing non-ASCII code points. Here's an example:: @@ -267,7 +272,16 @@ Content-Disposition: attachment; filename="bud.gif" + An example with with non-ASCII characters:: + msg.add_header('Content-Disposition', 'attachment', + filename=('iso-8859-1', '', 'Fußballer.ppt')) + + Which produces :: + + Content-Disposition: attachment; filename*="iso-8859-1''Fu%DFballer.ppt" + + .. method:: replace_header(_name, _value) Replace a header. Replace the first header found in the message that @@ -356,7 +370,7 @@ :rfc:`2231`, you can collapse the parameter value by calling :func:`email.utils.collapse_rfc2231_value`, passing in the return value from :meth:`get_param`. This will return a suitably decoded Unicode - string whn the value is a tuple, or the original string unquoted if it + string when the value is a tuple, or the original string unquoted if it isn't. For example:: rawparam = msg.get_param('foo') Index: Lib/email/test/test_email.py =================================================================== --- Lib/email/test/test_email.py (revision 85191) +++ Lib/email/test/test_email.py (working copy) @@ -508,6 +508,21 @@ self.assertEqual(msg.get_payload(decode=True), bytes(x, 'raw-unicode-escape')) + def test_add_header(self): + # Issue 1078919 + msg = Message() + msg.add_header('Content-Disposition', 'attachment', + filename='bud.gif') + self.assertEquals(msg['Content-Disposition'], + 'attachment; filename="bud.gif"') + msg = Message() + msg.add_header('Content-Disposition', 'attachment', + filename=('iso-8859-1', '', 'Fußballer.ppt')) + self.assertEquals(msg['Content-Disposition'], + 'attachment; filename*="iso-8859-1\'\'Fu%DFballer.ppt"') + with self.assertRaises(ValueError): + msg.add_header('Content-Disposition', 'attachment', + filename="Fußballer.ppt") # Test the email.encoders module Index: Lib/email/message.py =================================================================== --- Lib/email/message.py (revision 85191) +++ Lib/email/message.py (working copy) @@ -39,7 +39,9 @@ def _formatparam(param, value=None, quote=True): """Convenience function to format and return a key=value pair. - This will quote the value if needed or if quote is true. + This will quote the value if needed or if quote is true. If value is a + three tuple (charset, language, value), it will be encoded according + to RFC2231 rules. """ if value is not None and len(value) > 0: # A tuple is used for RFC 2231 encoded parameter values where items @@ -49,6 +51,14 @@ # Encode as per RFC 2231 param += '*' value = utils.encode_rfc2231(value[2], value[0], value[1]) + else: + try: + value.encode('ascii') + except UnicodeEncodeError: + raise ValueError("{}: parameter values with non-ASCII " + "characters must be specified as a " + "(charset, language, value) " + "tuple".format(value)) # BAW: Please check this. I think that if quote is set it should # force quoting even if not necessary. if quote or tspecials.search(value): @@ -392,11 +402,16 @@ name is the header field to add. keyword arguments can be used to set additional parameters for the header field, with underscores converted to dashes. Normally the parameter will be added as key="value" unless - value is None, in which case only the key will be added. + value is None, in which case only the key will be added. If a + parameter value contains non-ASCII characters it must be specified as a + three-tuple of (charset, language, value), in which case it will be + encoded according to RFC2231 rules. - Example: + Examples: msg.add_header('content-disposition', 'attachment', filename='bud.gif') + msg.add_header('content-disposition', 'attachment', + filename=('utf-8', '', Fußballer.ppt')) """ parts = [] for k, v in _params.items():