How to get muc room vcard trough ejabberd admin API? - xmpp

so as the tittle suggests I cannot seem to get vcard info from muc rooms when using ejabberd's admin api as available here: https://docs.ejabberd.im/developer/ejabberd-api/admin-api/#get-vcard .
Neither get_vcard (as well as get_vcard2) nor set_vcard work when I try those on a MUC room.
I am doing, for instance:
ejabberdctl get_vcard my-room.jid conference.myhostname.com NICKNAME
and getting the errors:
** exception error: {module_not_loaded,mod_vcard,
<<"conference.myhostname.com">>}
in function gen_mod:get_module_opts/2 (src/gen_mod.erl, line 338)
in call from gen_mod:get_module_opt/3 (src/gen_mod.erl, line 318)
in call from gen_mod:db_mod/3 (src/gen_mod.erl, line 352)
in call from mod_vcard:get_vcard/2 (src/mod_vcard.erl, line 311)
in call from mod_admin_extra:get_vcard_content/3 (src/mod_admin_extra.erl, line 1153)
in call from mod_admin_extra:get_vcard/3 (src/mod_admin_extra.erl, line 1132)
in call from ejabberd_ctl:call_command/4 (src/ejabberd_ctl.erl, line 315)
in call from ejabberd_ctl:try_call_command/4 (src/ejabberd_ctl.erl, line 280)
I have all the same requests successfully working on normal users.
Is this feature simply not supported for MUC rooms?
EDIT: btw I am using ejabberd 20.4.0.
Thanks in advance!

There is no mention to vcards in XEP-0045, and no mention to MUC rooms in XEP-0054, so I wonder if this is an unexpected "feature".
In ejabberd, the MUC room vcard is not stored using mod_vcard, instead it's stored in the room own configuration. For that reason, the get_vcard commands do not work, as they use mod_vcard, and mod_vcard knows nothing about MUC or MUC room vcards.
I've now implemented support for MUC room vcard in the get_vcard commands, see:
https://github.com/processone/ejabberd/commit/19019bbe32be2074e3b78ac13fdfc30c260fff5e
Regarding setting a MUC room vcard, right now the only way would be using change_room_option, and setting the whole room vcard.

Related

Smack throws NullPointerException in Roster's presence listener

