#!/usr/bin/python import os, argparse, hashlib, sqlite3, time, shutil, cgi, re, math from datetime import datetime parser = argparse.ArgumentParser(description='Renders static HTML pages and indexes from an SQLite database of emails and an attachment folder.') parser.add_argument('-o', dest='output_dir', action='store', default='rendered_files', help='path of the directory where rendered files should be stored') parser.add_argument('-t', dest='template_dir', action='store', default='templates', help='path where the template files are') parser.add_argument('-i', dest='title', action='store', default='Inbox', help='title for the rendered pages') parser.add_argument('-d', dest='database', action='store', default='emails.db', help='path of the database that should be used to render the e-mail files') parser.add_argument('-a', dest='attachment_dir', action='store', default='attachments', help='path where attachments are stored') parser.add_argument('-n', dest='per_page', action='store', default='20', help='amount of entries per page') parser.add_argument('-r', dest='original_path', action='store', default=None, help='path where original .eml files can be found') parser.add_argument('-x', dest='index', action='store', default='date_desc', help='the sorting state you wish to use as initial page') args = parser.parse_args() options = vars(args) if options['original_path'] is not None: originals_available = True else: originals_available = False def format_size(num): for unit in [' bytes','KB','MB','GB']: if num < 1024.0: return "%3.1f%s" % (num, unit) num /= 1024.0 return "%3.1f%s" % (num, 'TB') def chunk(iterable, chunksize, fillvalue=None): result = [] num_chunks = int(math.ceil(len(iterable) / (chunksize * 1.0))) for i in xrange(0, num_chunks): start = (chunksize * i) if (chunksize * (i + 1)) > len(iterable): end = len(iterable) else: end = (chunksize * (i + 1)) result.append((iterable[start:end])) return result def is_selected(i, page): if i == page: return "selected" else: return "" def render_index(email_list, title, identifier): email_list = chunk(email_list, int(options['per_page'])) current_page = 0 for list_chunk in email_list: if current_page == 0: prevpage = " " else: prevpage = '<< previous page' % (identifier, current_page - 1) if current_page == len(email_list) - 1: nextpage = "" else: nextpage = 'next page >>' % (identifier, current_page + 1) variables = { 'page': title, 'pagenum': "Page %d of %d" % (current_page + 1, len(email_list)), 'title': options['title'], 'index': "../index.html", 'items': "".join('
%s" % textbody, 'title': options['title'], 'version': "Plaintext version", 'index': "../index.html", 'versions': version_list, 'attachments': attachments } generated = template_message % variables open('%s/messages/%s_text.html' % (options['output_dir'], sha1_hash), 'w').write(generated.encode('UTF-8')) print "Successfully generated plaintext version of %s." % sha1_hash if available_html == True: # HTML version variables = { 'subject': subject, 'date': timestamp, 'from': sender, 'to': recipient, 'body': htmlbody, 'title': options['title'], 'version': "HTML version", 'index': "../index.html", 'versions': version_list, 'attachments': attachments } generated = template_message % variables open('%s/messages/%s_html.html' % (options['output_dir'], sha1_hash), 'w').write(generated.encode('UTF-8')) print "Successfully generated HTML version of %s." % sha1_hash try: snippet = "%s..." % re.search("^(.{0,200})\\b", textbody, re.DOTALL).group(1) except AttributeError: snippet = "" if available_html == True: page_name = "%s_html.html" % sha1_hash elif available_text == True: page_name = "%s_text.html" % sha1_hash else: continue email_list.append((sha1_hash, available_text, available_html, sender, recipient, subject, timestamp, len(attachment_list), snippet, unixtime, page_name)) # Sort by timestamp, ascending sorted_list = sorted(email_list, key=lambda email: email[9]) render_index(sorted_list, "Sorted from old to new", "date_asc") # Sort by timestamp, descending sorted_list.reverse() render_index(sorted_list, "Sorted from new to old", "date_desc") # Sort by sender, ascending sorted_list = sorted(email_list, key=lambda email: email[3].lower()) render_index(sorted_list, "Sorted by sender, ascending", "from_asc") # Sort by sender, descending sorted_list.reverse() render_index(sorted_list, "Sorted by sender, descending", "from_desc") # Sort by recipient, ascending sorted_list = sorted(email_list, key=lambda email: email[4].lower()) render_index(sorted_list, "Sorted by recipient, ascending", "to_asc") # Sort by recipient, descending sorted_list.reverse() render_index(sorted_list, "Sorted by recipient, descending", "to_desc") # Sort by hash, ascending sorted_list = sorted(email_list, key=lambda email: email[0].lower()) render_index(sorted_list, "Sorted by SHA1 hash, ascending", "hash_asc") # Sort by hash, descending sorted_list.reverse() render_index(sorted_list, "Sorted by SHA1 hash, descending", "hash_desc") # Sort by subject, ascending sorted_list = sorted(email_list, key=lambda email: email[5].lower()) render_index(sorted_list, "Sorted by subject, ascending", "subject_asc") # Sort by subject, descending sorted_list.reverse() render_index(sorted_list, "Sorted by subject, descending", "subject_desc") shutil.copy('%s/style.css' % options['template_dir'], '%s/style.css' % options['output_dir']) shutil.copy('%s/up.png' % options['template_dir'], '%s/up.png' % options['output_dir']) shutil.copy('%s/down.png' % options['template_dir'], '%s/down.png' % options['output_dir']) shutil.copy('%s/index_%s_0.html' % (options['output_dir'], options['index']), '%s/index.html' % options['output_dir']) if originals_available == True: # Copy all original email messages into a subfolder of the output directory try: shutil.copytree(options['original_path'], '%s/original' % options['output_dir']) print "Original e-mail files copied." except OSError: print "ERROR: Could not copy original e-mail files. Ensure the original/ directory does NOT exist in your output directory yet." try: shutil.copytree(options['attachment_dir'], '%s/attachments' % options['output_dir']) print "Attachments copied." except OSError: print "ERROR: Could not copy attachments. Ensure the attachments/ directory does NOT exist in your output directory yet."