2

我正在尝试编写一个简单的 Perl 脚本来发送即时消息。Jabber 似乎是最有利的协议。但以下脚本失败:

#!/usr/bin/env perl
use Jabber::SimpleSend qw(send_jabber_message);
send_jabber_message('me@gmail.com',
                    'CENSORED',
                    'you@gmail.com',
                    'subject test',
                    "body test");

它说:

Can't call method "can_read" on an undefined value at 
/opt/local/lib/perl5/site_perl/5.8.9/XML/Stream.pm line 1421.

正如卡特曼的回答所指出的,代码实际上应该是

#!/usr/bin/env perl
use Jabber::SimpleSend qw(send_jabber_message);
send_jabber_message('me%40gmail.com@talk.google.com',
                    'CENSORED',
                    'you%40gmail.com@talk.google.com',
                    'subject test',
                    "body test");

但这失败并出现以下错误:

No SASL mechanism found
 at /usr/local/lib/perl5/site_perl/5.10.0/Authen/SASL.pm line 74

我确实安装了 Authen::SASL cpan 模块。

4

4 回答 4

3

Jabber::SimpleSend 是与标准 Jabber 服务器交互的更简单方法,但不要让模块名称误导您:gtalk 确实有点不同,需要 TLS 加密(Jabber::SimpleSend 不会这样做)和主机名改变。使用 Net::XMPP 并直接处理其 API,您将获得更好的结果。

请参阅http://www.gridpp.ac.uk/wiki/Nagios_jabber_notification以获得使用 Net::XMPP 在 75 行 perl 中得到充分注释的完整工作实现。它旨在发送 nagios 通知,但它完全符合您的需要。

于 2009-05-07T14:27:41.707 回答
2

我不熟悉代码,但 XML::Stream 中的那一行是模块开始 select() 循环的地方。第 523-524 行是将 IO::Select 一个套接字传递给目标服务器的地方,而 IO::Select 本身传递了一个祝福引用,这绝不应该像 XML::Stream 那样使用它。

某些东西可能正在修改 Jabber 模块中 XML::Stream 对象的“SELECT”元素,这可能是在错误地尝试纠正服务器连接错误。对不起,我不能更具体。


响应更新:

这些是奇怪的错误,无论如何我一直想查看 Jabber 模块的内部,所以我查看了源代码。以下内容基于查看可从 CPAN 获得的模块的最新版本。除非您想开始对这些模块进行子类化并添加代码以查看意外发生的位置,否则这可能不是很有用。(如果您对 Jabber 模块的内部结构不感兴趣,可以跳过下一段。)

从更新的信息中,我追踪到了 Authen::SASL::Perl 在第 41 行发出的声音。它需要 $parent->mechanism 的结果,并且有两个可能的原因,假设 Authen::SASL 不是没坏 要么是在没有来自 Net::XMPP::Protocol 的参数(第 2968 行)的情况下错误地调用它,这似乎不太可能,要么它在构造函数中为 Authen::SASL 设置的“机制”不存在。Net::XMPP::Protocol 定义了“机制”(GetStreamFeature 被调用,第 2958 行;该方法在第 3340 行周围定义)return $self->{STREAM}->GetStreamFeature($self->GetStreamID(),$feature);,其中 $feature 只是从被调用者传递的字符串和 XML::Stream 对象的 id 部分会议。

根据原始 XML 错误和会话 ID 变坏的可能性,服务器似乎在某个时间点向 XML::Stream 发送了错误的数据,并且使用它的模块无法解释。我不相信 foo%40gmail.com@talk.google.com 是正确的用户名格式,但我不知道如果 Jabber 服务器没有做错什么,这会导致这些错误。

我会在不同的服务器上使用不同的用户名重新开始,看看 Jabber::SimpleSend 是否有效,然后尝试以某种方式捕获服务器的输出以查看 XML::Stream 阻塞的内容。


更新:对于它的价值,我安装了模块并且我得到了完全相同的错误。Authen::SASL::Perl::PLAIN 和所有其他先决条件确实存在。当我将用户名设置为 gmailaccountname@talk.google.com 并启用全局警告(例如,#!/usr/bin/perl -w 或 perl -w filename.pl)时,XML::Stream 会显示一堆未定义的值问题,SimpleSend 实际上吐出警告“无法连接到 Jabber 服务器”!(不,我不知道这真正意味着什么:()。


更新:我试图安装 Net::Jabber::Bot (在一些 ssl 模块错误后我放弃了)看看它是否能解决任何问题,我注意到它的构造函数有这个选项并注意:

gtalk => 0 # Default to off, 1 for on. needed now due to gtalk differences from std jabber server.

这强化了服务器正在做一些不寻常的事情的想法,XML::Stream 不会费心为其抛出异常。

于 2009-04-29T00:35:44.897 回答
1

您的用户名应该是 me@gmail.com,但服务器名称是 talk.google.com。所以第一个参数应该是 me@gmail.com@talk.google.com,但我不确定 Perl 是否可以理解双 @ 符号。您可以尝试使用 %40 转义第一个 @ ,以便第一个参数是 me%40gmail.com@talk.google.com 。

更新 I:关于第二个错误,您似乎缺少 SASL 身份验证模块。GMail 使用 SASL 普通身份验证。那么你有 /usr/local/lib/perl5/site_perl/5.10.0/Authen/SASL/Perl/PLAIN.pm 文件吗?

于 2009-05-02T22:17:40.653 回答
1

看起来您需要安装 Authen::SASL::Cyrus (C 实现)或 Authen::SASL::Perl (Perl 实现)以及 Authen::SASL (它只是试图找到安装在你的机器,对你来说,两者都找不到)。

检查您是否安装了其中之一。

那是我对源代码和手册的阅读-我还没有测试过,ymmv。

于 2009-05-04T09:57:00.480 回答