Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

How to read an email with Java

Posted on 2012-08-21
17
Medium Priority
?
2,891 Views
Last Modified: 2012-08-23
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
Comment
Question by:errang
  • 8
  • 6
  • 2
  • +1
17 Comments
 
LVL 10

Assisted Solution

by:chubby_informer
chubby_informer earned 200 total points
ID: 38318845
0
 
LVL 17

Assisted Solution

by:krakatoa
krakatoa earned 200 total points
ID: 38319795
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 38319817
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 

Author Comment

by:errang
ID: 38324379
>>  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
 
LVL 86

Expert Comment

by:CEHJ
ID: 38324401
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
 

Author Comment

by:errang
ID: 38324969
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 38325264
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
 

Author Comment

by:errang
ID: 38325526
>> 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
 
LVL 86

Accepted Solution

by:
CEHJ earned 1600 total points
ID: 38327464
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
 

Author Comment

by:errang
ID: 38327479
>> 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
 
LVL 86

Expert Comment

by:CEHJ
ID: 38327485
I would first try to ensure you have the latest version of java mail and its dependencies in your classpath
0
 
LVL 17

Expert Comment

by:krakatoa
ID: 38327490
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 38327512
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
 

Author Comment

by:errang
ID: 38327521
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 38327560
If you can forward it to me, i'll check it.
0
 

Author Comment

by:errang
ID: 38327591
>> 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
 
LVL 86

Expert Comment

by:CEHJ
ID: 38327596
np :)
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When we want to run, execute or repeat a statement multiple times, a loop is necessary. This article covers the two types of loops in Python: the while loop and the for loop.
Don’ts and Dos are two important end products of software testing basics that a tester needs to regard. This article attempts to explain the principles of both.
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
Suggested Courses

569 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question