How do I uniquely identify a Java Mail Message using IMAP? - java

IMAP Message in Java Mail is identified by it's relative position number which starts from 1.
refer,
http://docs.oracle.com/javaee/1.4/api/javax/mail/Message.html#getMessageNumber()
Message number is a temporary details.
Is there a way to permanently uniquely identify a mail/message which accessing a mailbox via IMAP using Java Mail API which holds true across sessions ?

Look at the UIDFolder interface, which exposes the IMAP UID capability.

You can get a unique identifier for a message using the following code as an example
Folder folder = imapStore.getFolder("INBOX"); // get reference for inbox folder
UIDFolder uf = (UIDFolder)folder; // cast folder to UIDFolder interface
folder.open(Folder.READ_ONLY); // open folder
Message messages[] = folder.getMessages(); // get all messages
Long messageId = uf.getUID(messages[0]); // get message Id of first message in the inbox

Adding this because I think this will help
If you want to loop over the messages and get uids the above code does not do got performance as you have to loop and get uid, easy way to get that with the messages is below
Folder emailFolder = store.getFolder("INBOX");
emailFolder.open(Folder.READ_ONLY);
UIDFolder uf = (UIDFolder)emailFolder;
Message messages[] = emailFolder.getMessages();
FetchProfile profile = new FetchProfile();
//profile.add(FetchProfile.Item.ENVELOPE);
profile.add(FetchProfile.Item.FLAGS);
//profile.add(FetchProfile.Item.CONTENT_INFO);
profile.add(UIDFolder.FetchProfileItem.UID);
emailFolder.fetch(messages, profile);
this will get the messages with the uid
after this if you loop and do uf.getUID(messages[i]); you will get the uid but this time it will be faster.

Related

What is the deleted folder name link for Outlook?

