| 1 | #!/usr/bin/env python |
| 2 | |
| 3 | """Unpack a MIME message into a directory of files. |
| 4 | |
| 5 | Usage: unpackmail [options] msgfile |
| 6 | |
| 7 | Options: |
| 8 | -h / --help |
| 9 | Print this message and exit. |
| 10 | |
| 11 | -d directory |
| 12 | --directory=directory |
| 13 | Unpack the MIME message into the named directory, which will be |
| 14 | created if it doesn't already exist. |
| 15 | |
| 16 | msgfile is the path to the file containing the MIME message. |
| 17 | """ |
| 18 | |
| 19 | import sys |
| 20 | import os |
| 21 | import getopt |
| 22 | import errno |
| 23 | import mimetypes |
| 24 | import email |
| 25 | |
| 26 | |
| 27 | def usage(code, msg=''): |
| 28 | print >> sys.stderr, __doc__ |
| 29 | if msg: |
| 30 | print >> sys.stderr, msg |
| 31 | sys.exit(code) |
| 32 | |
| 33 | |
| 34 | def main(): |
| 35 | try: |
| 36 | opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) |
| 37 | except getopt.error, msg: |
| 38 | usage(1, msg) |
| 39 | |
| 40 | dir = os.curdir |
| 41 | for opt, arg in opts: |
| 42 | if opt in ('-h', '--help'): |
| 43 | usage(0) |
| 44 | elif opt in ('-d', '--directory'): |
| 45 | dir = arg |
| 46 | |
| 47 | try: |
| 48 | msgfile = args[0] |
| 49 | except IndexError: |
| 50 | usage(1) |
| 51 | |
| 52 | try: |
| 53 | os.mkdir(dir) |
| 54 | except OSError, e: |
| 55 | # Ignore directory exists error |
| 56 | if e.errno <> errno.EEXIST: raise |
| 57 | |
| 58 | fp = open(msgfile) |
| 59 | msg = email.message_from_file(fp) |
| 60 | fp.close() |
| 61 | |
| 62 | counter = 1 |
| 63 | for part in msg.walk(): |
| 64 | # multipart/* are just containers |
| 65 | if part.get_content_maintype() == 'multipart': |
| 66 | continue |
| 67 | # Applications should really sanitize the given filename so that an |
| 68 | # email message can't be used to overwrite important files |
| 69 | filename = part.get_filename() |
| 70 | if not filename: |
| 71 | ext = mimetypes.guess_extension(part.get_type()) |
| 72 | if not ext: |
| 73 | # Use a generic bag-of-bits extension |
| 74 | ext = '.bin' |
| 75 | filename = 'part-%03d%s' % (counter, ext) |
| 76 | counter += 1 |
| 77 | fp = open(os.path.join(dir, filename), 'wb') |
| 78 | fp.write(part.get_payload(decode=1)) |
| 79 | fp.close() |
| 80 | |
| 81 | |
| 82 | if __name__ == '__main__': |
| 83 | main() |