┏第12号━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ .NETプログラミング研究 ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜メニュー
■.NET Tips
・POP3メールサーバーからメールを受信する
■ピンポイントリンク
・C#のコードをVB.NETへ変換する(及びその逆)
前回の修正と捕捉
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
───────────────────────────────
■.NET Tips
───────────────────────────────
●POP3メールサーバーからメールを受信する
.NET Frameworkでは、System.Web.Mail.SmtpMailクラスを使用すると、
簡単にメールを送信することが出来ます。多分そのために、「メール
の受信も簡単に出来るのでは?」と思ったり、「メーラーを作りたい」
と思い立つ人が多いようで、「メールの受信はどうするの?」といっ
た質問を多く受けるようになりました。
しかし残念ながら、メールの受信はそう簡単ではありません。POP3メー
ルサーバーからメールを受信するには、今まで通り、ソケットを使っ
てやり取りをする必要があります。それだけならまだしも、受信した
メールを正しく解釈するには、MIMEなどのややこしい知識が要ります。
以下にTcpClientクラスを使用してPOP3メールサーバーからすべてのメー
ルを受信するごく簡単な例を紹介しますが、多少まともなPOP3クライ
アントを作成するつもりであれば、更なるPOP3やMIME等の知識が絶対
に必要であることを認識しておいてください。つまり、RFCの該当箇所
(「Post Office Protocol - Version 3」など)を読んで理解する必
要があります。
・IETF RFC Page
http://www.ietf.org/rfc
・Post Office Protocol - Version 3
http://www.ietf.org/rfc/rfc1939.txt
もしちゃんと勉強するつもりがなく、それでもメールを受信したいと
いうのであれば、COMなどに頼るのがよいでしょう。Tatsuo Babaさん
のBASP21 DLLが有名で、お勧めです。
・Baba Centerfolds
http://www.hi-ho.ne.jp/babaq/index.html
以上のように初心者の方には全く勧められませんが、ごく簡単な例を
以下に紹介します。次のコードは、コンソールアプリケーションとし
て、POP3サーバー(サーバー名:localhost、ポート番号:110)のメー
ルボックス(ユーザー名:userid、パスワード:password)からメール
を受信する(さらにメールは削除する)例です。Pop3Mailクラスの
Receiveメソッドは受信したすべてのメールをstring型配列として返し
ます。
//[C#]・・・・・・・・・・・・・・・・・・・・・・・・・・・・
using System;
using System.Text;
using System.Net.Sockets;
namespace Dobon.Net.Mail
{
public class Pop3Mail
{
//エントリポイント
public static void Main()
{
string[] mails;
mails = Receive("localhost", 110, "userid", "password", true);
Console.ReadLine();
}
///
/// POP3サーバーからメールをすべて受信する
///
/// POP3サーバー名
/// POP3サーバーのポート番号
/// ユーザーID
/// パスワード
/// メールを削除するか
/// 取得したメールの配列
public static string[] Receive(string hostName,
int portNumber,
string userId,
string passWord,
bool deleteMails)
{
string[] mails;
string msg = "";
NetworkStream stream;
//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
{
//切断
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 = "";
//すべて受信する
//(無限ループに陥る恐れあり)
do
{
//受信
len = stream.Read(data, 0, data.Length);
//文字列に変換する
msg += enc.GetString(data, 0, len);
}
while (stream.DataAvailable ||
((!multiLines || msg.StartsWith("-ERR")) &&
!msg.EndsWith("\r\n")) ||
(multiLines && !msg.EndsWith("\r\n.\r\n")));
//"-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);
}
}
}
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
'[VB.NET]・・・・・・・・・・・・・・・・・・・・・・・・・・
'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.Net.Mail
Public Class Pop3Mail
'エントリポイント
Public Shared Sub Main()
Dim mails() As String
mails = Receive("localhost", 110, "userid", "password", True)
Console.ReadLine()
End Sub 'Main
'/
'/ POP3サーバーからメールをすべて受信する
'/
'/ POP3サーバー名
'/ POP3サーバーのポート番号
'/ ユーザーID
'/ パスワード
'/ メールを削除するか
'/ 取得したメールの配列
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
Dim msg As String = ""
Dim stream As NetworkStream
'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) {}
'すべてのメールの内容を受信
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
Finally
'切断
client.Close()
End Try
Return mails
End Function 'Receive
'データを受信する
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) As Byte
Dim len As Integer
Dim msg As String = ""
'すべて受信する
'(無限ループに陥る恐れあり)
Do
'受信
len = stream.Read(data, 0, data.Length)
'文字列に変換する
msg += enc.GetString(data, 0, len)
Loop While stream.DataAvailable Or _
((Not multiLines Or msg.StartsWith("-ERR")) And _
Not msg.EndsWith(vbCrLf)) Or _
(multiLines And Not msg.EndsWith(vbCrLf + "." + vbCrLf))
'"-ERR"を受け取った時は例外をスロー
If msg.StartsWith("-ERR") Then
Throw New ApplicationException("Received Error")
End If
'表示
Console.Write(("S: " + msg))
Return msg
End Function 'ReceiveData
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 'ReceiveData
Private Overloads Shared Function ReceiveData( _
ByVal stream As NetworkStream, _
ByVal multiLines As Boolean) As String
Return ReceiveData(stream, multiLines, 256)
End Function 'ReceiveData
Private Overloads Shared Function ReceiveData( _
ByVal stream As NetworkStream) As String
Return ReceiveData(stream, False)
End Function 'ReceiveData
'データを送信する
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 'SendData
Private Overloads Shared Sub SendData( _
ByVal stream As NetworkStream, _
ByVal msg As String)
SendData(stream, msg, Encoding.ASCII)
End Sub 'SendData
End Class 'Pop3Mail
End Namespace 'Dobon.Net.Mail
'・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
・POP3メールサーバーからメールを受信する
http://dobon.net/vb/dotnet/internet/receivepop3mail.html
───────────────────────────────
■ピンポイントリンク
───────────────────────────────
●C#のコードをVB.NETへ変換する(及びその逆)
前回の補足と修正
前回、C#のコードをVB.NETのコードへ、VB.NETのコードをC#のコード
へ変換するのに役立つツールをいくつか紹介しましたが、今回はその
記事の修正と補足をさせていただきます。
まず前回「Convert C# to VB .NET」
http://www.kamalpatel.net/ConvertCSharp2VB.aspx
に関して、
「日本語を含むコードを変換しようとすると、エラーになることがあ
ります。」
と書きましたが、これは間違いのようで、実際には";"の前で改行され
ている(文の途中で改行されている)とエラーが発生することがある
ようです。また「Convert C# to VB .NET」の場合、エラーが発生しな
くても、文の途中で改行されているコードは正しく変換されないこと
が非常に多いため、「Convert C# to VB .NET」を使用する際は文の途
中で改行していないコードを入力することをお勧めします。
さらに前回は「Convert C# to VB .NET」と「C# to VB.NET Translator」
http://www.aspalliance.com/aldotnet/examples/translate.aspx
のどちらが優れているか分からないと書きましたが、何度となく使っ
ているうちに、「C# to VB.NET Translator」の方が圧倒的に優れてい
ると感じるようになりました。
例えば上記「.NET Tips」で紹介したコードを「Convert C# to VB
.NET」で変換すると、文の途中の改行を削除してから変換しても、何
十箇所と修正しなければならないほど散々な結果でした。それに比べ
て「C# to VB.NET Translator」では、1つのエラーも出ることがあり
ませんでした。しかし厄介なことに、do...while文の条件式で括弧の
つけ方を間違えて、エラーが出なくても正常に機能しないコードにな
ってしまいました。この一箇所を除けば、他は完璧に変換できたよう
です。(なんとも惜しい...。)
また、C#からVB.NETのコードへの変換で役に立つツールに関して、「
VBCS翻訳機」というツールがあることを教えていただきました。「
VBCS翻訳機」はsanta martaさんのフリーウェアで、「Visual Basic
.NET で記述されたソースコードをVisual C# .NET に翻訳するための
ツール」とのことです。
VBCS翻訳機
http://santamartaofthepeace.hp.infoseek.co.jp/products/vbcstranslator.html
この「VBCS翻訳機」や前回紹介した「Convert Visual Basic .NET to C#」
http://www.ellkay.com/ConvertVB2CSharp.htm
を使ってみると、正直なところ、C#からVB.NETへの変換ツールと比べ
て、まだまだ実際に使用できるレベルになっていないというのが実感
です。VB.NETからC#への変換は簡単にはいかないようです。
===============================
■このマガジンの購読、購読中止、バックナンバー、説明に関しては
次のページをご覧ください。
http://www.mag2.com/m/0000104516.htm
■発行人・編集人:どぼん!
http://dobon.net
dobon@bigfoot.com
■ご質問等はメールではなく、掲示板へお願いいたします。
http://dobon.net/bbs
■上記メールアドレスへのメールは確実に読まれる保障はありません
(スパム、ウィルス対策です)。メールは下記URLのフォームメール
から送信してください。
http://dobon.net/mail.html
Copyright (c) 2003 DOBON! All rights reserved.
===============================