Local time for mutt email display

I use mutt as my email client. Something that has recently been bugging me is that when reading a message it displays the original Date: header with the sender's timezone. Since I work with people in several different zones I am constantly having to do timezone math when looking at these. So I decided to fix that with a bit of python.

One of mutt's features is that you can feed every email you view through a filter by using the display_filter setting. So I created a small python app using the email module to parse the message, grab the original date and add a new header named X-Date: that has my local time in it. It looks like this:

#!/usr/bin/env python
"""
    Copyright 2011 by Brian C. Lane
"""
import sys
import email

raw_msg = sys.stdin.read()
msg = email.message_from_string(raw_msg)
date = msg.get('Date', None)
if date:
    from email.utils import mktime_tz, parsedate_tz, formatdate

    try:
        # Convert to local TZ
        tz_tuple = parsedate_tz(date)
        epoch_time = mktime_tz(tz_tuple)
        msg.add_header('X-Date', formatdate( epoch_time, localtime=True ))

        from cStringIO import StringIO
        from email.generator import Generator
        fp = StringIO()
        g = Generator(fp, mangle_from_=False, maxheaderlen=200)
        g.flatten(msg)
        sys.stdout.write(fp.getvalue())
    except:
        import traceback
        print traceback.format_exc()
        sys.stdout.write(raw_msg)
else:
    # just write it out
    sys.stdout.write(raw_msg)

Add this to your muttrc file to use it: set display_filter="$HOME/.mutt/local-date.py"

Messages are passed to the filter on stdin and read from stdout so I read in the whole message first, parse it for the Date and if it doesn't exist just output the raw message on stdout and exit. If Date is there I use a couple of methods from the email module to convert the original time to UTC and then add the new header using the local timezone. I then write the parsed message to stdout and exit. If there are any errors I output the traceback and then the original message.

Note that the message on disk is never changed. Processing happens in memory as you are reading them so the original is safe from accidents.