1 #!/usr/bin/env python 2 3 """ 4 Show a MIME-encoded e-mail message as plain text. 5 6 Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 from email import message_from_string 23 from email.generator import Generator 24 from os.path import split 25 import sys 26 27 try: 28 from cStringIO import StringIO 29 except ImportError: 30 from StringIO import StringIO 31 32 def until_from(f, skip=0): 33 number = 0 34 while number <= skip: 35 l = [] 36 s = f.readline() 37 while s: 38 l.append(s) 39 s = f.readline() 40 if s.startswith("From "): 41 number += 1 42 break 43 else: 44 number += 1 45 break 46 if number > skip: 47 return "".join(l) 48 else: 49 return "" 50 51 def as_string(message): 52 53 """ 54 Return the string representation of 'message', attempting to preserve the 55 precise original formatting. 56 """ 57 58 out = StringIO() 59 generator = Generator(out, False, 0) # disable reformatting measures 60 generator.flatten(message) 61 return out.getvalue() 62 63 def decode(part): 64 65 """ 66 Change the transfer encoding on 'part' and its subparts so that a plain text 67 representation may be displayed. 68 """ 69 70 payload = part.get_payload(decode=True) 71 if payload: 72 encoding = part.get("Content-Transfer-Encoding") 73 if encoding: 74 del part["Content-Transfer-Encoding"] 75 part["Content-Transfer-Encoding"] = "8bit" 76 part.set_payload(payload) 77 else: 78 for p in part.get_payload(): 79 decode(p) 80 81 # Main program. 82 83 if __name__ == "__main__": 84 if len(sys.argv) > 1 and sys.argv[1] == "--help": 85 print >>sys.stderr, """\ 86 Usage: %s [ <messages to skip> ] 87 88 Read MIME-encoded e-mail messages from standard input, writing the decoded 89 messages to standard output. 90 91 Where <messages to skip> is given, the indicated number of messages will be 92 skipped in the input, with the first subsequent message being written out. 93 """ % split(sys.argv[0])[1] 94 sys.exit(1) 95 96 skip = int((sys.argv[1:] or [0])[0]) 97 message = message_from_string(until_from(sys.stdin, skip)) 98 decode(message) 99 print as_string(message) 100 101 # vim: tabstop=4 expandtab shiftwidth=4