現在、メールクライアントとしてThunderbirdを使っていて機能的にはまぁ満足しているんですが、結構重い… なので、GUIじゃなくて、Cygwin + Teraterm上で動かせるような軽いCUIのメールクライアントを、最近欲しています。
CUIでは、以前Emacsを使っていたときにMewというメールクライアントを使っていました。かなり快適に使えていたのですが、左手小指の痛みと共にEmacsと決別してしまったので、それ以降はBecky->Thunderbirdと乗り換えてきました。
MuttというCUIメールクライアントがあるので、後々はこれを試してみようかと思っているのですが、折角なのでOCamlで自作を試みてみようかと思います(OCaml縛り中なので)。そしてあっさり玉砕してMuttに乗り換えてしまう姿が目に浮かびます。
それではメールクライアントを作るうえで必要なプロトコルの一つ、POP3を練習してみます。何せメールクライアントを作るのですから、手打ちでサーバーと会話できるようになっておきたいものです。基本的にはtelnetコマンドで110ポートに接続して、
・USER ユーザ名
・PASS パスワード
・LIST
・STAT
・RETR メッセージ番号
等のコマンドを叩けば、簡単に会話できます。Web上にたくさん参考例があるので興味のある方は試してみてください。
ところで私はGMailをつかっているのですが、その場合はSSL上でPOP3プロトコルを話さなければなりません。そうするとtelnetだととても難しい。そこで、opensslサブコマンドの一つs_clientを使ってみます。
$ openssl s_client -host pop.gmail.com -port 995 CONNECTED(00000003) depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com verify error:num=20:unable to get local issuer certificate verify return:1 depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com verify error:num=27:certificate not trusted verify return:1 depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com verify error:num=21:unable to verify the first certificate verify return:1 --- Certificate chain 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority --- Server certificate : --- No client certificate CA names sent --- SSL handshake has read 891 bytes and written 332 bytes --- New, TLSv1/SSLv3, Cipher is DES-CBC3-SHA Server public key is 1024 bit SSL-Session: Protocol : TLSv1 Cipher : DES-CBC3-SHA Session-ID: 187DA38D74524F731EDAE3AF1F62EB183C5E0122D69B27464F643FC1E8629C49 Session-ID-ctx: Master-Key: 2C566EFC2C1CEDE6FA53CAC421E815D0B2CBC31B70EF080E1BF1CBCB496A2DA736F5E5746DF5E0223DE7FA579EC588C3 Key-Arg : None Start Time: 1208679843 Timeout : 300 (sec) Verify return code: 21 (unable to verify the first certificate) --- +OK Gpop ready for requests from xxx.xxx.xxx.xxx xxxxxxxxx.0 USER xxxxxxx +OK send PASS PASS xxxxxxxx +OK Welcome. LIST +OK 61 messages (11242524 bytes) 1 30389 2 124225 3 3394 4 5433 5 141886 : . RETR 1 RENEGOTIATING depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com verify error:num=20:unable to get local issuer certificate verify return:1 depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com verify error:num=27:certificate not trusted verify return:1 depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com verify error:num=21:unable to verify the first certificate verify return:1
がーん、RETRコマンドでメールを取得しようとするとRENEGOTIATINGとなり再認証しようとして失敗してしまうようです。Web上を軽く探してみましたが対応方法がのってません。
仕方がないのでopensslのソースでも見てみましょう(@FreeBSD)。
$ pwd /usr/ports/security/openssl $ sudo make extract ===> Vulnerability check disabled, database not found => openssl-0.9.8g.tar.gz doesn't seem to exist in /usr/ports/distfiles/. => Attempting to fetch from http://www.openssl.org/source/. openssl-0.9.8g.tar.gz 100% of 3276 kB 100 kBps 00m00s ===> Extracting for openssl-0.9.8g => MD5 Checksum OK for openssl-0.9.8g.tar.gz. => SHA256 Checksum OK for openssl-0.9.8g.tar.gz. ===> openssl-0.9.8g depends on file: /usr/local/bin/perl5.8.8 - found $
これでソースが取れました。それではどこでRENEGOTIATINGと返しているか探しましょう。
$ find . -type f | xargs grep RENEGOTIATING ./apps/s_client.c: BIO_printf(bio_err,"RENEGOTIATINGn");
apps/s_client.cを見てみると…
1223 if (crlf) 1224 { 1225 int j, lf_num; 1226 1227 i=read(fileno(stdin),cbuf,BUFSIZZ/2); : 1254 if ((!c_ign_eof) && (cbuf[0] == 'R')) 1255 { 1256 BIO_printf(bio_err,"RENEGOTIATINGn"); 1257 SSL_renegotiate(con); 1258 cbuf_len=0; 1259 }
う〜〜〜む、標準入力から読み込んだバッファの一文字目が'R'だとSSL_renegotiate()が呼ばれるようですねぇ。詳細には深入りせず、ここは「小文字なら見逃してはくれまいか?」と安直に考えてみましょう。再度、s_clientコマンド上から…
retr 63 +OK message follows Delivered-To: xxxxxxxx@gmail.com Received: by xxx.xxx.xxx.xxx with SMTP id yyyyyyyyy; :
やったぁ。成功です。よくわからんが小文字 'r' は見逃してくれたようです。このあと当該メールの件名や本文も無事表示されました。
今回は、s_clientを経由したので、大文字 'R' でRENEGOTIATINGしていましたが、メールクライアントプログラムではあまり懸念しなくてもよさそうです。
後は、SMTPプロトコルとOCamlのSSLライブラリを調べれば、なんとか目処が立ちそうな気がしております。
※このエントリはZDNetブロガーにより投稿されたものです。朝日インタラクティブ および ZDNet編集部の見解・意向を示すものではありません。