【问题标题】:Retrieving all unread emails using javamail with POP3 protocol使用带有 POP3 协议的 javamail 检索所有未读电子邮件
【发布时间】:2012-10-19 16:46:13
【问题描述】:

我正在尝试访问我的 gmail 帐户并从中检索所有未读电子邮件的信息。

我在参考了许多链接后编写了我的代码。我提供了一些链接供参考。

Send & Receive emails through a GMail account using Java

Java Code to Receive Mail using JavaMailAPI

为了测试我的代码,我创建了一个 Gmail 帐户。所以我收到了来自 Gmail 的 4 条消息。 我在检查邮件数量后运行我的应用程序。这显示了正确的结果。 4 封未读邮件。 正在显示所有信息(例如日期、发件人、内容、主题等)

然后我登录到我的新帐户,阅读其中一封电子邮件并重新运行我的应用程序。 现在未读消息的计数应该是 3,但它显示“未读消息的数量:0”

我在这里复制代码。

public class MailReader

{

    Folder inbox;

    // Constructor of the calss.

    public MailReader() {
        System.out.println("Inside MailReader()...");
        final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";

        /* Set the mail properties */

        Properties props = System.getProperties();
        // Set manual Properties
        props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);
        props.setProperty("mail.pop3.socketFactory.fallback", "false");
        props.setProperty("mail.pop3.port", "995");
        props.setProperty("mail.pop3.socketFactory.port", "995");
        props.put("mail.pop3.host", "pop.gmail.com");

        try

        {

            /* Create the session and get the store for read the mail. */

            Session session = Session.getDefaultInstance(
                    System.getProperties(), null);

            Store store = session.getStore("pop3");

            store.connect("pop.gmail.com", 995, "abc@gmail.com",
                    "paasword");

            /* Mention the folder name which you want to read. */

            // inbox = store.getDefaultFolder();
            // inbox = inbox.getFolder("INBOX");
            inbox = store.getFolder("INBOX");

            /* Open the inbox using store. */

            inbox.open(Folder.READ_ONLY);

            /* Get the messages which is unread in the Inbox */

            Message messages[] = inbox.search(new FlagTerm(new Flags(
                    Flags.Flag.SEEN), false));
            System.out.println("No. of Unread Messages : " + messages.length);

            /* Use a suitable FetchProfile */
            FetchProfile fp = new FetchProfile();
            fp.add(FetchProfile.Item.ENVELOPE);

            fp.add(FetchProfile.Item.CONTENT_INFO);

            inbox.fetch(messages, fp);

            try

            {

                printAllMessages(messages);

                inbox.close(true);
                store.close();

            }

            catch (Exception ex)

            {
                System.out.println("Exception arise at the time of read mail");

                ex.printStackTrace();

            }

        }

        catch (MessagingException e)
        {
            System.out.println("Exception while connecting to server: "
                    + e.getLocalizedMessage());
            e.printStackTrace();
            System.exit(2);
        }

    }

    public void printAllMessages(Message[] msgs) throws Exception
    {
        for (int i = 0; i < msgs.length; i++)
        {

            System.out.println("MESSAGE #" + (i + 1) + ":");

            printEnvelope(msgs[i]);
        }

    }

    public void printEnvelope(Message message) throws Exception

    {

        Address[] a;

        // FROM

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

        Date receivedDate = message.getReceivedDate();
        Date sentDate = message.getSentDate(); // receivedDate is returning
                                                // null. So used getSentDate()

        String content = message.getContent().toString();
        System.out.println("Subject : " + subject);
        if (receivedDate != null) {
            System.out.println("Received Date : " + receivedDate.toString());
        }
        System.out.println("Sent Date : " + sentDate.toString());
        System.out.println("Content : " + content);

        getContent(message);

    }

    public void getContent(Message msg)

    {
        try {
            String contentType = msg.getContentType();
            System.out.println("Content Type : " + contentType);
            Multipart mp = (Multipart) msg.getContent();
            int count = mp.getCount();
            for (int i = 0; i < count; i++) {
                dumpPart(mp.getBodyPart(i));
            }
        } catch (Exception ex) {
            System.out.println("Exception arise at get Content");
            ex.printStackTrace();
        }
    }

    public void dumpPart(Part p) throws Exception {
        // Dump input stream ..
        InputStream is = p.getInputStream();
        // If "is" is not already buffered, wrap a BufferedInputStream
        // around it.
        if (!(is instanceof BufferedInputStream)) {
            is = new BufferedInputStream(is);
        }
        int c;
        System.out.println("Message : ");
        while ((c = is.read()) != -1) {
            System.out.write(c);
        }
    }

    public static void main(String args[]) {
        new MailReader();
    }
}

我在谷歌上搜索,但我发现你应该使用 Flags.Flag.SEEN 来阅读未读电子邮件。 但在我的情况下,这并没有显示正确的结果。

有人能指出我可能在哪里做错了吗?

如果您需要完整的代码,我可以编辑我的帖子。

注意:我编辑了我的问题以包含整个代码,而不是我之前发布的 sn-p。