I have a code snippet for deleting emails from Gmail. But I need to change that line store.getFolder("[Gmail]/Trash"); to work with the Outlook server.
What is the deleted(trash) folder name link for Outlook?
store = session.getStore("imaps");
store.connect("imap.gmail.com",<username>,<password>);
inbox = store.getFolder("Inbox");
inbox.open(Folder.READ_WRITE);
deletedMessages.add(message);
message.setFlag(Flag.SEEN,true);
if (inbox.isOpen()) {
if(deletedMessages.size() > 0){
trash = store.getFolder("[Gmail]/Trash");
Message[] tempMessageArray = deletedMessages.toArray(new Messag e[deletedMessages.size()]);
inbox.copyMessages(tempMessageArray,trash);
deletedMessages.clear();
}
inbox.close(true);
In Outlook, there are two options:
So you could use [Outlook]/Deleted Items or [Outlook]/Junk Email. Probably most comparable to [Gmail]/Trash is [Outlook]/Deleted Items. Junk Email catches additional Spam email not blocked by Outlooks filters.
For more info, see : https://support.microsoft.com/en-us/office/working-with-message-folders-in-outlook-com-6bb0723a-f39f-4a8d-bb3f-fab5dcc2510a#:~:text=In%20the%20folder%20pane%2C%20right%2Dclick%20the%20folder%20you%20want,the%20folder%20and%20press%20Enter.

Reading emails from IMAP - how to flag them as SEEN when processed?

I'm reading and processing emails received from IMAP using JODD mail library. API is very nice but I struggle with one logical issue. I'm using code as following:
EmailFilter filter= new EmailFilter();
filter.flag(Flags.Flag.SEEN, false);
session.receiveEmailAndMarkSeen(filter);
By calling session.receiveEmailAndMarkSeen I receive all unread emails and these are marked as read immediately. Now when processing fails in my code for any reason, and I try to receive emails again all these unprocessed emails are marked as read already and not downloaded anymore. I would rather download emails and mark them as read individualy as beeing processed successfully.
So I tried to receive them with session.receiveEmail but not sure how to mark them as read when processed? Any hint how to do it? I can see that email object has 'flag' property I can set but not sure how to send this information back to server.
To summarize possible solutions:
Re-fetch email with Seen flag. The downside is that email is fetched again.
What you wrote - using a Session and a Folder.
Finally - starting from the next version of Jodd, you will have the method updateEmailFlags that would give you options to just call it:
mymail.flags(newFlags);
ReceiveMailSession.updateEmailFlags(mymail);
The result would be the same.
SOLVED: I'm creating connection manualy using common JAVA mail classes - Session and Store.
Session sess = Session.getDefaultInstance(props, null);
Store store = sess.getStore("imaps");
store.connect("imapServerHost", "username","password");
... then I create folder object (points to Inbox)
Folder folder = store.getFolder(this.imapFolder);
folder.open(Folder.READ_WRITE);
... then I receive emails using session and store
ReceiveMailSession session=new ReceiveMailSession(sess, store);
... after email processed, I send back SEEN=true message using folder object.
Flags f=new Flags();
f.add(Flags.Flag.SEEN);
folder.setFlags(new int[] {email.getMessageNumber()}, f,true);

How to properly delete a copied gmail message using javamail?

I have a scenario like this. I have copied a gmail message from Inbox to a child folder of Inbox, say test-folder. Now the message is there in Inbox and as well as in Inbox/test-folder. Now later if I want to delete (expunge) the copy in Inbox/test-folder using javamail, it is also being deleted from Inbox also.
I know that gmail maintains only 1 copy of the message in its database and it just tags folder names to the message, so it is obvious if I expunge it from other folder, it will also get deleted from the original folder.
The following code works for other IMAP based mails like yahoo and etc.
Folder inbox = store.getFolder("INBOX");
Folder child = store.getFolder("INBOX/test-folder");
inbox.open(Folder.READ_WRITE);
child.open(Folder.READ_WRITE);
AppendUID[] appendUIDs = inbox.copyUIDMessages(new Message[]{ message }, child);
AppendUID appendUID = appendUIDs[0];
long uid = appendUID.uid;
// EDIT: I have to close and reopen the child folder, otherwise getMessageByUID will return null.
child.close(false);
child.open(Folder.READ_WRITE);
Message copiedMessage = child.getMessageByUID(uid);
if (!copiedMessage.isExpunged() && !copiedMessage.isSet(Flags.Flag.DELETED)) {
copiedMessage.setFlag(Flags.Flag.DELETED, true);
}
inbox.close(true);
child.close(true);
The above code delete only the message in Inbox/test-folder, not from Inbox for Yahoo and all. But for gmail it deletes the message from Inbox as well as Inbox/test-folder.
Email client like evolution, handles this scenario properly for gmail. It deletes the message only from the target folder. So how to achieve this using javamail or gimap library?
NOTE: I am using 1.5.5 of the javamail library.
Seems like that should work, but Gmail doesn't exactly follow the imap spec. What does the debug output show?

Gmail fetching mails from Sent items as well

I have the following code to connect to an inbox of a mail server:
Store popStore = popSession.getStore("pop3");
popStore.connect(address, userName, password);
Folder inboxFolder = popStore.getFolder("Inbox");
Post this i check for new mails. Now when I connect to Gmail, I am getting mails from Sent Items as well when actually it is supposed to be only from the Inbox folder. With Yahoo this is working fine.
Any Idea what can be causing this issue in Gmail?
Edit: I have tried with INBOX as well and the result is the same
Interesting issue. I did a little research and found this post in which Google says:
When you enable POP, all messages are downloaded to your client, except for Spam, Trash, and Chats. If you don't want messages that you send from the web interface downloaded to your mail client's inbox, we suggest creating a filter within your client.
To create a filter by sender, you can do this:
String filter = "Not([SenderEmailAddress] = 'XXXXX#gmail.com')";
Items inboxItems = inboxFolder.Items.Restrict(filter);
where XXXXX#gmail.com is your email address. This filter will give you only the items which are sent by someone other than yourself. Additionally, the Restrict method can be replaced with Find, but Restrict will be much faster for larger datasets.
Following is a code snippet. When I checked with gmail, there is no overlap between inbox and sent mail. (This should have been a comment, posting as answer for formatting)
javax.mail.Folder[] folders = store.getDefaultFolder().list("*");
for (javax.mail.Folder folder : folders) {
if ((folder.getType() & javax.mail.Folder.HOLDS_MESSAGES) != 0) {
if (folder.getFullName().equalsIgnoreCase("[Gmail]/Sent Mail")
|| folder.getFullName().equalsIgnoreCase("Inbox")) {
System.out.println(folder.getFullName() + ": " + folder.getMessageCount());
folder.open(Folder.READ_ONLY);
for (Message m : folder.getMessages(
folder.getMessageCount() - 5,
folder.getMessageCount())) {
System.out.println("m.getSubject() = " + m.getSubject());
}
folder.close(true);
}
}
}
firstly try this
Folder folder = store.getDefaultFolder();
folder = folder.getFolder("INBOX");
folder.open(Folder.READ_WRITE);
when you communicate through mail using reply or reply to all in gmail it will considered as inbox mail. Because it is conversation view. so that your sent mail is also an inbox mail. so you will get that mails in your messages.
Read this official google answer.

How to mark messages that are received by an java application using javax Mail Api?

I want to create an application that gets all e-mails from an e-mail account using imap.
When I first run the application I get all mails, than if I run it again I want to mark the messages that was read before so I can receive only new messages.
I found that Message Object contains Flags(System Flags and User defined flags), but I can't manage to set one user defined flag.
It is possible to mark the messages received by my application on the e-mail account, or I have to retain all message ids and every time when I get messages from imap I have to compare their id with retained ids and get only the messages that has different ids?
Some IMAP servers don't permit you to set user-defined flags. Most do, however. Via JavaMail, you'd do the following:
Flags flags = new Flags("fetched");
message.setFlags(flags, true);
Those flags aren't permanent, however -- another IMAP client could clear them just as easily as you set them. (Though they probably won't.)
Another option is to track the UIDs of the messages you've seen. You can get them via ImapFolder.getUID(Message). It's more straightforward than tracking Message-ID headers, which are much more costly to fetch and, since they're strings, occupy more memory in your app.
Yet another option is to use POP and track UIDLs.
Yes it is possible to mark the messages as read, and when the next time you want to read the messages you can only read the new messages.
Use the following code:
Folder emailFolder = emailStore.getFolder("INBOX");
Message messages[] = emailFolder.search(new FlagTerm(new Flags(Flag.SEEN), false));
System.out.println("no of messages=" + messages.length);
for (int i = 0; i < messages.length; i++) {
Message message = messages[i];
//here write your code to read the message and whatever you wanna do//
//now at the end of the message(remember at the end of the message u read using code) write the following code//
message.setFlag(Flag.SEEN, true);
}//end of for loop

Categories