(CLOSEコマンド・LOGOUTコマンド)System.Net.Sockets.TcpClientクラスを使ってIMAPサーバーからメールを受信するサンプル。FrameworkにはIMAPクライアントにあたるクラスが用意されていないため、独自に実装する必要がある。以下のコードはIMAPサーバーに接続してメールを取得し、ファイルに保存するIMAPクライアントのサンプル。SslStreamを使ってSSLによる接続を行う。3.8で動作確認済み。v2.2.13での動作を確認している。送信するコマンドとレスポンス解析上の要点などについては後述する。<summary>文字列をクオートした結果を返す。<summary>TcpClientを継承してSSL接続とIMAPコマンドの送受信に最適化したクライアント。<summary>現在の接続をSSLにアップグレードする。<summary>サーバー証明書の検証を行う。<summary>IMAPコマンドを送信する。<summary>IMAPレスポンスを受信する。<summary>文字列を改行文字で分割してIEnumerable<string>で返す。stringの拡張メソッドとして使用可能。<summary>文字列をクオートした結果を返す。<summary>TcpClientを継承してSSL接続とIMAPコマンドの送受信に最適化したクライアント。<summary>現在の接続をSSLにアップグレードする。<summary>サーバー証明書の検証を行う。<summary>IMAPコマンドを送信する。<summary>IMAPレスポンスを受信する。String)で返す。Stringの拡張メソッドとして使用可能。2.上記サンプルの制限事項や改良可能な点など。8bitのメールでは文字化けが発生する可能性があるUpgradeToSsl()の呼び出しを行わなければSSLを使用しない通常のIMAP接続を行うことができるSTARTTLSコマンドを送信してレスポンスを受信した後にUpgradeToSsl()を呼び出すようにすればSTARTTLSに対応することができるIMAPプロトコル概説IMAPサーバーからメールを受信するために必要となる知識として、IMAPコマンドとレスポンスについて解説する。以下はIMAPサーバーに接続してメールを受信する処理を行うために送受信するコマンドとレスポンスの流れ。(この例ではGMailに接続している)C:の行はクライアントが送信するコマンド、S:の行はサーバーから返送されるレスポンスを表す。C:とS:自体はクライアントとサーバーを区別して表すためのラベルで、実際に送受信される内容ではない点に注意。IMAPでは、コマンド・レスポンスとも行末は常にCRLFで終端される。(Success)以下で上記の送受信内容について1ステップずつ解説する。4rev1や文中のリンクを参照のこと。av5mb180262435pbd接続が確立した後(SSL接続の場合はセッションが確立した後)、サーバー側からグリーティングバナーが送信されてくる。*の後にOKが続く場合は成功であり、以降IMAPコマンドを受信できる状態であることを表す。OK以降の文字列はサーバーによって異なる。(Success)LOGINコマンドを使い、ユーザー名とパスワードを指定してIMAPサーバーにログインする。ここではユーザー名にuser、パスワードにpassを指定している。空白がコマンド引数の区切りとみなされるため、引数に空白を含む場合は必ず二重引用符"でクォートする必要がある。OKに前置されている00は、タグ(tag)と呼ばれるもの。タグはコマンドとそれに対応するレスポンスを識別し、他のコマンドの結果との区別を行うための文字列。タグには任意の文字列を使用することができるが、以降ここではコマンドの通番を使用する。認証に失敗したなどコマンドが失敗した場合はOKではなくNOやBADとなる。OK以降の文字列はコマンドの結果を表す一種のコメントでありプロトコル上意味のある文字列では無く、その内容はサーバーによって異なる。CAPABILITYはサーバーの能力(サポートする機能)を表す付加的なレスポンスで、コマンドの結果を表すものではない。このような付加的なレスポンスが送信されるかどうか、またその内容はサーバーによって異なる。LOGINコマンドは平文での認証を行う。DIGEST-MD5やCRAM-MD5などを使って認証したい場合はAUTHENTICATEコマンドを使用する。(Success)取得したいメールが含まれているメールボックスを選択するためにSELECTコマンドを送信する。コマンドの引数に選択したいメールボックス名を指定する。ここではデフォルトで存在するメールボックスであるINBOXを指定している。UTF-7でメールボックス名をエンコードする必要がある。EXISTSの行は、メールボックスにメールが1件格納されていることを表す。RECENTの行は、新着メールが0件格納されている、つまり新着メールはないことを表す。EXISTSおよびRECENTは、SELECTコマンドのレスポンスとして常に返送されてくる。Successメールの内容を取得するためにFETCHコマンドを送信する。コマンドの引数に取得したいメールの番号(メールボックス内での通番)と、取得したい内容を指定する。ここではメール番号に1、メール本文の内容を取得するためにBODY.PEEK[]を指定している。指定された番号のメールがない場合などにはOKではなくNOとなる。{388}とそれに続くCRLF以降の部分に格納される。388はBODY[]のオクテット数を表すもので、{388}とその直後のCRLFに続く388オクテット分がBODY[]の内容(つまり取得したメール)となる。FETCHコマンドでは、BODY.PEEK[]の代わりにBODY[]を指定するとメール本文の取得と同時にメールを既読状態にすることができる。メール番号はメールボックスに格納された順で1から始まる連続した番号が割り当てられる。メールの削除を行った場合にはその番号が割り当て直されて変化する点に注意。FETCHコマンドを使用するとメール番号の代わりにメールのユニークIDを指定して取得を行うことができる。ユニークIDはメールボックスに格納される時に割り当てられた以降は変化することがない。メールクライアントのひとつであるThunderbirdでは、「受信順」のカラムを表示することでメールに割り当てられたユニークIDを確認することができる。FETCHコマンドでは、引数を変えることによりメール本文以外にもメールに関する様々な情報を取得することができる。6.4.5)SEARCHコマンドを使用すると、メールの件名などの条件からメール番号を検索することができる。(Success)メールの取得のみを行う場合はこのコマンドを送信せず即座に切断することもできる。メールの削除を行う場合はCLOSEコマンドを送信してメールボックスを閉じない限り削除されない。LOGOUTコマンドを送信すると、レスポンスが返送された後接続がサーバー側から切断される。