【问题讨论】:

  • 不应该是Message messages[]Message[] messages
  • 其实两者都有效。阅读here上的答案以获取详细说明:) @berbt
  • 一个新的意想不到的知识。感谢您的链接!
  • 现在对你有用吗?对我来说,它返回“连接到服务器时出现异常:[AUTH] 需要 Web 登录:support.google.com/mail/answer/78754”——而且我想知道如果常见问题解答说“POP3 协议不提供对任何永久标志的支持,所以它如何工作” RECENT 标志没有用。com.sun.mail.pop3 包文档讨论了处理此问题的几种策略。对于“如何判断 POP3 中哪些消息是新消息?”这个问题...@Bill Shannon
  • 在设置中启用不安全的应用程序并添加 Session emailSession = Session.getDefaultInstance(properties, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(user , 密码); } });

标签: java jakarta-mail pop3


【解决方案1】:

您无法使用 POP3 获取未读邮件。来自JavaMail API

POP3 不支持永久标志(请参阅 Folder.getPermanentFlags())。在 特别是,永远不会为 POP3 设置 Flags.Flag.RECENT 标志 消息。由应用程序决定一个消息中的哪些消息 POP3 邮箱是“新的”。

您可以像这样使用 IMAP 协议并使用 SEEN 标志:

public Message[] fetchMessages(String host, String user, String password, boolean read) {
    Properties properties = new Properties();
    properties.put("mail.store.protocol", "imaps");

    Session emailSession = Session.getDefaultInstance(properties);
    Store store = emailSession.getStore();
    store.connect(host, user, password);

    Folder emailFolder = store.getFolder("INBOX");
    // use READ_ONLY if you don't wish the messages
    // to be marked as read after retrieving its content
    emailFolder.open(Folder.READ_WRITE);

    // search for all "unseen" messages
    Flags seen = new Flags(Flags.Flag.SEEN);
    FlagTerm unseenFlagTerm = new FlagTerm(seen, read);
    return emailFolder.search(unseenFlagTerm);
}

要注意的另一件事是 POP3 不处理文件夹。 IMAP 获取文件夹,POP3 只获取收件箱。更多信息请访问:How to retrieve gmail sub-folders/labels using POP3?

【讨论】:

    【解决方案2】:

    请使用此方法获取未读邮件

    getNewMessageCount()

    参考以下链接:

    https://javamail.java.net/nonav/docs/api/com/sun/mail/imap/IMAPFolder.html

    【讨论】:

      【解决方案3】:

      正确使用的标志是

      Flags.Flag.RECENT
      

      【讨论】:

      • 尽管 Folder#getNewMessageCount 的 JavaDoc 说它检查 RECENT 标志来识别新消息,但 GMail 实际上使用标志 SEEN 来标记已读消息。
      【解决方案4】:

      inbox.open(Folder.READ_ONLY); 更改为inbox.open(Folder.READ_WRITE); 它会将您的邮件更改为收件箱中的已读邮件。

      【讨论】:

      • 你确定这适用于 pop3 吗?就我而言,它没有。
      【解决方案5】:
      Flags seen = new Flags(Flags.Flag.RECENT);
      FlagTerm unseenFlagTerm = new FlagTerm(seen, false);
      messages = inbox.search(unseenFlagTerm);
      

      【讨论】:

      • 这是不正确的。您可以查看最近的电子邮件。 Technotronic 提供了检索 UNREAD 电子邮件的正确方法。
      【解决方案6】:

      您的代码应该可以工作。如果你想要的只是计数,你也可以使用 Folder.getUnreadMessageCount() 方法。

      JavaMail 只能告诉您 Gmail 告诉它的内容。也许 Gmail 认为所有这些邮件都已阅读?也许 Gmail 网络界面将这些邮件标记为已读?也许您有另一个应用程序正在监视文件夹中的新消息?

      尝试使用 JavaMail 读取未读邮件,看看计数是否发生变化。

      您可能会发现打开会话调试很有用,这样您就可以看到 Gmail 返回的实际 IMAP 响应;见JavaMail FAQ

      【讨论】:

      • 嗨,比尔,感谢您的帮助。我不想要只是未读电子邮件的数量。我需要的是所有未读的电子邮件。这只是一个演示程序,但最后我想在我的主项目中处理收到的电子邮件的附件。我已经尝试在收件箱上使用 getUnreadMessageCount() 方法。但它总是返回-1。所以这在我的情况下也不起作用。我将编辑我的问题并在此处发布我的整个代码。因为我认为某处出了点问题。
      • 嗨,我知道问题出在哪里了。正如你所说,我尝试调试它,发现 Gmail 正在返回这些结果。我从选项卡转发和 POP/IMAP 更改了我的 Gmail 帐户设置。所以现在它工作正常。感谢帮助。 :)
      猜你喜欢
      • 1970-01-01
      • 2011-08-23
      • 1970-01-01
      • 1970-01-01
      • 2021-06-29
      • 1970-01-01
      • 2011-07-19
      • 2016-03-09
      • 1970-01-01
      相关资源
      最近更新 更多