IMAP - JavaMail - How to know which messages to process? - jakarta-mail

What I want to achieve:
I am coding a Java program that uses IMAP to connect to some gmail accounts every 5 minutes and extract information from some messages.
I want to check all the messages (incoming and outgoing) and take only the ones I have not processed. By "processed" I do not mean only "read" or "seen" messages. My application does not care whether or not another user has accessed that account and read a message. My application needs to keep track of which was the last message it processed and, the next time it goes through the messages, start with the first non-processed message.
I do not want to change anything in the messages. I do not want to mark them as seen or read.
What I have implemented:
Establish IMAP connection.
Open and access all messages in "[Gmail]/All Mail" folder.
What I have tried:
I have been reading about UID and message number, but I am not sure if any of them could help me achieve what I want. Maybe UID could, but: how do I retrieve it with JavaMail?
I found Folder.getMessages(int start, int end), but I think it refers to the index of the message in a folder, which I believe can easily change.
Can anyone provide some guidance at what is the best approach to take here?
Thanks!

IMAP UIDs are relative to the folder containing the message. I don't know how Gmail handles UIDs for messages in the "[Gmail]/All Mail" folder, but if it does the right thing you could use the UIDFolder interface to get the UIDs. And as described, once you've processed a certain UID, all the new messages will have larger UIDs, which can make processing more efficient.
The alternative is to use Message-IDs, which has a different set of problems...

Related

Show facebook chat bot has seen message

How can I send a facebook messenger response that acknowledges seeing the input but does not deliver a message?
Use Case:
I am attempting to improve my chat bot by better handling of multiple rapid inputs.
For example:
User: Order a pizza.
Bot: What toppings would you like?
User: cheees
User: cheese
It usually happens if the user misspelled a word and quickly sends a corrected spelling as in the example.
The bot currently processes the first input of cheees and prepares a response.
Then processes the second input of cheese as if it is an answer to the undelivered response.
So I am detecting if a second input is received before delivering the first in order to cancel that response, but I want to at least show that the first input was seen while waiting for the second input's response to be delivered.
It's definitely possible. There are sender actions. You're looking for mark_seen what exactly makes messages being seen by your bot.
I would have several recommendations here:
Always mark messages as seen. From the user perspective it shows that there is someone on the other side.
Prior to sending a message, you should consider sending a typing indicator for a second. This is how the user is used to see chat with his friends.
You could also wait one or two seconds before processing the user input if you receive something else.
We've build in these solutions into Amio Bot Builder. Feel free to use it or copy it.

registration process in sip protocol

I am new to sip protocol,i went through the basics and have these following doubts
1)In registering process when i captured using wireshark,i figured out that from and to headers are same when i read rfc 3261,it says that "to" header indicates whose registration is to be done and from" indicates person responsible for registration.The to and from fields are same unless it is a third party registration.it is not clear to me,how can it both be same and what is a third party registration.
2)Does sip have any keep alive mechanism,in zoiper we have the option of giving expiry time (3600 default),but for registration it is 70,for subscribe it is 60 and for invite it is 3600. how these values are automatically selected?
3)The user agent finds registrars using configuration.dns look up and multi-casting.In what case multi casting is preferred,pls explain the method also
what i did was ,installed an asterisk server ,zoiper applicationregister msg capture is attached,created a zoiper account,captured using wireshark in loop back mode.attaching screenshots of captures.Thanks in Advance
Regarding to and from fields in REGISTER:
The "from" field here is just a logical field which should not be checked. If differs from the "to" field that means that "from" registers in name of "to".
But I can't think of any scenario when this should be checked (maybe it can be used for something -app specific- in some complicated scenario). You should just follow the usual authentication process (digest auth or other) and skip this field.
Regarding point 2 (expiry time):
Your mentioned settings in Zoiper are just arbitrary.
Low values (below 200) can be used if client or server doesn't support NAT keep alive (via NOTIFY or simple \r\n\r\n messages). In this case the REGISTER message will keep alive the UDP binding in NAT routers.
Higher values can save some server side processing work and CPU resources
I usually recommend a 600 sec expire timer and 40 sec NAT keep-alive messages.
For INVITE the expire field actually means maximum ring time and it is rarely used.
Regarding point 3 (finding registrars):
The SIP server (registrar server) is usually entered manually in client configuration or set by auto-provisioning. If the server is on the same LAN, then you might be also to detect it also by multicast but this is rarely used.
Here is a good tutorial.

Camel Multicast Subroutes out of order

