【Gmail一斉送信アプリ】名探偵自作のGmail一斉送信アプリを紹介します

【Gmail一斉送信アプリ】名探偵自作のGmail一斉 送信アプリを紹介します!
【Gmail一斉送信アプリ】名探偵自作のGmail一斉送信アプリを紹介します

今回はGmail一斉送信アプリをWindowsFormで実装していきます。

機能を軽く説明しますと、

アプリ機能
  1. メールアドレスを登録
  2. メール作成で件名と本文を入力して送信
  3. 無事遅れたら「送信できました」のダイアログ表示

このような流れで作ります。

目次

必要設定

事前に以下の設定が必要になります。

  • Googleでの2段階認証の設定
  • アプリパスワードの設定→こちら参照

こちらの設定をしておかないとGmailを操作できないのでやっておきましょう。

アプリの仕様

アプリの機能は以下の通りです。

  • 送信元はGmailで行う
  • 最大99メールアドレス分の一斉送信を可能とする
  • メールアドレス一覧リストを作成する
  • 件名+本文でメールを送れるようにする
  • メールアドレス一覧から任意のメールアドレスを削除
  • 管理項目はメールアドレスのみ
  • メールアドレス追加画面の作成
  • 本文作成画面の作成
  • メール一覧リストのパス:C:\SendMail\INI\MailList.ini
  • Libraryクラスで共通化
  • Libraryクラス実装機能:INIファイル読み、書き、削除

以上がアプリの一通りの機能です。

共通ライブラリ

共通ライブラリを作成してメール送信関連の機能はすべてここに書いています。

共通ライブラリ機能
  • INIファイル名、ファイルパスなどの定義
  • INIファイルからのデータ取得、追加、削除

