| #! /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() |