Smdn.Net.Pop3.WebClientsのドキュメントのアーカイブです。 Smdn.Net.Pop3.WebClientsは現在開発を停止しているので、Smdn.Net.Pop3.Clientを使用してください。 ソースコードおよびビルド済みDLLパッケージの配布はリリース一覧 §.Smdn.Net.Pop3.WebClientsにて継続しています。

§1 概要

C#で書いた.NET Framework/Mono用POP3クライアントライブラリです。 Smdn.Net.Pop3.ClientをラップしてSystem.Net.WebRequest/System.Net.WebResponseを使ってPOPの操作を行えるようにしたものです。 メッセージのダウンロードにWebClientクラスのメソッドを使うこともできます。 POP URL(RFC 2384)を用いたリクエストに対応していて、System.Net.FtpWebRequest等と同様にWebRequest.Methodプロパティで送信するコマンドを制御できます。

§2 導入

もっとも簡単なサンプルコードとして、System.Net.WebClientクラスとPOP URLを使ったメッセージのダウンロード方法を例示します。 Gmailアカウントにアクセスし、メッセージをダウンロードしてファイルに保存するサンプルです。

using System;
using System.Net;

using Smdn.Net.Pop3.WebClients;

class GpopRetrieveExample {
  static void Main()
  {
    PopWebRequestCreator.RegisterPrefix();
    PopSessionManager.ServerCertificateValidationCallback += delegate {
      return true;
    };

    using (var client = new WebClient()) {
      client.Credentials = new NetworkCredential("username", "password");
      client.DownloadFile("pops://username@pop.gmail.com/;MSG=1", "message.eml");
    }
  }
}

この例で使用している修飾子(;MSG=1)はPOP URLに対する独自の拡張です。

ライブラリの詳細については§.PopWebRequest/PopWebResponseクラス、この他のサンプルコードについては§.サンプルコードを参照してください。 また、本ライブラリのデモ用アプリケーションTundereBirdもあわせてご覧ください。

§3 サンプルコード

個々のクラス・メソッド・プロパティについての解説は後述します。 サンプルコード中では証明書の検証を省略している箇所がありますが、実際に使用するコードでは必ず適切な検証を行うように書き換えてください。

§3.1 メッセージをダウンロードしてファイルに保存する

using System;
using System.Net;

using Smdn.Net.Pop3.WebClients;

class SaveToFile {
  static void Main(string[] args)
  {
    PopWebRequestCreator.RegisterPrefix();

    using (var client = new WebClient()) {
      client.Credentials = new NetworkCredential("user", "pass");

      // メールボックスにある1件目のメッセージをダウンロードしてファイルsample.emlに保存
      client.DownloadFile("pop://user;AUTH=DIGEST-MD5@localhost/;MSG=1", "sample.eml");
    }
  }
}

§3.2 Gmailアカウントのメールボックスから、最新のメッセージをダウンロードする

using System;
using System.IO;
using System.Text;
using System.Net;

using Smdn.Net.Pop3;
using Smdn.Net.Pop3.WebClients;

class GpopRetrieveRecent {
  static void Main(string[] args)
  {
    PopWebRequestCreator.RegisterPrefix();
    PopSessionManager.ServerCertificateValidationCallback += delegate {
      // 証明書の検証は省略 (エラーを無視してすべて受け入れる)
      return true;
    };

    var baseUrl = new Uri("pops://user@pop.gmail.com/");
    var credential = new NetworkCredential("user", "pass");

    // STATコマンドでメールボックスにあるメッセージの数を取得
    var request = WebRequest.Create(baseUrl) as PopWebRequest;

    request.Credentials = credential;
    request.Method = "STAT";
    request.KeepAlive = true; // リクエストが完了しても接続したままにする

    long recentMessageNumber;

    using (var response = request.GetResponse() as PopWebResponse) {
      recentMessageNumber = response.DropList.MessageCount;
    }

    if (recentMessageNumber == 0) {
      // メールボックスにメッセージがない
      Console.WriteLine("no messages");
      return;
    }

    // 取得するメッセージ番号を含む相対URLを作成
    var recentMessageUrl = string.Format("./;MSG={0}", recentMessageNumber);

    // RETRコマンドでメッセージの本文を取得
    request = WebRequest.Create(new Uri(baseUrl, recentMessageUrl)) as PopWebRequest;

    request.Credentials = credential;
    request.Method = "RETR";
    request.KeepAlive = false; // リクエストが完了したら切断する

    using (var response = request.GetResponse()) {
      using (var stream = response.GetResponseStream()) {
        // メッセージ本文をiso-2022-jpでデコードして表示
        var reader = new StreamReader(stream, Encoding.GetEncoding("iso-2022-jp"));

        Console.WriteLine(reader.ReadToEnd());
      }
    }
  }
}

