def _flatten(message): r"""Flatten a message to bytes. >>> from pgp_mime.email import encodedMIMEText >>> message = encodedMIMEText('Hi\nBye') >>> _flatten(message) # doctest: +ELLIPSIS b'Content-Type: text/plain; charset="us-ascii"\r\nMIME-Version: ...' """ bytesio = _io.BytesIO() generator = _BytesGenerator(bytesio, policy=_email_policy.SMTP) generator.flatten(message) return bytesio.getvalue()
def _flatten(message): r"""Flatten an email.message.Message to bytes >>> import rss2email.config >>> config = rss2email.config.Config() >>> config.read_dict(rss2email.config.CONFIG) Here's a 7-bit, base64 version: >>> message = get_message( ... sender='John <*****@*****.**>', recipient='Ζεύς <*****@*****.**>', ... subject='Homage', ... body="You're great, Ζεύς!\n", ... content_type='plain', ... config=config) >>> for line in _flatten(message).split(b'\n'): ... print(line) # doctest: +REPORT_UDIFF b'MIME-Version: 1.0' b'Content-Type: text/plain; charset="utf-8"' b'Content-Transfer-Encoding: base64' b'From: John <*****@*****.**>' b'To: =?utf-8?b?zpbOtc+Nz4I=?= <*****@*****.**>' b'Subject: Homage' b'' b'WW91J3JlIGdyZWF0LCDOls61z43PgiEK' b'' Here's an 8-bit version: >>> config.set('DEFAULT', 'use-8bit', str(True)) >>> message = get_message( ... sender='John <*****@*****.**>', recipient='Ζεύς <*****@*****.**>', ... subject='Homage', ... body="You're great, Ζεύς!\n", ... content_type='plain', ... config=config) >>> for line in _flatten(message).split(b'\n'): ... print(line) # doctest: +REPORT_UDIFF b'MIME-Version: 1.0' b'Content-Type: text/plain; charset="utf-8"' b'From: John <*****@*****.**>' b'To: =?utf-8?b?zpbOtc+Nz4I=?= <*****@*****.**>' b'Subject: Homage' b'Content-Transfer-Encoding: 8bit' b'' b"You're great, \xce\x96\xce\xb5\xcf\x8d\xcf\x82!" b'' Here's an 8-bit version in UTF-16: >>> config.set('DEFAULT', 'encodings', 'US-ASCII, UTF-16-LE') >>> message = get_message( ... sender='John <*****@*****.**>', recipient='Ζεύς <*****@*****.**>', ... subject='Homage', ... body="You're great, Ζεύς!\n", ... content_type='plain', ... config=config) >>> for line in _flatten(message).split(b'\n'): ... print(line) # doctest: +REPORT_UDIFF b'MIME-Version: 1.0' b'Content-Type: text/plain; charset="utf-16-le"' b'From: John <*****@*****.**>' b'To: =?utf-8?b?zpbOtc+Nz4I=?= <*****@*****.**>' b'Subject: Homage' b'Content-Transfer-Encoding: 8bit' b'' b"\x00Y\x00o\x00u\x00'\x00r\x00e\x00 \x00g\x00r\x00e\x00a\x00t\x00,\x00 \x00\x96\x03\xb5\x03\xcd\x03\xc2\x03!\x00\n\x00" """ bytesio = _io.BytesIO() generator = _BytesGenerator(bytesio) # use policies for Python >=3.3 try: generator.flatten(message) except UnicodeEncodeError as e: # HACK: work around deficiencies in BytesGenerator _LOG.warning(e) b = message.as_string().encode(str(message.get_charset())) m = _email.message_from_bytes(b) if not m: raise h = {k:_decode_header(v) for k,v in m.items()} head = {k:_decode_header(v) for k,v in message.items()} body = str(m.get_payload(decode=True), str(m.get_charsets()[0])) if (h == head and body == message.get_payload()): return b raise else: return bytesio.getvalue()
def _flatten(message): r"""Flatten an email.message.Message to bytes >>> import rss2email.config >>> config = rss2email.config.Config() >>> config.read_dict(rss2email.config.CONFIG) Here's a 7-bit, base64 version: >>> message = get_message( ... sender='John <*****@*****.**>', recipient='Ζεύς <*****@*****.**>', ... subject='Homage', ... body="You're great, Ζεύς!\n", ... content_type='plain', ... config=config) >>> for line in _flatten(message).split(b'\n'): ... print(line) # doctest: +REPORT_UDIFF b'MIME-Version: 1.0' b'Content-Type: text/plain; charset="utf-8"' b'Content-Transfer-Encoding: base64' b'From: John <*****@*****.**>' b'To: =?utf-8?b?zpbOtc+Nz4I=?= <*****@*****.**>' b'Subject: Homage' b'' b'WW91J3JlIGdyZWF0LCDOls61z43PgiEK' b'' Here's an 8-bit version: >>> config.set('DEFAULT', 'use-8bit', str(True)) >>> message = get_message( ... sender='John <*****@*****.**>', recipient='Ζεύς <*****@*****.**>', ... subject='Homage', ... body="You're great, Ζεύς!\n", ... content_type='plain', ... config=config) >>> for line in _flatten(message).split(b'\n'): ... print(line) # doctest: +REPORT_UDIFF b'MIME-Version: 1.0' b'Content-Type: text/plain; charset="utf-8"' b'From: John <*****@*****.**>' b'To: =?utf-8?b?zpbOtc+Nz4I=?= <*****@*****.**>' b'Subject: Homage' b'Content-Transfer-Encoding: 8bit' b'' b"You're great, \xce\x96\xce\xb5\xcf\x8d\xcf\x82!" b'' Here's an 8-bit version in UTF-16: >>> config.set('DEFAULT', 'encodings', 'US-ASCII, UTF-16-LE') >>> message = get_message( ... sender='John <*****@*****.**>', recipient='Ζεύς <*****@*****.**>', ... subject='Homage', ... body="You're great, Ζεύς!\n", ... content_type='plain', ... config=config) >>> for line in _flatten(message).split(b'\n'): ... print(line) # doctest: +REPORT_UDIFF b'MIME-Version: 1.0' b'Content-Type: text/plain; charset="utf-16-le"' b'From: John <*****@*****.**>' b'To: =?utf-8?b?zpbOtc+Nz4I=?= <*****@*****.**>' b'Subject: Homage' b'Content-Transfer-Encoding: 8bit' b'' b"\x00Y\x00o\x00u\x00'\x00r\x00e\x00 \x00g\x00r\x00e\x00a\x00t\x00,\x00 \x00\x96\x03\xb5\x03\xcd\x03\xc2\x03!\x00\n\x00" """ bytesio = _io.BytesIO() # TODO: use policies argument instead of policy set in `message` # see https://docs.python.org/3.5/library/email.generator.html?highlight=bytesgenerator#email.generator.BytesGenerator generator = _BytesGenerator(bytesio) try: generator.flatten(message) except UnicodeEncodeError as e: # HACK: work around deficiencies in BytesGenerator _LOG.warning(e) b = message.as_string().encode(str(message.get_charset())) m = _email.message_from_bytes(b) if not m: raise h = {k: _decode_header(v) for k, v in m.items()} head = {k: _decode_header(v) for k, v in message.items()} body = str(m.get_payload(decode=True), str(m.get_charsets()[0])) if (h == head and body == message.get_payload()): return b raise else: return bytesio.getvalue()