以前、メールをテキストファイルとして保存するアプリを作成しました。今回は送信です。メールを送るときに少しだけ変えて送ることはないでしょうか?
件名:佐藤さん、おはようございます
メール本文:やっぱり早起きは三文の徳です。佐藤さんも早寝早起きを実践しましょう。
件名:鈴木さん、おはようございます
メール本文:やっぱり早起きは三文の徳です。鈴木さんも早寝早起きを実践しましょう。
件名:高橋さん、おはようございます
メール本文:やっぱり早起きは三文の徳です。高橋さんも早寝早起きを実践しましょう。
サンプルなので内容ゼロのメールですが、このような少しだけ件名と内容が違う複数のメールを出すことはよくある話です。専用のメールアプリを使えばできそうなのですが、自分自身の勉強のためにつくってみました。
メール受信のときと同様に.NET用メール送受信クラスライブラリ (TKMP.DLL) を使います。
.NET用メール送受信クラスライブラリ (TKMP.DLL)
今回もYahooメールを使う前提でアプリを作成します。
以下の方法で送信することができます。ちょっとハマったのはメール本文のなかに改行があるときです。RichTextBoxの改行は”\n”ですが、メールを送るのであれば”\r\n”にしなければなりません。
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 |
//メールの送信先サーバー名 string smtpserver = "smtp.mail.yahoo.co.jp"; int port = 465; string userid = <アカウント名>; string pass = <パスワード>; string from = <送信元のメールアドレス>; System.Net.IPAddress address = System.Net.Dns.GetHostEntry(smtpserver).AddressList[0]; //ログオンクラスを作成します TKMP.Net.ISmtpLogon logon; //AUTH LOGINでログオンを行ないます logon = new TKMP.Net.AuthLogin(userid, pass); //SMTPへの接続クラスを作成 TKMP.Net.SmtpClient smtp = new TKMP.Net.SmtpClient(address, port, logon); //SSLを使用します smtp.AuthenticationProtocol = TKMP.Net.AuthenticationProtocols.SSL; //証明書に問題があった場合に独自の処理を追加します smtp.CertificateValidation += new TKMP.Net.CertificateValidationHandler(smtp_CertificateValidation); //サーバーへ接続 if(!smtp.Connect()) { System.Windows.Forms.MessageBox.Show("接続失敗"); return; } //送信メールの作成クラスを定義 TKMP.Writer.MailWriter writer = new TKMP.Writer.MailWriter(); //メールの実際の差出人 writer.FromAddress = from; //メールヘッダの差出人情報 writer.Headers.Add("From", "差出人名 <" + from + ">"); //メールの実際の宛先 string to = mail.Adress; writer.ToAddressList.Add(to); //メールヘッダの宛先情報 writer.Headers.Add("To", "宛先人名 <" + to + ">"); //件名 writer.Headers.Add("Subject", "ここにメールの件名をいれる"); //本文 writer.MainPart = new TKMP.Writer.TextPart("ここにメールの本文をいれる\r\n改行コードに注意"); //メール送信 smtp.SendMail(writer); //サーバーから切断 smtp.Close(); |
ひな形になる元のメールの件名、本文を入力しておき、差し替えたい部分を”$$n$$”にしています。
件名:$$1$$さん、おはようございます
メール本文:やっぱり早起きは三文の徳です。$$1$$さんも早寝早起きを実践しましょう。
メールアドレスとの組み合わせで$$1$$を登録しておくとメールを複数送信することができます($$1$$~$$8$$まで登録可能)。ただしこれを悪用してスパムメールを送信することは絶対にしないでください。ツールは使い方次第で「善」にも「悪」にもなります。
まずメールアドレスと差し替えたい言葉をセットで扱うためのDataクラスを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class Data { public string Address = ""; public string[] Texts = null; public Data() { } public Data(string address, string text1, string text2, string text3, string text4, string text5, string text6, string text7, string text8) { Address = address; List<string> vs = new List<string>(); vs.Add(text1); vs.Add(text2); vs.Add(text3); vs.Add(text4); vs.Add(text5); vs.Add(text6); vs.Add(text7); vs.Add(text8); Texts = vs.ToArray(); } } |
[送信情報] ⇒ [追加]を選択するとリストボックスにアイテムが追加されます。また[送信情報] ⇒ [削除]を選択するとアイテムが削除されます。
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 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void MenuItemAddItem_Click(object sender, EventArgs e) { string newName = "Address@Address"; if(listBox1.SelectedIndex == -1) { Data data = new Data(); data.Address = newName; Datas.Insert(0, data); listBox1.Items.Insert(0, newName); listBox1.SelectedIndex = 0; } else { int index = listBox1.SelectedIndex; Data data = new Data(); data.Address = newName; Datas.Insert(index + 1, data); listBox1.Items.Insert(index+1, newName); listBox1.SelectedIndex = index + 1; } } private void MenuItemDeleteItem_Click(object sender, EventArgs e) { if(listBox1.SelectedIndex == -1) return; int index = listBox1.SelectedIndex; listBox1.SelectedIndex = -1; listBox1.Items.RemoveAt(index); Datas.RemoveAt(index); if(listBox1.Items.Count == 0) { foreach(TextBox textBox in GetTextBoxDatas()) textBox.Text = ""; TextBoxMailAddress.Text = ""; } if(listBox1.Items.Count > index) listBox1.SelectedIndex = index; else listBox1.SelectedIndex = index-1; } } |
選択されているアイテムが変更されるとテキストボックスに入力されている文字列がデータとして保存され、新しく選択されたアイテムに対応するデータが表示されます。
SaveOldData()はこれまで選択されていたアイテムのデータを保存するためのものです。LoadStringTextBoxes(Data data)はDataオブジェクトのなかからデータを読み出してテキストボックスに表示するためのメソッドです。またSaveStringTextBoxes(Data data)は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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
public partial class Form1 : Form { int selectedIndex = -1; private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { if(selectedIndex == listBox1.SelectedIndex) { return; } SaveOldData(); int index = listBox1.SelectedIndex; if(index != -1) { Data data = Datas[index]; LoadStringTextBoxes(data); } else { List<TextBox> textBoxes = GetTextBoxDatas(); foreach(TextBox textBox in textBoxes) textBox.Text = ""; } selectedIndex = index; } void SaveOldData() { // selectedIndexはこれまで選択されていたインデックス if(selectedIndex != -1) { SaveStringTextBoxes(Datas[selectedIndex]); listBox1.Items[selectedIndex] = Datas[selectedIndex].Address; } } void SaveCurData() { int index = listBox1.SelectedIndex; if(index != -1) { Data data = Datas[index]; SaveStringTextBoxes(data); if((string)listBox1.Items[index] != TextBoxMailAddress.Text) { listBox1.SelectedIndex = -1; listBox1.Items.RemoveAt(index); listBox1.Items.Insert(index, TextBoxMailAddress.Text); listBox1.SelectedIndex = index; } } } List<TextBox> GetTextBoxDatas() { List<TextBox> textBoxes = new List<TextBox>(); textBoxes.Add(TextBoxData1); textBoxes.Add(TextBoxData2); textBoxes.Add(TextBoxData3); textBoxes.Add(TextBoxData4); textBoxes.Add(TextBoxData5); textBoxes.Add(TextBoxData6); textBoxes.Add(TextBoxData7); textBoxes.Add(TextBoxData8); return textBoxes; } void LoadStringTextBoxes(Data data) { TextBoxMailAddress.Text = data.Address; List<TextBox> textBoxes = GetTextBoxDatas(); foreach(TextBox textBox in textBoxes) { textBox.Text = ""; } if(data.Texts != null) { for(int i =0; i< data.Texts.Length; i++) { textBoxes[i].Text = data.Texts[i]; } } } void SaveStringTextBoxes(Data data) { data.Address = TextBoxMailAddress.Text; List<TextBox> textBoxes = GetTextBoxDatas(); data.Texts = new string[textBoxes.Count]; for(int i = 0; i < textBoxes.Count; i++) { data.Texts[i] = textBoxes[i].Text; } } } |
以下のメソッドはデータをファイルに保存したり、ファイルからデータを読み出すためのメソッドです。
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 |
public partial class Form1 : Form { private void MenuItemSaveFile_Click(object sender, EventArgs e) { SaveCurData(); XmlSerializer xml = new XmlSerializer(typeof(Doc)); SaveFileDialog save = new SaveFileDialog(); save.Filter = "メールデータ(*.maildata)|*.maildata"; save.DefaultExt = "maildata"; if(save.ShowDialog() == DialogResult.OK) { Doc doc = new Doc(Datas, TextBoxSubject.Text, richTextBoxMailContent.Text); StreamWriter sw = new StreamWriter(save.FileName); xml.Serialize(sw, doc); sw.Close(); } save.Dispose(); } private void MenuItemOpenFile_Click(object sender, EventArgs e) { XmlSerializer xml = new XmlSerializer(typeof(Doc)); OpenFileDialog open = new OpenFileDialog(); open.Filter = "メールデータ(*.maildata)|*.maildata"; open.DefaultExt = "maildata"; if(open.ShowDialog() == DialogResult.OK) { StreamReader sr = new StreamReader(open.FileName); Doc doc = (Doc)xml.Deserialize(sr); sr.Close(); Datas = doc.Datas; listBox1.SelectedIndex = -1; listBox1.Items.Clear(); foreach(Data data in Datas) { listBox1.Items.Add(data.Address); } richTextBoxMailContent.Text = doc.MailContent; TextBoxSubject.Text = doc.MailSubject; if(Datas.Count > 0) listBox1.SelectedIndex = 0; } open.Dispose(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class Doc { public Doc(){} public Doc(List<Data> datas, string mailSubject, string mailContent) { Datas = datas; MailSubject = mailSubject; MailContent = mailContent; } public List<Data> Datas = null; public string MailContent = ""; public string MailSubject = ""; } |
そして[メールを送信する]をクリックするとリッチテキストボックス上の文字列が一部置き換えられてメールとして送る文字列が生成されます。これとメールアドレスが組み合わされてSendMailsメソッドが呼び出されます。MailInfoクラスはメールアドレスとメールの件名、メール本文を管理するためのクラスです。
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 buttonMailSend_Click(object sender, EventArgs e) { if(Datas.Count == 0) { MessageBox.Show("データが登録されていません!", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if(textBoxId.Text == "" || textBoxPass.Text == "") { MessageBox.Show("アカウントとパスワードを入力してください!", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if(TextBoxFrom.Text == "") { MessageBox.Show("送信元のメールアドレスを入力してください!", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } SaveOldData(); List<MailInfo> mailInfos = new List<MailInfo>(); foreach(Data data in Datas) { string mailContent = richTextBoxMailContent.Text; string mailSubject = TextBoxSubject.Text; int len = data.Texts.Length; for(int i=0; i<len; i++) { string str1 = String.Format("$${0}$$", i+1); if(data.Texts[i] != "") mailContent = mailContent.Replace(str1, data.Texts[i]); if(data.Texts[i] != "") mailSubject = mailSubject.Replace(str1, data.Texts[i]); } mailInfos.Add(new MailInfo(data.Address, mailSubject, mailContent)); } SendMails(mailInfos); } } |
1 2 3 4 5 6 7 8 9 10 11 12 |
public class MailInfo { public MailInfo(string adress, string mailSubject, string mailContent) { Adress = adress; MailSubject = mailSubject; MailContent = mailContent; } public string Adress = ""; public string MailSubject = ""; public string MailContent = ""; } |
最後に作成された件名と本文でメールを送信します。
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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
public partial class Form1 : Form { public void SendMails(List<MailInfo> mailInfos) { SaveCurData(); //メールの送信先サーバー名 string smtpserver = "smtp.mail.yahoo.co.jp"; int port = 465; string userid = textBoxId.Text; string pass = textBoxPass.Text; string from =TextBoxFrom.Text; System.Net.IPAddress address = System.Net.Dns.GetHostEntry(smtpserver).AddressList[0]; //ログオンクラスを作成します TKMP.Net.ISmtpLogon logon; //AUTH LOGINでログオンを行ないます logon = new TKMP.Net.AuthLogin(userid, pass); //SMTPへの接続クラスを作成 TKMP.Net.SmtpClient smtp = new TKMP.Net.SmtpClient(address, port, logon); //SSLを使用します smtp.AuthenticationProtocol = TKMP.Net.AuthenticationProtocols.SSL; //証明書に問題があった場合に独自の処理を追加します smtp.CertificateValidation += new TKMP.Net.CertificateValidationHandler(smtp_CertificateValidation); //サーバーへ接続 if(!smtp.Connect()) { MessageBox.Show("接続失敗", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } int successCount = 0; foreach(MailInfo mail in mailInfos) { string to = mail.Adress; try { //送信メールの作成クラスを定義 TKMP.Writer.MailWriter writer = new TKMP.Writer.MailWriter(); //メールの実際の差出人 writer.FromAddress = from; //メールヘッダの差出人情報 writer.Headers.Add("From", "差出人名 <" + from + ">"); //メールの実際の宛先 writer.ToAddressList.Add(to); //メールヘッダの宛先情報 writer.Headers.Add("To", "宛先人名 <" + to + ">"); //件名 writer.Headers.Add("Subject", mail.MailSubject); //本文 // 改行コードに注意 writer.MainPart = new TKMP.Writer.TextPart(mail.MailContent.Replace("\n", "\r\n")); //メール送信 smtp.SendMail(writer); successCount++; } catch { MessageBox.Show(to + "への送信に失敗しました。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); } } //サーバーから切断 smtp.Close(); MessageBox.Show(successCount + "件送信しました", "完了"); } private void smtp_CertificateValidation(object sender, TKMP.Net.CertificateValidationArgs e) { //全ての証明書を信用します e.Cancel = false; } } |