#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2019 Daniel Kahn Gillmor # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or (at # your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ''' This script reads a MIME message from stdin and produces a treelike representation on it stdout. Example: 0 dkg@alice:~$ printmimestructure < 'Maildir/cur/1269025522.M338697P12023.monkey,S=6459,W=6963:2,Sa' └┬╴multipart/signed 6546 bytes ├─╴text/plain inline 895 bytes └─╴application/pgp-signature inline [signature.asc] 836 bytes 0 dkg@alice:~$ If you want to number the parts, i suggest piping the output through something like "cat -n" ''' import email import sys def print_part(z, prefix): fname = '' if z.get_filename() is None else ' [' + z.get_filename() + ']' cset = '' if z.get_charset() is None else ' (' + z.get_charset() + ')' disp = z.get_params(None, header='Content-Disposition') if (disp is None): disposition = '' else: disposition = '' for d in disp: if d[0] in [ 'attachment', 'inline' ]: disposition = ' ' + d[0] if z.is_multipart(): nbytes = len(z.as_string()) else: nbytes = len(z.get_payload()) print('{}{}{}{}{} {:d} bytes'.format( prefix, z.get_content_type(), cset, disposition, fname, nbytes, )) def test(z, prefix=''): if (z.is_multipart()): print_part(z, prefix+'┬╴') if prefix.endswith('└'): prefix = prefix.rpartition('└')[0] + ' ' if prefix.endswith('├'): prefix = prefix.rpartition('├')[0] + '│' parts = z.get_payload() i = 0 while (i < parts.__len__()-1): test(parts[i], prefix + '├') i += 1 test(parts[i], prefix + '└') # FIXME: show epilogue? else: print_part(z, prefix+'─╴') test(email.message_from_file(sys.stdin), '└')