How to Solve the Email Debocle Step-by-Step

Posted by Prolific Programmer Mon, 09 Jun 2008 15:29:00 GMT

Below is a start at instructing users how to email. You'll need javamail and a supported JRE. Remember to change the username and set the password. I'll be refining this further in the coming days.

import java.util.*;
import javax.mail.internet.*;
import javax.mail.*;

public class MailTest {
    Message first;
    public MailTest() {
        Session session; Store store = null; Folder folder;
        try {
        Properties props = new Properties();
        props.put("mail.pop3.host", "pop.gmail.com");
        props.put("mail.pop3.user", "hasan.diwan@gmail.com");
        props.put("mail.pop3.port", "995");
        props.put("mail.pop3.starttls.enable", "true");
        props.put("mail.pop3.auth", "true");
        props.put("mail.pop3.socketFactory.port", "995");
        props.put("mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        session = Session.getDefaultInstance(props);
        System.err.println("session initialized!");
        store = session.getStore("pop3s");
        System.err.println("store initialized!");
        store.connect("pop.gmail.com", "hasan.diwan@gmail.com", System.getProperty("password")); //
        System.err.println("Connected!");
        folder = store.getFolder("INBOX");
        folder.open(Folder.READ_ONLY);
        System.err.println("inbox opened!");
        first = folder.getMessage(1);
        System.err.println("Message retrieved!");
        if (first.getRecipients(Message.RecipientType.TO).length != 1) {
            System.err.println("God damn! More than one recipient on the to line!"); 
        }
        } catch (Exception e) { System.err.println("EXCEPTION: "+e.getMessage()); }
        finally { 
        try { store.close(); } catch (Exception e) { }
        }
    }

    public static void main (String[] args) throws Exception {
        MailTest m = new MailTest();
    }
}

              

How to Search GMail from the Comfort of Your Command-Line

Posted by Prolific Programmer Fri, 04 Apr 2008 14:16:00 GMT

The command-line gmail search is working. Next step: see how to speed it up. It's still taking almost a minute to search 317 messages. Code pasted after the flip, as with the last message.

package com.prolificprogrammer.lucenegmail;
import java.io.File;
import java.util.logging.Logger;
import java.util.logging.Level;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;

public class SearchGMail {
    private static Logger logger = Logger.getLogger(new SearchGMail().getClass().getCanonicalName());
    public static void main (String[] args) throws Exception {
	//logger.setLevel(java.util.logging.Level.FINE);
	try {
	    File path = new File(System.getProperty("java.io.tmpdir")+File.separator+"gmail.index");
	    path.mkdir();
	    path.deleteOnExit();
	    long starttime = System.currentTimeMillis();
	    IndexWriter index = new IndexWriter(path.getAbsolutePath(), new StandardAnalyzer(), true);
	    Session session = Session.getDefaultInstance(System.getProperties(), null);
	    Store store = session.getStore("pop3s");
	    store.connect("pop.gmail.com", args[0], args[1]);
	    logger.fine("Connected!");
	    Folder folder = store.getDefaultFolder();
	    folder = folder.getFolder("INBOX");
	    folder.open(Folder.READ_ONLY);
	    logger.fine("Opened INBOX");
	    Message[] messages = folder.getMessages();
	    int x;
	    for (x = 0; x != messages.length; x++) {
		try {
		    Document document = new Document();
		    String allField = ((InternetAddress)messages[x].getFrom()[0]).getAddress()+"\n"+messages[x].getSubject();
		    document.add(new Field("all", allField, Field.Store.YES, Field.Index.TOKENIZED));
		    Field messageNumberField = new Field("messageNumber", new Integer(x).toString(), Field.Store.YES, Field.Index.NO);
		    messageNumberField.setBoost((float)0.0);
		    document.add(messageNumberField);
		    index.addDocument(document);
		    logger.fine("Message "+x+" added.");
		} catch (OutOfMemoryError e) {
		    index.optimize();
		    continue;
		}
	    }
	    index.optimize();
	    index.close();
	    
	    logger.info("Index Constructed -- now searching");
	    
	    IndexSearcher searcher = new IndexSearcher(path.getAbsolutePath());
	    Analyzer analyzer = new StandardAnalyzer();
	    String query = args[2];
	    QueryParser queryParser = new QueryParser("all", analyzer);
	    Query parsedQuery = queryParser.parse(query);
	    Hits hits = searcher.search(parsedQuery);
	    for (int i = 0; i!= hits.length();i++) {
		Document doc = hits.doc(i);
		System.out.println("Message "+doc.getField("messageNumber").stringValue()+" matches "+query+" with a score of "+hits.score(i));
	    }
	    searcher.close();
	    long endtime = System.currentTimeMillis();
	    logger.severe("program took "+new Long(endtime-starttime).toString()+" miliseconds to search "+new Integer(x).toString()+" messages, which occupy "+new Long(path.length()).toString()+" bytes.");
	    java.awt.Toolkit.getDefaultToolkit().beep();
	} catch (ArrayIndexOutOfBoundsException e) {
	    logger.severe("Usage: "+new SearchGMail().getClass().getName()+" [google login] [password] [query]\nAll required");
	    System.exit(-1);
	}
    }
}

How to Search Gmail from the comfort of your Keyboard 2

Posted by Prolific Programmer Fri, 04 Apr 2008 02:41:00 GMT

The Java code below leverages Lucene 2.3.1 and javamail to create a command-line search of your GMail inbox. It's actually quite slow, so I'd like to speed it up over time, but it does give updates as it runs, perhaps too many. Any (and all) suggestions appreciated?

package com.prolificprogrammer.lucenegmail;
import java.io.File;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;

public class SearchGMail {
    public static void main (String[] args) throws Exception {
	File path = new File(System.getProperty("java.io.tmpdir")+File.separator+"gmail.index");
	path.mkdir();
	path.deleteOnExit();
	long starttime = System.currentTimeMillis();
	IndexWriter index = new IndexWriter(path.getAbsolutePath(), new StandardAnalyzer(), true);
	Session session = Session.getDefaultInstance(System.getProperties(), null);
	Store store = session.getStore("imaps");
	store.connect("imap.gmail.com", args[0], args[1]);
	System.err.println("Connected!");
	Folder folder = store.getDefaultFolder();
	folder = folder.getFolder("INBOX");
	folder.open(Folder.READ_ONLY);
	System.err.println("Opened INBOX");
	Message[] messages = folder.getMessages();
	System.err.println("Messages retrieved!");
	int x;
	for (x = 0; x != messages.length; x++) {
	    Document document = new Document();
	    String allField = ((InternetAddress)messages[x].getFrom()[0]).getAddress()+"\n"+messages[x].getSubject();
	    document.add(new Field("all", allField, Field.Store.YES, Field.Index.TOKENIZED));
	    document.add(new Field("messageNumber", new Integer(x).toString(), Field.Store.YES, Field.Index.NO));
	    index.addDocument(document);
	    System.err.println("Message "+x+" added.");
	}
	index.optimize();
	index.close();

	System.err.println("Ok, index constructed with "+x+" messages in "+path.getAbsolutePath()+", now searching it");

	IndexSearcher searcher = new IndexSearcher(path.getAbsolutePath());
	Analyzer analyzer = new StandardAnalyzer();
	String query = args[3];
	QueryParser queryParser = new QueryParser("all", analyzer);
	Query parsedQuery = queryParser.parse(query);
	Hits hits = searcher.search(parsedQuery);
	for (int i = 0; i!= hits.length();i++) {
	    Document doc = hits.doc(i);
	    System.out.println(doc.getField("messageNumber"));
	}
	searcher.close();
	long endtime = System.currentTimeMillis();
	System.err.println("program took "+endtime-starttime+" miliseconds to search "+x+" messages, which occupy "+path.length()+" bytes.");
	java.awt.Toolkit.getDefaultToolkit().beep();
    }
}

How to Search Your Gmail in One Command

Posted by Prolific Programmer Wed, 19 Mar 2008 04:22:00 GMT

So, tonight, aside from reminiscing about old flames, Tareeq and I got to implementing a command line search for Gmail. Leveraging Javamail, lucene and maintaining no notion of state whatever. It allows you to type ./search.sh from:Tareeq subject:Tunis and returns the subject lines of messages that match the query, sorted by score. This is my first maven-managed project and so far, I'm liking it much better than ant. I haven't timed a run yet, maybe at the weekend?

How to Encrypt Email using Java

Posted by Prolific Programmer Tue, 01 Jan 2008 19:43:00 GMT

A few months ago, I received a message from Zafar, a friend of mine, who was serving with her majesty's forces in Basra. 3,000 of his pictures were being solicited by the Defence Ministry as evidence. To keep with some directive, they had to be encrypted using OpenPGP. I decided to try to complete it at a Super Happy Dev House and couldn't, so I just wrote a bunch of batch files and the task was completed. A few years on, I finally realised how easy this is.

Using JavaMail, construct a message full of parts, one additional one per file. Encrypt each file using commons-openpgp with the patch attached to that issue. Do the encryption using the code below:

import org.apache.commons.openpgp.OpenPGPEncryptor;
import org.apache.commons.openpgp.BouncyCastleOpenPgpEncryptor; // or another implementation of the above interface
// irrelevant code
OpenPgpEncryptor encryptor = (OpenPgpEncryptor)new BouncyCastleOpenPgpEncryptor(); 
// more irrelevant code
FileInputStream f = new FileInputStream(filename);
encryptor.encrypt(f, recipientsPublicKey, recipientUserId, filename);
Your code will now be stored in the filename with ".asc" appended. Now, construct a MimeBodyPart for the files as follows:
Iterator oneFile = files.iterator(); // Collection of filenames
while (oneFile.hasNext()) {
   String filename = oneFile.next();
   encrypt(filename, recipientEncKey, recipientUser);
   encryptedFile.add(filename+".asc");
}
Iterator encryptedFilesIterator = encryptedFile.iterator();
while (encryptedFilesIterator.hasNext()) {
    String filename = encryptedFilesIterator.next();
    MimeBodyPart part = new MimeBodyPart(new FileInputStream(filename));
    message.addBodyPart(part);
}
Now send the message:
public void send(String from, String[] bcc, String subject) {
   Properties mailProperties = new Properties();
   mailProperties.put("mail.smtp.host", "smtp.at.your.isp");
   Session session = Session.getDefaultInstance(mailProperties, null);
   MimeMessage message = new MimeMessage(session);
   message.setFrom(new InternetAddress(from));
   for (int i = 0; i != bcc.length;i++) {
      message.addRecipient(new InternetAddress(bcc[i]), Message.Recipient.BCC);
   }
   message.addRecipient(new InternetAddress("randomString@mailinator.com"), Message.Recipient.TO);
   message.setSubject(subject);
   // while loops above go here
   Transport.send(message);
}