Question

I'm trying to write a simple Perl script to send an Instant Message. Jabber seemed like it might be the most conducive protocol. But the following script fails:

#!/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");

It says:

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.

As cartman's answer points out, the code should actually be

#!/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");

But that fails with the following error:

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

I do have the Authen::SASL cpan module installed.

Was it helpful?

Solution

Jabber::SimpleSend is the easier way to interact with a standard Jabber server but don't let the module name mislead you: gtalk is indeed a bit different, requiring TLS encryption (that Jabber::SimpleSend won't do) and a hostname change. You will get better results using Net::XMPP and dealing directly with its API.

See http://www.gridpp.ac.uk/wiki/Nagios_jabber_notification for a well-commented, fully working implementation in 75 lines of perl using Net::XMPP. It's inteded to send nagios notifications but it does exactly what you need.

OTHER TIPS

I'm not familiar with the code, but that line in XML::Stream is where the module begins a select() loop. Line 523-524 is where is passes IO::Select a socket to the destination server, and IO::Select itself passes a blessed reference, which should never be undef the way XML::Stream uses it.

Something is probably modifying the "SELECT" element of the XML::Stream object in the Jabber modules, possibly in a misguided attempt to correct a server connection error. I'm sorry I couldn't be more specific.


In response to the update:

These are odd errors, and I've been meaning to look inside the Jabber modules anyway, so I took at look at the source. The following is based on looking at the latest versions of the modules used available from CPAN. This is probably not very useful unless you want to start subclassing these modules and adding code to see where something unexpected happens. (You can skip the next paragraph if you're not interested in the Jabber modules' internals.)

From the updated information, I've traced it to the point where Authen::SASL::Perl croaks on line 41. It needs a result from $parent->mechanism, and there are two possible causes, assuming Authen::SASL isn't broken. Either it's being called incorrectly with no arguments from Net::XMPP::Protocol (line 2968), which seems unlikely, or the "mechanisms" it set in the constructor for Authen::SASL don't exist. Net::XMPP::Protocol defines the "mechanisms" (GetStreamFeature called, line 2958; that method defined around line 3340) with return $self->{STREAM}->GetStreamFeature($self->GetStreamID(),$feature);, where $feature is just a string passed from the callee and the id part of the XML::Stream object's session.

Based on the original XML error and the possibility of the session id going bad, it appears that the server either sends bad data at some point unexpected to XML::Stream and unaccounted for by the modules using it. I'm not convinced that foo%40gmail.com@talk.google.com is the right user name format, but I don't know how that could be causing these errors without the Jabber server doing something wrong.

I would start fresh with different user names on a different server and see if Jabber::SimpleSend works at all, then try to capture the server's output somehow to see what XML::Stream is choking on.


Update: For what it's worth, I installed the module and I'm getting the exact same errors. Authen::SASL::Perl::PLAIN and all other prerequisites do exist. And when I set the user name to gmailaccountname@talk.google.com and enabled global warnings (eg, #!/usr/bin/perl -w or perl -w filename.pl), XML::Stream reveals a bunch of undefined value problems, and SimpleSend actually spits out the warning "Could not connect to Jabber server"! (No, I don't know what that really means :().


Update: I was trying to install Net::Jabber::Bot (I gave up after some ssl module errors) to see if it would solve anything, and I noticed its constructor has this option and note:

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

which reinforces the idea that the server's doing something unusual, which XML::Stream doesn't bother to throw an exception for.

Your username should be me@gmail.com but the server name is talk.google.com. So the first parameter should be me@gmail.com@talk.google.com, but I am not sure if Perl can grok that double @ signs. You may try to escape first @ with %40 so that the first parameter is me%40gmail.com@talk.google.com .

Update I: About the second error, looks like you are missing SASL authentication modules. GMail uses SASL Plain authentication. So do you have /usr/local/lib/perl5/site_perl/5.10.0/Authen/SASL/Perl/PLAIN.pm file ?

Looks like you require Authen::SASL::Cyrus (the C implementation) or Authen::SASL::Perl (the Perl implementation) to be installed as well as Authen::SASL (which simply tries to find the best option installed on your machine, and, for you, finds neither).

Check to see if you have one of them installed.

That's my reading of the source and the manual - I've not tested this, ymmv.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top