I'm using Smack with android chatting applications and recently I have updated Smack to version to 4.3.0 and getting some error in fabric. It is a NullPointerException inside of Smack:
Fatal Exception: java.lang.NullPointerException
Attempt to invoke virtual method 'int java.lang.Object.hashCode()' on a null object reference
java.util.concurrent.ConcurrentHashMap.get (ConcurrentHashMap.java:772)
org.jivesoftware.smack.roster.Roster.getPresencesInternal (Roster.java:374)
org.jivesoftware.smack.roster.Roster.getOrCreatePresencesInternal (Roster.java:388)
org.jivesoftware.smack.roster.Roster.access$1100 (Roster.java:94)
org.jivesoftware.smack.roster.Roster$PresencePacketListener$1.run (Roster.java:1502)
org.jivesoftware.smack.AsyncButOrdered$Handler.run (AsyncButOrdered.java:121)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1113)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:588)
java.lang.Thread.run (Thread.java:818)
"Use the source, Luke (and study the relevant open standard)" Obi-Wan Kenobi
Smack is open soure, so let us look at the source: One interesting part is
org.jivesoftware.smack.roster.Roster.getPresencesInternal (Roster.java:374)
which reads
Map<Resourcepart, Presence> entityPresences = presenceMap.get(entity);
Source: https://github.com/igniterealtime/Smack/blob/4.3.0/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java#L374
We also find that presenceMap is declared as follows
private final Map<BareJid, Map<Resourcepart, Presence>> presenceMap = new ConcurrentHashMap<>();
Source: https://github.com/igniterealtime/Smack/blob/4.3.0/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java#L168
So it is a ConcurrentHashMap, which matches with the stacktrace. It is obvous that entity above is null, which is the cause of the NullPointerException.
Now we need to walk the call stack up (or down, depening on your point of view), to determine where entity origins from. Here the interesting part is
org.jivesoftware.smack.roster.Roster$PresencePacketListener$1.run (Roster.java:1502)
which reads
userPresences = getOrCreatePresencesInternal(key);
Source: https://github.com/igniterealtime/Smack/blob/4.3.0/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java#L1562
so enitty is key here. Which is declare and define just a few lines above
final BareJid key = from != null ? from.asBareJid() : null;
Source: https://github.com/igniterealtime/Smack/blob/4.3.0/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java#L1562
So in case from is null, keywill also be null. Which later causes theNullPointerException. Looking at the code, we find that this is caused by a presence XMPP stanza without a from` attribute set.
The question is now if those stanzas are legal in XMPP. To determine that, we need to have a look at the specification. The relevant part is [RFC 6120 ยง 8.1.2.1 4.],1, which states
When the server generates a stanza from the server for delivery
to the client on behalf of the account of the connected client
(e.g., in the context of data storage services provided by the
server on behalf of the client), the stanza MUST either (a) not
include a 'from' attribute or (b) include a 'from' attribute
whose value is the account's bare JID (localpart#domainpart).
So a missing 'from' attribute is generally allowed and is equal to the "account's bare JID".
Now the question is: Are there any presence stanzas specified send from the server to the client which do not have a 'from' attribute? I could not find any while reading the related RFC 6121. And I am not aware when this should ever happen (I possibly could be missing someting). But right now this appears to be a bug in the entity which creates those presence stanzas, which is the used XMPP server implementation.
(What XMPP server implementation do you use?).

IMAP - search for all messages in a conversation thread by references

Please don't mark this as a duplicate of 16816425 because that one has incorrect search syntax which is corrected in this question. It is also not a duplicate of 6088914 because this question is about IMAP, not Gmail's IMAP extension.
I'm working on an IMAP client, and would like to be able to find a list of all messages that are referenced in a conversation thread.
I know that the "References" header includes a list of messages referenced in a conversation, so I tried searching it like so:
C: 3 SEARCH HEADER References {48}
S: + go ahead
C> <C63EF8D6-6874-401B-9E8C-B1D63B633246#gmail.com>
But it returns nothing. I've successfully searched for a single message using the "Message-ID" header, like so:
C: 3 SEARCH HEADER Message-Id {48}
S: + go ahead
C> <8D7F7FD5-9CD8-4D4B-BC8B-E1A3BC217350#gmail.com>
Is there any way to do this using IMAP 4?
Of course, I manually checked that <8D7F7FD5-9CD8-4D4B-BC8B-E1A3BC217350#gmail.com> was in the "References:" field in some emails in that mailbox and that very email is in the same mailbox too.
The above test was done against GMAIL.
NOTE: A google search suggested that gmail doesn't support RFC5256. I am validating if searching "References:" works before falling back to modify the IMAP library to use Gmail-specific IMAP command X-GM-THRID.

How can I get the Flagged mail Exchange

When I mark the message in this way
I use the method
var uids= folder.Search(SearchQuery.DeliveredAfter(DateTime.Parse("2016-9-29")).And(SearchQuery.Flagged));
cannot get the flagged mail,
but when I use methodfolder.AddFlags(new UniqueId(1693), MessageFlags.Flagged, false);
folder.Expunge();
the mail will be flagged and When I use the method
var uids= folder.Search(SearchQuery.DeliveredAfter(DateTime.Parse("2016-9-29")).And(SearchQuery.Flagged));
I can get the flagged mail,I don't know why, and how can I get the flagged mail?
You are conflating 2 different ways of "flagging" a message. Outlook does not set the MessageFlags.Flagged flag, that's why Search() does not find it.
Most likely Outlook either does not store anything on the IMAP server at all (and that state is stored locally in the .pst file) -or- it stores a custom UserFlags string on the IMAP server that you will need to figure out.
If you know of a particular message on your IMAP server that has this custom flag, you can use the Fetch() method with MessageSummaryItems.Flags to request what flags are set. Then, you can examine the item.UserFlags and hope that you find what you are looking for.

phpmailer error codes for outcome processing

I am building a mailout capability and it is working OK as far as it goes. However, I want to distinguish between various potential (high level) outcomes in order to determine what happens to each message after the current send attempt.
This must be a common requirement so I seem to be missing something pretty obvious, but I can't find anything that addresses it, either here or via Google or on PHPMailer site or .. . Possibly because there are so many questions about specific errors that I just can't find anything useful in all the other results.
At very high level:
Attempt send, and assess resulting error/result. Identify whether this message has been sent, must be retried later, or failed permanently.
- success -> update message status as 'SENT: OK'
- sent, but some issues (e.g. one recipient failed, others processed OK)-> 'SENT: some error'
- failed, due to temporary problem (e.g. connection problem, attachment open) -> 'TRY LATER'
- failed, due to message-specific problem that we should NOT try to resend-> 'FAILED: some error'
As I was unable to find an existing resource with e.g. a table of errors, I spent some time working through the phpmailerException code to try to build one myself, but it's not simple because a) they don't appear to have been designed in terms of this kind of grouping logic, b) it is not easy to uniquely identify a particular error: PHPMailer provides human-friendly messages, which are different in different languages, rather than an identifiable code - given that my solution will need to work across different language installations that's a problem!
Obviously SMTP itself provides a range of errorcodes which I could potentially use for this purpose, but how do I access these via PHPMailer? (This would work for me as I only use SMTP at this point - however, this would NOT work if other message transport like sendmail was used, so I would prefer a PHPMailer solution)
If you want individual result codes for individual address, you really need to send each message separately. If you do get errors on some recipients, they will be listed in the ErrorInfo property - look in the smtpSend function to see how the error string is assembled. I agree that it's not especially easy to parse that info out. The error messages in PHPMailer are generally more for the developer than the end user, so the translations are not that significant. You can get slightly more information about errors if you enable exceptions rather than relying only on return values.

Openfire sends empty (without stamp attr) jabber:x:delay extension to smack

I receive offline message from openfire server, but it contains empty jabber:x:delay extension.
The message I receive is:
<message id="qU7N8-64" to="ac1#server.jj.ru" from="ac2#server.jj.ru/4847791" type="chat">
<body>test message</body>
<delay xmlns="urn:xmpp:delay"></delay>
<x xmlns="jabber:x:delay"></x>
</message>
This message I receive with smack library.
But when I connect to openfire with Miranda IM, openfire sends extension jabber:x:delay with data.
Why openfire sends empty jabber:x:delay only to smack library?
Add this line after connection.
ProviderManager.getInstance()addExtensionProvider("x","jabber:x:delay", new DelayInformationProvider());
Openfire doesn't do anything different since it doesn't know (or care) what client is connected. The packet you are showing is very peculiar, since it contains both the legacy and current versions of Delayed Delivery, but with missing required attributes in both.
Try running with VM argument -Dsmack.debugEnabled=true set. Then check the incoming raw packets for the actual message content. There is most likely one of 2 things happening.
The time is missing, so Miranda is compensating by populating it with some default value, like current date.
The time format is not according to spec, so the parser in Smack is omitting it.