C# 入門 & 実践 / C sharp

301-3. SendAsync による非同期メール送信!


SendAsync サンプル
http://msdn2.microsoft.com/en-us/library/system.net.mail.smtpclient.aspx

このサンプルにあるように

完了通知用の関数を作成して、
client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);

SendAsyncで送信するだけで完了です!

キャンセルするときは、SendAsyncCancel();でOKです。

このサンプルの場合、コンソールなので、上手く使えませんが。

スレッドを利用してダイアログを表示してキャンセルボタンでキャンセルできるものを作成してみます。

・mailSentで終了したかを判断します。
・mailre の値で終了結果を判断します。

送信開始後
・別スレッドでチェックします>showMessage()
・ダイアログ表示します。

キャンセルかOKボタンで終わります。
上手く出来ました^-^。

// スレッドを利用します。
using System.Threading;


    // +++++++++++++++++++++++++++++++++++
    //
    // メール送信用ダイアログクラス
    //
    public partial class BbSendMail : Form
    {
        //別スレッドからラベル変更に使用
        delegate void SetTextCallback(string text);

        // 送信用
        private SmtpClient sc;
        private MailMessage myMessage; 
        private static bool mailSent = false;
        private static int mailre = 0;

        private string to;
        private string from;
        private string title;
        private string message;


        public BbSendMail(string to, string from, string title, string message)
        {

            try
            {
                this.to = to;
                this.from = from;
                this.title = title;
                this.message = message;

                mailSent = false;
                mailre = 0;

                InitializeComponent();
                // ダイアログなので、コントロールを表示しない。
                this.ControlBox = false;
                // 縮小ボタンを出さない。
                this.MinimizeBox = false;
                // 最大化ボタンを出さない。
                this.MaximizeBox = false;
                // タスクバーに表示しない。
                this.ShowInTaskbar = false;

                this.mailCancel.Visible = true;
                this.okButton.Visible = false;


                sc = new SmtpClient();
                // 送信完了メッセージを待つ!
                sc.SendCompleted += new
                SendCompletedEventHandler(SendCompletedCallback);
                if (mail() == true)
                {
                    // このスレッドで、結果の内容を変更します。
                    Thread t1 = new Thread(new ThreadStart(showMessage));
                    t1.Start();
                    // まだ結果が出ていない場合のみ
                    // キャンセルボタンを表示
                    // 終わっていれば、OKボタンのみ表示
                    this.ShowDialog();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        // メール送信実行
        public bool mail()
        {
            if (SendMail())
            {
                //MessageBox.Show("TRUE");
            }
            else
            {
                // メール送信に失敗。
                MessageBox.Show("メール設定を確認してください。");
                return false;
            }
            return true;
        }


        // 別スレッド内で呼び出す場合
        private void SetText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.label1.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.mailCancel.Visible = false;
                this.okButton.Visible = true;
                this.label1.Text = text;
            }
        }

        // スレッドで呼び出し同期をとる。
        private void showMessage()
        {
            this.label1.Text = "メール送信中";
            int i = 0;
            int limit = 300;// 30秒
            while ( i < limit && mailSent == false)
            {
                Thread.Sleep(100);
                i++;
            }
            if(i >= limit && mailSent == false){
                sc.SendAsyncCancel();
                mailre = 4;
            }

            switch (mailre)
            {
                case 1:
                    SetText("キャンセルされました。");
                    break;
                case 2:
                    SetText("送信エラー");
                    break;
                case 3:
                    SetText("送信完了");
                    break;
                case 4:
                    SetText("タイムアウト");
                    break;
            }
        }

        private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
        {
            // Get the unique identifier for this asynchronous operation.
            String token = (string) e.UserState;

            if (e.Cancelled)
            {
//                MessageBox.Show("キャンセルされました。");
                mailre = 1;
            }
            else
            {
                if (e.Error != null)
                {

  //                  MessageBox.Show("メール送信エラー\n" + e.Error.ToString());
                    mailre = 2;
                }
                else
                {
                 //   label1.Text = "メール送信完了";
                 //   mailCancel.Visible = false;
    //                MessageBox.Show("完了しました。");
                    mailre = 3;
                }
            }
            mailSent = true;
        }

        // メール送信
        private bool SendMail()
        {
            try
            {
                sc.Host = @"smtp.server";
                //sc.Port = 25;

                myMessage = new MailMessage("junあっとめーる"
                    , to);
                myMessage.Subject = title;
                myMessage.SubjectEncoding = Encoding.GetEncoding("iso-2022-jp");
                // Encoding は、デフォルトで iso-2022-jp になっているので、
                // 指定する必要は無い。
                myMessage.BodyEncoding = Encoding.GetEncoding("iso-2022-jp");
                myMessage.Body = message;


                string userState = "test message";
                // メッセージ送信
                sc.SendAsync( myMessage, userState);

                return true;
            }
            catch
            {
                return false;
            }
        }
        // 送信キャンセルします。
        private void mailCancel_Click(object sender, EventArgs e)
        {
            if (mailSent == false)
            {
                sc.SendAsyncCancel();
            }
        }

        // OKで閉じる
        private void okButton_Click(object sender, EventArgs e)
        {
            this.Hide();
        }
    }

これを作っておくと何にでも使えますね!




301-2. メール送受信 - 2 - pop before smtp « メール送受信

C# 入門 & 実践 / C sharp