Decode a message header value without converting charset. Returns a list of (string, charset) pairs containing each of the decoded parts of the header. Charset is None for non-encoded parts of the header, otherwise a lower-case string containing the name of the character set s
(header)
| 57 | |
| 58 | |
| 59 | def decode_header(header): |
| 60 | """Decode a message header value without converting charset. |
| 61 | |
| 62 | Returns a list of (string, charset) pairs containing each of the decoded |
| 63 | parts of the header. Charset is None for non-encoded parts of the header, |
| 64 | otherwise a lower-case string containing the name of the character set |
| 65 | specified in the encoded string. |
| 66 | |
| 67 | header may be a string that may or may not contain RFC2047 encoded words, |
| 68 | or it may be a Header object. |
| 69 | |
| 70 | An email.errors.HeaderParseError may be raised when certain decoding error |
| 71 | occurs (e.g. a base64 decoding exception). |
| 72 | """ |
| 73 | # If it is a Header object, we can just return the encoded chunks. |
| 74 | if hasattr(header, '_chunks'): |
| 75 | return [(_charset._encode(string, str(charset)), str(charset)) |
| 76 | for string, charset in header._chunks] |
| 77 | # If no encoding, just return the header with no charset. |
| 78 | if not ecre.search(header): |
| 79 | return [(header, None)] |
| 80 | # First step is to parse all the encoded parts into triplets of the form |
| 81 | # (encoded_string, encoding, charset). For unencoded strings, the last |
| 82 | # two parts will be None. |
| 83 | words = [] |
| 84 | for line in header.splitlines(): |
| 85 | parts = ecre.split(line) |
| 86 | first = True |
| 87 | while parts: |
| 88 | unencoded = parts.pop(0) |
| 89 | if first: |
| 90 | unencoded = unencoded.lstrip() |
| 91 | first = False |
| 92 | if unencoded: |
| 93 | words.append((unencoded, None, None)) |
| 94 | if parts: |
| 95 | charset = parts.pop(0).lower() |
| 96 | encoding = parts.pop(0).lower() |
| 97 | encoded = parts.pop(0) |
| 98 | words.append((encoded, encoding, charset)) |
| 99 | # Now loop over words and remove words that consist of whitespace |
| 100 | # between two encoded strings. |
| 101 | droplist = [] |
| 102 | for n, w in enumerate(words): |
| 103 | if n>1 and w[1] and words[n-2][1] and words[n-1][0].isspace(): |
| 104 | droplist.append(n-1) |
| 105 | for d in reversed(droplist): |
| 106 | del words[d] |
| 107 | |
| 108 | # The next step is to decode each encoded word by applying the reverse |
| 109 | # base64 or quopri transformation. decoded_words is now a list of the |
| 110 | # form (decoded_word, charset). |
| 111 | decoded_words = [] |
| 112 | for encoded_string, encoding, charset in words: |
| 113 | if encoding is None: |
| 114 | # This is an unencoded word. |
| 115 | decoded_words.append((encoded_string, charset)) |
| 116 | elif encoding == 'q': |
no test coverage detected