From fcc31b44d24e8e8bddc19b27c916a051223e5164 Mon Sep 17 00:00:00 2001 From: Fred Drake Date: Tue, 1 Oct 2002 14:17:10 +0000 Subject: Split the long email package examples into separate files and use \verbatiminput instead of the verbatim environment -- this does the "right thing" regarding page breaks in long examples for the typeset formats, and has nice benefits for the HTML version as well. --- Doc/lib/email-dir.py | 123 +++++++++++++++++++++ Doc/lib/email-mime.py | 34 ++++++ Doc/lib/email-simple.py | 25 +++++ Doc/lib/email-unpack.py | 83 +++++++++++++++ Doc/lib/email.tex | 277 +----------------------------------------------- 5 files changed, 269 insertions(+), 273 deletions(-) create mode 100644 Doc/lib/email-dir.py create mode 100644 Doc/lib/email-mime.py create mode 100644 Doc/lib/email-simple.py create mode 100644 Doc/lib/email-unpack.py diff --git a/Doc/lib/email-dir.py b/Doc/lib/email-dir.py new file mode 100644 index 0000000..aa3b5e5 --- /dev/null +++ b/Doc/lib/email-dir.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python + +"""Send the contents of a directory as a MIME message. + +Usage: dirmail [options] from to [to ...]* + +Options: + -h / --help + Print this message and exit. + + -d directory + --directory=directory + Mail the contents of the specified directory, otherwise use the + current directory. Only the regular files in the directory are sent, + and we don't recurse to subdirectories. + +`from' is the email address of the sender of the message. + +`to' is the email address of the recipient of the message, and multiple +recipients may be given. + +The email is sent by forwarding to your local SMTP server, which then does the +normal delivery process. Your local machine must be running an SMTP server. +""" + +import sys +import os +import getopt +import smtplib +# For guessing MIME type based on file name extension +import mimetypes + +from email import Encoders +from email.Message import Message +from email.MIMEAudio import MIMEAudio +from email.MIMEMultipart import MIMEMultipart +from email.MIMEImage import MIMEImage +from email.MIMEText import MIMEText + +COMMASPACE = ', ' + + +def usage(code, msg=''): + print >> sys.stderr, __doc__ + if msg: + print >> sys.stderr, msg + sys.exit(code) + + +def main(): + try: + opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) + except getopt.error, msg: + usage(1, msg) + + dir = os.curdir + for opt, arg in opts: + if opt in ('-h', '--help'): + usage(0) + elif opt in ('-d', '--directory'): + dir = arg + + if len(args) < 2: + usage(1) + + sender = args[0] + recips = args[1:] + + # Create the enclosing (outer) message + outer = MIMEMultipart() + outer['Subject'] = 'Contents of directory %s' % os.path.abspath(dir) + outer['To'] = COMMASPACE.join(recips) + outer['From'] = sender + outer.preamble = 'You will not see this in a MIME-aware mail reader.\n' + # To guarantee the message ends with a newline + outer.epilogue = '' + + for filename in os.listdir(dir): + path = os.path.join(dir, filename) + if not os.path.isfile(path): + continue + # Guess the content type based on the file's extension. Encoding + # will be ignored, although we should check for simple things like + # gzip'd or compressed files. + ctype, encoding = mimetypes.guess_type(path) + if ctype is None or encoding is not None: + # No guess could be made, or the file is encoded (compressed), so + # use a generic bag-of-bits type. + ctype = 'application/octet-stream' + maintype, subtype = ctype.split('/', 1) + if maintype == 'text': + fp = open(path) + # Note: we should handle calculating the charset + msg = MIMEText(fp.read(), _subtype=subtype) + fp.close() + elif maintype == 'image': + fp = open(path, 'rb') + msg = MIMEImage(fp.read(), _subtype=subtype) + fp.close() + elif maintype == 'audio': + fp = open(path, 'rb') + msg = MIMEAudio(fp.read(), _subtype=subtype) + fp.close() + else: + fp = open(path, 'rb') + msg = MIMEBase(maintype, subtype) + msg.set_payload(fp.read()) + fp.close() + # Encode the payload using Base64 + Encoders.encode_base64(msg) + # Set the filename parameter + msg.add_header('Content-Disposition', 'attachment', filename=filename) + outer.attach(msg) + + # Now send the message + s = smtplib.SMTP() + s.connect() + s.sendmail(sender, recips, outer.as_string()) + s.close() + + +if __name__ == '__main__': + main() diff --git a/Doc/lib/email-mime.py b/Doc/lib/email-mime.py new file mode 100644 index 0000000..28c8d2e --- /dev/null +++ b/Doc/lib/email-mime.py @@ -0,0 +1,34 @@ +# Import smtplib for the actual sending function +import smtplib + +# Here are the email pacakge modules we'll need +from email.MIMEImage import MIMEImage +from email.MIMEMultipart import MIMEMultipart + +COMMASPACE = ', ' + +# Create the container (outer) email message. +msg = MIMEMultipart() +msg['Subject'] = 'Our family reunion' +# me == the sender's email address +# family = the list of all recipients' email addresses +msg['From'] = me +msg['To'] = COMMASPACE.join(family) +msg.preamble = 'Our family reunion' +# Guarantees the message ends in a newline +msg.epilogue = '' + +# Assume we know that the image files are all in PNG format +for file in pngfiles: + # Open the files in binary mode. Let the MIMEImage class automatically + # guess the specific image type. + fp = open(file, 'rb') + img = MIMEImage(fp.read()) + fp.close() + msg.attach(img) + +# Send the email via our own SMTP server. +s = smtplib.SMTP() +s.connect() +s.sendmail(me, family, msg.as_string()) +s.close() diff --git a/Doc/lib/email-simple.py b/Doc/lib/email-simple.py new file mode 100644 index 0000000..a445f1b --- /dev/null +++ b/Doc/lib/email-simple.py @@ -0,0 +1,25 @@ +# Import smtplib for the actual sending function +import smtplib + +# Import the email modules we'll need +from email.MIMEText import MIMEText + +# Open a plain text file for reading. For this example, assume that +# the text file contains only ASCII characters. +fp = open(textfile, 'rb') +# Create a text/plain message +msg = MIMEText(fp.read()) +fp.close() + +# me == the sender's email address +# you == the recipient's email address +msg['Subject'] = 'The contents of %s' % textfile +msg['From'] = me +msg['To'] = you + +# Send the message via our own SMTP server, but don't include the +# envelope header. +s = smtplib.SMTP() +s.connect() +s.sendmail(me, [you], msg.as_string()) +s.close() diff --git a/Doc/lib/email-unpack.py b/Doc/lib/email-unpack.py new file mode 100644 index 0000000..b166fdb --- /dev/null +++ b/Doc/lib/email-unpack.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python + +"""Unpack a MIME message into a directory of files. + +Usage: unpackmail [options] msgfile + +Options: + -h / --help + Print this message and exit. + + -d directory + --directory=directory + Unpack the MIME message into the named directory, which will be + created if it doesn't already exist. + +msgfile is the path to the file containing the MIME message. +""" + +import sys +import os +import getopt +import errno +import mimetypes +import email + + +def usage(code, msg=''): + print >> sys.stderr, __doc__ + if msg: + print >> sys.stderr, msg + sys.exit(code) + + +def main(): + try: + opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) + except getopt.error, msg: + usage(1, msg) + + dir = os.curdir + for opt, arg in opts: + if opt in ('-h', '--help'): + usage(0) + elif opt in ('-d', '--directory'): + dir = arg + + try: + msgfile = args[0] + except IndexError: + usage(1) + + try: + os.mkdir(dir) + except OSError, e: + # Ignore directory exists error + if e.errno <> errno.EEXIST: raise + + fp = open(msgfile) + msg = email.message_from_file(fp) + fp.close() + + counter = 1 + for part in msg.walk(): + # multipart/* are just containers + if part.get_content_maintype() == 'multipart': + continue + # Applications should really sanitize the given filename so that an + # email message can't be used to overwrite important files + filename = part.get_filename() + if not filename: + ext = mimetypes.guess_extension(part.get_type()) + if not ext: + # Use a generic bag-of-bits extension + ext = '.bin' + filename = 'part-%03d%s' % (counter, ext) + counter += 1 + fp = open(os.path.join(dir, filename), 'wb') + fp.write(part.get_payload(decode=1)) + fp.close() + + +if __name__ == '__main__': + main() diff --git a/Doc/lib/email.tex b/Doc/lib/email.tex index c80305f..f25c86d 100644 --- a/Doc/lib/email.tex +++ b/Doc/lib/email.tex @@ -285,289 +285,20 @@ MIME messages. First, let's see how to create and send a simple text message: -\begin{verbatim} -# Import smtplib for the actual sending function -import smtplib - -# Import the email modules we'll need -from email.MIMEText import MIMEText - -# Open a plain text file for reading. For this example, assume that -# the text file contains only ASCII characters. -fp = open(textfile, 'rb') -# Create a text/plain message -msg = MIMEText(fp.read()) -fp.close() - -# me == the sender's email address -# you == the recipient's email address -msg['Subject'] = 'The contents of %s' % textfile -msg['From'] = me -msg['To'] = you - -# Send the message via our own SMTP server, but don't include the -# envelope header. -s = smtplib.SMTP() -s.connect() -s.sendmail(me, [you], msg.as_string()) -s.close() -\end{verbatim} +\verbatiminput{email-simple.py} Here's an example of how to send a MIME message containing a bunch of family pictures that may be residing in a directory: -\begin{verbatim} -# Import smtplib for the actual sending function -import smtplib - -# Here are the email pacakge modules we'll need -from email.MIMEImage import MIMEImage -from email.MIMEMultipart import MIMEMultipart - -COMMASPACE = ', ' - -# Create the container (outer) email message. -msg = MIMEMultipart() -msg['Subject'] = 'Our family reunion' -# me == the sender's email address -# family = the list of all recipients' email addresses -msg['From'] = me -msg['To'] = COMMASPACE.join(family) -msg.preamble = 'Our family reunion' -# Guarantees the message ends in a newline -msg.epilogue = '' - -# Assume we know that the image files are all in PNG format -for file in pngfiles: - # Open the files in binary mode. Let the MIMEImage class automatically - # guess the specific image type. - fp = open(file, 'rb') - img = MIMEImage(fp.read()) - fp.close() - msg.attach(img) - -# Send the email via our own SMTP server. -s = smtplib.SMTP() -s.connect() -s.sendmail(me, family, msg.as_string()) -s.close() -\end{verbatim} +\verbatiminput{email-mime.py} Here's an example\footnote{Thanks to Matthew Dixon Cowles for the original inspiration and examples.} of how to send the entire contents of a directory as an email message: -\begin{verbatim} -#!/usr/bin/env python - -"""Send the contents of a directory as a MIME message. - -Usage: dirmail [options] from to [to ...]* - -Options: - -h / --help - Print this message and exit. - - -d directory - --directory=directory - Mail the contents of the specified directory, otherwise use the - current directory. Only the regular files in the directory are sent, - and we don't recurse to subdirectories. - -`from' is the email address of the sender of the message. - -`to' is the email address of the recipient of the message, and multiple -recipients may be given. - -The email is sent by forwarding to your local SMTP server, which then does the -normal delivery process. Your local machine must be running an SMTP server. -""" - -import sys -import os -import getopt -import smtplib -# For guessing MIME type based on file name extension -import mimetypes - -from email import Encoders -from email.Message import Message -from email.MIMEAudio import MIMEAudio -from email.MIMEMultipart import MIMEMultipart -from email.MIMEImage import MIMEImage -from email.MIMEText import MIMEText - -COMMASPACE = ', ' - - -def usage(code, msg=''): - print >> sys.stderr, __doc__ - if msg: - print >> sys.stderr, msg - sys.exit(code) - - -def main(): - try: - opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) - except getopt.error, msg: - usage(1, msg) - - dir = os.curdir - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-d', '--directory'): - dir = arg - - if len(args) < 2: - usage(1) - - sender = args[0] - recips = args[1:] - - # Create the enclosing (outer) message - outer = MIMEMultipart() - outer['Subject'] = 'Contents of directory %s' % os.path.abspath(dir) - outer['To'] = COMMASPACE.join(recips) - outer['From'] = sender - outer.preamble = 'You will not see this in a MIME-aware mail reader.\n' - # To guarantee the message ends with a newline - outer.epilogue = '' - - for filename in os.listdir(dir): - path = os.path.join(dir, filename) - if not os.path.isfile(path): - continue - # Guess the content type based on the file's extension. Encoding - # will be ignored, although we should check for simple things like - # gzip'd or compressed files. - ctype, encoding = mimetypes.guess_type(path) - if ctype is None or encoding is not None: - # No guess could be made, or the file is encoded (compressed), so - # use a generic bag-of-bits type. - ctype = 'application/octet-stream' - maintype, subtype = ctype.split('/', 1) - if maintype == 'text': - fp = open(path) - # Note: we should handle calculating the charset - msg = MIMEText(fp.read(), _subtype=subtype) - fp.close() - elif maintype == 'image': - fp = open(path, 'rb') - msg = MIMEImage(fp.read(), _subtype=subtype) - fp.close() - elif maintype == 'audio': - fp = open(path, 'rb') - msg = MIMEAudio(fp.read(), _subtype=subtype) - fp.close() - else: - fp = open(path, 'rb') - msg = MIMEBase(maintype, subtype) - msg.set_payload(fp.read()) - fp.close() - # Encode the payload using Base64 - Encoders.encode_base64(msg) - # Set the filename parameter - msg.add_header('Content-Disposition', 'attachment', filename=filename) - outer.attach(msg) - - # Now send the message - s = smtplib.SMTP() - s.connect() - s.sendmail(sender, recips, outer.as_string()) - s.close() - - -if __name__ == '__main__': - main() -\end{verbatim} +\verbatiminput{email-dir.py} And finally, here's an example of how to unpack a MIME message like the one above, into a directory of files: -\begin{verbatim} -#!/usr/bin/env python - -"""Unpack a MIME message into a directory of files. - -Usage: unpackmail [options] msgfile - -Options: - -h / --help - Print this message and exit. - - -d directory - --directory=directory - Unpack the MIME message into the named directory, which will be - created if it doesn't already exist. - -msgfile is the path to the file containing the MIME message. -""" - -import sys -import os -import getopt -import errno -import mimetypes -import email - - -def usage(code, msg=''): - print >> sys.stderr, __doc__ - if msg: - print >> sys.stderr, msg - sys.exit(code) - - -def main(): - try: - opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) - except getopt.error, msg: - usage(1, msg) - - dir = os.curdir - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-d', '--directory'): - dir = arg - - try: - msgfile = args[0] - except IndexError: - usage(1) - - try: - os.mkdir(dir) - except OSError, e: - # Ignore directory exists error - if e.errno <> errno.EEXIST: raise - - fp = open(msgfile) - msg = email.message_from_file(fp) - fp.close() - - counter = 1 - for part in msg.walk(): - # multipart/* are just containers - if part.get_content_maintype() == 'multipart': - continue - # Applications should really sanitize the given filename so that an - # email message can't be used to overwrite important files - filename = part.get_filename() - if not filename: - ext = mimetypes.guess_extension(part.get_type()) - if not ext: - # Use a generic bag-of-bits extension - ext = '.bin' - filename = 'part-%03d%s' % (counter, ext) - counter += 1 - fp = open(os.path.join(dir, filename), 'wb') - fp.write(part.get_payload(decode=1)) - fp.close() - - -if __name__ == '__main__': - main() -\end{verbatim} +\verbatiminput{email-unpack.py} -- cgit v0.12