| #! /usr/bin/env python3 | 
 |  | 
 | # Convert  MH directories (1 message per file) or MMDF mailboxes (4x^A | 
 | # delimited) to unix mailbox (From ... delimited) on stdout. | 
 | # If -f is given, files contain one message per file (e.g. MH messages) | 
 |  | 
 | import rfc822 | 
 | import sys | 
 | import time | 
 | import os | 
 | import stat | 
 | import getopt | 
 | import re | 
 |  | 
 | def main(): | 
 |     dofile = mmdf | 
 |     try: | 
 |         opts, args = getopt.getopt(sys.argv[1:], 'f') | 
 |     except getopt.error as msg: | 
 |         sys.stderr.write('%s\n' % msg) | 
 |         sys.exit(2) | 
 |     for o, a in opts: | 
 |         if o == '-f': | 
 |             dofile = message | 
 |     if not args: | 
 |         args = ['-'] | 
 |     sts = 0 | 
 |     for arg in args: | 
 |         if arg == '-' or arg == '': | 
 |             sts = dofile(sys.stdin) or sts | 
 |         elif os.path.isdir(arg): | 
 |             sts = mh(arg) or sts | 
 |         elif os.path.isfile(arg): | 
 |             try: | 
 |                 f = open(arg) | 
 |             except IOError as msg: | 
 |                 sys.stderr.write('%s: %s\n' % (arg, msg)) | 
 |                 sts = 1 | 
 |                 continue | 
 |             sts = dofile(f) or sts | 
 |             f.close() | 
 |         else: | 
 |             sys.stderr.write('%s: not found\n' % arg) | 
 |             sts = 1 | 
 |     if sts: | 
 |         sys.exit(sts) | 
 |  | 
 | numeric = re.compile('[1-9][0-9]*') | 
 |  | 
 | def mh(dir): | 
 |     sts = 0 | 
 |     msgs = os.listdir(dir) | 
 |     for msg in msgs: | 
 |         if numeric.match(msg) != len(msg): | 
 |             continue | 
 |         fn = os.path.join(dir, msg) | 
 |         try: | 
 |             f = open(fn) | 
 |         except IOError as msg: | 
 |             sys.stderr.write('%s: %s\n' % (fn, msg)) | 
 |             sts = 1 | 
 |             continue | 
 |         sts = message(f) or sts | 
 |     return sts | 
 |  | 
 | def mmdf(f): | 
 |     sts = 0 | 
 |     while 1: | 
 |         line = f.readline() | 
 |         if not line: | 
 |             break | 
 |         if line == '\1\1\1\1\n': | 
 |             sts = message(f, line) or sts | 
 |         else: | 
 |             sys.stderr.write( | 
 |                     'Bad line in MMFD mailbox: %r\n' % (line,)) | 
 |     return sts | 
 |  | 
 | counter = 0 # for generating unique Message-ID headers | 
 |  | 
 | def message(f, delimiter = ''): | 
 |     sts = 0 | 
 |     # Parse RFC822 header | 
 |     m = rfc822.Message(f) | 
 |     # Write unix header line | 
 |     fullname, email = m.getaddr('From') | 
 |     tt = m.getdate('Date') | 
 |     if tt: | 
 |         t = time.mktime(tt) | 
 |     else: | 
 |         sys.stderr.write( | 
 |                 'Unparseable date: %r\n' % (m.get('Date'),)) | 
 |         t = os.fstat(f.fileno())[stat.ST_MTIME] | 
 |     print('From', email, time.ctime(t)) | 
 |     # Copy RFC822 header | 
 |     for line in m.headers: | 
 |         print(line, end=' ') | 
 |     # Invent Message-ID header if none is present | 
 |     if 'message-id' not in m: | 
 |         global counter | 
 |         counter = counter + 1 | 
 |         msgid = "<%s.%d>" % (hex(t), counter) | 
 |         sys.stderr.write("Adding Message-ID %s (From %s)\n" % | 
 |                          (msgid, email)) | 
 |         print("Message-ID:", msgid) | 
 |     print() | 
 |     # Copy body | 
 |     while 1: | 
 |         line = f.readline() | 
 |         if line == delimiter: | 
 |             break | 
 |         if not line: | 
 |             sys.stderr.write('Unexpected EOF in message\n') | 
 |             sts = 1 | 
 |             break | 
 |         if line[:5] == 'From ': | 
 |             line = '>' + line | 
 |         print(line, end=' ') | 
 |     # Print trailing newline | 
 |     print() | 
 |     return sts | 
 |  | 
 | if __name__ == "__main__": | 
 |     main() |