Fred Drake | fcc31b4 | 2002-10-01 14:17:10 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | """Send the contents of a directory as a MIME message. |
| 4 | |
| 5 | Usage: dirmail [options] from to [to ...]* |
| 6 | |
| 7 | Options: |
| 8 | -h / --help |
| 9 | Print this message and exit. |
| 10 | |
| 11 | -d directory |
| 12 | --directory=directory |
| 13 | Mail the contents of the specified directory, otherwise use the |
| 14 | current directory. Only the regular files in the directory are sent, |
| 15 | and we don't recurse to subdirectories. |
| 16 | |
| 17 | `from' is the email address of the sender of the message. |
| 18 | |
| 19 | `to' is the email address of the recipient of the message, and multiple |
| 20 | recipients may be given. |
| 21 | |
| 22 | The email is sent by forwarding to your local SMTP server, which then does the |
| 23 | normal delivery process. Your local machine must be running an SMTP server. |
| 24 | """ |
| 25 | |
| 26 | import sys |
| 27 | import os |
| 28 | import getopt |
| 29 | import smtplib |
| 30 | # For guessing MIME type based on file name extension |
| 31 | import mimetypes |
| 32 | |
| 33 | from email import Encoders |
| 34 | from email.Message import Message |
| 35 | from email.MIMEAudio import MIMEAudio |
Barry Warsaw | 65367ca | 2003-11-21 20:28:15 +0000 | [diff] [blame] | 36 | from email.MIMEBase import MIMEBase |
Fred Drake | fcc31b4 | 2002-10-01 14:17:10 +0000 | [diff] [blame] | 37 | from email.MIMEMultipart import MIMEMultipart |
| 38 | from email.MIMEImage import MIMEImage |
| 39 | from email.MIMEText import MIMEText |
| 40 | |
| 41 | COMMASPACE = ', ' |
| 42 | |
| 43 | |
| 44 | def usage(code, msg=''): |
| 45 | print >> sys.stderr, __doc__ |
| 46 | if msg: |
| 47 | print >> sys.stderr, msg |
| 48 | sys.exit(code) |
| 49 | |
| 50 | |
| 51 | def main(): |
| 52 | try: |
| 53 | opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) |
| 54 | except getopt.error, msg: |
| 55 | usage(1, msg) |
| 56 | |
| 57 | dir = os.curdir |
| 58 | for opt, arg in opts: |
| 59 | if opt in ('-h', '--help'): |
| 60 | usage(0) |
| 61 | elif opt in ('-d', '--directory'): |
| 62 | dir = arg |
| 63 | |
| 64 | if len(args) < 2: |
| 65 | usage(1) |
| 66 | |
| 67 | sender = args[0] |
| 68 | recips = args[1:] |
| 69 | |
| 70 | # Create the enclosing (outer) message |
| 71 | outer = MIMEMultipart() |
| 72 | outer['Subject'] = 'Contents of directory %s' % os.path.abspath(dir) |
| 73 | outer['To'] = COMMASPACE.join(recips) |
| 74 | outer['From'] = sender |
| 75 | outer.preamble = 'You will not see this in a MIME-aware mail reader.\n' |
| 76 | # To guarantee the message ends with a newline |
| 77 | outer.epilogue = '' |
| 78 | |
| 79 | for filename in os.listdir(dir): |
| 80 | path = os.path.join(dir, filename) |
| 81 | if not os.path.isfile(path): |
| 82 | continue |
| 83 | # Guess the content type based on the file's extension. Encoding |
| 84 | # will be ignored, although we should check for simple things like |
| 85 | # gzip'd or compressed files. |
| 86 | ctype, encoding = mimetypes.guess_type(path) |
| 87 | if ctype is None or encoding is not None: |
| 88 | # No guess could be made, or the file is encoded (compressed), so |
| 89 | # use a generic bag-of-bits type. |
| 90 | ctype = 'application/octet-stream' |
| 91 | maintype, subtype = ctype.split('/', 1) |
| 92 | if maintype == 'text': |
| 93 | fp = open(path) |
| 94 | # Note: we should handle calculating the charset |
| 95 | msg = MIMEText(fp.read(), _subtype=subtype) |
| 96 | fp.close() |
| 97 | elif maintype == 'image': |
| 98 | fp = open(path, 'rb') |
| 99 | msg = MIMEImage(fp.read(), _subtype=subtype) |
| 100 | fp.close() |
| 101 | elif maintype == 'audio': |
| 102 | fp = open(path, 'rb') |
| 103 | msg = MIMEAudio(fp.read(), _subtype=subtype) |
| 104 | fp.close() |
| 105 | else: |
| 106 | fp = open(path, 'rb') |
| 107 | msg = MIMEBase(maintype, subtype) |
| 108 | msg.set_payload(fp.read()) |
| 109 | fp.close() |
| 110 | # Encode the payload using Base64 |
| 111 | Encoders.encode_base64(msg) |
| 112 | # Set the filename parameter |
| 113 | msg.add_header('Content-Disposition', 'attachment', filename=filename) |
| 114 | outer.attach(msg) |
| 115 | |
| 116 | # Now send the message |
| 117 | s = smtplib.SMTP() |
| 118 | s.connect() |
| 119 | s.sendmail(sender, recips, outer.as_string()) |
| 120 | s.close() |
| 121 | |
| 122 | |
| 123 | if __name__ == '__main__': |
| 124 | main() |