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?
Related
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.
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);
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.
Currently im doing as following,
#Override
public void saveDraftMessage(MimeMessage draftMessage) throws MessagingException
{
Folder draftsMailBoxFolder = imapsStore.getFolder("inbox");//[Gmail]/Drafts
draftsMailBoxFolder.open(Folder.READ_WRITE);
draftMessage.setFlag(Flag.DRAFT, true);
MimeMessage draftMessages[] = {draftMessage};
draftsMailBoxFolder.appendMessages(draftMessages);
}
It works but , as you could see message is being appended to "inbox" folder without complain from server end !
Is there any kind of validation or an alternative method to ensure that message is saved as Draft only at appropriate place.
As others have suggested above, you need to store your draft messages in a different folder. You can choose the name of that folder. If you're only using Gmail and you want to be consistent with what Gmail is doing, saving it in the folder Gmail uses ("[Gmail]/Drafts"?) would make sense. Remember to delete the message from the folder when you send it.
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.