§4 PopWebRequest/PopWebResponseクラス

ここではPopWebRequest/PopWebResponseクラスおよびSmdn.Net.Pop3.WebClients名前空間のクラスの詳細と使い方を紹介します。

§4.1 概説

本ライブラリはSmdn.Net.Pop3.Clientのクラスをラップして実装しています。 そのため、基本的な機能と動作についてはSmdn.Net.Pop3.Clientの解説をご覧ください。 ここではSmdn.Net.Pop3.WebClientsおよびPopWebRequest/PopWebResponseクラスに固有な部分を中心に解説します。

基本的にはHttpWebRequest/HttpWebResponseやFtpWebRequest/FtpWebResponseを用いた操作と同様で、

  1. リクエストURLを指定してWebRequest.CreateメソッドでPopWebRequestのインスタンスを作成
  2. Method、Credentialsなどのプロパティを指定
  3. PopWebRequest.GetResponseでリクエストを実行、レスポンスを取得
  4. 取得したPopWebResponseインスタンスを参照、必要に応じてPopWebResponse.GetResponseStreamメソッドを呼び出す

の順でPOPコマンドを実行、レスポンスを取得します。

§4.2 pop, popsスキームの登録

WebRequestクラスがpopスキームおよびpopsスキームのURLを処理できるように、PopWebRequest/PopWebResponseクラスを使う前にPopWebRequestCreator.RegisterPrefixメソッドを呼び出しておく必要があります。

このメソッドはWebRequest.RegisterPrefixメソッドを呼び出し、popスキームおよびpopsスキームに対してPopWebRequestCreatorを関連付けます。

記述例
using System;
using System.Net;
using Smdn.Net.Pop3;
using Smdn.Net.Pop3.WebClients;

  :
  :
// popおよびpopsスキームの登録
PopWebRequestCreator.RegisterPrefix();

// PopWebRequestインスタンスの作成
var request = WebRequest.Create("pop://user@pop.example.net/");
  :
  :

§4.3 リクエストURLと接続・認証時の動作

§4.3.1 接続と認証

接続・認証時の動作は、リクエストURLに記述されるスキーム・ホスト名・ポート・認証方式・ユーザ名に基づいて決まります。

リクエストURLで記述されない接続・認証時の動作は、PopWebRequestクラスのプロパティで指定できますPopWebRequestのプロパティも合わせて参照してください

接続・認証時の動作を指定するPopWebRequestクラスのプロパティ
プロパティ 解説
Credentials 認証時に使用する資格情報(パスワード等)を指定します
UseTlsIfAvailable 認証を開始する前に、可能ならSSL/TLSへアップグレードするかどうかを指定します
UsingSaslMechanisms 認証時に試行する認証メカニズムを指定します
AllowInsecureLogin 接続がSSL/TLSで保護されていない場合でも、平文またはAPOPによる認証を許可するかどうか指定します

以下はコード上での記述と接続・認証時の動作の例です。 実際にSSL/TLSを使用する場合は証明書の検証等が必要になります。

記述例
// popおよびpopsスキームの登録
PopWebRequestCreator.RegisterPrefix();

/*
 * ホスト"pop.example.net"のPOPSデフォルトポート(995)にSSL/TLSを用いて接続。
 * ユーザ名に"user"、パスワードに"pass"を使用。 認証方式は対応しているものを順に試行。
 */
var request1 = WebRequest.Create(new Uri("pops://user@pop.example.net/"));

request1.Credentials = new NetworkCredential("user", "pass");

/*
 * ホスト"pop.example.net"のポート10110に接続、可能ならSSL/TLSにアップグレード。
 * ユーザ名に"user"、パスワードに"pass"を使用。 認証方式はAPOPを試行。
 */
var request2 = WebRequest.Create(new Uri("pop://user;AUTH=+APOP@pop.example.net:10110/")) as PopWebRequest;

request2.UseTlsIfAvailable = true;
request2.Credentials = new NetworkCredential("user", "pass");

/*
 * ホスト"pop.example.net"のポート10110にSSL/TLSを用いて接続。
 * ユーザ名に"user"、パスワードに"pass"を使用。 認証方式はDIGEST-MD5を試行。
 */
var request3 = WebRequest.Create(new Uri("pops://user;AUTH=DIGEST-MD5@pop.example.net:10110/")) as PopWebRequest;

