import json
import requests
import ssl

from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager

class MintHTTPSAdapter(HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, **kwargs):
        self.poolmanager = PoolManager(num_pools=connections, maxsize=maxsize, ssl_version=ssl.PROTOCOL_SSLv3, **kwargs)

def get_accounts(email, password):
    # 1: Login.
    session = requests.Session()
    session.mount('https://', MintHTTPSAdapter())

    if session.get("https://wwws.mint.com/login.event?task=L").status_code != requests.codes.ok:
        raise Exception("Failed to load Mint login page")
    
    data = {"username": email, "password": password, "task": "L", "browser": "firefox", "browserVersion": "27", "os": "linux"}
    headers = {"accept": "application/json"}
    response = session.post("https://wwws.mint.com/loginUserSubmit.xevent", data=data, headers=headers).text
    if "token" not in response:
        raise Exception("Mint.com login failed[1]")

    response = json.loads(response)
    if not response["sUser"]["token"]:
        raise Exception("Mint.com login failed[2]")

    # 2: Grab token.
    token = response["sUser"]["token"]

    # 3. Issue service request.
    request_id = "42" # magic number? random number?
    data = {"input": json.dumps([
        {"args": {
            "types": [
                "BANK", 
                "CREDIT", 
                "INVESTMENT", 
                "LOAN", 
                "MORTGAGE", 
                "OTHER_PROPERTY", 
                "REAL_ESTATE", 
                "VEHICLE", 
                "UNCLASSIFIED"
            ]
        }, 
        "id": request_id, 
        "service": "MintAccountService", 
        #"task": "getAccountsSorted"
        "task": "getAccountsSortedByBalanceDescending"
        }
    ])}
    response = session.post("https://wwws.mint.com/bundledServiceController.xevent?legacy=false&token="+token, data=data, headers=headers).text
    if request_id not in response:
        raise Exception("Could not parse account data: " + response)
    response = json.loads(response)
    accounts = response["response"][request_id]["response"]
    return accounts

def main():
    import getpass
    import sys

    # Handle Python 3's raw_input change.
    try: input = raw_input
    except NameError: pass

    if len(sys.argv) >= 3:
        email, password = sys.argv[1:]
    else:
        email = input("Mint email: ")
        password = getpass.getpass("Password: ")

    accounts = get_accounts(email, password)
    print(json.dumps(accounts, indent=2))
    
if __name__ == "__main__":
    main()

@@ -33,16 +33,46 @@
 rt ssl%0A%0A
+from datetime import datetime%0A
 from req
@@ -168,16 +168,115 @@
 anager%0A%0A
+DATE_FIELDS = %5B%0A    'addAccountDate',%0A    'closeDate',%0A    'fiLastUpdated',%0A    'lastUpdated',%0A%5D%0A%0A%0A
 class Mi
@@ -2313,16 +2313,383 @@
 ponse%22%5D%0A
+%0A    # Return datetime objects for dates%0A    for account in accounts:%0A        for df in DATE_FIELDS:%0A            if df in account:%0A                # Convert from javascript timestamp to unix timestamp%0A                # http://stackoverflow.com/a/9744811/5026%0A                ts = account%5Bdf%5D / 1e3%0A                account%5Bdf + 'InDate'%5D = datetime.fromtimestamp(ts)%0A%0A
     retu

Return datetime objects for dates