[Python-checkins] cpython: #20477: add examples of using the new contentmanager API.

r.david.murray python-checkins at python.org
Fri Feb 7 16:55:33 CET 2014


http://hg.python.org/cpython/rev/a9d7d53d5fbd
changeset:   89014:a9d7d53d5fbd
user:        R David Murray <rdmurray at bitdance.com>
date:        Fri Feb 07 10:55:17 2014 -0500
summary:
  #20477: add examples of using the new contentmanager API.

files:
  Doc/includes/email-alternative-new-api.py      |  56 +++++++
  Doc/includes/email-read-alternative-new-api.py |  74 ++++++++++
  Doc/library/email-examples.rst                 |  28 +++
  3 files changed, 158 insertions(+), 0 deletions(-)


diff --git a/Doc/includes/email-alternative-new-api.py b/Doc/includes/email-alternative-new-api.py
new file mode 100644
--- /dev/null
+++ b/Doc/includes/email-alternative-new-api.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python3
+
+import smtplib
+
+from email.message import EmailMessage
+from email.headerregistry import Address
+from email.utils import make_msgid
+
+# Create the base text message.
+msg = EmailMessage()
+msg['Subject'] = "Ayons asperges pour le déjeuner"
+msg['From'] = Address("Pepé Le Pew", "pepe at example.com")
+msg['To'] = (Address("Penelope Pussycat", "penelope at example.com"),
+             Address("Fabrette Pussycat", "fabrette at example.com"))
+msg.set_content("""\
+Salut!
+
+Cela ressemble à un excellent recipie[1] déjeuner.
+
+[1] http://www.yummly.com/recipe/Roasted-Asparagus-Epicurious-203718
+
+--Éric
+""")
+
+# Add the html version.  This converts the message into a multipart/alternative
+# container, with the original text message as the first part and the new html
+# message as the second part.
+asparagus_cid = make_msgid()
+msg.add_alternative("""\
+<html>
+  <head></head>
+  <body>
+    <p>Salut!<\p>
+    <p>Cela ressemble à un excellent
+        <a href="http://www.yummly.com/recipe/Roasted-Asparagus-Epicurious-203718>
+            recipie
+        </a> déjeuner.
+    </p>
+    <img src="cid:{asparagus_cid}" \>
+  </body>
+</html>
+""".format(asparagus_cid=asparagus_cid[1:-1]), subtype='html')
+# note that we needed to peel the <> off the msgid for use in the html.
+
+# Now add the related image to the html part.
+with open("roasted-asparagus.jpg", 'rb') as img:
+    msg.get_payload()[1].add_related(img.read(), 'image', 'jpeg',
+                                     cid=asparagus_cid)
+
+# Make a local copy of what we are going to send.
+with open('outgoing.msg', 'wb') as f:
+    f.write(bytes(msg))
+
+# Send the message via local SMTP server.
+with smtplib.SMTP('localhost') as s:
+    s.send_message(msg)
diff --git a/Doc/includes/email-read-alternative-new-api.py b/Doc/includes/email-read-alternative-new-api.py
new file mode 100644
--- /dev/null
+++ b/Doc/includes/email-read-alternative-new-api.py
@@ -0,0 +1,74 @@
+import os
+import sys
+import tempfile
+import mimetypes
+import webbrowser
+
+# Import the email modules we'll need
+from email import policy
+from email.parser import BytesParser
+
+# An imaginary module that would make this work and be safe.
+from imaginary import magic_html_parser
+
+# In a real program you'd get the filename from the arguments.
+msg = BytesParser(policy=policy.default).parse(open('outgoing.msg', 'rb'))
+
+# Now the header items can be accessed as a dictionary, and any non-ASCII will
+# be converted to unicode:
+print('To:', msg['to'])
+print('From:', msg['from'])
+print('Subject:', msg['subject'])
+
+# If we want to print a priview of the message content, we can extract whatever
+# the least formatted payload is and print the first three lines.  Of course,
+# if the message has no plain text part printing the first three lines of html
+# is probably useless, but this is just a conceptual example.
+simplest = msg.get_body(preferencelist=('plain', 'html'))
+print()
+print(''.join(simplest.get_content().splitlines(keepends=True)[:3]))
+
+ans = input("View full message?")
+if ans.lower()[0] == 'n':
+    sys.exit()
+
+# We can extract the richest alternative in order to display it:
+richest = msg.get_body()
+partfiles = {}
+if richest['content-type'].maintype == 'text':
+    if richest['content-type'].subtype == 'plain':
+        for line in richest.get_content().splitlines():
+            print(line)
+        sys.exit()
+    elif richest['content-type'].subtype == 'html':
+        body = richest
+    else:
+        print("Don't know how to display {}".format(richest.get_content_type()))
+        sys.exit()
+elif richest['content-type'].content_type == 'multipart/related':
+    body = richest.get_body(preferencelist=('html'))
+    for part in richest.iter_attachments():
+        fn = part.get_filename()
+        if fn:
+            extension = os.path.splitext(part.get_filename())[1]
+        else:
+            extension = mimetypes.guess_extension(part.get_content_type())
+        with tempfile.NamedTemporaryFile(suffix=extension, delete=False) as f:
+            f.write(part.get_content())
+            # again strip the <> to go from email form of cid to html form.
+            partfiles[part['content-id'][1:-1]] = f.name
+else:
+    print("Don't know how to display {}".format(richest.get_content_type()))
+    sys.exit()
+with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
+    # The magic_html_parser has to rewrite the href="cid:...." attributes to
+    # point to the filenames in partfiles.  It also has to do a safety-sanitize
+    # of the html.  It could be written using html.parser.
+    f.write(magic_html_parser(body.get_content(), partfiles))
+webbrowser.open(f.name)
+os.remove(f.name)
+for fn in partfiles.values():
+    os.remove(fn)
+
+# Of course, there are lots of email messages that could break this simple
+# minded program, but it will handle the most common ones.
diff --git a/Doc/library/email-examples.rst b/Doc/library/email-examples.rst
--- a/Doc/library/email-examples.rst
+++ b/Doc/library/email-examples.rst
@@ -40,6 +40,34 @@
 .. literalinclude:: ../includes/email-alternative.py
 
 
+Examples using the Provision API
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Here is a reworking of the last example using the provisional API.  To make
+things a bit more interesting, we include a related image in the html part, and
+we save a copy of what we are going to send to disk, as well as sending it.
+
+This example also shows how easy it is to include non-ASCII, and simplifies the
+sending of the message using the :meth:`.send_message` method of the
+:mod:`smtplib` module.
+
+.. literalinclude:: ../includes/email-alternative-new-api.py
+
+If we were instead sent the message from the last example, here is one
+way we could process it:
+
+.. literalinclude:: ../includes/email-read-alternative-new-api.py
+
+Up to the prompt, the output from the above is::
+
+    To: Penelope Pussycat <"penelope at example.com">, Fabrette Pussycat <"fabrette at example.com">
+    From: Pepé Le Pew <pepe at example.com>
+    Subject: Ayons asperges pour le déjeuner
+
+    Salut!
+
+    Cela ressemble à un excellent recipie[1] déjeuner.
+
+
 .. rubric:: Footnotes
 
 .. [1] Thanks to Matthew Dixon Cowles for the original inspiration and examples.

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list