SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

Rubyで簡易POP3サーバを作る

RubyによるネットワークプログラミングとUNIXシステムプログラミングの基礎

POP3の概要

 この節では、POP3について概要を説明します。

POP3とは

 POP3(Post Office Protocol version 3)は、いわゆる「メールを受信する」ためのプロトコルです。

 POP3のおおまかな特徴は以下の2つです。

  1. クライアント・サーバ形式
  2. テキストベースのプロトコル

 まず、POP3はクライアント・サーバ形式です。つまり、ネットワーク経由で通信するプログラム同士の立場が非対称で、「相手に使われる」プログラム(=サーバ)と「相手を使う」プログラム(=クライアント)に分かれます。POP3ではメールを持っているほうがサーバで、メールを受信する側がクライアントです。POP3サーバの例としてはqpopper、POP3クライアントの例としてはMicrosoft OfficeのOutlookなどが挙げられます。

 次に、POP3はテキストベースのプロトコルです。つまり、ASCIIのプレーンテキストでサーバとクライアントが通信します。この点はウェブの基本プロトコルであるHTTPや、メール送信用プロトコルであるSMTPと似ています。

POP3セッションの例

 百聞は一見に如かずです。実際にPOPdを動かして、POP3の中身を見てみましょう。コマンドラインで次のように入力するとPOPdをデバッグモード、かつinetdモードで実行できます。このモードでは、端末からPOPdと直接やりとりできます。

$ ruby -d popd.rb --inetd
Exception `Errno::ENOTSOCK' at popd.rb:92 - Socket operation
 on non-socket - getpeername(2)
+OK popd <1162129240.4663.154af7768c@pop.example.com>

 「Exception……」の行はrubyが(正しく捕捉された)例外の情報を表示しているだけなので、無視してください。次の「+OK……」と表示されている行からが、POPdの出力です。

 ここでキーボードからPOP3のコマンドを打ち込んでみましょう。最初にAPOPコマンドで認証を行います。

C: APOP taro xxxx
S: +OK

 「C:」と「S:」は説明のために付けているだけで、実際には表示されません。頭に「C:」と付いている行はこちら(クライアント)からの入力、「S:」と付いている行がPOPd(サーバ)からの出力を表しています。

 さて、APOPコマンドの引数は2つです。1つめの引数「taro」がユーザー名で、2つめの引数「xxxx」は実装の節で詳述する「ダイジェスト」です。サーバが「+OK」と返してきたら問題なく認証されたということを示しています。

 認証が済んだらメールボックスにアクセスできます。まずSTATコマンドでメール数などを調べてみましょう。

C: STAT
S: +OK 3 10867

 うまくいきました。この返答は、「メールボックスにはメールが3通あり、そのバイト数の合計は10867バイトである」という意味です。

 ところで、さきほどからサーバが返してきている「+OK」は、「処理が問題なくうまくいった」という意味です。何か問題が起きた場合は「-ERR」が返ってきます。例えば次はPOP3には存在しないコマンドを入力してみましょう。

C: NO_SUCH_COMMAND
S: -ERR unknown command

 このように、POP3にはないコマンドを送ったらサーバから「-ERR」が返ってきました。

 次はLISTコマンドを使ってメールをリストアップしてみます。

C: LIST
S: +OK
S: 1 1370
S: 2 4901
S: 3 4596
S: .

 LISTコマンドへの返答は複数行です。POP3で複数行の応答があるときは、「.」だけの行で終わりを示します。

 この返答の意味は、「メール番号1のメールはサイズが1370バイト、メール番号2のメールはサイズが4901バイト、メール番号3のメールはサイズが4596バイト」です。通常、メール番号は1から通し番号が振られています。

 今度は、RETRコマンドでメールを取得してみましょう。RETRはretrieve(受け取る)の略です。

C: RETR 1
S: +OK 1370 octets
S: Return-path: <xxxxxxxxx@example.com>
S: Envelope-to: taro@example.com
S: Delivery-date: Sun, 29 Oct 2006 00:49:01 +0900
S: Received: from [xxx.xxx.xxx.xxx]
S:         by pop.example.com with smtp
S:         id 1GdqQe-0007Mo-Ug
S:         for taro@example.com; Sun, 29 Oct 2006 00:49:01 +0900
                (メールの内容は中略)
S: この行はメールの本体……
S: この行もメールの本体……
S: .

 RETRコマンドの引数は、取得したいメールのメール番号です。この例では1番のメールを取得しようとしています。サーバはそれに応答して、まず2行目の「+OK 1370 octets」で「次の行からメールを送る」と言っています。次の行からはメールの内容が続き、最後に「.」だけの行でメールの終わりを示します。

 なお、この仕組みだともともと「.」だけの行を含むメールを受信するときに問題が起きそうな気もしますが、POP3ではそのための対策も用意されています。この対策についてはRETRコマンドの実装をするときに述べます。

 メールを取得できたら、DELEコマンドでメールを削除します。

C: DELE 1
S: +OK

 これでメール番号1番のメールが削除できました。最後に、QUITコマンドでPOP3セッションを終了します。

C: QUIT
S: +OK

 最後の「+OK」が送られてくると同時にTCP接続がサーバ側から切断されて、コマンドプロンプトに戻ってきます。

 次の節からは実際のコードを見ていくことにしましょう。

次のページ
サーバの起動

この記事は参考になりましたか?

特集記事連載記事一覧

もっと読む

この記事の著者

青木 峰郎(アオキ ミネロウ)

ふつうの文系プログラマ。Ruby界隈で活動中。主著は『ふつうのLinuxプログラミング』(ソフトバンククリエイティブ、2005)、『Rubyソースコード完全解説』(インプレス、2002)。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/687 2006/11/10 00:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー