blob: a0d062a20c5563901fb7f46602a0e3b992b7627c [file] [log] [blame]
Guido van Rossum8b3febe2007-08-30 01:15:14 +00001# Copyright (C) 2001-2006 Python Software Foundation
2# Author: Barry Warsaw
3# Contact: email-sig@python.org
4
5"""Encodings and related functions."""
6
7__all__ = [
8 'encode_7or8bit',
9 'encode_base64',
10 'encode_noop',
11 'encode_quopri',
12 ]
13
Guido van Rossum8b3febe2007-08-30 01:15:14 +000014
R David Murray6d94bd42011-03-16 15:52:22 -040015from base64 import encodebytes as _bencode
Guido van Rossum8b3febe2007-08-30 01:15:14 +000016from quopri import encodestring as _encodestring
17
18
19
20def _qencode(s):
21 enc = _encodestring(s, quotetabs=True)
22 # Must encode spaces, which quopri.encodestring() doesn't do
R David Murrayf6069f92013-06-27 18:37:00 -040023 return enc.replace(b' ', b'=20')
Guido van Rossum8b3febe2007-08-30 01:15:14 +000024
25
Guido van Rossum8b3febe2007-08-30 01:15:14 +000026def encode_base64(msg):
27 """Encode the message's payload in Base64.
28
29 Also, add an appropriate Content-Transfer-Encoding header.
30 """
31 orig = msg.get_payload()
R. David Murray7da8f062010-06-04 16:11:08 +000032 encdata = str(_bencode(orig), 'ascii')
Guido van Rossum8b3febe2007-08-30 01:15:14 +000033 msg.set_payload(encdata)
34 msg['Content-Transfer-Encoding'] = 'base64'
35
36
37
38def encode_quopri(msg):
39 """Encode the message's payload in quoted-printable.
40
41 Also, add an appropriate Content-Transfer-Encoding header.
42 """
43 orig = msg.get_payload()
R David Murrayf6069f92013-06-27 18:37:00 -040044 if isinstance(orig, str):
45 # If it is a string, the model data may have binary data encoded in via
46 # surrogateescape. Convert back to bytes so we can CTE encode it.
47 orig = orig.encode('ascii', 'surrogateescape')
Guido van Rossum8b3febe2007-08-30 01:15:14 +000048 encdata = _qencode(orig)
R David Murrayf6069f92013-06-27 18:37:00 -040049 msg.set_payload(encdata.decode('ascii', 'surrogateescape'))
Guido van Rossum8b3febe2007-08-30 01:15:14 +000050 msg['Content-Transfer-Encoding'] = 'quoted-printable'
51
52
53
54def encode_7or8bit(msg):
55 """Set the Content-Transfer-Encoding header to 7bit or 8bit."""
56 orig = msg.get_payload()
57 if orig is None:
58 # There's no payload. For backwards compatibility we use 7bit
59 msg['Content-Transfer-Encoding'] = '7bit'
60 return
R David Murray56a9d7e2011-03-15 12:20:02 -040061 # We play a trick to make this go fast. If encoding/decode to ASCII
62 # succeeds, we know the data must be 7bit, otherwise treat it as 8bit.
Guido van Rossum8b3febe2007-08-30 01:15:14 +000063 try:
R David Murray56a9d7e2011-03-15 12:20:02 -040064 if isinstance(orig, str):
65 orig.encode('ascii')
66 else:
67 orig.decode('ascii')
Guido van Rossum8b3febe2007-08-30 01:15:14 +000068 except UnicodeError:
Guido van Rossum8b3febe2007-08-30 01:15:14 +000069 charset = msg.get_charset()
70 output_cset = charset and charset.output_charset
R David Murrayec317a82013-02-11 10:51:28 -050071 # iso-2022-* is non-ASCII but encodes to a 7-bit representation
R. David Murrayef3d6bd2010-04-12 14:48:58 +000072 if output_cset and output_cset.lower().startswith('iso-2022-'):
Guido van Rossum8b3febe2007-08-30 01:15:14 +000073 msg['Content-Transfer-Encoding'] = '7bit'
74 else:
75 msg['Content-Transfer-Encoding'] = '8bit'
76 else:
77 msg['Content-Transfer-Encoding'] = '7bit'
R David Murrayec317a82013-02-11 10:51:28 -050078 if not isinstance(orig, str):
79 msg.set_payload(orig.decode('ascii', 'surrogateescape'))
Guido van Rossum8b3febe2007-08-30 01:15:14 +000080
81
82
83def encode_noop(msg):
84 """Do nothing."""
R David Murrayceaa8b12013-02-09 13:02:58 -050085 # Well, not quite *nothing*: in Python3 we have to turn bytes into a string
86 # in our internal surrogateescaped form in order to keep the model
87 # consistent.
88 orig = msg.get_payload()
89 if not isinstance(orig, str):
90 msg.set_payload(orig.decode('ascii', 'surrogateescape'))