C#でメール受信する方法を解説!

エンジニア
マネージャー
C#によるメール受信とは
メールの受信に限らずサーバー間の通信を行うには、プロトコルという決まりに従う必要があります。メール送信にはSMTP、メール受信にはPOPというプロトコルを使用します。C#の.Net FrameworkにはSmtpClientというクラスがあるので送信は簡単に行えます。
ところがC#にはPOP用のクラスがないのです。そのためメール受信するにはPOPに従って通信を行う処理を自作する必要があります。この記事ではC#によるシンプルなPOP通信を解説するので、是非これを読んでメール受信ができるようになってください。
メール受信をするMainメソッド
C#によるメール受信をするサンプルのMainメソッドは以下の通りです。次の項で順次説明しましょう。
using System;
using System.IO;
using System.Text;
using System.Net.Sockets;
public static void Main()
{
using (TcpClient tc = new TcpClient())
{
// 接続
tc.ReceiveTimeout = 5000;
tc.SendTimeout = 5000;
tc.Connect(“(サーバ名)”, 110);
NetworkStream st = tc.GetStream();
Receive(st,false);
// ログイン
Send(st, “USER (ユーザ名)\r\n”);
Receive(st,false);
Send(st, “PASS (パスワード)\r\n”);
Receive(st,false);
// STATで受信メール数を確認
Send(st, “STAT\r\n”);
string str = Receive(st,false);
int cnt = int.Parse(str.Split(‘ ‘)[1]);
//メールを全て受信
for (int i = 0; i < cnt; i++)
{
// RETRでメールの中身を取得
Send(st, “RETR ” + (i+1).ToString() + “\r\n”);
Receive(st, true);
}
// QUITを送信して終了
Send(st, “QUIT\r\n”);
Receive(st, false);
}
}
TcpClientクラスで接続する
それではこのC#サンプルを説明しましょう。まず、
using (TcpClient tc = new TcpClient())
としていますが、これでTCP通信を確立します。usingは、{}で囲まれた処理が終わると自動的にTcpClientのCloseメソッドを呼び出してくれます。次の、
tc.ReceiveTimeout = 5000;
tc.SendTimeout = 5000;
は、送受信のタイムアウト時間を設定しています。5000は5千ミリ秒、つまりサーバの通信の応答を5秒待つということです。それを過ぎると通信失敗と判断して例外が発生し、プログラムが中断します。
接続して応答を確認する
次の、
tc.Connect(“(サーバ名)”, 110);
はサーバー名(xxx.comやxxx.co.jp等)とポート番号を指定します。このC#サンプルを実際試す場合は、受信メールが消えても良いような適当なフリーメールアドレスで試してください。
NetworkStream st = tc.GetStream();
Receive(st,false);
で最初の通信を行っています。このReceiveというメソッドの中身は後で掲載します。今は受信を行っているんだな、くらいに理解しておいてください。Receiveではサーバからの応答を表示していますが、以下のようにコンソールに出てきます。
S:+OK Hello there.
ユーザ名とパスワードを送信する
次にユーザ名とパスワードを送信します。メールのユーザ名はメールアドレスと同じであることが多いですね。
Send(st, “USER (ユーザ名)\r\n”);
Receive(st,false);
Send(st, “PASS (パスワード)\r\n”);
Receive(st,false);
Sendというメソッドについても後で説明します。この部分が実行されると以下のように表示されます。
C:USER (ユーザー名)
S:+OK Password required.
C:PASS (パスワード)
S:+OK Connected to proxy server.
このような通信のやり取りを「プロトコル」と言うのです。
STATでメールの件数を確認する
次の、
Send(st, “STAT\r\n”);
str = Receive(st,false);
int cnt = int.Parse(str.Split(‘ ‘)[1]);
でSTATというコマンドをサーバに送信して、サーバにあるメール件数を取得しています。この処理を実行するとコンソールに以下のように表示されます。
C:STAT
S:+OK 2 6942
この場合、サーバにメールが2件あってサイズは6942byteという意味です。splitで2を取り出してcntという変数に入れています。
RETRでメールの中身を取得
次にcntの数だけメール受信を行います。RETRコマンドでメールの中身を取得できます。
for (int i = 0; i < cnt; i++)
{
// RETRでメールの中身を取得
Send(st, “RETR ” + (i+1).ToString() + “\r\n”);
Receive(st, true);
}
これを実行すると、
C:RETR 1
S:+OK 3449 octets follow.
(1つ目のメールの内容)
C:RETR 2
S:+OK 3493 octets follow.
(2つ目のメールの内容)
のように表示されます。3449と3493はメール受信したデータのバイト数です。
QUITとDELEについて
最後はQUITコマンドをサーバに送信してメール受信を終了します。
Send(st, “QUIT\r\n”);
Receive(st, false);
コンソールには以下のように表示されます。
C:QUIT
S:+OK Bye-bye.
なおこのC#サンプルはサーバのメールを読み取っているだけですが、同時にサーバのメールを削除したい場合は、forループのRETR処理の後に以下を追加すれば削除されます。
Send(st, “DELE ” + (i+1).ToString() + “\r\n”);
Receive(st, false);
Receiveメソッドについて
サーバからの受信に使用するReceiveメソッドの中身は以下の通りです。
private static string Receive(NetworkStream st, bool ml)
{
byte[] data = new byte[256];
int length;
string str = “”;
MemoryStream ms = new MemoryStream();
do
{
length = st.Read(data, 0, data.Length);
ms.Write(data, 0, length);
str = Encoding.UTF8.GetString(ms.ToArray());
}
while (st.DataAvailable ||
((!ml || str.StartsWith(“-ERR”)) &&
!str.EndsWith(“\r\n”)) ||
(ml && !str.EndsWith(“\r\n.\r\n”)));
ms.Close();
if (str.StartsWith(“-ERR”))
{
Console.WriteLine(“Receive:ERROR!”);
}
Console.Write(“S:” + str);
return str;
}
Receiveメソッドの説明
Receiveメソッドの要点について説明すると、まず
private static string Receive(NetworkStream st, bool ml)
のmlはmulti lineという意味で、複数行かどうかというフラグです。RETRの時だけこれをtrueで呼び出しています。メール受信の時は複数行になるためですね。whileループを継続する条件は「DataAvailableか、1行かエラーで末尾が改行でないか、複数行で末尾が改行.改行でないか」になっています。改行.改行はPOPのルールです。
それ以外については、
str = Encoding.UTF8.GetString(ms.ToArray());
でわかるように受信したデータはUTF-8でエンコーディングしています。そのため文字コードがShift_JISなどのメールは日本語が文字化けします。
Sendメソッドの説明
送信のSendメソッドは以下の通り簡単です。
private static void Send(NetworkStream st, string str)
{
byte[] data = Encoding.ASCII.GetBytes(str);
st.Write(data, 0, data.Length);
Console.Write(“C:” + str);
}
RETRなどのコマンドの送信は先頭にC:をつけてアスキーコードで行います。POPのプロトコルでそういったルールになっているのです。
エンジニア
マネージャー
プロトコルを学んでより優れたメールアプリを作ろう
C#によるメール受信を簡単に説明しました。POPのプロトコルについてはRFC1939で定められていて、しっかり動作するメール受信アプリを作るにはこの記事を読むだけでなく、より勉強する必要があります。メールプロトコルをマスターしてより優れたC#アプリを制作してください。
FEnet.NETナビ・.NETコラムは株式会社オープンアップシステムが運営しています。
株式会社オープンアップシステムはこんな会社です
秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
数多くのエンジニアが集まります。

-
スマホアプリから業務系システムまで
スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。
-
充実した研修制度
毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。
-
資格取得を応援
スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。
-
東証プライム上場企業グループ
オープンアップシステムは東証プライム上場「株式会社オープンアップグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
株式会社オープンアップシステムに興味を持った方へ
株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。


C#新着案件New Job
システム開発/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(新宿駅)システム開発/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(新宿駅)デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円神奈川県横浜市(桜木町駅)デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円神奈川県横浜市(桜木町駅)基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(西新宿駅)基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(西新宿駅)