1 # 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 
  14 
  15 from base64 import encodebytes as _bencode
  16 from quopri import encodestring as _encodestring
  17 
  18 
  19 
  20 def _qencode(s):
  21     enc = _encodestring(s, quotetabs=True)
  22     # Must encode spaces, which quopri.encodestring() doesn't do
  23     return enc.replace(b' ', b'=20')
  24 
  25 
  26 def 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(decode=True)
  32     encdata = str(_bencode(orig), 'ascii')
  33     msg.set_payload(encdata)
  34     msg['Content-Transfer-Encoding'] = 'base64'
  35 
  36 
  37 
  38 def 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(decode=True)
  44     encdata = _qencode(orig)
  45     msg.set_payload(encdata)
  46     msg['Content-Transfer-Encoding'] = 'quoted-printable'
  47 
  48 
  49 
  50 def encode_7or8bit(msg):
  51     """Set the Content-Transfer-Encoding header to 7bit or 8bit."""
  52     orig = msg.get_payload(decode=True)
  53     if orig is None:
  54         # There's no payload.  For backwards compatibility we use 7bit
  55         msg['Content-Transfer-Encoding'] = '7bit'
  56         return
  57     # We play a trick to make this go fast.  If encoding/decode to ASCII
  58     # succeeds, we know the data must be 7bit, otherwise treat it as 8bit.
  59     try:
  60         if isinstance(orig, str):
  61             orig.encode('ascii')
  62         else:
  63             orig.decode('ascii')
  64     except UnicodeError:
  65         charset = msg.get_charset()
  66         output_cset = charset and charset.output_charset
  67         # iso-2022-* is non-ASCII but encodes to a 7-bit representation
  68         if output_cset and output_cset.lower().startswith('iso-2022-'):
  69             msg['Content-Transfer-Encoding'] = '7bit'
  70         else:
  71             msg['Content-Transfer-Encoding'] = '8bit'
  72     else:
  73         msg['Content-Transfer-Encoding'] = '7bit'
  74 
  75 
  76 
  77 def encode_noop(msg):
  78     """Do nothing."""