from datetime import datetime import os from pathlib import Path from apiclient.discovery import build from apiclient import errors from httplib2 import Http import oauth2client from oauth2client import client import json import base64 import binascii from send_email import get_gmail_service import argparse import logging def ListMessagesWithLabels(service, user_id, label_ids=[]): """List all Messages of the user's mailbox with label_ids applied. Args: service: Authorized Gmail API service instance. user_id: User's email address. The special value "me" can be used to indicate the authenticated user. label_ids: Only return Messages with these labelIds applied. Returns: List of Messages that have all required Labels applied. Note that the returned list contains Message IDs, you must use get with the appropriate id to get the details of a Message. """ try: response = service.users().messages().list(userId=user_id, labelIds=label_ids).execute() messages = [] if 'messages' in response: messages.extend(response['messages']) while 'nextPageToken' in response: page_token = response['nextPageToken'] response = service.users().messages().list(userId=user_id, labelIds=label_ids, pageToken=page_token).execute() messages.extend(response['messages']) return messages except errors.HttpError as error: print(json.loads(error.content.decode('utf-8'))['error']['message']) def labels_dict(service, user_id): """Returns a dictionary mapping labels to labelids. Args: service: Authorized Gmail API service instance. user_id: User's email address. The special value "me" Returns: dictionary mapping labels to labelids. """ try: response = service.users().labels().list(userId=user_id).execute() labels = response['labels'] return {label['name']: label['id'] for label in labels} except errors.HttpError as error: print(json.loads(error.content.decode('utf-8'))['error']['message']) def get_msg(service, user_id, msg_id): try: message = service.users().messages().get(userId=user_id, id=msg_id, format='full').execute() return message except errors.HttpError as error: print(json.loads(error.content.decode('utf-8'))['error']['message']) def msg_content(msg): """Extract subject and body from a gmail message""" subject = [x['value'] for x in msg['payload']['headers'] if x['name']=='Subject'][0] payload = msg['payload'] if payload['mimeType'] == 'text/plain': body = payload['body'] elif payload['mimeType'] == 'multipart/alternative': parts = payload['parts'] body = parts[0]['body'] else: raise KeyError content = base64.urlsafe_b64decode(body['data']).decode('utf-8') date = msg['internalDate'] ## date /1000 to get timestamp return subject, content, date def update_emails(): """Download new emails that were labeled swaptions.""" service = get_gmail_service() labelsdict = labels_dict(service, 'me') p = Path(os.getenv("DATA_DIR")) / Path('swaptions') current_msgs = set([f.name for f in p.iterdir() if f.is_file()]) for msg in ListMessagesWithLabels(service, 'me', labelsdict['swaptions']): if msg['id'] not in current_msgs: try: subject, content, date = msg_content(get_msg(service, 'me', msg['id'])) except (binascii.Error, KeyError, UnicodeDecodeError) as e: logging.error("error decoding " + msg['id']) continue else: email = p / msg['id'] with email.open("w") as fh: fh.write(date + "\r\n") fh.write(subject + "\r\n") fh.write(content) if __name__ == '__main__': update_emails()