request3.Credentials = new NetworkCredential("user", "pass");

/*
 * ホスト"pop.example.net"のPOPデフォルトポート(110)に接続、SSL/TLSは使用しない。
 * ユーザ名に"user"、パスワードに"pass"を使用。 認証方式はDIGEST-MD5, CRAM-MD5, APOP, USER/PASSの順に試行。
 */
var request4 = WebRequest.Create(new Uri("pop://;AUTH=*@pop.example.net/")) as PopWebRequest;

request4.UseTlsIfAvailable = false;
request4.UsingSaslMechanisms = new[] {"DIGEST-MD5", "CRAM-MD5", "+APOP"};
request4.Credentials = new NetworkCredential("user", "pass");

/*
 * ホスト"pop.example.net"のPOPデフォルトポート(110)に接続、可能ならSSL/TLSを使用する。
 * ユーザ名に"user"、パスワードに"pass"を使用。
 * 認証方式はCRAM-MD5, PLAIN, APOP, USER/PASSの順に試行。 ただしSSL/TLSが使用できない場合、平文による認証を許可しない。
 */
var request5 = WebRequest.Create(new Uri("pop://user@pop.example.net/")) as PopWebRequest;

request5.UseTlsIfAvailable = true;
request5.UsingSaslMechanisms = new[] {"CRAM-MD5", "PLAIN"};
request5.AllowInsecureLogin = false;
request5.Credentials = new NetworkCredential("user", "pass");

/*
 * GMailのアカウント"user"にPOPで接続。 パスワードは"pass"を使用。
 */
var request6 = WebRequest.Create(new Uri("pops://user@pop.gmail.com/"));

request6.Credentials = new NetworkCredential("user", "pass");

§4.3.2 証明書の選択と検証

デフォルトでは、接続・認証時にPopSessionManagerクラスの以下のメンバを参照して証明書の選択と検証を行います。

SSL/TLS接続時に参照するメンバ(いずれもクラスプロパティ)
PopWebRequestクラスが参照するメンバ
X509Certificate2Collection PopSessionManager.ClientCertificates
RemoteCertificateValidationCallback PopSessionManager.ServerCertificateValidationCallback
RemoteCertificateValidationCallback PopSessionManager.ClientCertificateSelectionCallback

以下は証明書の検証を行う簡単な例です。

証明書の検証を行う例
using System;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using Smdn.Net.Pop3;
using Smdn.Net.Pop3.WebClients;

public class ValidateServerCerts {
  static void Main(string[] args)
  {
    PopWebRequestCreator.RegisterPrefix();

    // 証明書の検証を行うコールバックメソッドを指定
    PopSessionManager.ServerCertificateValidationCallback += ValidateRemoteCertificate;

    using (var client = new WebClient()) {
      client.Credentials = new NetworkCredential("user", "pass");
      client.DownloadFile("pops://user@localhost/;MSG=1", "sample.eml");
    }
  }

  private static bool ValidateRemoteCertificate(object sender,
                                                X509Certificate certificate,
                                                X509Chain chain,
                                                SslPolicyErrors sslPolicyErrors)
  {
#if DEBUG
    // デバッグ時のみSslPolicyErrors.RemoteCertificateNameMismatchを無視
    if ((int)(sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) != 0)
      sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateNameMismatch;
#endif

    if (sslPolicyErrors == SslPolicyErrors.None) {
      return true;
    }
    else {
      // エラーがあれば標準エラーに表示
      Console.Error.WriteLine(sslPolicyErrors);
      return false;
    }
  }
}

SSL/TLS接続時の動作をデフォルトからカスタマイズしたい場合は、PopSessionManager.CreateSslStreamCallbackに適切なコールバックメソッドを指定してください。

§4.4 リクエストURLとリクエスト・レスポンスの動作

POP URL(RFC 2384)ではPOPサーバ(メールボックス)を表す形式しか規定されていませんが、本ライブラリでは独自の拡張としてメッセージ番号を指定してリクエストできるようにしてあります。 リクエストURLにメッセージ番号(;MSG=x)が含まれているかどうかでリクエストの対象が変わります。

リクエストURLの形式とリクエストの対象
リクエストURLの形式 リクエストの対象
pop://pop.example.net/ URLで指定されたメールボックス
pop://pop.example.net/;MSG=1 URLで指定されたメールボックスにあるメッセージのうち、メッセージ番号に該当する特定のメッセージ

WebRequest.Createメソッドが返すWebRequestインスタンスのMethodプロパティにデフォルトで設定される値は、リクエストURLの形式によって決まります。