I have a scenario where I get as input Message A. Message A must then be split into 3 different types of message, and forwarded to other routes. It is important that the messages arrive in a precise order, Ie. A-1 must be sent before A-2, which must be sent before A-3.
To do this I have done the following (outline):
from("activemq:queue:somequeue-local")
.multicast().to("direct:a1","direct:a2","direct:a3");
from("direct:a1)
//split incoming message and prepare output document for A-1
.to("activemq:queue:otherqueue")
.from("direct:a2)
//split incoming message and prepare output document for A-2
.to("activemq:queue:otherqueue")
.from("direct:a3)
//split incoming message and prepare output document for A-3
.to("activemq:queue:otherqueue")
And in another context, responsible for sending out the info to the external system, I have
.from("activemq:queue:otherqueue?maxMessagesPerTask=1&concurrentConsumers=1&maxConcurrentConsumers=1")
// do different stuff based on which type we are called with then end with
.beanref("somebean","writeToFileAndCallImportbat");
Now, my problem is, that when I get to the receiver, I get the messages in random order. Sometimes A-1,A-3,A-2, sometimes right, A-1,A-2,A-3.
I have tried adding JMSXGroupID and JMSXGroupSeq to the messages, but without any luck.
I have also tried skipping the MQ part entirely, and use direct-vm: to call the shared receiver, but then it looks like I have three simultanious invocations of the receiver at once, and still in random execution order.
I was under the impression that multicast would run sequential, unless otherwise prompted to?
Is there something fundamentally wrong with the approach taken?
I am using Camel version 2.12.
Or, said more plainly:
I would like a route that creates three different output messages, and executes a batch file on them, in order. How do I go about that?
If you use the Splitter pattern, have you checked to see if the streaming property is set to false.
If enabled then Camel will split in a streaming fashion, which means it will split the input message in chunks. This reduces the memory overhead. For example if you split big messages its recommended to enable streaming. If streaming is enabled then the sub-message replies will be aggregated out-of-order, eg in the order they come back. If disabled, Camel will process sub-message replies in the same order as they where splitted.
So, it turned out to not be a problem with multicast after all.
Rather, in each of my sub-routes, I did this:
.split(..stax(SpecialClass)).streaming()
.beanRef("transformationBean","somefunction")
.aggregate(constant("1"), new MyAggregator())
.completionTimeout(5000)
.completionSize(1000)
.to(writeToFileAndRunBat)
Which, I assumed meant "Process all elements in the split, and if you aren't finished in 5 seconds or after 1000 elements, break out".
I changed it to
.split(..stax(SpecialClass), , new MyAggregator()).streaming()
.beanRef("transformationBean","somefunction")
.end()
.to(writeToFileAndRunBat)
Coming to think of it, it makes perfect sense, as the first version couldn't really know when we were done, while the last (I assume) just iterate over all elements in the split and calls the Aggregator for each.
Also, I had to .end() in the first version. So I guess the whole thing was just acting random.

Swipe-delete messages only for current user

thanks for taking time looking at my question.
Ok so I'm working on this iPhone app. I'm responsible for the server side code. Client side is asking for a solution to delete private messages from the app. I have created a HTTP DELETE for them that deletes a specific message. But this request deletes the message from the database and that makes the message disappear for both users and not only the one that have choosen to delete it.
I've been thinking but I can't seem to find the best solution for this. What I need is a solution to only delete the message for the current user.
Should I add some columns in the database that tells which user the private message should be shown for? And when a user deletes the message from the app it only stops showing on that users phone. Or is there a better solution for this?
I need help with some brainstorming. I hope it is an OK question.
Thanks!
A physical delete should probably be avoided. The first couple of reasons I can think of:
how can you do proper testing/audit if the information you're looking for is gone?
legal issues: do you need some levels of data retention?
You can implement some form of logical delete, for example with an extra relation such as UserMessage( UserID, MessageID, MessageStatus ), where MessageStatus could be "unread", "read", "deleted", "important", "spam", etc. (you can map the status to an arbitrary integer if you prefer). When a user deletes a message, you simply change its status in the UserMessage relation, and from the UI side you hide messages which are marked as "deleted".

How to get avatars of users in Jabber using libstrophe

How can I fetch the avatars of all the contacts in a user's XMPP/Jabber roster?
I have previously asked this question, and while implementing the <presence> handler, I noticed that the presence items my app receives are of the form:
<presence to="me" from="contact">
...some other stuff here...
<x xmlns="vcard-temp:x:update"><photo>3FB991AA97D7701C21EAFE65FB866E4BFF1B927C</photo></x>
</presence>
The 3FB991AA97D7701C21EAFE65FB866E4BFF1B927C part looks like a SHA hash to me, but how can I get the actual avatar of the user in question?
vCard-based Avatars are specified in XEP-0153. You are correct that the photo element contains a SHA1 hash. Request the vCard of the person that sent you the hash:
<iq to='juliet#capulet.com'
type='get'
id='vc2'>
<vCard xmlns='vcard-temp'/>
</iq>
And fish the photo out of the response:
<iq to='romeo#montague.net/orchard'
type='result'
id='vc2'>
<vCard xmlns='vcard-temp'>
<PHOTO>
<TYPE>image/jpeg</TYPE>
<BINVAL>
Base64-encoded-avatar-file-here!
</BINVAL>
</PHOTO>
</vCard>
</iq>
You MUST cache based on that if you're going to use this protocol, and you'll really want to throttle how often you ask for avatars when you start up (particularly the first time a user logs in). Grabbing bajillions of avatars in a short amount of time will likely get you rate-limited by your server otherwise.
Also, be very careful about calculating your SHA1 hash. I've seen several clients that aren't terribly careful, who end up in an endless loop re-requesting the same avatar over and over.
I suggest negative-caching if you request an avatar and it doesn't match the hash you expect; cache the fact that you aren't going to get an answer for that hash, and don't ask for it again next time. The sender's SHA1 logic is likely wrong in some interesting way, and it's not going to get better the next time you ask.
Finally, some clients are written to try asking the sender's server for vCard data using XEP-0054 first as XEP-0153 says, then fall back on asking the sender's client directly by sending an IQ get for the vCard to the sender's full JID (user#domain/resource). Be prepared to deal with those requests on the sender's side.

Resources