#python2.7
from bz2 import BZ2File
import argparse
import csv
import datetime
import email
import email.utils
import imaplib
import logging
import parsedatetime
import os
import re
import time
import titlecase
LOGFILE=\'procmail.py.log\'
rows = []
def add_paypal(data_in):
spot_re = re.compile(\'Merchant:.*\\n(.*)\\n\')
amt_re = re.compile(\'Payment: =24([^ ]+)\')
date_re = re.compile(\'Date: (.*)\')
logging.fatal(\'Paypal found!\')
spot = spot_re.search(data_in)
amt = amt_re.search(data_in)
datematch = date_re.search(data_in)
date_ = email.utils.parsedate(datematch.group(1))
date = datetime.datetime(*date_[:6]).isoformat()
data = [spot.group(1).strip(), amt.group(1).strip(), date]
rows.append([data[0], data[1], data[2]])
def add_amazon(data_in):
logging.debug(\'Amazon found!\')
amt_re = re.compile(r\'Grand Total:[^$]+\\$([0-9.]+)\')
date_re = re.compile(\'Date: (.*) -0[87]00\')
spot = \'Amazon\'
amt = amt_re.search(data_in)
date = date_re.search(data_in)
date = datetime.datetime.strptime(date.group(1),\'%a, %d %b %Y %H:%M:%S\')
date = date.isoformat()
data = [spot, amt.group(1), date]
rows.append([data[0], data[1], data[2]])
def add_lyft(data_in):
logging.debug(\'Lyft found!\')
date = amt = None
date_reg = \'Date: (.*).{7}\'
date_re = re.compile(date_reg)
date_fmt = \'%d %B %Y %H:%M\'
amt_fmt = \'Total charged to[^$]+\\$+([0-9.]+)\'
amt_re = re.compile(amt_fmt)
if date_re.search(data_in):
logging.debug(\'date match!\')
date_match = date_re.findall(data_in)[2]
date_match = date_match[:date_match.rindex(\'<br>\')]
date_line = date_match
logging.debug(\'dateline found: {}\'.format(date_line))
try:
date = datetime.datetime.strptime(date_line, date_fmt).isoformat()
logging.debug(\'Date is {}\'.format(date))
except ValueError:
pass
if amt_re.search(data_in) is not None:
amt = amt_re.search(data_in).group(1)
logging.debug(\'Amount: {}\'.format(amt))
logging.debug(\'Date: {0}, Amount: {1}, Location: Lyft\'.format(date,amt))
if date is not None and amt is not None:
rows.append([\'Lyft\', amt, date])
# TODO add calendar events requests
"""
If on the event day, popup event
"""
def google_event_alert(data_in):
p = parsedatetime.Calendar()
try:
event_time_struct = p.parse(data_in)
except Exception, e:
return
logging.debug(event_time_struct)
event_epoch_time = time.mktime(event_time_struct[0])
event_time = datetime.datetime.fromtimestamp(event_epoch_time)
logging.debug(\'date is {}\'.format(event_time.date()))
if event_time.date() == datetime.datetime.now().date():
if event_time > datetime.datetime.now():
logging.debug(\'event is today, but in the future\')
def add_rcpt(contents):
msg = email.message_from_string(contents)
logging.debug(msg._headers)
for h in msg._headers:
if h[0] == \'Subject\':
if h[1].startswith(\'Rcpt: \'):
parts = h[1].split(\' \')
amount = parts[-1]
spot = h[1][6:h[1].rindex(amount)].strip()
if h[0] == \'Date\':
date = email.utils.parsedate(h[1])
logging.debug(\'Date: "{0}"; Location: "{1}"; Amount: "{2}"\'.format(date, spot, amount))
rows.append([titlecase.titlecase(spot), amount, datetime.datetime.fromtimestamp(time.mktime(date)).isoformat()])
def receipts(FILE):
with BZ2File(FILE,\'w\') as rcptOut:
writer = csv.writer(rcptOut, quoting=csv.QUOTE_ALL)
writer.writerow([\'Store\',\'Amount\',\'Timestamp\'])
writer.writerows(rows)
if __name__ == \'__main__\':
try:
os.unlink(LOGFILE)
except OSError:
pass
parser = argparse.ArgumentParser(description=\'Process mail\')
parser.add_argument(\'-u\', \'--username\', type=str, help=\'IMAP Username\', default=\'hd1@jsc.d8u.us\')
parser.add_argument(\'-p\', \'--password\', type=str, help=\'IMAP Password\')
parser.add_argument(\'-s\', \'--server\', type=str, help=\'IMAP server\', default=\'imap.gmail.com\')
parser.add_argument(\'--out\', type=str, help=\'Receipts logging file\', default=\'/home/hdiwan/rcpts.bz2\')
parser.add_argument(\'--ssl\', action=\'store_true\', help=\'SSL IMAP server?\', default=True)
args = parser.parse_args()
logging.basicConfig(level=logging.DEBUG, filemode=\'w\', filename=LOGFILE, format=\'"%(asctime)s","%(message)s"\')
logging.debug(\'{}\'.format(sorted(dir(args))))
logging.debug(\'Username: {0}; Password: {1}; Server: {2}\'.format(args.username, args.password, args.server))
if args.ssl:
mail = imaplib.IMAP4_SSL(\'{}\'.format(args.server))
logging.debug(\'ssl!\')
else:
mail = imaplib.IMAP4(\'{}\'.format(args.server))
logging.debug(\'no ssl!\')
mail.login(u\'{}\'.format(args.username),\'{}\'.format(args.password))
logging.debug(\'logged in!\')
mail.select(u\'inbox\', readonly=True)
logging.debug(\'inbox selected\')
result,data = mail.search(None, \'ALL\')
logging.debug(\'iterating through messages\')
for id_ in data[0].split(\' \'):
contents = mail.fetch(id_, \'(RFC822)\')[1][0][1]
if contents.find(\'Amazon.com\') != -1:
add_amazon(contents)
elif contents.find(\'@paypal.com\') != -1:
add_paypal(contents)
elif contents.find(\'<no-reply@lyftmail.com>\') != -1:
add_lyft(contents)
elif contents.find(\'Subject: Rcpt\') != -1:
add_rcpt(contents)
#elif contents.find(\'www.google.com/calendar/event\'):
# google_event_alert(contents)
receipts(args.out)
messages = len(data[0].split(\' \'))
print(\'Processed {0} messages\'.format(messages))