On 05/31/2010 12:16 PM, M L wrote:
Specifically, I'm needing to login to a particular website,
and which username I use varies based on it being specified
in the email.

Are you in control of this email generation (that is, can you generate an email with an HTML form within, or is this email coming from a 3rd-party)?

Creating an HTML-email with a form to submit the username/password isn't a flawless solution because many folks (self included) configure their mail-reader to only display plain-text and ignore HTML components.

My real problem is how to get the username and password
passed to the browser.

If you can't create an HTML form in the source email, then it depends on what the web-server is expecting -- a GET (bad for users, good for you) or a POST (good web practice, but a pain for you). If the web login form is maldesigned and uses a GET submission, you can just parse the email body for the fields and generate a link of the form

  http://example.com/login?user=jsmith&pass=SeKrEt

However, if the website creates expects a POST to login (good design so credentials don't get saved in history, or get bookmarked accidentally), then you have to either

1) do some dark browser-specific hackery, perhaps with a bit of urllib magic to kludge the session into an active browser. Not a particularly inviting solution to implement.

2) generate a temporary HTML file with the prepopulated form in it, point the browser at that page and either (2a) have the user click on the [submit] button, and/or (2b) have a little JavaScript that clicks the [submit] button (or calls form.submit() more likely) after the temp-page is loaded. I'd do both in the event the user has JS turned off in their browser (again, that'd be me, thanks to NoScript). This temporary HTML file could be scraped (via urllib) from the login url itself, or hard-coded if you expect it to be of the same format for each website.

My crack at it looks something like
##########################
from sys import exit, stderr
from tempfile import NamedTemporaryFile
import email
import imaplib
import os
import re
import time
import urllib
import webbrowser

url_re = re.compile(r'\burl:\s*(http://.*)')
user_re = re.compile(r'\buser(?:name)?:\s*(.*)')
pass_re = re.compile(r'\bpass(?:word)?:\s*(.*)')

class MissingField(Exception): pass

IMAP = imaplib.IMAP4_SSL

def get_email(host, username, password):
  # ...
  for message in messages_I_care_about:
      yield message

def fields(msg):
  url_m = url_re.search(msg)
  if not url_m: raise MissingField("No URL")
  user_m = user_re.search(msg)
  if not user_m: raise MissingField("No username")
  pass_m = pass_re.search(msg)
  if not pass_m: raise MissingField("No password")
  return [m.group(1).strip() for m in (url_m, user_m, pass_m)]

def create_temp_html(url, username, password):
  f = NamedTemporaryFile(mode='w', suffix='.html')
  # HTML hard-coded here, but could be
  # scraped from the site, parsed with BeautifulSoup
  # searched for the form/uname/pwd values
  # and more programatically generated
  # but this is the lazy version you get for free ;-)
  f.write("""<html>
  <head>
  <title>Some Title</title>
  </head>
  <body onload="getElementById('f').submit();">
   Hang on...time to log in...
   <form id="f" method="POST" url="%s">
    <input type="text" value="%s" name="username"><br>
    <input type="password" value="%s" name="password"><br>
    <input type="submit" value="Log In">
   </form>
  </body>
  </html>
""" % (
    url,
    urllib.quote_plus(username),
    urllib.quote_plus(password),
    )
  )
  f.flush()
  return f

if __name__ == "__main__":
  HOST = 'mail.example.com'
  USER = 'email_usern...@example.com'
  PASS = 'SecretEmailPassword'
  EXPECTED_SENDER = 'someb...@example.net'

  for message in get_email(HOST, USER, PASS):
    msg = email.message_from_string(message)
    # if you don't want to limit the sender
    # delete/comment the next 3 lines
    if EXPECTED_SENDER not in msg['from'].lower():
      print "Unexpected sender...ignoring %r" % msg['subject']
      continue

    for part in msg.walk():
      # you may not want to skip HTML portions or other
      # MIME-types like attachments, but whatever
      if part.get_content_type() != 'text/plain': continue

      try:
        url, username, password = fields(msg.get_payload())
        print url, username, password
      except MissingField, e:
        print e
        continue
      f = create_temp_html(url, username, password)
      stderr.write(
        "Opening %r in %s\n" %
        (f.name, webbrowser.get().basename.title()))
      webbrowser.open(f.name)
      time.sleep(30) # wait for the browser to load the file
      # otherwise this .close() will delete it
      # before the web-browser could open it
      f.close()
##########################

Adjust regexps to find your URL/uname/pwd as desired, create the get_email() iterator that finds all the messages in your inbox that match your criteria (such as "not already seen, has XYZ in the subject, etc")

I'm not 100% sure of my JavaScript in the form.onload but you can also tweak that if your JS is enabled and you want to tinker with it for auto-login.

-tkc




--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to