PopWebRequest.GetResponseの動作は、リクエストURLで表されるリクエストの対象と、WebRequest.Methodプロパティに設定する値によって変わります。 以下でリクエストURLの形式とMethodプロパティに指定可能な値、リクエストとレスポンスについて解説します。 PopWebRequestクラスのプロパティのうち、リクエストに影響するその他のプロパティについてはPopWebRequestのプロパティで説明します。

§4.4.1 メールボックスに対するリクエスト

リクエストURLがメールボックスを表す場合(pop://pop.example.net/の形式)のリクエストとレスポンスの動作は次のとおりです。

Methodプロパティ リクエスト 解説 レスポンス
PopWebRequestMethods.List, "LIST"
(デフォルト)
LISTコマンドを送信してメールボックスにあるメッセージの一覧を取得します。 - 取得したメッセージの一覧は、PopWebResponse.ScanListsプロパティに設定されます。
PopWebRequestMethods.Rset, "RSET" RSETコマンドを送信してDELEコマンドの操作をキャンセルします。 -
PopWebRequestMethods.Stat, "STAT" STATコマンドを送信してメールボックスにあるメッセージの数と総サイズを取得します。 - 取得したメッセージ数と総サイズは、PopWebResponse.DropListプロパティに設定されます。
PopWebRequestMethods.Uidl, "UIDL" UIDLコマンドを送信してメールボックスにあるメッセージのIDの一覧を取得します。 - 取得したIDの一覧は、PopWebResponse.UniqueIdListsプロパティに設定されます。
Methodプロパティ リクエスト 解説 レスポンス

§4.4.2 特定のメッセージに対するリクエスト

リクエストURLが特定のメッセージを表す場合(pop://pop.example.net/;MSG=1の形式)のリクエストとレスポンスの動作は次のとおりです。

Methodプロパティ リクエスト 解説 レスポンス
PopWebRequestMethods.Retr, "RETR"
(デフォルト)
RETRコマンドを送信してメッセージの本文を取得します。 - メッセージ本文はWebResponse.GetResponseStreamメソッドが返すStreamから読み込めます。 取得したメッセージのサイズはWebResponse.ContentLengthプロパティに設定されます。
PopWebRequestMethods.Dele, "DELE" DELEコマンドを送信してメッセージを削除します。 - -
PopWebRequestMethods.List, "LIST" LISTコマンドを送信してメッセージの番号とサイズを取得します。 - 取得したメッセージ番号とサイズは、PopWebResponse.ScanListsプロパティに設定されます。
PopWebRequestMethods.Top, "TOP" TOPコマンドを送信してメッセージをヘッダ部分を取得します。 現時点ではTOPで取得するボディ部分の行数は指定できません(常に0を指定します)。 メッセージのヘッダ部分はWebResponse.GetResponseStreamメソッドが返すStreamから読み込めます。 取得したヘッダ部分のサイズはWebResponse.ContentLengthプロパティに設定されます。
PopWebRequestMethods.Uidl, "UIDL" UIDLコマンドを送信してメッセージの番号とIDを取得します。 - 取得したメッセージ番号とIDは、PopWebResponse.UniqueIdListsプロパティに設定されます。
Methodプロパティ リクエスト 解説 レスポンス

§4.4.3 リクエスト対象に制限されないリクエスト

リクエストURLの形式によらず使用可能なコマンドのリクエストとレスポンスの動作は次のとおりです。

Methodプロパティに指定可能な値 リクエスト 解説 レスポンス
PopWebRequestMethods.NoOp, "NOOP" NOOPコマンドを送信します。 このコマンドは何もしません。 自動ログアウトタイマの更新、セッションの接続性確認などに使います。 -
Methodプロパティに指定可能な値 リクエスト 解説 レスポンス

§4.4.4 PopWebRequestクラスのプロパティ

PopWebRequestクラスにはMethodプロパティ以外にもコマンド送信時の動作を制御するためのプロパティを用意してあります。 プロパティの値によってリクエスト内容と動作が変わります。

PopWebRequestクラスのプロパティ
プロパティ デフォルト 対象となるコマンド 解説
KeepAlive true 全て リクエストが終了した後もセッションを維持するかどうかを指定します。 trueの場合はリクエストが終了してもセッションは維持し、falseの場合はリクエストの度にセッションを開きリクエスト終了と同時にセッションを閉じます。
UseTlsIfAvailable true 全て(認証時) サーバがサポートしている場合、認証を行う前にSSL/TLSを使用した接続にアップグレードします。
UsingSaslMechanisms {"DIGEST-MD5", "CRAM-MD5", "NTLM"} 全て(認証時) 認証メカニズムが指定されていない場合に、試行する認証メカニズムとその順番を配列で指定します。 サーバ・クライアントの両方がサポートするメカニズム以外が指定されている場合は無視します。
AllowInsecureLogin false 全て(認証時) 接続がSSL/TLSで保護されていない場合でも、平文またはAPOPによる認証を許可するかどうか指定します。
DeleteAfterRetrieve false RETR RETRコマンドでのメッセージの受信が成功した場合、同じメッセージに対して自動的にDELEコマンドを発行します。
ExpectedErrorResponseCodes null 全て サーバから返されることが予期されるエラーレスポンスコードの配列を指定します。 サーバからこれらのレスポンスコードが返された場合は、エラーレスポンスでもWebExceptionがスローされません。

WebRequestクラスから継承されるプロパティのうち、以下のプロパティは使用することができます。

WebRequestクラスから継承されるプロパティ
プロパティ デフォルト 対象となるコマンド 解説
Timeout -1 全て リクエストを開始してからレスポンスを取得するまでのタイムアウト時間を指定します。
ReadWriteTimeout 300000 全て ソケット送受信のタイムアウト時間を指定します。

§4.4.5 PopWebRequestクラスのデフォルト値の変更

PopWebRequestDefaultsクラスのプロパティの値を変更することにより、PopWebRequestクラスのプロパティに設定されるデフォルト値を一括して指定することができます。 全てのリクエストでデフォルトの値を変更したい場合は、PopWebRequestDefaultsクラスのプロパティの値を変更してください。

PopWebRequestDefaultsクラスにはPopWebRequestプロパティと同名のプロパティを用意してあります。

§4.5 アプリケーション構成ファイルでの設定

アプリケーション構成ファイルを記述することにより、pop, popsスキームの登録と、PopWebRequestDefaultsクラスのデフォルト値を変更することができます。 コード上での変更をしたくない場合、する必要がない場合などは、アプリケーション構成ファイルに設定を記述することができます。 以下はアプリケーション構成ファイルの記述例です。

アプリケーション構成ファイルの記述例
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <!-- smdn.net.pop3.client要素を処理するためのセクションハンドラクラスの設定 -->
    <sectionGroup name="smdn.net.pop3.client">
      <section name="webRequestDefaults" type="System.Configuration.DictionarySectionHandler, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    </sectionGroup>
  </configSections>
  <system.net>
    <!-- pop, popsスキームの登録 -->
    <webRequestModules>
      <add prefix="pop"   type="Smdn.Net.Pop3.WebClients.PopWebRequestCreator, Smdn.Net.Pop3.WebClients" />
      <add prefix="pops"  type="Smdn.Net.Pop3.WebClients.PopWebRequestCreator, Smdn.Net.Pop3.WebClients" />
    </webRequestModules>
  </system.net>
  <smdn.net.pop3.client>
    <!-- PopWebRequestDefaultsクラスのデフォルト値の変更 -->
    <webRequestDefaults>
      <add key="timeout" value="-1"/>
      <add key="readWriteTimeout" value="-1"/>
      <add key="useTlsIfAvailable" value="true"/>
      <add key="deleteAfterRetrieve" value="false"/>
      <add key="keepAlive" value="true"/>
      <add key="usingSaslMechanisms" value="DIGEST-MD5, CRAM-MD5, NTLM"/>
      <add key="allowInsecureLogin" value="false"/>
      <add key="expectedErrorResponseCodes" value="SYS/TEMP"/>
    </webRequestDefaults>
  </smdn.net.pop3.client>
</configuration>

記述内容についてはネットワーク設定スキーマおよび構成セクション スキーマも合わせて参照してください。

§4.6 例外

PopWebRequestからはSystem.Net.WebExceptionまたはSystem.Net.ProtocolViolationExceptionをスローします。 WebExceptionをスローする場合は、エラーの状況によりWebException.StatusプロパティとInnerExceptionプロパティに値が設定されます。 また、サーバがエラー応答を返した場合は、Responseプロパティも設定されます。

§4.7 非同期操作・スレッドセーフティ

WebRequestから継承されるBeginGetResponse()/EndGetResponse()メソッドは実装済みのため、これらのメソッドを使って非同期操作を行えます。 ただし、.NET Framework上では、WebClient.OpenReadAsync()、WebClient.Download*Async()などのメソッドを使用した非同期操作は正しく動作しないようなので、現時点では使用できません。