ejabberd 16.08与18.01版本vCard自定义字段行为差异求助
解决ejabberd 18.01中Smack设置vCard自定义字段失效的问题
我之前碰到过类似的版本兼容坑,ejabberd从16.08到18.01对vCard的处理逻辑做了不少严格化调整,尤其是自定义字段的存储规则变化很大。下面是我排查和解决这个问题的具体思路:
可能的核心原因
- ejabberd对vCard字段的验证收紧:18.01版本的
mod_vcard模块默认可能只允许存储标准vCard字段(比如FN、N、EMAIL这类),非标准的自定义字段会被直接过滤,不会存入数据库。 - Smack的
setField格式不兼容:旧版本ejabberd接受直接添加自定义元素,但18.01要求自定义字段必须遵循vCard标准的扩展格式(用<X>元素配合TYPE属性),而Smack的setField生成的XML不符合这个规范,导致字段无法被识别存储。
具体排查与解决步骤
1. 先定位问题环节:存储还是解析
开启Smack的调试模式(初始化Connection时设置config.setDebuggerEnabled(true)),查看发送和接收的XML内容:
- 检查发送的vCard请求里,
myCustomField是否被正确包含在<vCard xmlns='vcard-temp'>节点下。 - 获取vCard时,看ejabberd返回的XML里有没有这个自定义字段。如果返回里没有,说明ejabberd没存储;如果有但Smack没解析出来,就是客户端解析逻辑的问题。
2. 调整ejabberd配置(针对存储问题)
打开ejabberd的配置文件(通常是ejabberd.yml),检查mod_vcard的配置项。18.01新增了控制自定义字段的参数,添加以下配置后重启ejabberd:
mod_vcard: allow_custom_fields: true
这个配置会明确允许存储非标准的自定义vCard字段。
3. 修改Smack代码,适配标准vCard扩展格式
如果ejabberd要求遵循标准扩展规范,就不能再用setField方法,改用标准的<X>元素添加自定义字段:
VCard vCard = new VCard(); vCard.setFirstName("MyName"); // 方式一:使用Smack内置的扩展字段方法 vCard.setExtendedField("myCustomField", "0002@0000@0000"); // 方式二:手动构建符合标准的XML元素(如果方式一无效) Element customExt = new Element("X"); customExt.setAttribute("TYPE", "myCustomField"); customExt.setText("0002@0000@0000"); vCard.addExtensionElement(customExt); // 保存vCard到服务器 vCard.save(connection);
获取自定义字段时,也要对应使用getExtendedField方法:
VCard retrievedVCard = new VCard(); retrievedVCard.load(connection); String customValue = retrievedVCard.getExtendedField("myCustomField");
4. 验证ejabberd的存储状态
如果以上步骤都无效,可以直接查看ejabberd的数据库(比如Mnesia或MySQL)里的vCard存储记录,确认自定义字段是否被写入。如果数据库里没有,说明mod_vcard确实过滤了该字段,需要进一步查看ejabberd的提交记录,看是否有关于vCard字段白名单的修改。
内容的提问来源于stack exchange,提问作者Bruno Louzada
相关产品推荐
相关产品推荐