以下がソースコードになります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace SendMail
{
    /// <summary>
    /// 共通定義クラス
    /// </summary>
    class Library
    {
        #region プライベート定数
        /// <summary>
        /// INIファイルパス
        /// </summary>
        private const string INI_FILE_PATH = @"C:\SendMail\INI";

        /// <summary>
        /// INIファイル名
        /// </summary>
        private const string INI_FILE_NAME = "MailList.ini";

        /// <summary>
        /// INIファイルパスフル
        /// </summary>
        private const string INI_FILE_PATH_FULL = @"C:\SendMail\INI\MailList.ini";

        /// <summary>
        /// セクション名
        /// </summary>
        private const string INI_FILE_SECTION = "List";

        /// <summary>
        /// キー名
        /// </summary>
        private const string INI_FILE_KEY = "mail";

        /// <summary>
        /// INIファイル最大行数
        /// </summary>
        private const int INI_FILE_MAX_ROW = 99;
        #endregion
        #region パブリックメソッド
        /// <summary>
        /// INIファイル存在チェック(なければ作成)
        /// </summary>
        public void CheckIniFile()
        {
            try
            {
                /* ---ファイルチェック ----- */
                if (!System.IO.Directory.Exists(INI_FILE_PATH))
                {
                    return;
                }
                // ファイル名取得
                string[] files = System.IO.Directory.GetFiles(INI_FILE_PATH, "*");
                for (int index = 0; index < files.Length; index++)
                {
                    files[index] = System.IO.Path.GetFileName(files[index]);
                }
                if (files != null)
                {
                    return;
                }
                else
                {
                    // ファイルパス
                    string path = INI_FILE_PATH + INI_FILE_NAME;
                    // FileInfoのインスタンスを生成する
                    System.IO.FileInfo fileInfo = new System.IO.FileInfo(path);
                    // ファイルを作成する
                    System.IO.FileStream fileStream = fileInfo.Create();
                    System.IO.StreamWriter sw = new System.IO.StreamWriter(path, true, Encoding.GetEncoding("shift_jis"));
                    sw.Write(INI_FILE_SECTION + sw.NewLine);
                }
                /* ---ファイルチェック ----- */
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// INIファイルからデータを取得
        /// </summary>
         public string[] GetIniFile()
        {
            string[] stockDataArry = new string[INI_FILE_MAX_ROW];
            int datarow = 1;

            try
            {
                // INIファイルが存在するか確認しなければ作成
                CheckIniFile();

                for (int row = 0; row < INI_FILE_MAX_ROW; row++)
                {
                    // 空の場合はそこでデータがないとみなし終了
                    stockDataArry[row] = GetIniString(INI_FILE_SECTION, INI_FILE_KEY + datarow.ToString(), INI_FILE_PATH + @"\" + INI_FILE_NAME);
                    if (stockDataArry[row] == string.Empty)
                    {
                        break;
                    }
                    datarow++;
                }
            }
            catch
            {
                throw;
            }
            return stockDataArry;
        }

        /// <summary>
        /// INIファイルにデータを追加
        /// </summary>
        /// <param name="mailAdress">ID</param>
        public void CreateIniFile(string mailAdress, int row)
        {
            string data = string.Empty;

            try
            {
                // keyを追加
                data = INI_FILE_KEY + row + "=" + mailAdress;
                // カンマ区切りでINIファイルに追加
                System.IO.StreamWriter sw = new System.IO.StreamWriter(INI_FILE_PATH_FULL, true, Encoding.GetEncoding("shift_jis"));
                sw.Write(data + sw.NewLine);
                //閉じる
                sw.Close();
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// INIファイルのデータを削除
        /// </summary>
        /// <param name="dataArray">全データ</param>
        public void DelIniFile(string[] dataArray)
        {
            string data = string.Empty;

            try
            {
                // 指定ファイルを削除
                System.IO.File.Delete(INI_FILE_PATH_FULL);

                // ファイルパス
                string path = INI_FILE_PATH_FULL;
                // FileInfoのインスタンスを生成する
                System.IO.FileInfo fileInfo = new System.IO.FileInfo(path);
                // ファイルを作成する
                System.IO.FileStream fileStream = fileInfo.Create();
                // ファイルを閉じる
                fileStream.Close();
                // セクション名を挿入
                System.IO.StreamWriter sw = new System.IO.StreamWriter(INI_FILE_PATH_FULL, true, Encoding.GetEncoding("shift_jis"));
                sw.Write("[List]" + sw.NewLine);

                // ファイルにデータを追加
                for (int count = 1; count <= dataArray.Length; count++)
                {
                    if (dataArray[count - 1] != null)
                    {
                        // key名をつける
                        data = "mail" + count.ToString() + "=" + dataArray[count - 1];
                        sw.Write(data + sw.NewLine);
                    }
                    else
                    {
                        break;
                    }
                }

                // ファイルを閉じる
                sw.Close();
            }
            catch
            {
                throw;
            }
        }

        [DllImport("KERNEL32.DLL")]
        private static extern uint GetPrivateProfileString(
        string lpAppName,
        string lpKeyName,
        string lpDefault,
        StringBuilder lpReturnedString,
        uint nSize,
        string lpFileName);

        [DllImport("KERNEL32.DLL")]
        private static extern uint GetPrivateProfileInt(
            string lpAppName,
            string lpKeyName,
            int nDefault,
            string lpFileName);

        [DllImport("KERNEL32.DLL")]
        private static extern uint WritePrivateProfileString(
            string lpAppName,
            string lpKeyName,
            string lpString,
            string lpFileName);

        /// <summary>
        /// INIファイルから値を取得する
        /// </summary>
        /// <param name="lpSection">セッション名称</param>
        /// <param name="lpKeyName">キー名称</param>
        /// <param name="lpFileName">INIファイル名</param>
        /// <returns></returns>
        public static string GetIniString(string lpSection, string lpKeyName, string lpFileName)
        {
            System.Text.StringBuilder strValue = new System.Text.StringBuilder(1024);

            uint sLen = GetPrivateProfileString(lpSection, lpKeyName, "", strValue, 1024, lpFileName);

            return strValue.ToString();
        }
        #endregion
    }
}

メールアドレス一覧画面の機能説明

メールアドレス一覧
メールアドレス一覧

上記がメールアドレス一覧のレイアウトになります。

メールアドレス一覧機能
  • 全体:メールアドレスを表示している(最大99件)
  • 削除ボタン:選択行に対して削除を行う
  • 追加ボタン:追加画面に遷移する
  • メール作成ボタン:メール作成画面に遷移する

基本的にメールアドレスの一覧を表示して確認する画面になります。

以下がソースコードになります。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SendMail
{
    public partial class FrmMailList : Form
    {
        #region プロパティ
        /// <summary>
        /// INIファイルデータ
        /// </summary>
        private string[] IniFileData
        {
            get;
            set;
        }

        /// <summary>
        /// メールアドレス数保持用
        /// </summary>
        private int RowNum
        {
            get;
            set;
        }
        #endregion
        #region プライベート定数
        /// <summary>
        /// メールアドレス列番号
        /// </summary>
        private const int DGV_MAIL_ADRESS = 0;

        /// <summary>
        /// 最大列数
        /// </summary>
        private const int DGV_MAX_COLUM = 1;

        /// <summary>
        /// 最大行数
        /// </summary>
        private const int DGV_MAX_ROW = 99;

        /// <summary>
        /// 列幅(メールアドレス)
        /// </summary>
        private const int MAIL_ADRESS_WIDTH = 499;

        /// <summary>
        /// メールアドレス
        /// </summary>
        private const string MAIL_HEADER = "メールアドレス";

        #endregion

        #region コンストラクタ
        public FrmMailList()
        {
            InitializeComponent();
        }
        #endregion

        #region イベントメソッド
        /// <summary>
        /// ロードイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmMailList_Load(object sender, EventArgs e)
        {
            try
            {
                // デザインプロパティ設定
                SetDesignPropaty();

                // 表示処理
                DisplaySerch();

                // 追加処理のための行数を保持
                GetRowIndex();
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// フォームアクティブイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmMailList_Activated(object sender, EventArgs e)
        {
            try
            {
                // 表示処理
                DisplaySerch();

                // 追加処理のための行数を保持
                GetRowIndex();
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 削除クリックイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDel_Click(object sender, EventArgs e)
        {
            string[] dataArray = new string[dgvMailList.RowCount];
            Library library = new Library();

            try
            {
                // 選択グリッドの行を削除する
                dgvMailList.Rows.RemoveAt(dgvMailList.CurrentRow.Index);

                // 削除後のデータを配列に格納
                dataArray = GetArrayData();

                // 削除されたデータをINIファイルからも削除する
                library.DelIniFile(dataArray);

                // 再描画
                DisplaySerch();

                // 行数を保持しておく
                GetRowIndex();
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 追加クリックイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAdd_Click(object sender, EventArgs e)
        {
            FrmAddMail frmAddMail = new FrmAddMail(this.RowNum);

            try
            {
                frmAddMail.Show();
                this.RowNum = 0;
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// メール作成クリックイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSend_Click(object sender, EventArgs e)
        {
            FrmSendMail frmSendMail = new FrmSendMail(this.IniFileData);
            try
            {
                frmSendMail.Show();
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 行追加イベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dgvMailList_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            try
            {
                DataGridView dgv = (DataGridView)sender;
                if (dgv.RowHeadersVisible)
                {
                    //行番号を描画する範囲を決定する
                    Rectangle rect = new Rectangle(
                        e.RowBounds.Left, e.RowBounds.Top,
                        dgv.RowHeadersWidth, e.RowBounds.Height);
                    rect.Inflate(-2, -2);
                    //行番号を描画する
                    TextRenderer.DrawText(e.Graphics,
                        (e.RowIndex + 1).ToString(),
                        e.InheritedRowStyle.Font,
                        rect,
                        e.InheritedRowStyle.ForeColor,
                        TextFormatFlags.Right | TextFormatFlags.VerticalCenter);
                }
            }
            catch
            {
                throw;
            }
        }
        #endregion
        #region プライベートメソッド

        /// <summary>
        /// 検索処理
        /// </summary>
        private void DisplaySerch()
        {
            Library library = new Library();

            try
            {
                // INIファイルからメールアドレス一覧を取得
                this.IniFileData = library.GetIniFile();

                // 取得データをデータグリッドビューに配置
                for (int row = 0; row < this.dgvMailList.RowCount; row++)
                {
                    // INIファイルのデータがある場合はデータグリッドビューに追加
                    if (this.IniFileData[row] != null)
                    {
                        this.dgvMailList.Rows[row].Cells[DGV_MAIL_ADRESS].Value = this.IniFileData[row];
                    }
                    else
                    {
                        break;
                    }
                }
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// デザインプロパティ設定
        /// </summary>
        private void SetDesignPropaty()
        {
            try
            {
                //ユーザーがセルを編集できないようにする
                dgvMailList.EditMode = DataGridViewEditMode.EditProgrammatically;

                //セルを選択すると行全体が選択されるようにする
                this.dgvMailList.MultiSelect = false;
                this.dgvMailList.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

                // データグリッドビューの表示列の設定
                this.dgvMailList.ColumnCount = DGV_MAX_COLUM;
                this.dgvMailList.RowCount = DGV_MAX_ROW;

                // 幅設定
                this.dgvMailList.Columns[DGV_MAIL_ADRESS].Width = MAIL_ADRESS_WIDTH;

                // ヘッダー設定
                this.dgvMailList.Columns[DGV_MAIL_ADRESS].HeaderText = MAIL_HEADER;

                // データグリッドビューアライメント設定
                this.dgvMailList.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomCenter;
                this.dgvMailList.Columns[DGV_MAIL_ADRESS].DefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomCenter;

                // フォントサイズ指定
                dgvMailList.Font = new Font("MS ゴシック", 20);

            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 追加する行の行数取得
        /// </summary>
        /// <returns></returns>
        private void GetRowIndex()
        {
            int rowIndex = 0;

            try
            {
                for (int row = 0; row < dgvMailList.RowCount; row++)
                {
                    // データがなければ処理を抜ける
                    if (dgvMailList.Rows[row].Cells[DGV_MAIL_ADRESS].Value == null)
                    {
                        rowIndex = row;
                        break;
                    }
                }

                this.RowNum = rowIndex;
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// カンマ区切りのデータを取得
        /// </summary>
        private string[] GetArrayData()
        {
            string[] dataArray = new string[dgvMailList.RowCount];

            try
            {
                for (int index = 0; index < dgvMailList.RowCount; index++)
                {
                    if (dgvMailList.Rows[index].Cells[DGV_MAIL_ADRESS].Value != null && dgvMailList.Rows[index].Cells[DGV_MAIL_ADRESS].Value.ToString() != string.Empty)
                    {
                        // カンマ区切りで格納
                        dataArray[index] = dgvMailList.Rows[index].Cells[DGV_MAIL_ADRESS].Value.ToString();
                    }
                    else
                    {
                        break;
                    }
                }
            }
            catch
            {
                throw;
            }

            return dataArray;

            #endregion
        }
    }
}

メールアドレス追加画面の機能説明

追加画面
追加画面

上記がメールアドレス追加画面になります。

追加画面機能
  • メールアドレスを入力する
  • 追加ボタンでメールアドレスをINIファイルに追加する
  • 戻るでフォームを閉じる

以下がソースコードになります。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SendMail
{
    public partial class FrmAddMail : Form
    {
        /// <summary>
        /// インデックス番号
        /// </summary>
        private int RowIndex
        {
            get;
            set;
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public FrmAddMail(int row)
        {
            InitializeComponent();

            // インデックス番号を取得
            this.RowIndex = row;
        }

        #region イベントメソッド
        /// <summary>
        /// 追加クリックイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAdd_Click(object sender, EventArgs e)
        {
            Library library = new Library();

            try
            {
                // メールアドレスを追加
                library.CreateIniFile(txtadres.Text + lblat.Text + txtdomain.Text, this.RowIndex);

                // 閉じる
                this.Close();
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 戻るクリックイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnReturn_Click(object sender, EventArgs e)
        {
            try
            {
                this.Close();
            }
            catch
            {
                throw;
            }
        }
        #endregion
    }
}

メール送信画面の機能説明

メール送信画面
メール送信画面

上記がメール送信画面になります。

メール送信画面機能
  • 件名と本文を入力
  • メール送信ボタンでメール一覧にあるメールアドレスへ一斉送信
  • 戻るボタンでフォームを閉じる

以下がソースコードになります。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Mail;

namespace SendMail
{
    public partial class FrmSendMail : Form
    {
        private string[] MailList
        {
            get;
            set;
        }
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public FrmSendMail(string[] mailList)
        {
            InitializeComponent();

            this.MailList = mailList;
        }

        #region イベントメソッド
        /// <summary>
        /// ロードイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmSendMail_Load(object sender, EventArgs e)
        {
            try
            {

            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// メール送信クリックイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSend_Click(object sender, EventArgs e)
        {
            try
            {
                // 送信処理
                SendMail(this.MailList, this.txtSubject.Text, this.txtText.Text);

                // フォームを閉じる
                this.Close();
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 戻るイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnReturn_Click(object sender, EventArgs e)
        {
            try
            {
                this.Close();
            }
            catch
            {
                throw;
            }
        }
        #endregion

        #region プライベートメソッド
        /// <summary>
        /// メール送信
        /// </summary>
        private void SendMail(string[] mailList, string subject, string text)
        {
            try
            {
                using (MailMessage mail = new MailMessage())
                {
                    mail.From = new MailAddress("送信元メールアドレス");

                    for (int index = 0; index < mailList.Length; index++)
                    {
                        if (mailList[index] != string.Empty && mailList[index] != null)
                        {
                            mail.To.Add(mailList[index]);
                        }
                        else
                        {
                            break;
                        }
                    }
                    mail.Subject = subject;
                    mail.Body = text;
                    mail.IsBodyHtml = true;
                    using (var smtp = new SmtpClient("smtp.gmail.com", 587))
                    {
                        // SSL接続を有効にする
                        smtp.EnableSsl = true;
                        smtp.Credentials = new System.Net.NetworkCredential("送信元メールアドレス", "アプリパスワード");
                        smtp.Send(mail);
                    }
                }

                // できればメール送信相手の一覧を出す
                MessageBox.Show("メール送信成功しました");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
        #endregion
    }
}

今後の課題と機能追加

今後本アプリをよくするための課題と追加予定の機能を紹介します。

機能の課題
  • 改行して本文を送れるようにする
  • メールを送る相手を選べるようにする
  • BCCを活用できるにする
機能の拡張
  • 時間指定ができるように画面を増やす

まとめ

本アプリで楽にメールを一斉送信できたらと思っています。

メルマガにも活用できると思って作りました。

まだまだ修正は必要ですがもっといいものができるように頑張ろうと思っております。

また新しいアプリを作りますのでよろしくお願いいたします。

ポートフォリオ作成方法が知りたい方は以下の記事をご覧ください。

よかったらシェアしてね!

この記事を書いた人

・文系大卒からプログラマーとしてIT企業に就職!
・就活ではIT企業20社受けて19社不採用。残りの1つから内定をいただきなんとかエンジニアデビュー!
・現在はIT企業退職しフリーランスエンジニアとして活動中。
・未経験からエンジニアになる難しさを知っているので、これからエンジニアを目指す方のために未経験からエンジニアになるための方法を発信中

コメント

コメントする

目次
閉じる