2007年8月31日

穿透HTTP代理用 python-xmpp 给 google talk 发消息

python-xmpp 实现了 jabber 的大部分协议,能够用 python 发 jabber 消息
因为 google talk 本身就是基于 jabber 协议扩展的,所以也能给 google talk 发消息


早期的 python-xmpp 不支持 SSL 认证登录,所以只能登到一些非SSL认证的服务器,如 Jabber.org ,再给 google talk 的用户发消息,新版本已经解决这个问题。我现在使用的版本里 auth.py 是 v 1.35 2006/01/18 19:26:43
auth的参数是(节点,密码)
j_CLIENT.auth('shaozx','password')
第一次写的时候传入了 user@gmail.com 导致程序报错,后来跟踪调试,找到了第 143行,
它的本意是通过 user@gmail.com 截断得到 gmail.com,然后 DNS 解晰得到实际服务器 talk.l.google.com,
最后组合得到 user@talk.l.google.com,可是程序里几个变量都叫 server ,把自已也搞糊了!
140 if "DIGEST-MD5" in mecs:
141 node=Node('auth',attrs={'xmlns':NS_SASL,'mechanism':'DIGEST-MD5'})
142 elif "PLAIN" in mecs:
143 sasl_data='%s\x00%s\x00%s'%(self.username+'@'+self._owner.Server,self.username,se lf.password)
144 node=Node('auth',attrs={'xmlns':NS_SASL,'mechanism':'PLAIN'},payload=[base64.enco destring(sasl_data)])
145 else:
146 self.startsasl='failure'
147 self.DEBUG('I can only use DIGEST-MD5 and PLAIN mecanisms.','error')
148 return



我现在使用的python-xmpp里带的 transport .py 版本是 transports.py,v 1.28 2006/01/26 13:09:35
我修改屏蔽了第 182 行,否则使用代理服务器的时候总是报错,无法认证成功,还没想明白为什么
172 def send(self,raw_data):
173 """ Writes raw outgoing data. Blocks until done.
174 If supplied data is unicode string, encodes it to utf-8 before send."""
175 if type(raw_data)==type(u''): raw_data = raw_data.encode('utf-8')
176 elif type(raw_data)<>type(''): raw_data = ustr(raw_data).encode('utf-8')
177 try:
178 self._send(raw_data)
179 # Avoid printing messages that are empty keepalive packets.
180 if raw_data.strip():
181 self.DEBUG(raw_data,'sent')
182 #self._owner.Dispatcher.Event('', DATA_SENT, raw_data)
183 except:
184 self.DEBUG("Socket error while sending data",'error')
185 self._owner.disconnected()


如果是直接连接互联网,connect的写法如下:
j_CLIENT.connect()
中间如果有代理服务器,connect的写法如下:
j_CLIENT.connect(proxy={'host':'192.168.1.254','port':8080,'user':'guest','password':'cisco'})
注意 port 变量是整型,用程序代码生成proxy的时候格外要注意,不然会报错
可以参考 python-xmpp 的API文档


如果从命令行或其它地方传入文本,还需要注意编码转换
msg = unicode(msg,'gb18030').encode('utf8')
然后再发送出去
j_CLIENT.send(xmpp.Message('接收者',msg))


sendInitPresence(50)是置发送者状态为“在线”,置发送者状态后接收方会多弹出一个“XXX上线”的消息,我遇到过Palm上的一个jabber客户端,登录成功后就置了一个 0 ,然后死活发不出去消息,晕倒!


自带的程序原型 xsend.py 简化如下:
#!/usr/bin/python
# -*- coding: utf8 -*-
import xmpp

j_CLIENT=xmpp.Client('gmail.com',debug=[])
j_CLIENT.connect(proxy={'host':'192.168.1.254','port':8080,'user':'guest','password':'cisco'})
#j_CLIENT.connect()
j_CLIENT.auth('shaozx','password')
#j_CLIENT.sendInitPresence(50)
j_CLIENT.send(xmpp.Message('shaozx@gmail.com','test'))


写python的东西感觉架着滑翔机,
对老手来说是一种享受,而新手战战兢兢如履薄冰
最后祝你好运!

没有评论: