抓虫记(一)
最近,在负责一个邮件收发相关的一个模块。用的是第三方的SDK:chilkat。chilkat支持非常多的协议和功能,如:MAIL,ZIP,HTTP,FTP2,XML,IMAP,SSH/SFTP等,这个组件也有多个语言的版本,如:.NET,RUBY,PYTHON,PERL,JAVA,C++等。对多平台和编译器的支持也不错,如:
Chilkat C/C++ Libraries for: Microsoft VC++ 6, 7, 8, 9, and 10. MAC OS X IOS Linux, CentOS, RHEL, etc. FreeBSD Solaris BlackBerry QNX C++ Builder HP/UX MinGW Windows Mobile
总之,对多语言多平台的支持非常不错。(chilkat官网:http://www.chilkatsoft.com)
我正在开发的模块用的是VC++,主要是通过chilkat和IMAP协议来接收邮件服务器上的收件箱和已发邮箱中的邮件。chikat通过SelectMailbox函数来进行mailbox的切换,切换后,就可以对当前的mailbox进行各种操作了,如:收取邮件:
#define USERNAME "test.test1@gmail.com" #define PASSWORD "123456" #define IMAPADDRESS "imap.gmail.com" CkImap imap; bool success; // Anything unlocks the component and begins a fully-functional 30-day trial. success = imap.UnlockComponent("TEST"); if (success != true) { printf("%s\n",imap.lastErrorText()); return; } imap.put_Port(993); // Connect to an IMAP server. success = imap.Connect(IMAPADDRESS); if (success != true) { printf("%s\n",imap.lastErrorText()); return; } // Login success = imap.Login(USERNAME,PASSWORD); if (success != true) { printf("%s\n",imap.lastErrorText()); return; } // Select an IMAP mailbox to retrieve success = imap.SelectMailbox("[Gmail]/Sent Mail"); if (success != true) { printf("%s\n",imap.lastErrorText());//这里出现问题 return; } //...接下去进行邮件的接收
但是,我开发的过程中,通过我的测试账号:
#define USERNAME "mytest@gmail.com" #define PASSWORD "123456" #define IMAPADDRESS "imap.gmail.com"
测试没有任何问题。为什么到了生产环境中,通过账号test.test1@gmail.com测试就接收到:
The return result: ChilkatLog: Login: DllDate: Sep 18 2008 Username: sow11 Component: Visual C++ 8.0 login: test.test1@gmail.com SelectMailbox: mailbox: [Gmail]/Sent Mail separatorChar: . utf7EncodedMailboxName: [Gmail]/Sent Mail Failed to select mailbox mailbox: [Gmail]/Sent Mail ImapResponse: aaac NO [NONEXISTENT] Unknown Mailbox: [Gmail]/Sent Mail (Failure
找到QA,QA再做了一遍,我旁边观察,没有发现任何问题。接下去,我又做了如下测试:
1. 是否mailbox的名字:[Gmail]/Sent Mail,QA写错了?---没有写错
2. mailbox的名字:[Gmail]/Sent Mail在QA的数据库中,是否保存的字符集不一样,导致取出来的时候解码不对?---解码正确
3. QA的测试机器的区域和语言是否是中文或者其它语言,才导致mailbox的名字解码不正确?----一样的区域和语言
4. 再次检查下QA的程序有什么其它特殊设置吗?----无
5. 尝试用开发机器连接到QA的测试数据库中,这个时候是否还是有问题?-----还是有问题。
经过尝试,一一验证上面的假设。BUG还是存在。再次仔细查看错误报告:
separatorChar: .
utf7EncodedMailboxName: [Gmail]/Sent Mail
嗯?QA的测试账号是:test.test1中间有个'.',是这个问题?我马上在QA的机器上换上我的测试账号mytest,yeah!正常了!问题发现了,QA的测试账号有问题。为什么呢?推测:
chikat这个SDK有个BUG,当账号中有分隔符'.'的时候,不能正确的SelectMailbox。
嗯,现在可以高高兴兴的跟QA说:你们不要用有'.'分割的账号进行测试,这个是因为第三方的SDK有BUG,我们也修不了...先耗着...换个账号测试吧...
不对!我应该也试试其他的邮箱服务,比如exchange。刚好公司内部的邮箱就是exchange,我的邮箱名字是lyp.killer的,刚好可以测试。经过测试发现lyp.killer可以SelectMailbox...晕了,为什么呢?推测:
gmail中对于带'.'的邮箱有个bug....
也不对,我用outlook同步我的gmail好多年了,POP3和IMAP都正常的...为什么呢?
嗯,没办法,写个case来枚举GMAIL中所以得mailbox吧:
CkImap imap; bool success; // Anything unlocks the component and begins a fully-functional 30-day trial. success = imap.UnlockComponent("TEST"); if (success != true) { printf("%s\n",imap.lastErrorText()); return; } imap.put_Port(993); // Connect to an IMAP server. success = imap.Connect(IMAPADDRESS); if (success != true) { printf("%s\n",imap.lastErrorText()); return; } // Login success = imap.Login(USERNAME,PASSWORD); if (success != true) { printf("%s\n",imap.lastErrorText()); return; } // Select all mailboxes matching this pattern: CkString wildcardedMailbox; wildcardedMailbox = "*"; CkMailboxes *mboxes = 0; mboxes = imap.ListMailboxes("",wildcardedMailbox); if (mboxes == 0 ) { printf("%s\n",imap.lastErrorText()); return; } int i; for (i = 0; i <= mboxes->get_Count() - 1; i++) { printf("%s\n",mboxes->getName(i)); }
测试mytest@gmail.com结果如下:
INBOX Personal Receipts Travel Work [Gmail] [Gmail]/All Mail [Gmail]/Drafts [Gmail]/Important [Gmail]/Sent Mail [Gmail]/Spam [Gmail]/Starred [Gmail]/Trash
测试test.test1@gmail.com结果如下:
INBOX Personal Receipts Travel Work [Gmail] [Gmail]/垃圾邮件 [Gmail]/已删除邮件 [Gmail]/已加星标 [Gmail]/已发邮件 [Gmail]/所有邮件 [Gmail]/草稿 [Gmail]/重要
嗯!发现问题了....test.test1的已发邮箱的名字是:[Gmail]/已发邮件,竟然不是[Gmail]/Sent Mail。用这两个邮箱通过浏览器登录到gmail中发现:test.test1的默认界面是中文,而mytest的默认界面是英文...推测:
应该是GMAIL邮箱中的语言设置问题
跑到test.test1的设置中,把常规-->语言中的GMAIL界面语言该为英文...再测试,一切OK...
总结:
1. 别早下结论:如果我默认是第三方SDK的问题,也许就错过了发现根本原因的机会
2. 首先要认识到bug很大程度是自己产生的,不要一下就认为是别人的错。
3. 要刨根究底