From ad7070d61e91b235db05dfc2bcfb0af0d379d3e5 Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 3 Sep 2004 00:55:35 +0000 Subject: [PATCH] preliminary GMail support darcs-hash:20040903005535-5007d-1e15174bdd354c04a3df28f0243d41c05b3e8632.gz --- src/org/ibex/mail/protocol/GMail.java | 279 ++++++++++++++++++++++++++++++--- 1 file changed, 255 insertions(+), 24 deletions(-) diff --git a/src/org/ibex/mail/protocol/GMail.java b/src/org/ibex/mail/protocol/GMail.java index 058f821..8b277f5 100644 --- a/src/org/ibex/mail/protocol/GMail.java +++ b/src/org/ibex/mail/protocol/GMail.java @@ -5,6 +5,8 @@ import org.ibex.jinetd.Listener; import org.ibex.jinetd.Worker; import org.ibex.mail.*; import org.ibex.util.*; +import org.ibex.net.*; +import org.ibex.js.*; import org.ibex.mail.target.*; import java.util.*; import java.net.*; @@ -12,33 +14,262 @@ import java.text.*; import java.io.*; public class GMail extends Account { - public Mailbox getMailbox(Class protocol) { return this.root; } - public GMail(String user, String pass) { - super(user, Address.parse(user + "@gmail.com")); - Log.warn(GMail.class, "logging in " + user + "@gmail.com..."); + + public static final String login = "https://www.google.com/accounts/ServiceLoginBoxAuth"; + public static final String gmail = "https://gmail.google.com/gmail"; + + private HTTP.Cookie.Jar jar = new HTTP.Cookie.Jar(); + private String captchaString = null; + private String ctoken = null; + private String email = null; + private String password = null; + + + // Constructor ////////////////////////////////////////////////////////////////////////////// + + private static Hash cache = new Hash(); + static { HTTP.userAgent = "Mozilla/5.0 (compatible;)"; } + public static GMail getGMail(String email, String pass) { try { - Process p = - Runtime.getRuntime().exec(new String[] { - "/usr/bin/python", - "/usr/local/libgmail/demos/archive.py", - user, - pass - }); - final Mailbox inbox = new MessageArrayMailbox(Mbox.parse(new Stream(p.getInputStream()))); - this.root = - new Mailbox.Default() { - public void add(Message m) { throw new RuntimeException("not supported"); } - public void add(Message m, int i) { throw new RuntimeException("not supported"); } - public int uidValidity() { return 1; } - public Mailbox.Iterator iterator() { return new Mailbox.Iterator.NullIterator(); } - public int uidNext() { return 500; } - public String[] children() { return new String[] { "gmail" }; } - public Mailbox slash(String name, boolean create) { return inbox; } - }; - p.waitFor(); - Log.warn(GMail.class, " succeeded for " + user + "@gmail.com!"); + GMail g = (GMail)cache.get(email, pass); + if (g == null) cache.put(email, pass, g = new GMail(email, pass)); + g.init(); + return g; } catch (Exception e) { Log.error(GMail.class, e); + return null; + } + } + + public GMail(String email, String pass) throws IOException { + super(email.substring(0, email.indexOf('@')), Address.parse(email)); + this.email = email; this.password = pass; + Log.warn(GMail.class, "logging in " + email); + } + + void init() throws IOException { + if (success) return; + Vector v = makeRequest(); + Message[] m = new Message[v.size()]; + v.copyInto(m); + final Mailbox inbox = new MessageArrayMailbox(m); + this.root = + new Mailbox.Default() { + public void add(Message m) { throw new RuntimeException("not supported"); } + public void add(Message m, int i) { throw new RuntimeException("not supported"); } + public Mailbox.Iterator iterator() { return new Mailbox.Iterator.NullIterator(); } + public int uidNext() { return 500; } + public String[] children() { + if (success) return new String[] { "INBOX" }; + return new String[] { "Captcha" }; + } + public Mailbox slash(String name, boolean create) { return inbox; } + }; + Log.warn(GMail.class, " succeeded for " + email); + } + + + // Implementation ////////////////////////////////////////////////////////////////////////////// + + public Vector makeRequest() throws IOException { + final Vector messages = new Vector(); + Log.warn(this, "captchaString = " + captchaString); + Log.warn(this, "ctoken = " + ctoken); + String crud = + "continue=" + URLEncoder.encode(gmail) + + "&service=mail" + + "&Email=" + URLEncoder.encode(user) + + "&Passwd=" + password + + "&null=Sign+in" + + (captchaString != null ? "&captcha="+URLEncoder.encode(captchaString) : "") + + (captchaString != null ? "&ctoken="+URLEncoder.encode(ctoken) : ""); + captchaString = null; + Log.warn("[request]", crud); + + String result = + captchaString == null ? + new String(InputStreamToByteArray.convert(new HTTP(login+"?"+crud).GET(null, jar))) + : + new String(InputStreamToByteArray.convert(new HTTP(login).POST("application/x-www-form-urlencoded", crud, null, jar))); + System.err.println(result); + + try { + if (result.indexOf("top.location") == -1) { + Log.warn(GMail.class,"no relocator found; checking for captcha"); + ctoken = result.substring(result.indexOf("id=\"ctoken\" value=\"") + "id=\"ctoken\" value=\"".length()); + ctoken = ctoken.substring(0, ctoken.indexOf("\"")); + + Log.warn(this, "captchaString = " + captchaString); + Log.warn(this, "ctoken = " + ctoken); + + String image = result.substring(result.indexOf("Captcha?")); + image = image.substring(0, image.indexOf("\"")); + Message m = new Message(new Stream( + "From: google@google.com\r\n" + + "To: you@yourself.com\r\n" + + "Subject: Captcha\r\n" + + "Date: Mon Aug 30 19:05:40 PDT 2004\r\n" + + "Content-Type: text/html\r\n" + + "\r\n" + + "\r\n" + + "Hi there. Google is lame; please type in the word you see below and " + + "click submit. You might have to click 'get mail' again after that.
" + + "\r\n" + + "
\r\n"+ + " \r\n"+ + " \r\n"+ + " \r\n"+ + " \r\n"+ + " \r\n"+ + "
\r\n"+ + "\r\n"), + null); + messages.addElement(m); + return messages; + } + } catch (Exception e) { + e.printStackTrace(); + return messages; + } + result = result.substring(result.indexOf("top.location")); + result = result.substring(result.indexOf("CheckCookie?continue=") + "CheckCookie?continue=".length()); + result = result.substring(0, result.indexOf('\"')); + result = URLDecoder.decode(result); + Log.warn("[]", "getting " + result); + + // just need the cookie off of this page + String s = new String(InputStreamToByteArray.convert(new HTTP(result).GET(null, jar))); + Log.warn("[]", s); + + final Semaphore sem = new Semaphore(); + try { + JSArray ret = grab(gmail + "?search=inbox&start=0&view=tl", jar); + for(int i=0; i') + 1); + name = name.substring(0, name.indexOf("")); + String subject = (String)m.get(6); + //Log.warn("[]", name + " <"+email+"> " + subject); + //Log.warn("[]", ); + } + } else if (j2.elementAt(0).equals("mi")) { + JSArray m = j2; + String date = m.get(9).toString(); + String to = m.get(8).toString(); + String toemail = m.get(10).toString(); + String from = m.get(4).toString(); + String name = m.get(6).toString(); + String email = m.get(7).toString(); + String subject = m.get(15).toString(); + Log.warn("[]", name + " <"+email+"> " + subject); + Stream thestream = new Stream(new HTTP(gmail+"?search=query&start=0&view=om&th=" + + URLEncoder.encode(threadid)).GET(null, jar)); + thestream.readln(); + messages.addElement(new Message(thestream, null)); + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + sem.release(); + } + } }.start(); + } + } + sem.release(); + Log.warn(GMail.class, "block"); + sem.block(); + Log.warn(GMail.class, "release"); + } catch (Exception e) { + e.printStackTrace(); + } + success = true; + for(int i=0; i") != -1) { inscript = true; continue; } + if (s.indexOf("") != -1) { inscript = false; continue; } + if (inscript) buf.append(s); + } + buf.append("return ret;"); + synchronized(GMail.class) { + JS js = JS.fromReader("google", 0, new StringReader(buf.toString())); + return (JSArray)js.call(null, null, null, null, 0); + } + } + + public Mailbox getMailbox(Class protocol) { return this.root; } + + + // HTTP Listener for Captcha requests ////////////////////////////////////////////////////////////////////////////// + + public static void handleRequest(Connection conn) { + String top = null; + for(String s = conn.readln(); s != null && s.length() > 0; s = conn.readln()) { + if (top == null) top = s; + Log.warn(GMail.class, s); + } + if (top.startsWith("GET /Captcha")) { + top = top.substring(top.indexOf('?')+1); + top = top.substring(0, top.indexOf(' ')); + StringTokenizer st = new StringTokenizer(top, "&"); + Hash h = new Hash(); + while(st.hasMoreTokens()) { + String tok = st.nextToken(); + h.put(URLDecoder.decode(tok.substring(0, tok.indexOf('='))), + URLDecoder.decode(tok.substring(tok.indexOf('=')+1))); + } + ((GMail)cache.get((String)h.get("email"), (String)h.get("pass"))).setCaptcha(h); + conn.println("HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n\r\n"); + } else { + conn.println("HTTP/1.0 500 Error\r\n\r\n"); + } + conn.flush(); + conn.close(); + } + + public void setCaptcha(Hash h) { + captchaString = (String)h.get("captcha"); + ctoken = (String)h.get("ctoken"); + Log.warn(GMail.class, "captchaString = " + captchaString); + Log.warn(GMail.class, "ctoken = " + ctoken); + Log.warn(GMail.class, "initting..." + ctoken); + try { + init(); + Log.warn(GMail.class, " done..." + ctoken); + } catch (Exception e) { + Log.error(this, e); } } } -- 1.7.10.4