I have built an external openfire component based on the Whack library by extending the AbstractComponent class. I want clients to subscribe to my component and receive presence notifications when the component goes online and offline. So my question is how we can deal with presence and presence subscriptions for external component based on AbstractComponent?
Currently I can respond to the presence request by using the handlePresence() method but how do should I add clients to the component roster (does external components allow for roster in the first place)?
#Override
protected void handlePresence(Presence presence){
if (presence.getType() == Presence.Type.subscribe){
System.out.println("The component has received Subscribtion request.");
Presence original = presence;
Presence response = new Presence();
//Swap the sender/recipient fields
response.setTo(original.getFrom());
response.setFrom(original.getTo());
//Convert the text to upper case
response.setType(Presence.Type.subscribed);
send(response);
}
}
Components do not have a roster provided by the server. You can store your own roster in a database if you need to. Some applications can get away with no roster at all (when they simply want to appear online to everyone).
To appear online to everyone (simplest approach, no roster storage required):
When you receive <presence type="subscribe"/> reply with <presence type="subscribed"/>
When you receive <presence type="probe"/> reply with <presence/> (or whatever status you want to be shown as)
To store a roster requires a bit more work, but allows you to keep track of who is authorized to see your presence, and whose presence you are authorized to see. In some cases you might prefer to use a normal client connection here, if you don't want to manage your own roster. Jack Moffitt wrote a blog post on the idea here: http://metajack.im/2008/08/04/thoughts-on-scalable-xmpp-bots/
Note that throughout this post I omit the 'to' and 'from' attributes on stanzas. It is up to the component to put a 'to' and 'from' on outgoing stanzas. All incoming stanzas will have a 'to' and 'from'.
Displaying a component's presence to users
The basic incoming stanzas you need to handle are:
<presence type="subscribe">
The sender wants to subscribe to your presence updates. You can either approve or decline this. If you approve, you should store the sender's JID in your database so you know you need to send them your presence updates when necessary.
Specification: http://xmpp.org/rfcs/rfc6121.html#sub-request-handle
<presence type="unsubscribe">
The sender wants to stop receiving presence updates from you. You should remove them from the list of people subscribed to your updates, and then send back <presence type="unsubscribed"> and <presence type="unavailable">.
Specification: http://xmpp.org/rfcs/rfc6121.html#sub-cancel-inbound (though the text is tailored more towards servers than components here).
<presence type="probe">
The sender is asking for your current presence. Simply reply with your latest presence stanza for that user. This is typically sent by the user's server when they log in.
Receiving presence of users in a component
Additionally if you want the component to know the presence of users, you need to send a subscription request to them: <presence type="subscribe">. You should be prepared to receive either an approval (<presence type="subscribed">) or denial (<presence type="unsubscribed">).
When the component first comes online, it can fetch the current presence for a user by sending <presence type="probe"> to each user. There is no need to do this more than once per user while the component is running - the user's server will automatically send you presence updates if the user approved your subscription request as above.
Related
If I have a bot in a group, and I want to make the bot respond only if it was mentioned in the message, is there any way to achieve this?
When a message contains a mention by username then the Message object contains a MessageEntity with MessageEntity.type equals to 'mention' (since bots always have username).
You can check MessageEntity.offset to get the position of the entity in the text of the message, then parse the text of the message to check if the username mentioned is you bot's username.
Consider that by default bots run in privacy mode
A bot running in privacy mode will not receive all messages that
people send to the group. Instead, it will only receive:
Messages that start with a slash ‘/’
Replies to the bot's own messages
Service messages (people added or removed from the group, etc.)
Messages from channels where it's a member
I'm sending automated emails using java mail to my colleagues in different states (all within our company). I set the return path as their manager's emails. In case the recipient's mail box is full, their manager would get an undeliverable email notification.
Is there any way I can customize that undeliverable message, so that their managers who receive the undeliverable notification, would also get instructions on how to handle those emails and "couch their subordinates" ?
I couldn't find any documentation on this. Is this even possible ?
The undeliverable message is sent by your mail server. Depending on the mail server you're using, you might be able to customize the returned message.
For some cases you could try to enable the mail.smtp.reportsuccess session property and use the results to gather the invalid addresses. Then use the com.sun.mail.dsn to create a custom delivery status notification to send it to the return address.
I am currently building an chat application for android.
XMPP Server: MongooseIM.
XMPP Client: Smack 4.1.5.
Currently the logged in user keeps getting presence updates from his roaster buddies. I would like to receive these presence updates only when the application is open and block them when the application is closed. Is there a way to achieve this behavior? I have tried using privacy list but with no luck.
This is what i have tried so far.
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(mXMPPConnection);
ArrayList privacyItems = new ArrayList();
PrivacyItem item = new PrivacyItem(PrivacyItem.Type.subscription, "to", false, 1);
item.setFilterPresenceIn(true);
privacyItems.add(item);
privacyManager.createPrivacyList("subscription", privacyItems);
I assume that you want to stay connected to receive message but want to limit the presence traffic.
ejabberd supports XEP-0352 Client State Indication, which does exactly this. When going to background switch your client to inactive mode and presence update will not be send. When going back to foreground, switch CSI state to active and you will receive the relevant presence update, optimised by removing redundant obsolete presence informations.
You can check ejabberd documentation: mod_client_state
I have a scenario whereby I want to inform users of my site that someone has commented on an article on which they have also commented. This is a lot like the way that SO notifies me when someone responds to a question!
Server side, I persist the comment and then look up all users who commented on the same article. I then broadcast (I'm using Atmosphere):
PushContext pushContext = PushContextFactory.getDefault().getPushContext();
for(User u : users){
// channel name, message
pushContext.push("/user_" + u.id, "someone commented! blah blah");
}
The "channel" I am broadcasting to is the user's "own" channel, since I don't want every user to be notified. I use the user's ID in the channel name to achieve this.
Is this the right way to do ensure only relevant users get notified?
I guess I also want to do two more things:
Only push to users whom I believe are still online. If they aren't online, then it's a waste of resources pushing to them.
Encrypt the message, because otherwise anybody could listen for my messages, if they know my user ID.
Is there anything else I need to think of?
SO uses WebSockets, for example when a comment is made on this posting, you get a notification in your status bar at the top left of the SO page.
When the page is loaded, the browser makes a protocol upgrade request which looks like this:
Request URL:ws://sockets-se.or.stackexchange.com/
Request Method:GET
Status Code:101 Switching Protocols
Request Headersview source
Connection:Upgrade
Cookie:__qca=P0-1697817643-1763440830313; __utma=27376923.959753990.1338240830.1353943751.1384115154.33; __utmc=27693525; __utmz=27699983.1356175156.31.31.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)
Host:sockets-se.or.stackexchange.com
Origin:http://stackoverflow.com
Sec-WebSocket-Extensions:x-webkit-deflate-frame
Sec-WebSocket-Key:6qFl45+6gZ526yMMo79zWQ==
Sec-WebSocket-Version:13
Upgrade:websocket
(Key3):00:00:00:00:00:00:00:00
Response Headersview source
Connection:Upgrade
Sec-WebSocket-Accept:B4h2G+gi78iNZZXg+o6iAztgF1I=
Upgrade:websocket
(Challenge Response):00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
The socket is then open, and the server can send updates to the browser. For example, a notification of my comment is received by the browser as:
{"action":"1-question-12993099","data":"{\"a\":\"comment-add\",\"id\":12993099,\"commentid\":19334206,\"acctid\":1298157}"}
It doesn't contain the actual comment; it appears that this is simply used to tell the browser to show the red icon. When you then click, it makes a request to get the page, including the comment. The question ID (12993099), comment ID (19334206) and account ID (1298157) is contained in that frame.
I cannot see anything in the above which would stop some hacker creating a web socket to listen to your notifications. The cookies look to me to be Google Analytics cookies to me, or at least the second and third ones do. Perhaps the first is some code which you wouldn't know, had I not just published it (no worries, I change it!).
In your example of Atmosphere, I know that when Web Sockets does not work, it defaults to long polling, which then requests a URL with the channel name in it. So you could get the client to generate a channel name which only it would know and associate that with the logged in user. But anyone sniffing the network would again have access to your traffic, so you'd have to secure it using secure web sockets (WSS) and HTTPS (for long polling fallback).
I have to send messages to many clients. But many of them bounce back. I want a list of those email addresses. How can I get that list from my Java application?
Make a special email address bounced#yourdomain.com where you will capture all bounced emails for analysis.
Add the following header to your sent emails:
Return-Path: <bounced#yourdomain.com>
Now the emails are going to bounce back to that address.
Read emails at that address from your java program from time to time, for example via IMAP (or depending on your server via a notification interface/whatever), and when you see an email address record it in your database
Note that if you are doing a newsletter app, you should not blacklist the email from the first time, but make count it's bounces, and blacklist it after 3-4 bounces (some people set their email to bounce when they go in vacation and such, so they need special taking care of).
I solve this question using
SMTPMessage msg = new SMTPMessage(getSession());
msg.setEnvelopeFrom(bounceAddr);
Please see the javamail doc and see it:
void com.sun.mail.smtp.SMTPMessage.setEnvelopeFrom(String from)
Set the From address to appear in the SMTP envelope. Note that this is different than the From address that appears in the message itself. The envelope From address is typically used when reporting errors. See RFC 821 for details.
If set, overrides the mail.smtp.from property.
Parameters:
from the envelope From address