さくら美緒(さくら・みお)

問題
メール・サーバーと通信して,受信しているメールの内容をメールボックスから読み出し,タイトル(Subject)の一覧を表示するプログラムを作ってください。

 私は昔から,ほかのパソコンや通信機器につないでデータのやり取りをする通信系プログラムの開発に携わっていました。今でこそイベント・ドリブンという言葉は一般的ですが,「何かが来たらそれに合わせた処理をして,また受け取りを待つ」処理を初めて覚えたのは通信系プログラムの開発を通じてでした。

通信系のプログラムはアルゴリズムの勉強に向く

 「AとBがデータをやり取りする」という考えは,ほとんどのプログラムで出てきます。今回のテーマであるインターネットで使われているプログラムなどはもちろん,データベースもそうですし,GUIの処理でも似たようなことをしています。もっと単純に,クラス間通信や関数同士を連携させたいといったときにも利用できます。また,「ややこしい」と思う処理でも「操作する自分」と「操作される相手」というように分けて考えるとうまく作れることもあります。

 今回のテーマである通信を行うプログラムから学べることはたくさんあります。「データを送る/受け取る」といった一連の処理をイメージしやすいので,アルゴリズムの組み立て方がよくわかるようになるからです。アルゴリズムを考えるのが苦手な方は,通信系プログラムを作ることをお勧めします。

 ただし通信系のプログラムは,不特定多数の人が利用するサーバーでテストすると,何か問題が起こったときに影響が多大なものになってしまいます。とは言うものの,擬似的なものでは,生きていないものを相手にしている感じがしてあまり面白くありません。そこで今回は「メール・サーバーへの接続とデータの取り出し」という比較的簡単なテーマを選びました。メール・サーバーの立ち上げはそれほど難しくありませんから,作りかけのプログラムをテストするときは独自のサーバーを立ち上げて行えば安全です。

 メールを取り出すためには,ソケットの接続やデータのデコードなど,いろいろなことをしなくてはいけません。今回はその中から,一番楽しいところである「データをやり取りするためのアルゴリズムを組み立てる」ことを考えてみます。

「あなた」と「私」のプロトコル

 通信と言えば,データのやり取りの方法を決めた手順「プロトコル」です。例えば,メール・サーバーからメールを取り出すときには,POP3(Post Office Protocol Version 3)*1というプロトコルが決められています。

 「プロトコルとは何ぞや?」と多少なりとも知っている人に尋ねると,「あいさつ」「キャッチボール」「会話」などという答えが返ってくることが多いでしょう。

 社会人のプロトコルでは,「名刺を渡す」→「○○と申します」という「あいさつ」→「今日も暑いですなあ」といった「差し障りのない会話」,という手順を経て,ようやく「本題」である商談に入ります。あいさつもせずにいきなり商談を始めたら,「あなたは一体何者?」となってその商談はダメになってしまうでしょう。

 通信におけるプロトコルは,「データを正確に転送する」「必要なタイミングで必要なデータを渡す」ための「手順」を決めたものです。コンピュータの世界ではだいたいどのプロトコルも,データ転送を始めるための準備となる「ネゴシエーション」に始まり,「データ転送開始」「データ転送」「データ転送終了」「切断処理」といった手順で構成されています。データの大きさや意味を定めていることもよくあります。

 プロトコルは相手がいないと成り立ちません。二人の人が互いに何かを言い合っているようなものです。したがって,プロトコルをプログラミングするときは,「どちらか一方の立場で考えてみる」とわかりやすくなります。探偵が犯人の気持ちになって行動を追跡するのと何だか似ています。

 まず,やり取りの一つが「自分から相手にAと言う」→「相手はBだと答える」という「問いかけ」です。自分が「データをほしい」と思ったときに「サーバーに接続できるか」「このデータを送れるのか」などを問い合わせるような「自分が中心になって何かしたいとき」はこのパターンになります。この場合「相手が答える」→「受け取ったと相手に返事をする」ということが必要になるプロトコルもあります。

 もう一つは「相手からAと言われる」→「相手にBだと答える」という「応答」です。サーバーから「次はこうしたデータがほしい」と言われたときは,それに答えて結果を待つことになります。「問いかけ」と「応答」が入り組んだ複雑なプロトコルもありますが,この二つがもっとも基本的なものです。これはプログラムを作るときに大事な足場となります。

POP3はASCIIテキストでやり取りを行う

 メールのプロトコル,というと難しそうに聞こえるかもしれませんが,POP3を理解するのは簡単です。POP3は,コマンドといくつかのパラメータ/ データをASCIIテキストで送信し,結果もASCIIテキストとして受け取ります。表1に代表的なコマンドと使い方を示します。

表1●POP3の代表的なコマンドと使い方
表1●POP3の代表的なコマンドと使い方

 メール・サーバーに接続すると「+OK」とメール・サーバーの情報が送られてきます。その後で表1のコマンドを使ってユーザー名とパスワードを認証してもらいます。接続できたら,後はコマンドを使ってサーバーから情報を取得します。例えば「STAT」という4文字に続けて改行を表す「CR」+「LF」*2を送信すると,「+OK 受信しているメールの数メールの全体サイズ」+「CR」+「LF」が返事として返ってきます。大体の返事は「+OK」+「内容」+「CR」+「LF」という1行のテキストとして返されます。エラーが起こったら「-ERR」+「内容」+「CR」+「LF」が返されます。メールの本文などの複数行からなるデータのときは,「+OK」の後にデータが流され,最後に「.」+「CR」+「LF」だけの行が来て終わりとなります。

 メールのタイトル(Subject)だけをもらいたいときは,「STAT」でメールボックスに入っているメールの数を得た後,その数から1まで数を1ずつ減らしながら「TOP 数 0」というコマンドを繰り返します。TOPの二つ目のパラメータとして0を指定すると,最初の行,つまりタイトルや宛先が含まれているヘッダー部分だけが送られてきます。ここに含まれている「Subject: 」以降にあるテキスト・データを取り出すと,タイトルが得られます。

 ちなみにコマンド・プロンプトから「telnet サーバー名 110」*3と実行してメール・サーバーと接続すると,表1のコマンドを実際に入力して試すことができます。おもしろいのでやってみてください。