我们在使用facebook、开心网这些SNS网站的时候,里面有一项功能,就是通过邮件邀请好友,它可以导出你在Hotmail、Gmail、Yahoo、网易、新浪等Web Mail里的通讯录,然后给这些好友发送邀请信,这种病毒式营销推广方式起到了非常好的效果,facebook、开心网这些网站得以迅速壮大,这项功能也成了SNS网站的标配,从技术角度,我们就来探讨一下实现这项功能的原理和方法。
先说Gmail、Hotmail,Google和MS还是非常强大的,Google提供了Account Authentication API,它允许第三方的网站通过它的认证服务后,通过Google的Service取得用户的数据,包括通讯录等,MS也有Windows Live ID服务,不过我对微软的东西研究的不深,MSDN上找到的Windows Live ID SDK的资料,http://msdn.microsoft.com/en-us/library/bb404787.aspx。
接下来说说其他邮件系统的取得方式,主要的原理就是通过模拟用户行为,登陆Web Mail系统,取得用户通讯录的信息,很多Web Mail都提供通讯录CSV格式的下载服务,我们取得这个CSV文件就可以了,网易的邮件系统似乎已经不提供CSV文件的下载,那只能通过通讯录页面的HTML分析,来取得信息,所以相对复杂一些,而Sohu的通讯录虽然前端采用了Ajax,但后端取得通讯返回的格式是Json,应该是最方便。
接下来说模拟用户行为,其实就是通过在自己服务器端向Web Mail发送相对的HTTP请求,而模拟出用户登陆的行为,在Linux下,我们用cURL这个组件,在编译PHP的时候把cURL编译进去,使PHP支持cURL,cURL非常好用,也非常强大,在libcurl里有大多数开发语言的支持,如果使用JAVA的话,还可以使用Apache的HttpClient。
我们要模拟出用户登陆Web Mail的过程,我们就要对通常情况下,登陆Web Mail的HTTP请求过程有所了解,HttpWatch是一个非常好的工具,在做为插件安装倒IE和FireFox上,在IE或是FireFox里就可以看到所有的HTTP请求的信息了。
我们看看网易163的邮件的登陆过程
00:00:00.000 跳转提示
+ 0.000 0.231 1543 2352 POST 200 text/html; charset=UTF-8 http://reg.163.com/login.jsp?type=1&url=http://entry.mail.163.com/coremail/fcg/ntesdoor2?lightweight%3D1%26verifycookie%3D1%26language%3D-1%26style%3D35
0.231 1543 2352 1 request
00:00:00.462 0.177 0 0 GET (History Cache) image/x-icon http://reg.163.com/favicon.ico
00:00:00.469 网易电子邮箱 – 简约3.0Beta
+ 0.000 0.118 1703 604 GET 302 Redirect to http://g4a30.mail.163.com/jy3/main.jsp?sid=gAJQIqzzbBwvsaVoDhzztmnXQvBRiMuz http://entry.mail.163.com/coremail/fcg/ntesdoor2?lightweight=1&verifycookie=1&language=-1&style=35&username=xxx
+ 0.245 0.366 1664 6788 GET 200 text/html;charset=GBK http://g4a30.mail.163.com/jy3/main.jsp?sid=gAJQIqzzbBwvsaVoDhzztmnXQvBRiMuz
+ 0.422 0.158 0 0 GET (Cache) text/css http://mimg.126.net/p/jy3style/lib/0903090940/jscss/globle.css
+ 0.659 0.087 0 0 GET (Cache) application/x-javascript http://mimg.126.net/p/jy3style/js/0903090940/tools.js
+ 0.816 0.067 0 0 GET (Cache) text/css http://mimg.126.net/p/jy3style/lib/0903090940/cmcss/skin_blue.css
+ 0.998 0.578 1586 5521 GET 200 text/html;charset=GBK http://g4a30.mail.163.com/jy3/top.jsp?sid=gAJQIqzzbBwvsaVoDhzztmnXQvBRiMuz
+ 1.015 0.624 1589 24844 GET 200 text/html;charset=GBK http://g4a30.mail.163.com/jy3/folder.jsp?sid=gAJQIqzzbBwvsaVoDhzztmnXQvBRiMuz
+ 1.025 0.316 1590 10490 GET 200 text/html;charset=GBK http://g4a30.mail.163.com/jy3/welcome.jsp?sid=gAJQIqzzbBwvsaVoDhzztmnXQvBRiMuz
+ 1.034 3.174 1592 2043 GET 200 text/html;charset=GBK http://g4a30.mail.163.com/jy3/justfresh.jsp?sid=gAJQIqzzbBwvsaVoDhzztmnXQvBRiMuz
+ 1.280 0.439 0 0 GET (Cache) text/css http://mimg.126.net/p/jy3style/lib/0903090940/jscss/globle.css
+ 1.632 0.407 0 0 GET (Cache) text/css http://mimg.126.net/p/jy3style/lib/0903090940/jscss/globle.css
+ 1.647 0.432 0 0 GET (Cache) text/css http://mimg.126.net/p/jy3style/lib/0903090940/jscss/welcome2.css
+ 1.876 0.235 0 0 GET (Cache) text/css http://mimg.126.net/p/jy3style/lib/0903090940/jscss/globle.css
+ 2.179 0.117 0 0 GET (Cache) application/x-javascript http://mimg.126.net/p/jy3style/js/0903090940/tools.js
+ 2.263 0.167 0 0 GET (Cache) application/x-javascript http://mimg.126.net/p/jy3style/js/0903090940/tools.js
+ 2.354 0.207 0 0 GET (Cache) application/x-javascript http://mimg.126.net/p/jy3style/js/0903090940/tools.js
+ 2.488 0.209 0 0 GET (Cache) text/css http://mimg.126.net/p/jy3style/lib/0903090940/cmcss/skin_blue.css
+ 2.614 0.152 0 0 GET (Cache) text/css http://mimg.126.net/p/jy3style/lib/0903090940/cmcss/skin_blue.css
+ 2.619 0.192 0 0 GET (Cache) application/x-javascript http://mimg.126.net/p/jy3style/js/0903090940/welcome.js
+ 2.740 0.325 0 0 GET (Cache) text/css http://mimg.126.net/p/jy3style/lib/0903090940/cmcss/skin_blue.css
4.208 9724 50290 20 requests
00:00:00.878 0.124 0 0 GET (History Cache) image/x-icon http://www.163.com/favicon.ico
00:00:03.572 网易电子邮箱 – 简约3.0Beta
+ 0.000 0.541 0 0 GET (Cache) text/html; charset=GB2312 http://mimg.163.com/tianqi/city_simple/58367_090311.html
+ 0.531 0.715 1424 250 GET 304 text/css http://mimg.163.com/jy3style/lib/jscss/ifr_weather2.css
+ 1.614 0.245 0 0 GET (Cache) image/gif http://mimg.163.com/jy3style/lib/images/weather2.gif
1.859 1424 250 3 requests
首先,将用户名和密码POST到http://reg.163.com/login.jsp?type=1&url=http://entry.mail.163.com/coremail/fcg/ntesdoor2?lightweight%3D1%26verifycookie%3D1%26language%3D-1%26style%3D35,reg.163.com是网易通行证,后面的url是用户登陆网易通行证后要转向的地址,在这里我们看到就是http://entry.mail.163.com/coremail/fcg/ntesdoor2,这就是网易邮件的入口,在我们模拟登陆的时候,可以不传这个url过去,至于用户名和密码表单的name,看mail.163.com的HTML代码就知道了。相关错误处理,在POST到http://reg.163.com/login.jsp这个地址之后,返回的信息要取得的,因为如果用户输错了用户名或是密码,还是应该要提示用户的,而且在错误的情况下,也不用往下进行了,reg.163.com返回的错误页面里有“您的密码不正确”或是“用户名不正确”这样的信息,以此就可以判断用户是否成功登陆了。
之后我们要模拟用户访问http://entry.mail.163.com/coremail/fcg/ntesdoor2?lightweight=1&verifycookie=1&language=-1&style=35&username=xxx,就是登陆邮件的过程,注意,这里是个GET方法,用POST方法是不行的,访问entry.mail.163.com这个URL之后,会返回一个302码,就是要Redirect转向,到http://g4a30.mail.163.com/jy3/main.jsp?sid=gAJQIqzzbBwvsaVoDhzztmnXQvBRiMuz这个地址,这也就是大家看到的邮件登陆进去的首页了,注意这个sid要抓出来,应该是登陆的一个token,还有http://g4a30.mail.163.com这个地址,网易邮件是个集群,有非常多的服务器,你们每次上去的服务器是随随机的,用你的sid访问其他服务器也是没问题的,比如http://g1a98.mail.163.com/jy3/main.jsp?sid=gAJQIqzzbBwvsaVoDhzztmnXQvBRiMuz,所以这个服务器地址你可以写死。
解析来我们要看看网易邮件通讯录的URL,在UI看到是http://g4a30.mail.163.com/jy3/address/addrlist.jsp?sid=gAJQIqzzbBwvsaVoDhzztmnXQvBRiMuz&gid=all,我们模拟用户访问这个URL,然后抓取这个页面的内容HTML,分析一下,就可以了,在PHP里有个很好的HTML Parser工具PHP Simple HTML DOM Parser,可以像jQuery一样取得页面元素,这样就很方便的取得页面信息了。
其他一些Web Mail的登陆过程分析也是类似的,如果是取得CSV文件就更简单了,通过取到的通讯录内容,就可以在SNS网站上邀请了。
在这里我向国内这些大的门户网站或是Mail服务商提个建议,现在的互联网是一个开放化、平台化的趋势,网站应该开放自己的资源,可以让第三方的的应用更方便的访问,固步自封是不能发展的,试想如果QQ开放他的好友平台,引入第三方应用,那它将轻松超过Facebook,成为世界第一大SNS社区。