oblac / jodd-mail

Simple Java Mail library.

Home Page:https://mail.jodd.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

reason for why all messages are parsed even if not needed?

maxandersen opened this issue · comments

I'm mainly interested in processing/filtering mail and jodd mail fluent interface is awesome to express it BUT at the moment jodd mail forces parsing/init of Message content that is (at least for my usecase) unnecessary.

Example:

	session.receive().filter(filter().to("me@mail.com")).moveToFolder("somewhere").get();

This call which is intended to simply take all emails sent to me@mail.com and move it to somewhere

This should mainly just result in 2 queries to the imap server. 1 for the query, 1 for the move/cope operation.

What does happen instead in case there are 500 messages matching:

1 query
500+ fetches
500+ updates to unset SEEN
1 for move

This all happens because of all messages are processed and then unset flag.

Is there a reason why this is done for all kind of searches and aren't an optional thing?

the fetches seem to be when getFlags/getHeaders called and if not envelope then all bodies are fetched too.
How about ReceiveMessages lazily did this rather than upfront?

Or maybe introduce a .getResult() method which returns a ReceiveResults which wraps Messages[] array so one avoid doing all that fetching unless really need it?

I guess the main reason for this is that library wraps both POP3 and IMAP...

But you are right, we should add some lazy fetching... let me see.

@maxandersen here is the thing:

 session.receiveMessages(filter, flagsToSet, flagsToUnset, envelopeOnly, messages -> {
	if (targetFolder != null) {
		try {
			session.folder.copyMessages(messages, session.getFolder(targetFolder));
		} catch (MessagingException e) {
			throw new MailException("Copying messages failed");
		}
	}
});

the problem is with the session.folder.copyMessages as it requires Message[] as input. Even IMAPFolder implementation has moveMessages that has Message[] as input.

The first thing receiveMessages do is to get messages from the folder.

			if (filter == null) {
				messages = folder.getMessages();
			} else {
				messages = folder.search(filter.getSearchTerm());
			}

So I am not sure how to get lazy the Message[] from the folder so I can use the move later...

But the Messages[] are not filled in. So they are "lazy" by default.

To avoid having to convert to ReceiveMessage Im suggesting to have a SearchResult intermediære that keeps Message[] around and then only convert to ReceiveMessage if absolute necessary.

I got it, I was not expecting messages[] not filled in :)

Here is the attempt: #13

Your expression would be written as:

session.receive().filter(filter().to("me@mail.com")).moveToFolder("somewhere").run();

We need to find a better name for run(), it is just a temporary one.

What I still have to figure out is the method:

private ReceivedEmail[] _fetch() throws MessagingException {

What can we/should execute right away and what is ok to be delayed in the _fetch() method?

Any chance you saw the change @maxandersen ? Maybe I can build a snapshot so we can test?

@igr sorry - I did see it and I thought I commented already but apparently that didn't "stick" :)

So I like the idea but I can say that my current approach is that I have the filters and action separated - and that works nicely as it allows me to reuse the filter definition for both bulk operations and where I have a set of mails needing to filter manually.

My question is what would 'session.receive().filter(...)..run()' return ?
and would it be possible to have session.recieve().filter(...).do(Actions::myCustomAction).run() ?

snapshot would be nice to try or simply a PR then I can use it more or less directly with jitpack.

the PR is open already: #13 :)

I just added with(consumer).run() method chain.

Friendly ping :)

sorry - completely missed this. trying it out now :)

looks good - works for a nice fluent solution!

Thanx you @maxandersen !!! Will prepare a release :)

Merged!