如何在Android上获取电子邮件?

时间:2015-06-09 17:30:47

标签: java android email javamail

我正在尝试开发一款应用程序,该应用程序从不是Google的POP3服务器获取电子邮件,而且我遇到了很多问题。
我正在使用JavaMail库并遵循TutorialsPoint教程。他们的pop3示例在Eclipse /桌面上工作正常,但是当我在Android上移动代码时,它永远无法工作,我很沮丧。
在logcat中,我得到了所有大量的错误,其中首先说明了

  

W / System.err:android.os.NetworkOnMainThreadException即使我正在使用AsyncTask(可能不正确)。

有没有办法可以修复AsyncTask才能正常工作?

另外,有没有办法让我可以做这样的事情而不使用像K-9 Mail这样的专业应用程序?

有人感兴趣的代码:

 public class FetchPop extends AsyncTask{

    public static void fetch(String pop3Host, String storeType, String user,
                             String password) {
        try {
            // create properties field
            Properties properties = new Properties();
            properties.put("mail.store.protocol", "pop3");
            properties.put("mail.pop3.host", pop3Host);
            properties.put("mail.pop3.port", "995");
            properties.put("mail.pop3.starttls.enable", "true");
            Session emailSession = Session.getDefaultInstance(properties);
            // emailSession.setDebug(true);

            // create the POP3 store object and connect with the pop server
            Store store = emailSession.getStore("pop3s");

            store.connect(pop3Host, user, password);

            // create the folder object and open it
            Folder emailFolder = store.getFolder("INBOX");
            emailFolder.open(Folder.READ_ONLY);

            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    System.in));

            // retrieve the messages from the folder in an array and print it
            Message[] messages = emailFolder.getMessages();
            Log.d("No. messages:", messages.length + ""); //just the number at first


/*for (int i = 0; i < messages.length; i++) {
                Message message = messages[i];
                writePart(message);
                String line = reader.readLine();
                if ("YES".equals(line)) {
                    message.writeTo(System.out);
                } else if ("QUIT".equals(line)) {
                    break;
                }
            }*/
            // close the store and folder objects
            emailFolder.close(false);
            store.close();

        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (MessagingException e) {
            e.printStackTrace();
        } /*catch (IOException e) {
            e.printStackTrace();
        }*/ catch (Exception e) {
            e.printStackTrace();
        }
    }


        @Override
        protected Object doInBackground(Object[] params) {
            String host = "pop.gmail.com";// I tried google's pop 
            String mailStoreType = "pop3";
            String username =
                    "myusername";// change accordingly
            String password = "notmyrealpass";// change accordingly

            //Call method fetch
            fetch(host, mailStoreType, username, password);
            Log.d("mytag","done!");
            return null;
        }

    public void GO() {
        doInBackground(null);
    }





    /*
    * This method checks for content-type
    * based on which, it processes and
    * fetches the content of the message
    */
    public static void writePart(Part p) throws Exception {
        if (p instanceof Message)
            //Call methos writeEnvelope
            writeEnvelope((Message) p);

       /* System.out.println("----------------------------");
        System.out.println("CONTENT-TYPE: " + p.getContentType());*/

        //check if the content is plain text
        if (p.isMimeType("text/plain")) {
            System.out.println("This is plain text");
            System.out.println("---------------------------");
            System.out.println((String) p.getContent());
        }
        //check if the content has attachment
        else if (p.isMimeType("multipart/*")) {
            System.out.println("This is a Multipart");
            System.out.println("---------------------------");
            Multipart mp = (Multipart) p.getContent();
            int count = mp.getCount();
            for (int i = 0; i < count; i++)
                writePart(mp.getBodyPart(i));
        }
        //check if the content is a nested message
        else if (p.isMimeType("message/rfc822")) {
            System.out.println("This is a Nested Message");
            System.out.println("---------------------------");
            writePart((Part) p.getContent());
        }
        //check if the content is an inline image
        else if (p.isMimeType("image/jpeg")) {
            System.out.println("--------> image/jpeg");
            Object o = p.getContent();

            InputStream x = (InputStream) o;
            // Construct the required byte array
            int i;
            byte[] bArray = new byte[0];
            System.out.println("x.length = " + x.available());
            while ((i = (int) ((InputStream) x).available()) > 0) {
                int result = (int) (((InputStream) x).read(bArray));
                if (result == -1)
                    i=0;
                bArray = new byte[x.available()];

                break;
            }
            FileOutputStream f2 = new FileOutputStream("/tmp/image.jpg");
            f2.write(bArray);
        }
        else if (p.getContentType().contains("image/")) {
            System.out.println("content type" + p.getContentType());
            File f = new File("image" + new Date().getTime() + ".jpg");
            DataOutputStream output = new DataOutputStream(
                    new BufferedOutputStream(new FileOutputStream(f)));
            com.sun.mail.util.BASE64DecoderStream test =
                    (com.sun.mail.util.BASE64DecoderStream) p
                            .getContent();
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = test.read(buffer)) != -1) {
                output.write(buffer, 0, bytesRead);
            }
        }
        else {
            Object o = p.getContent();
            if (o instanceof String) {
                System.out.println("This is a string");
                System.out.println("---------------------------");
                System.out.println((String) o);
            }
            else if (o instanceof InputStream) {
                System.out.println("This is just an input stream");
                System.out.println("---------------------------");
                InputStream is = (InputStream) o;
                is = (InputStream) o;
                int c;
                while ((c = is.read()) != -1)
                    System.out.write(c);
            }
            else {
                System.out.println("This is an unknown type");
                System.out.println("---------------------------");
                System.out.println(o.toString());
            }
        }

    }
    /*
    * This method would print FROM,TO and SUBJECT of the message
    */
    public static void writeEnvelope(Message m) throws Exception {
        System.out.println("This is the message envelope");
        System.out.println("---------------------------");
        Address[] a;

        // FROM
        if ((a = m.getFrom()) != null) {
            for (int j = 0; j < a.length; j++)
                System.out.println("FROM: " + a[j].toString());
        }

        // TO
        if ((a = m.getRecipients(Message.RecipientType.TO)) != null) {
            for (int j = 0; j < a.length; j++)
                System.out.println("TO: " + a[j].toString());
        }

        // SUBJECT
        if (m.getSubject() != null)
            System.out.println("SUBJECT: " + m.getSubject());

    }

}

