Question

Note: added after answer: Thanks.. Yeah I had tried the Flag.SEEN to true and saveChanges.. I also had read getContent marks it read. I tried using it in the for statement that loops through the messages. But I got the messages again from the folder anyways in the next loop. I was assuming the folder was live, so grabbing the content, then grabbing the messages again from the folder with the filter to not get any seen should work, but I was still getting the same message. I could try closing the folder and reopen as a test to see if it's marked. Also if I go over to my client and click the message, then my code stops seeing it even in the loop, so I was hoping to do the same in the code.

original: I'm using javamail to get email from a gmail account, it's working great, when I get the message I'd like to mark it as read, can anyone give me some direction? Here is my current code:

    Properties props = System.getProperties();
    props.setProperty("mail.store.protocol", "imaps");
    try {
        Session session = Session.getDefaultInstance(props, null);
        Store store = session.getStore("imaps");

        store.connect("imap.gmail.com", eUserName, ePassWord);
        // Get folder
        Folder folder = store.getFolder("INBOX");
        if (folder == null || !folder.exists()) {
            return null;
        }
        folder.open(Folder.READ_ONLY);

        // Only pull unread
        FlagTerm ft = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
        Message messages[]; // = folder.search(ft);

        for(int x = 0; x < timeOutInSeconds; x++) {
            log.reportMessage("looking for emails");
            try {
                folder.getMessages();
                messages = folder.search(ft);

                if (messages.length > 0) {
                    for (Message message : messages) {
                        //log.reportMessage("found message: should not see again, marking read");
                        // want to mark as read

                    }
                }
                Thread.sleep(1000);
            }
            catch(Exception ex) {

            }
        }

        // Close connection
        folder.close(false);
        store.close();
        return null;

    }
    catch (NoSuchProviderException ex) {

        return null;
    }
    catch (MessagingException ex) {

        return null;
    }


}
Was it helpful?

Solution

First of all, you can't mark a message as read if you are using a POP3 server - the POP3 protocol doesn't support that. However, the IMAP v4 protocol does.

You might think the way to do this is to get the message, set the Flags.Flag.SEEN flag to true, and then call message.saveChanges(). Oddly, this is not the case.

Instead, the JavaMail API Design Specification, Chapter 4, section "The Flags Class" states that the SEEN flag is implicitly set when the contents of a message are retrieved. So, to mark a message as read, you can use the following code:

myImapFolder.open(Folder.READ_WRITE);
myImapFolder.getMessage(myMsgID).getContent();
myImapFolder.close(false);

Or another way is to use the MimeMessage copy constructor, ie:

MimeMessage source = (MimeMessage) folder.getMessage(1)
MimeMessage copy = new MimeMessage(source);

When you construct the copy, the seen flag is implicitly set for the message referred to by source.

OTHER TIPS

One liner that will do it WITHOUT downloading the entire message:

single message:

folder.setFlags(new Message[] {message}, new Flags(Flags.Flag.SEEN), true);

all messages:

folder.setFlags(messages, new Flags(Flags.Flag.SEEN), true);

Other methods of calling getContent() or creating a copy with new MimeMessage(original) cause the client to download the entire message, and creates a huge performance hit.

Note that the inbox must be opened for READ_WRITE:

folder.open(Folder.READ_WRITE);

Well this post is old but the easiest solution hasn´t been posted yet.

You are accessing the Message. message.setFlag(Flag.SEEN, true);

for (Message message : messages) {
                    message.setFlag(Flags.Flag.SEEN,true);
                }

and change the below line

folder.open(Folder.READ_ONLY);

to this

folder.open(Folder.READ_WRITE);

You may also consider having a public static int max_message_number, and storing in it the message[i].getMessageNumber(); as soon as you read a message. Then before reading any message just check if the max_message_number < message[i].getmessageNumber(). If true then don't print this message (as it has been already read)

If you are using a for loop to read or check a mail one by one, the code can be as follows to mark a gmail message as read:

    Message[] unreadMessages = inbox.search(new FlagTerm(new Flags(Flag.SEEN), false));
            for (int q = 0; q < unreadMessages.length; q++) {

              unreadMessages[q].setFlag(Flag.SEEN, true);

            }

What this code does is that it makes it unread one by one.

And also folder/inbox needs to be READ_WRITE, instead of READ_ONLY:

folder.open(Folder.READ_WRITE);

message.setFlag( Flag.SEEN,true ) give "cannot find symbol" message.setFlag( Flags.Flag.SEEN,true ) seems good.

The easiest way to do that is set the folder to be read or written into or from. Means like this...

    Folder inbox = null;
    inbox.open(Folder.READ_WRITE);      

the Folder class should be imported.

You can also try

head over to the gmail settings > Forwarding and POP/IMAP

from the dropdown of When messages are accessed with POP select mark Gmail's copy as read and save the changes

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top