残念ながら.NET FrameworkはPOP3サーバーから簡単にメールを受信する方法を用意してくれていません。つまりPOP3メールサーバーからメールを受信するには、ソケットを使ってやり取りをする必要があります。それだけならまだしも、受信したメールを正しく解釈するには、MIMEなどのややこしい知識が要ります。
以下にTcpClientクラスを使用してPOP3メールサーバーからすべてのメールを受信するごく簡単な例を紹介しますが(受信するだけです)、多少まともなPOP3クライアントを作成するつもりであれば、より多くのPOP3やMIME等の知識が絶対に必要であることを認識しておいてください。つまり最低でも、RFCの該当箇所(「Post Office Protocol - Version 3」など)を読んで理解する必要があります。
もしちゃんと勉強するつもりがなく、それでもメールを受信したいというのであれば、第三者の作成したライブラリや、COMなどに頼るのがよいでしょう。Tatsuo BabaさんのBASP21 DLLが有名で、お勧めです。
以上のように初心者の方には全く勧められませんが、ごく簡単な例を以下に紹介します。次のコードは、コンソールアプリケーションとして、POP3サーバー(サーバー名:localhost、ポート番号:110)のメールボックス(ユーザー名:userid、パスワード:password)からメールを受信する(さらにメールは削除する)例です。Pop3MailクラスのReceiveメソッドは受信したすべてのメールをstring型配列として返します。
'C#のコードを'C# to VB.NET Translator'で変換し、修正したコードです 'http://www.aspalliance.com/aldotnet/examples/translate.aspx Imports System Imports System.Text Imports System.Net.Sockets Namespace Dobon.Samples.Mail Public Class Pop3Mail 'エントリポイント Public Shared Sub Main() Dim mails() As String mails = Receive("localhost", 110, "userid", "password", True) Console.ReadLine() End Sub ''' <summary> ''' POP3サーバーからメールをすべて受信する ''' </summary> ''' <param name="hostName">POP3サーバー名</param> ''' <param name="portNumber">POP3サーバーのポート番号</param> ''' <param name="userId">ユーザーID</param> ''' <param name="passWord">パスワード</param> ''' <param name="deleteMails">メールを削除するか</param> ''' <returns>取得したメールの配列</returns> Public Shared Function Receive( _ ByVal hostName As String, _ ByVal portNumber As Integer, _ ByVal userId As String, _ ByVal passWord As String, _ ByVal deleteMails As Boolean) As String() Dim mails As String() = Nothing Dim msg As String = "" Dim stream As NetworkStream = Nothing 'TcpClientの作成 Dim client As New TcpClient 'タイムアウトの設定 client.ReceiveTimeout = 10000 client.SendTimeout = 10000 Try 'サーバーに接続 client.Connect(hostName, portNumber) 'ストリームの取得 stream = client.GetStream() '受信 msg = ReceiveData(stream) 'USERの送信 SendData(stream, "USER " + userId + vbCrLf) '受信 msg = ReceiveData(stream) 'PASSの送信 SendData(stream, "PASS " + passWord + vbCrLf) '受信 msg = ReceiveData(stream) 'STATの送信 SendData(stream, "STAT" + vbCrLf) '受信 msg = ReceiveData(stream) 'メール数の取得 Dim mailsCount As Integer = Integer.Parse(msg.Split(" "c)(1)) mails = New String(mailsCount - 1) {} 'すべてのメールの内容を受信 Dim i As Integer For i = 1 To mailsCount 'RETRの送信(メール本文を受信) SendData(stream, "RETR " + i.ToString() + vbCrLf) '受信 msg = ReceiveData(stream, True) mails((i - 1)) = msg.Substring((msg.IndexOf(vbCrLf) + 2)) 'メールを削除するか If deleteMails Then 'DELEの送信(メールに削除マークを付ける) SendData(stream, "DELE " + i.ToString() + vbCrLf) '受信 msg = ReceiveData(stream) End If Next i 'QUITの送信 SendData(stream, "QUIT" + vbCrLf) '受信 msg = ReceiveData(stream) Catch Throw Finally '切断 If Not stream Is Nothing Then stream.Close() End If client.Close() End Try Return mails End Function 'データを受信する Private Overloads Shared Function ReceiveData( _ ByVal stream As NetworkStream, _ ByVal multiLines As Boolean, _ ByVal bufferSize As Integer, _ ByVal enc As Encoding) As String Dim data(bufferSize - 1) As Byte Dim len As Integer Dim msg As String = "" Dim ms As New System.IO.MemoryStream 'すべて受信する '(無限ループに陥る恐れあり) Do '受信 len = stream.Read(data, 0, data.Length) ms.Write(data, 0, len) '文字列に変換する msg = enc.GetString(ms.ToArray()) Loop While stream.DataAvailable OrElse _ ((Not multiLines OrElse msg.StartsWith("-ERR")) AndAlso _ Not msg.EndsWith(vbCrLf)) OrElse _ (multiLines AndAlso Not msg.EndsWith(vbCrLf + "." + vbCrLf)) ms.Close() '"-ERR"を受け取った時は例外をスロー If msg.StartsWith("-ERR") Then Throw New ApplicationException("Received Error") End If '表示 Console.Write(("S: " + msg)) Return msg End Function Private Overloads Shared Function ReceiveData( _ ByVal stream As NetworkStream, _ ByVal multiLines As Boolean, _ ByVal bufferSize As Integer) As String Return ReceiveData(stream, multiLines, bufferSize, _ Encoding.GetEncoding(50220)) End Function Private Overloads Shared Function ReceiveData( _ ByVal stream As NetworkStream, _ ByVal multiLines As Boolean) As String Return ReceiveData(stream, multiLines, 256) End Function Private Overloads Shared Function ReceiveData( _ ByVal stream As NetworkStream) As String Return ReceiveData(stream, False) End Function 'データを送信する Private Overloads Shared Sub SendData( _ ByVal stream As NetworkStream, _ ByVal msg As String, _ ByVal enc As Encoding) 'byte型配列に変換 Dim data As Byte() = enc.GetBytes(msg) '送信 stream.Write(data, 0, data.Length) '表示 Console.Write(("C: " + msg)) End Sub Private Overloads Shared Sub SendData( _ ByVal stream As NetworkStream, _ ByVal msg As String) SendData(stream, msg, Encoding.ASCII) End Sub End Class End Namespace
using System; using System.Text; using System.Net.Sockets; namespace Dobon.Samples.Mail { public class Pop3Mail { //エントリポイント public static void Main() { string[] mails; mails = Receive("localhost", 110, "userid", "password", true); Console.ReadLine(); } /// <summary> /// POP3サーバーからメールをすべて受信する /// </summary> /// <param name="hostName">POP3サーバー名</param> /// <param name="portNumber">POP3サーバーのポート番号</param> /// <param name="userId">ユーザーID</param> /// <param name="passWord">パスワード</param> /// <param name="deleteMails">メールを削除するか</param> /// <returns>取得したメールの配列</returns> public static string[] Receive(string hostName, int portNumber, string userId, string passWord, bool deleteMails) { string[] mails; string msg = ""; NetworkStream stream = null; //TcpClientの作成 TcpClient client = new TcpClient(); //タイムアウトの設定 client.ReceiveTimeout = 10000; client.SendTimeout = 10000; try { //サーバーに接続 client.Connect(hostName, portNumber); //ストリームの取得 stream = client.GetStream(); //受信 msg = ReceiveData(stream); //USERの送信 SendData(stream, "USER " + userId + "\r\n"); //受信 msg = ReceiveData(stream); //PASSの送信 SendData(stream, "PASS " + passWord + "\r\n"); //受信 msg = ReceiveData(stream); //STATの送信 SendData(stream, "STAT\r\n"); //受信 msg = ReceiveData(stream); //メール数の取得 int mailsCount = int.Parse(msg.Split(' ')[1]); mails = new string[mailsCount]; //すべてのメールの内容を受信 for (int i = 1; i <= mailsCount; i++) { //RETRの送信(メール本文を受信) SendData(stream, "RETR " + i.ToString() + "\r\n"); //受信 msg = ReceiveData(stream, true); mails[i - 1] = msg.Substring(msg.IndexOf("\r\n") + 2); //メールを削除するか if (deleteMails) { //DELEの送信(メールに削除マークを付ける) SendData(stream, "DELE " + i.ToString() + "\r\n"); //受信 msg = ReceiveData(stream); } } //QUITの送信 SendData(stream, "QUIT\r\n"); //受信 msg = ReceiveData(stream); } catch { throw; } finally { //切断 if (stream != null) { stream.Close(); } client.Close(); } return mails; } //データを受信する private static string ReceiveData(NetworkStream stream, bool multiLines, int bufferSize, Encoding enc) { byte[] data = new byte[bufferSize]; int len; string msg = ""; System.IO.MemoryStream ms = new System.IO.MemoryStream(); //すべて受信する //(無限ループに陥る恐れあり) do { //受信 len = stream.Read(data, 0, data.Length); ms.Write(data, 0, len); //文字列に変換する msg = enc.GetString(ms.ToArray()); } while (stream.DataAvailable || ((!multiLines || msg.StartsWith("-ERR")) && !msg.EndsWith("\r\n")) || (multiLines && !msg.EndsWith("\r\n.\r\n"))); ms.Close(); //"-ERR"を受け取った時は例外をスロー if (msg.StartsWith("-ERR")) { throw new ApplicationException("Received Error"); } //表示 Console.Write("S: " + msg); return msg; } private static string ReceiveData(NetworkStream stream, bool multiLines, int bufferSize) { return ReceiveData(stream, multiLines, bufferSize, Encoding.GetEncoding(50220)); } private static string ReceiveData(NetworkStream stream, bool multiLines) { return ReceiveData(stream, multiLines, 256); } private static string ReceiveData(NetworkStream stream) { return ReceiveData(stream, false); } //データを送信する private static void SendData(NetworkStream stream, string msg, Encoding enc) { //byte型配列に変換 byte[] data = enc.GetBytes(msg); //送信 stream.Write(data, 0, data.Length); //表示 Console.Write("C: " + msg); } private static void SendData(NetworkStream stream, string msg) { SendData(stream, msg, Encoding.ASCII); } } }
注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。