メールをテキストファイルとして保存する必要があるときにひとつひとつ開いてコピペするのは効率が悪い。そこでC#を使って効率よくテキストファイルに変換できないかと考えてみる。さてどうすればいいのでしょうか?
.NET用メール送受信クラスライブラリ (TKMP.DLL) があるので、ここはありがたく使わせていただきましょう。全部自分でやろうとすると大変なことになります。
.NET用メール送受信クラスライブラリ (TKMP.DLL)
ではどのようにプログラミングすればいいのでしょうか?
今回はYahoo!メールで考えます。設定は以下のようにする必要があります。
1件だけ取得するのであれば、これでうまくいきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
//接続情報 string server = "pop.mail.yahoo.co.jp"; int port = 995; string userid = "自分のID"; string pass = "自分で設定したパスワード"; //サーバへの接続用クラスを作成する System.Net.IPAddress address = System.Net.Dns.GetHostEntry(server).AddressList[0]; TKMP.Net.IPopLogon logon = new TKMP.Net.BasicPopLogon(userid, pass); TKMP.Net.PopClient pop = new TKMP.Net.PopClient(logon, address, port); //SSLを使用します pop.AuthenticationProtocol = TKMP.Net.AuthenticationProtocols.SSL; //証明書に問題があった場合に独自の処理を追加します pop.CertificateValidation += new TKMP.Net.CertificateValidationHandler(pop_CertificateValidation); //接続開始 if(!pop.Connect()) { MessageBox.Show("接続失敗"); return; } //着信件数の読み出し int mailcount = pop.MailDatas.Length; if(mailcount == 0) { MessageBox.Show("着信メールはありません"); return; } // 1件だけ取得する(全部取得するのであればループを回せばよい) TKMP.Net.MailData Mail = pop.MailDatas[0]; if(!Mail.ReadBody()) { MessageBox.Show("データ受信に失敗しました"); continue; } // メール解析 TKMP.Reader.MailReader reader = new TKMP.Reader.MailReader(Mail.DataStream, false); { // メールの件名取得 string subject = reader.HeaderCollection["Subject"]; // メールの日時を取得 string date = reader.HeaderCollection["Date"]; // 日時をDateTime型に変換 DateTime dt = System.DateTime.ParseExact(date, "ddd, d MMM yyyy HH':'mm':'ss zzz", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None); // メールの本文取得 string mainText = reader.MainText; } // メール解析 終わり //切断 pop.Close(); |
1 2 3 4 5 |
private void pop_CertificateValidation(object sender, TKMP.Net.CertificateValidationArgs e) { //全ての証明書を信用します e.Cancel = false; } |
全部を取得してファイルとして保存するのであれば・・・
まずデータを管理するためのクラスをつくります。必要なのはメールのタイトル、日時、本文だけだと思うので・・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
public class Data { public Data(string subject, string date, string mainText) { Subject = subject; MainText = mainText; Date = GetDateTime(date); } public string Subject { get; private set; } = ""; public DateTime Date { get; private set; } public string MainText { get; private set; } = ""; DateTime GetDateTime(string str) { try { return System.DateTime.ParseExact(str, "ddd, d MMM yyyy HH':'mm':'ss zzz", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None); } catch { return DateTime.MinValue; } } } |
以下のメソッドはメールを取得してその結果をDataのリストで返します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
public partial class Form1 : Form { List<Data> GetMails() { List<Data> datas = new List<Data>(); //接続情報 string server = "pop.mail.yahoo.co.jp"; int port = 995; string userid = "自分のID"; string pass = "自分で設定したパスワード"; //サーバへの接続用クラスを作成する System.Net.IPAddress address = System.Net.Dns.GetHostEntry(server).AddressList[0]; TKMP.Net.IPopLogon logon = new TKMP.Net.BasicPopLogon(userid, pass); TKMP.Net.PopClient pop = new TKMP.Net.PopClient(logon, address, port); pop.AuthenticationProtocol = TKMP.Net.AuthenticationProtocols.SSL; pop.CertificateValidation += new TKMP.Net.CertificateValidationHandler(pop_CertificateValidation); if(!pop.Connect()) { MessageBox.Show("接続失敗"); return datas; } int mailcount = pop.MailDatas.Length; if(mailcount == 0) { MessageBox.Show("着信メールはありません"); return datas; } for(int i = 0; i < mailcount; i++) { TKMP.Net.MailData Mail = pop.MailDatas[i]; if(!Mail.ReadBody()) { MessageBox.Show("データ受信に失敗しました"); continue; } TKMP.Reader.MailReader reader = new TKMP.Reader.MailReader(Mail.DataStream, false); string subject = reader.HeaderCollection["Subject"]; string date = reader.HeaderCollection["Date"]; string mainText = reader.MainText; datas.Add(new Data(subject, date, mainText)); } //切断 pop.Close(); MessageBox.Show("取得完了!"); return datas; } } |
あとはこれを保存すればテキストファイルとして保存できます。
以下はユーザーにフォルダを指定させて、そこにテキストファイルとして保存するプログラムです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public partial class Form1 : Form { private void button1_Click(object sender, EventArgs e) { List<Data> datas = GetMails(); FolderBrowserDialog dialog = new FolderBrowserDialog(); dialog.Description = "テキストファイルを保存するフォルダを指定してください"; if(dialog.ShowDialog() == DialogResult.OK) { string folderPath = dialog.SelectedPath; int i = 0; foreach(Data data in datas) { i++; string filePath = folderPath + "\\" + i.ToString() + ".txt"; System.IO.StreamWriter sw = new System.IO.StreamWriter(filePath, false, Encoding.Default); string str = String.Format("【件名】{0}\n{1}\n\n【本文】\n{2}\n", data.Subject, data.Date.ToString("F"), data.MainText); sw.Write(str); sw.Close(); } } dialog.Dispose(); } } |
以下はCSVファイルで保存するプログラムです。フィールドがコンマ、ダブルクォート、改行を含む場合はダブルクォートで囲まなければなりません。またフィールドに含まれるダブルクォートは2つ並べてエスケープします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
public partial class Form1 : Form { private void button2_Click(object sender, EventArgs e) { List<Data> datas = GetMails(); SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "csvファイル(*.csv)|*.csv"; dialog.DefaultExt = "csv"; string filePath = ""; if(dialog.ShowDialog() == DialogResult.OK) filePath = dialog.FileName; dialog.Dispose(); if(filePath == "") return; StringBuilder sb = new StringBuilder(); sb.Append("件名,日時,本文\n"); foreach(Data data in datas) { string str = ""; string str1 = data.Subject.Replace("\"", "\"\""); str = String.Format("\"{0}\",", str1); sb.Append(str); str = String.Format("\"{0}\",", data.Date.ToString("F")); sb.Append(str); str1 = data.MainText.Replace("\"", "\"\""); str = String.Format("\"{0}\"\n\n", str1); sb.Append(str); } System.IO.StreamWriter sw = new System.IO.StreamWriter(filePath, false, Encoding.Default); sw.Write(sb.ToString()); sw.Close(); } } |