Last active
December 14, 2015 09:19
-
-
Save bootandy/5064264 to your computer and use it in GitHub Desktop.
python - logs into email and prints your oyster card costs per month by looking for the 'Oyster card topped up' messages in your TFL_MAILBOX email folder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import imaplib | |
import email | |
from pprint import pprint | |
import re | |
import collections | |
from email.Iterators import typed_subpart_iterator | |
""" Assumes you have TFL email you each time your oyster auto top up occurs """ | |
USERNAME = "" # Gmail user | |
PASSWORD = "" # Gmail pass | |
TFL_MAILBOX = "good mailshots/trains/tfl" # Gmail label where your TFL emails go to | |
def get_charset(message, default="ascii"): | |
"""Get the message charset""" | |
if message.get_content_charset(): | |
return message.get_content_charset() | |
if message.get_charset(): | |
return message.get_charset() | |
return default | |
def get_body(message): | |
"""Get the body of the email message""" | |
if message.is_multipart(): | |
#get the plain text version only | |
text_parts = [part | |
for part in typed_subpart_iterator(message, | |
'text', | |
'plain')] | |
body = [] | |
for part in text_parts: | |
charset = get_charset(part, get_charset(message)) | |
body.append(unicode(part.get_payload(decode=True), | |
charset, | |
"replace")) | |
return u"\n".join(body).strip() | |
else: # if it is not multipart, the payload will be a string | |
# representing the message body | |
body = unicode(message.get_payload(decode=True), | |
get_charset(message), | |
"replace") | |
return body.strip() | |
money_pattern = re.compile("was topped up with .?(\d+)") | |
money_pattern_html = re.compile("was topped up with £(\d+)") | |
def extract_money(payload): | |
return int(money_pattern.search(payload).group(1)) | |
conn = imaplib.IMAP4_SSL("imap.gmail.com", 993) | |
conn.login(USERNAME, PASSWORD) | |
conn.select() | |
try: | |
conn.select(TFL_MAILBOX) | |
typ, msg_ids = conn.search(None, '(SUBJECT "Your Oyster card has been topped up")') | |
result = [] | |
for num in msg_ids[0].split(): | |
typ, msg_data = conn.fetch(num, '(RFC822)') | |
for response_part in msg_data: | |
if isinstance(response_part, tuple): | |
msg = email.message_from_string(response_part[1]) | |
body = get_body(msg) | |
try: | |
result.append( (msg.get('date'), extract_money(body)) ) | |
except Exception, e: | |
print e | |
print body | |
print 'bad one on day: ' + msg.get('date') | |
r_map = collections.OrderedDict() | |
for r in result: | |
index = r[0].split()[3] + r[0].split()[2] | |
r_map.setdefault(index, 0) | |
r_map[index] += r[1] | |
for r,v in r_map.items(): | |
print r + ':' + str(v) | |
finally: | |
try: | |
conn.close() | |
except: | |
pass | |
conn.logout() | |
# list_response_pattern = re.compile(r'\((?P<flags>.*?)\) "(?P<delimiter>.*)" (?P<name>.*)') | |
# def parse_list_response(line): | |
# flags, delimiter, mailbox_name = list_response_pattern.match(line).groups() | |
# mailbox_name = mailbox_name.strip('"') | |
# return (flags, delimiter, mailbox_name) | |
# def view_mailboxes(conn): | |
# typ, data = conn.list() | |
# for line in data: | |
# flags, delimiter, mailbox_name = parse_list_response(line) | |
# print conn.status(mailbox_name, '(MESSAGES RECENT UIDNEXT UIDVALIDITY UNSEEN)') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment