• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3134
  • Last Modified:

How to read an email with Java

Hey,

       I'm trying to read email using Java; and I found a bit of sample code to get me started:

import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;

public class GMailReader extends javax.mail.Authenticator {
	private static final String TAG = "GMailReader";

	private String mailhost = "imap.gmail.com";
	private Session session;
	private Store store;

	public GMailReader(String user, String password) {

		Properties props = System.getProperties();
		if (props == null) {
			System.out.println("Properties are null !!");
		} else {
			props.setProperty("mail.store.protocol", "imaps");

			System.out.println("Transport: "
					+ props.getProperty("mail.transport.protocol"));
			System.out.println("Store: "
					+ props.getProperty("mail.store.protocol"));
			System.out.println("Host: " + props.getProperty("mail.imap.host"));
			System.out.println("Authentication: "
					+ props.getProperty("mail.imap.auth"));
			System.out.println("Port: " + props.getProperty("mail.imap.port"));
		}
		try {
			session = Session.getDefaultInstance(props, null);
			store = session.getStore("imaps");
			store.connect(mailhost, user, password);
			System.out.println("Store: " + store.toString());
		} catch (NoSuchProviderException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MessagingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public synchronized Message[] readMail() throws Exception {
		try {
			Folder folder = store.getFolder("Inbox");
			folder.open(Folder.READ_ONLY);

			Message[] msgs = folder.getMessages();
			return msgs;
		} catch (Exception e) {
			System.out.println("readMail" + e.getMessage() + e);
			return null;
		}
	}
}

Open in new window


I'm using the following jars I got from this stackoverflow question: http://stackoverflow.com/questions/2020088/sending-email-in-android-using-javamail-api-without-using-the-default-built-in-a/2033124#2033124

I'm using the mail.jar, activation.jar and additional.jar files located there.

I'm trying to read the content of the emails; but I haven't had much success with that, here's my code:

public static void main(String[] args){
		GMailReader gm = new GMailReader("", "");
		
		try {
			Message m[] = gm.readMail();
			Object content = m[m.length - 1].getContent();
			System.out.println(m[m.length - 1].getSubject());
			Multipart mp = (Multipart)m[m.length - 5].getContent();
		    // the content was not fetched from the server

		    // parse each Part
		    for (int i = 0; i < mp.getCount(); i++) {
		        Part inner_part = mp.getBodyPart(i);

		        if( inner_part.isMimeType("text/plain") ) {
		            String text = inner_part.toString();
		            // the content of this Part was fetched from the server
		            System.out.println(text);
		        }
		    }
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

Open in new window


I took out the username and password out of the GMailReader constructor; for obvious reasons.

I'm getting this error: java.lang.ClassCastException: com.sun.mail.imap.IMAPInputStream cannot be cast to javax.mail.Multipart

I know what the error means; but I can't find any other way to read the body of the email, could anyone give me a hint on this?

Appreciate any help!
0
errang
Asked:
errang
  • 8
  • 6
  • 2
  • +1
3 Solutions
 
chubby_informerCommented:
0
 
CEHJCommented:
Your cast is assumptive. The structure of an email message is potentially complex and you need to discover what kind of Part you've got. The following should show you how to approach the parsing

http://wrongnotes.blogspot.co.uk/2007/09/javamail-parsing-made-easy.html
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
errangAuthor Commented:
>>  Your cast is assumptive.

Well, I'm mainly trying to read and analyze the text; that's why I was just going for plain text.  Not sure how complicated parsing an HTML document can be.
0
 
CEHJCommented:
It's not the html that's complex, it's potentially the mail, since it can contain many parts, and those parts can be nested. You can even have nested Message instances
0
 
errangAuthor Commented:
The link provided by chubby_informer works fine:

>> http://forum.codecall.net/topic/62143-how-to-read-your-emails-using-java/

There are just two problems with this one:

- It prints out all the metadata associated with the email (like when you convert a .rtf file to a .txt file).
- It doesn't have a good way to get the number of messages in the inbox; I came up with a very "hacky" fix:

                int x = 2;
                output.println("RETR 1");
                while (!response.equals("-ERR Message number out of range.")) {
                        response = readOneLine();
                        System.out.println(response);
                        output.println("RETR " + x);
                        x++;
                }

Open in new window


The above code would go at the end of the connect() method; overwriting the while loop.

The thing is... that snippet works for about 100 or so mails and then dies, saying the number is out of range... and it over shoots it by a wide margin.  I have 20k mails in my inbox, and this thing goes to 190k.

What am I missing here?
0
 
CEHJCommented:
I'll let chubby_informer comment on his own post, though if it 'works fine' (though not sure how it would since GMail's implementation is by default secure IMAP, not POP) there shouldn't be much need for comment.

Your own code should reflect pretty accurately the number of messages present by a simple
System.out.println(msgs.length);

Open in new window

0
 
errangAuthor Commented:
>> I'll let chubby_informer comment on his own post, though if it 'works fine'

Well, by 'works fine'; I mean that it prints out the contents of a mail, along with all sorts of meta data I don't really want.

>> Your own code should reflect pretty accurately the number of messages present by a simple

Yea; I know about that, but the code in chubby_informer's post is almost like its retrieving a database entry...

output.println("RETR x");

Open in new window

Where 'x' is the index of the mail.

I'm trying to understand the code you (CHEJ) linked here: http://wrongnotes.blogspot.co.uk/2007/09/javamail-parsing-made-easy.html , but I can't just copy paste the code into my program and have it work... I'm looking at how I need to restructure the code.

I'm trying to following up every lead I can to read the content of an email... I'm not looking for complex embedded HTML stuff... I'm just trying to read emails with plain text.
0
 
CEHJCommented:
It would appear on close inspection that the code at the link i posted is flawed. Try the following, simplified for your use case. Some imports can probably be deleted
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;


public class GMailReader extends javax.mail.Authenticator {
    private static final String TAG = "GMailReader";
    private String mailhost = "imap.gmail.com";
    private Session session;
    private Store store;

    public GMailReader(String user, String password) {
        Properties props = System.getProperties();

        if (props == null) {
            System.out.println("Properties are null !!");
        } else {
            props.setProperty("mail.store.protocol", "imaps");

            System.out.println("Transport: " +
                props.getProperty("mail.transport.protocol"));
            System.out.println("Store: " +
                props.getProperty("mail.store.protocol"));
            System.out.println("Host: " + props.getProperty("mail.imap.host"));
            System.out.println("Authentication: " +
                props.getProperty("mail.imap.auth"));
            System.out.println("Port: " + props.getProperty("mail.imap.port"));
        }

        try {
            session = Session.getDefaultInstance(props, null);
            store = session.getStore("imaps");
            store.connect(mailhost, user, password);
            System.out.println("Store: " + store.toString());
        } catch (NoSuchProviderException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (MessagingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        GMailReader r = new GMailReader("uname", "pass");
        Message[] msgs = r.readMail();
        System.out.printf("Found %d message(s)\n", msgs.length);

        List<String> mTexts = new ArrayList<String>();

        for (int i = 0; i < 5; i++) {
            r.getText(msgs[i], mTexts);
        }

        System.out.println(mTexts);
    }

    public synchronized Message[] readMail() throws Exception {
        try {
            Folder folder = store.getFolder("Inbox");
            folder.open(Folder.READ_ONLY);

            Message[] msgs = folder.getMessages();

            return msgs;
        } catch (Exception e) {
            System.out.println("readMail" + e.getMessage() + e);

            return null;
        }
    }

    private void getText(Part part, List<String> textList)
        throws MessagingException, IOException {
        if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            int count = mp.getCount();

            for (int i = 0; i < count; i++) {
                BodyPart bp = mp.getBodyPart(i);

                getText(bp, textList);
            }
        } else if (part.isMimeType("text/*")) {
            String content = (String) part.getContent();

            textList.add(content);
        } else if (part.isMimeType("message/rfc822")) {
            // nested messages need recursion        
            getText((Part) part.getContent(), textList);
        } else {
            return;
        }
    }
}

Open in new window

0
 
errangAuthor Commented:
>> It would appear on close inspection that the code at the link i posted is flawed. Try the following, simplified for your use case. Some imports can probably be deleted

I appreciate that, thanks; but... I'm still getting this error:

Exception in thread "main" java.lang.ClassCastException: com.sun.mail.imap.IMAPInputStream cannot be cast to javax.mail.Multipart
      at GMailReader.getText(GMailReader.java:90)
      at GMailReader.main(GMailReader.java:66)

Are you using any specific IDE or anything else?  Because now it seems more and more likely that I haven't set up my environment correctly.
0
 
CEHJCommented:
I would first try to ensure you have the latest version of java mail and its dependencies in your classpath
0
 
krakatoaCommented:
More than likely you didn't read the link to the lit I posted.

For content-types that are unknown to the DataHandler system, an input stream is returned as the content
0
 
CEHJCommented:
It could be that you have a rogue mail (couldn't resist that sorry) in that it's non-compliant. In that case, the phenomenon that krakatoa refers to could come into play. If the mail is not confidential, you could forward it to me and i could test it on my system.
Worst case scenario is that you'd have to miss such mails and trap the CCE
0
 
errangAuthor Commented:
Its not confidential; its just the welcome email gmail has when you first sign up for an account.

I'm using a Mac... and they have their own weird version of JDK; I'm guessing you aren't using a Mac?  I'm trying out your program on Ubuntu now, see if that helps.
0
 
CEHJCommented:
If you can forward it to me, i'll check it.
0
 
errangAuthor Commented:
>> If you can forward it to me, i'll check it.

That's fine... it works now.

Apparently... I had to install the latest java mail package and import the jars into the project.

Previously; I downloaded mail.jar, additional.jar and authentication.jar from a stackoverflow question.

Now I downloaded it straight from oracle: http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-eeplat-419426.html#javamail-1.4.5-oth-JPR

I'm sorry about the mess.
0
 
CEHJCommented:
np :)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 8
  • 6
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now