2 个答案:

答案 0 :(得分:0)

尝试使用此库https://code.google.com/p/javamail-android/

不知道lib的确切状态,但是他们在这个博客(http://www.jondev.net/articles/Sending_Emails_without_User_Intervention_%28no_Intents%29_in_Android)中有一个很好的例子,他们说

  

“这是JavaMail API的特殊版本,专门为Android编写。”

答案 1 :(得分:0)

看起来你没有正确使用AsyncTask,特别是看到你有一个直接调用GO()的{​​{1}}方法。删除doInBackground()方法,不需要它。

执行AsyncTask的正确方法是使用GO()方法,该方法调用execute()并在工作线程上运行它,这将消除您doInBackground()运行时错误到目前为止。

因此,除了使用特定于Android的库之外,还要修复AsyncTask,以便它实际在工作线程而不是主UI线程中运行NetworkOnMainThreadException方法。

一般来说,最好使用泛型和变量而不是让doInBackground()doInBackground()作为参数。 每次执行AsyncTask时都能传递用户名和密码也很有用,所以请使用String varargs参数。

Object[]

然后,要正确执行AsyncTask,请使用public class FetchPop extends AsyncTask<String, Void, Void> { @Override protected Void doInBackground(String... params) { String host = "pop.gmail.com";// I tried google's pop String mailStoreType = "pop3"; String username = params[0]; //passed in through the execute() method String password = params[1]; //passed in through the execute() method //Call method fetch fetch(host, mailStoreType, username, password); Log.d("mytag", "done!"); return null; } } 方法,并传入用户名和密码:

execute()

另请注意,任何与UI相关的代码都需要放在 //First get the username and password from the user through the UI String user = "myusername"; // change accordingly String pass = "notmyrealpass"; // change accordingly new FetchPop().execute(user, pass); 中,因为所有UI任务都需要在Android的主UI线程上执行。

有关AsyncTasks的更多常规信息,this question and the answers posted

中有很多有用的信息