diff -r a8f8ada7825c Lib/email/message.py --- a/Lib/email/message.py Fri Jun 12 16:48:30 2015 -0400 +++ b/Lib/email/message.py Sat Jun 13 18:11:10 2015 +1200 @@ -91,7 +91,7 @@ return plist -def _unquotevalue(value): +def _unquotevalue(value, strict=False): # This is different than utils.collapse_rfc2231_value() because it doesn't # try to convert the value to a unicode. Message.get_param() and # Message.get_params() are both currently defined to return the tuple in @@ -99,7 +99,7 @@ if isinstance(value, tuple): return value[0], value[1], utils.unquote(value[2]) else: - return utils.unquote(value) + return utils.unquote(value, strict=strict) @@ -643,7 +643,8 @@ params = utils.decode_params(params) return params - def get_params(self, failobj=None, header='content-type', unquote=True): + def get_params(self, failobj=None, header='content-type', unquote=True, + strict=False): """Return the message's Content-Type parameters, as a list. The elements of the returned list are 2-tuples of key/value pairs, as @@ -661,12 +662,12 @@ if params is missing: return failobj if unquote: - return [(k, _unquotevalue(v)) for k, v in params] + return [(k, _unquotevalue(v, strict=strict)) for k, v in params] else: return params def get_param(self, param, failobj=None, header='content-type', - unquote=True): + unquote=True, strict=False): """Return the parameter value if found in the Content-Type header. Optional failobj is the object to return if there is no Content-Type @@ -694,7 +695,7 @@ for k, v in self._get_params_preserve(failobj, header): if k.lower() == param.lower(): if unquote: - return _unquotevalue(v) + return _unquotevalue(v, strict=False) else: return v return failobj diff -r a8f8ada7825c Lib/email/utils.py --- a/Lib/email/utils.py Fri Jun 12 16:48:30 2015 -0400 +++ b/Lib/email/utils.py Sat Jun 13 18:11:10 2015 +1200 @@ -238,11 +238,18 @@ # rfc822.unquote() doesn't properly de-backslash-ify in Python pre-2.3. -def unquote(str): +def unquote(str, strict=False): """Remove quotes from a string.""" if len(str) > 1: - if str.startswith('"') and str.endswith('"'): - return str[1:-1].replace('\\\\', '\\').replace('\\"', '"') + if str.startswith('"'): + if str.endswith('"') or not strict: + str = str[1:-1] + else: + try: + str = str[1:str[1:].index('"') + 1] + except IndexError: + return str + return re.sub(r'\\(.)',r'\1',str[1:-1]) if str.startswith('<') and str.endswith('>'): return str[1:-1] return str