【業務自動化】Chapter3-5:メール送信を自動化しよう

一つ前のページでは 残業集計ツール を作成しました。
今回は メール送信の自動化 を行いましょう。
Chapter1:PythonでExcelを操作しよう
Chapter2:PyInstallerで自動化ツール(.exe)を作ろう
Chapter3:便利な自動化ツールを5つ作ろう
・Chapter3-1:Excelファイルをフォルダ丸ごと結合しよう
・Chapter3-2:テンプレートを使った請求書自動作成
・Chapter3-3:グラフ付き売上レポート自動生成ツールを作ろう
・Chapter3-4:勤怠の丸め・残業集計自動化ツールを作ろう
・Chapter3-5:メール送信を自動化しよう ◁今回はここ
Chapter4:Webスクレイピング入門
Chapter5:自動化ツールを作って稼ごう
Excel にまとまったアドレス帳をもとに、一括でメールを送れる仕組みをPythonで作成してみましょう。
もちろん、それは一般のメールソフトにもできる基本的な機能です。しかし、Pythonで自動化することで以下のようなメリットが生まれます。
- 社内の定型報告や請求書送付を定期的に自動送信できる
- Webスクレイピング(Chapter4で学習)と組み合わせて、ネット上の情報を自動収集 ⇒ 自動送信できる
- Excelにある顧客リストから自動で宛先を読み込み、本文を個別にカスタマイズした上で自動送信
本記事で紹介するコードはただの「メールの一括送信ツール」です。これだけではそれほど価値はありません。
しかしこれをベースとして拡張していくことで、実務に役立つ強力な仕組みに発展させられるのが最大の価値です。
Pythonでメール送信を自動化する仕組み
Pythonでメールを送るときには、メールソフトを使うわけではなく「プログラムが直接メールサーバーに接続して送信」します。
そのため単純なコマンドだけで済むわけではなく、メールの仕組みや通信のルールをある程度知っておく必要があります。
ここからは、Pythonでのメール送信に必要な基本要素を順に解説します。
まずは「メールの仕組み」「SMTP」「MIMEText」といったキーワードを押さえていきましょう。


メール配信の仕組みと流れ
普段私たちが使っているメールは、Gmail や Outlook などのアプリを通じて送受信しています。
しかし、アプリが直接相手に届けているわけではなく、必ず「メールサーバー」を介してやり取りが行われます。
送信の流れをシンプルに表すと、次のようになります。
- 送信者が書いたメールを、まず自分が利用する送信サーバーに渡す
- サーバー同士がやり取りをして、宛先の受信サーバーへ転送する
- 受信サーバーに保存されたメールを、受信者が自分のアプリから読み込む
この仕組みを理解しておくと、Pythonでメールを送るときに「プログラムがどの役割を担うのか」が見えてきます。
つまり、Pythonは送信者の代わりに 送信サーバーへ接続してメールを託す 役割を果たします。
SMTPとは|Pythonのsmtplibでサーバーへ送信する基本
SMTP(Simple Mail Transfer Protocol)は、インターネット上でメールを送信するための基本的な通信規格です。
私たちがGmailやOutlookで送ったメールも、裏側では必ずSMTPのルールに従ってサーバーに届けられています。
Pythonでメールを自動送信する際も、プログラムがSMTPサーバーに接続して「誰から誰へ」「件名は何か」「本文はどんな内容か」を指示する必要があります。
そのために使うのが、標準ライブラリに含まれる smtplib です。
今回のサンプルコードでは学習用として、外部にメールを送信するのではなく ローカル環境で起動したダミーSMTPサーバー に接続する仕組みを採用しています。
これにより誤って本物のメールを送ってしまう心配がなく、メールの送信処理を安全に試せます。
MIMETextとは|テキスト/HTML本文と文字エンコードの基礎
メールは単純に「文字列を送りつける」だけでは成立しません。
送信者や宛先、件名、本文といった複数の情報をひとつの「メールメッセージ」として組み立てる必要があります。
そのために利用されるのが MIME(Multipurpose Internet Mail Extensions) という仕組みです。
Pythonでは、標準ライブラリの email.mime.text.MIMETextクラス を使うことで、本文をメール形式に整形できます。これを利用すると:
- 本文の文字コード(例:UTF-8)を指定できる
- 本文の種類(プレーンテキストかHTMLか)を選べる
- サーバーが理解できる「正式なメール構造」として扱える
今回紹介するサンプルコードでは MIMEText(body, "plain", "utf-8") という形で呼び出し、Excelから読み込んだ本文を プレーンテキスト形式 でメールメッセージに変換しています。
こうすることで、件名や送信元と組み合わせた「完成したメール」としてサーバーに渡せるようになります。

サンプルスクリプト|openpyxlでExcel→SMTP送信
メール送信自動化のサンプルスクリプトを紹介します。
このサンプルで実現できること
ここからは実際にコードを動かしながら、Excelに記載した宛先リストをもとにメールをまとめて送信する仕組みを学んでいきます。
今回用意しているサンプルスクリプトは、次のような流れで処理を行います。
- Excelファイルから宛先・件名・本文を読み込む
→ 1行目はヘッダー、2行目以降をデータとして扱います。 - メールメッセージを組み立てる
→MIMETextを利用して本文をメール形式に整形し、件名や宛先を追加します。 - SMTPサーバーに接続してメールを送信する
→ 学習用のダミーサーバーに送信し、ターミナルに内容を表示させます。
つまり、このサンプルコードを動かすことで「Excelのリストをもとにメールをまとめて処理する」一連の流れを確認できます。
実際の業務にそのまま使うのではなく、仕組みを理解するための最小限のモデルケースだと考えてください。
送信リストExcelの自動生成スクリプト
サンプルを動かす前に、メール送信に必要な宛先リストをExcelファイルとして準備する必要があります。
手作業で作っても構いませんが、練習用にあらかじめ テスト用Excelを自動生成するスクリプト を用意してあります。
このスクリプトを実行すると、次のような処理が行われます。
- プロジェクト内の
inputフォルダを作成(存在しない場合のみ) - 新しいExcelブックを生成し、シート名を
mail_listに設定 - 1行目にヘッダーとして「To」「Subject」「Body」を追加
- サンプル用の宛先・件名・本文を3件ほど書き込み
- 最終的に
send_mail_list.xlsxという名前で保存
以下のコードをコピーし、適切な場所に保存して実行してください。
import openpyxl
import pathlib
input_dir = pathlib.Path(__file__).parent / "input"
input_dir.mkdir(exist_ok=True)
# 保存ファイル名
file_name = input_dir / "send_mail_list.xlsx"
# 新規ブック作成
book = openpyxl.Workbook()
sheet = book.active
sheet.title = "mail_list"
# ヘッダー行
sheet.append(["To", "Subject", "Body"])
# サンプルデータ
sample_data = [
["user1@example.com", "テスト件名1", "これは本文のテスト1です。"],
["user2@example.com", "テスト件名2", "これは本文のテスト2です。"],
["user3@example.com", "テスト件名3", "これは本文のテスト3です。"]
]
for row in sample_data:
sheet.append(row)
# 保存
book.save(file_name)
print(f"{file_name} を作成しました。")ダミーSMTPサーバーの起動|aiosmtpdで安全に送信テスト
メール送信のコードをいきなり本番のサーバーに接続して試すのは、誤送信のリスクがあるため危険です。
学習段階ではまず ダミーのSMTPサーバー を使い、送信内容を実際には外部に送らず、ターミナルに出力させる方法が安全です。
Pythonにはこれを実現できるモジュールとして aiosmtpd が利用できます。
これは実際のSMTPサーバーと同じように振る舞いますが、受け取ったメールを外部に配送するのではなく、その内容をコンソールに表示するだけです。
まずはこのaiosmtpdを使用するため、コマンドプロンプトにてインストールしましょう。
pip install aiosmtpd
ダミーサーバーを起動するには、ターミナルやコマンドプロンプトで次のコマンドを実行してください。
python -m aiosmtpd -n -l localhost:1025
-n: サーバーをフォアグラウンドで動かす(終了は Ctrl+C)-l localhost:1025: ローカルホストのポート1025で待ち受け
この状態で送信スクリプトを動かすと、実際に外部には送られず、ターミナルに受信したメール内容(宛先、件名、本文)が表示されます。
これにより、安全にコードの挙動を確認できるというわけです。
サンプルスクリプト|MIMETextで本文生成し一斉送信
ここまで準備したExcelファイルとダミーSMTPサーバーを組み合わせて動作させるのが、Chapter3-5_send_mail.py です。
このスクリプトを実行すると、Excelから読み込んだ宛先リストに基づいて、ダミーサーバーにメールを順番に送信していきます。
処理の流れは次のようになっています。
- Excelの読み込み
send_mail_list.xlsxを開き、2行目以降のデータ(宛先・件名・本文)をリストに格納します。- 1行目はヘッダー行としてスキップされます。
- メールメッセージの生成
MIMETextを使って本文を整形し、件名(Subject)、送信元(From)、宛先(To)を設定します。- 送信元はダミーとして
noreply@example.comを使用しています。
- SMTPサーバーへの送信
smtplib.SMTP("localhost", 1025)でローカルに立てたダミーサーバーへ接続。- 作成したメッセージを
send_messageメソッドで送信します。
- 完了メッセージ
- すべての送信処理が終わると「送信テスト完了!」と表示され、ターミナル側に各メールの内容が出力されます。
このスクリプトを実行すれば、「Excelで管理した複数の宛先に、まとめてメールを送る」という自動化の流れを体験できます。
実際の業務で使うにはさらに設定が必要ですが、自作の自動送信ツールを拡張する基礎として非常に重要なステップになります。
import openpyxl, pathlib, sys
import smtplib
from email.mime.text import MIMEText
# === 実行環境に応じた基準ディレクトリ ===
if getattr(sys, 'frozen', False):
BASE_DIR = pathlib.Path(sys.executable).parent
else:
BASE_DIR = pathlib.Path(__file__).parent
input_dir = BASE_DIR / "input"
# Excelファイルの読み込み
file_name = input_dir / "send_mail_list.xlsx"
book = openpyxl.load_workbook(file_name)
sheet = book.active
to_list = []
subject_list = []
body_list = []
# 2行目以降を読み込む(1行目はヘッダー)
for row in sheet.iter_rows(min_row=2, values_only=True):
to_address, subject, body = row
if not any(row): # 完全な空行はスキップ
continue
if not to_address: # 宛先がない行はスキップ
continue
to_list.append(to_address)
subject_list.append(subject or "(件名なし)")
body_list.append(body or "")
# === ダミーSMTPサーバーに送信 ===
# aiosmtpd を別ターミナルで起動しておく: python -m aiosmtpd -n -l localhost:1025
with smtplib.SMTP("localhost", 1025) as server:
for i in range(len(to_list)):
msg = MIMEText(body_list[i], "plain", "utf-8")
msg["Subject"] = subject_list[i]
msg["From"] = "noreply@example.com" # ダミー送信元
msg["To"] = to_list[i]
# ★ 学習用: コンソールに内容を表示 ★
print("=== 送信メール ===")
print("To:", to_list[i])
print("Subject:", subject_list[i])
print("Body:", body_list[i])
print("------------------")
server.send_message(msg)
print("送信テスト完了!ターミナルにメール内容が出力されています。")このコードを実行すると、コマンドプロンプトに以下のように出力されます。
---------- MESSAGE FOLLOWS ----------
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Subject: =?utf-8?b?44OG44K544OI5Lu25ZCNMQ==?=
From: noreply@example.com
To: user1@example.com
X-Peer: ('::1', 62175, 0, 0)
44GT44KM44Gv5pys5paH44Gu44OG44K544OIMeOBp+OBmeOAgg==
------------ END MESSAGE ------------
---------- MESSAGE FOLLOWS ----------
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Subject: =?utf-8?b?44OG44K544OI5Lu25ZCNMg==?=
From: noreply@example.com
To: user2@example.com
X-Peer: ('::1', 62175, 0, 0)
44GT44KM44Gv5pys5paH44Gu44OG44K544OIMuOBp+OBmeOAgg==
------------ END MESSAGE ------------
---------- MESSAGE FOLLOWS ----------
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Subject: =?utf-8?b?44OG44K544OI5Lu25ZCNMw==?=
From: noreply@example.com
To: user3@example.com
X-Peer: ('::1', 62175, 0, 0)
44GT44KM44Gv5pys5paH44Gu44OG44K544OIM+OBp+OBmeOAgg==
------------ END MESSAGE ------------それぞれのメールが MIME形式 で表示されていて、日本語部分は Base64エンコードされています。
本来ならば日本語で読めるように表示したいところですが、Python3.12 以降では 標準ライブラリsmtpd が削除されており、複雑な対応が必要となってしまいました。
上記のように表示されれば送信は成功していますので、このまま以下の内容に進んでください。

実運用への応用方法|本番SMTP・Gmail連携・認証の注意点
ここまで紹介したコードは学習用として「ダミーSMTPサーバー」に送信する仕組みになっていました。
そのためターミナルにはメール内容が出力されますが、実際の受信者には届きません。
ここでは、実際に受信者にメールを届ける方法を紹介します。
本番でメールを送るには|SMTPサーバー設定とポート/暗号化
実際にメールを送信するには、次の手順が必要になります。
- 利用するSMTPサーバーの情報を取得する
- 会社のメールサーバーやGmailなどのSMTPホスティングサービスを利用します。
- 例:Gmailなら「smtp.gmail.com」、ポートは「587」。
- 認証情報(ユーザー名・パスワード)を設定する
- SMTPサーバーは不正利用を防ぐため、必ずログイン認証を行います。
- 送信者のメールアドレスとパスワードを安全に管理し、プログラムから利用します。
- 暗号化通信(TLS/SSL)の利用
- 通常、ポート587で接続して「STARTTLS」を使い、暗号化した通信に切り替えます。
- Pythonの
smtplibではserver.starttls()を呼び出すことで対応できます。
これらを組み合わせることで、サンプルコードを 実際に外部へメールを送れるスクリプト へ拡張できます。
以下のコード(Outlookを使用する例)を参考にしてください。
import pathlib
import sys
import smtplib
import openpyxl
from email.mime.text import MIMEText
# PyInstallerでexe化した場合はsys.executableのパスを基準に、
# 通常の.py実行時は__file__のあるフォルダを基準にする
if getattr(sys, "frozen", False):
BASE_DIR = pathlib.Path(sys.executable).parent
else:
BASE_DIR = pathlib.Path(__file__).parent
input_dir = BASE_DIR / "input"
# Excelファイルの読み込み
file_name = input_dir / "send_mail_list.xlsx"
book = openpyxl.load_workbook(file_name)
sheet = book.active
to_list = []
subject_list = []
body_list = []
# 2行目以降を読み込む(1行目はヘッダー)
for row in sheet.iter_rows(min_row=2, values_only=True):
to_address, subject, body = row
if to_address is None:
break
to_list.append(to_address)
subject_list.append(subject)
body_list.append(body)
# OutlookのSMTPサーバー情報
smtp_server = "smtp-mail.outlook.com"
smtp_port = 587
# 送信元アドレスとパスワード
from_address = "あなたのアドレス@outlook.com"
password = "あなたのパスワード"
# Outlook SMTPサーバーに接続して送信
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls()
server.login(from_address, password)
for i in range(len(to_list)):
msg = MIMEText(body_list[i], "plain", "utf-8")
msg["Subject"] = subject_list[i]
msg["From"] = from_address
msg["To"] = to_list[i]
server.send_message(msg)
print("メール送信完了!")
注意:このコードを実際に動かすと、本当に相手へメールが届くよ!
最初は必ず 自分自身のアドレスを宛先にしてテストしよう。
Gmailのアプリパスワードについて
GmailをPythonから操作してメールを送信する場合、通常のログインパスワードは利用できません。
Googleはセキュリティ強化のために「安全性の低いアプリからのアクセス」を廃止しており、代わりに アプリパスワード を使う必要があります。
アプリパスワードとは、Googleアカウントの本来のパスワードとは別に発行される、アプリ専用の16桁のパスワードです。
これを使うことで、プログラムから安全にGmailのSMTPサーバーへログインできます。
アプリパスワードを発行する手順
- Googleアカウントで 2段階認証を有効化 する
- アプリパスワードは2段階認証を設定していないと発行できません。
- Googleアカウントの「セキュリティ」設定 にアクセスする
- 「アプリ パスワード」を選択
- アプリ名を「Python」など任意で入力して生成する
- 表示された16桁のコードが「アプリパスワード」
プログラムでの利用方法
サンプルコードでは次のように利用します。
from_address = "あなたのメールアドレス@gmail.com" app_password = "ここに発行した16桁のアプリパスワード"
このアプリパスワードは、Googleアカウント本体のパスワードとは異なり、そのアプリ専用 なので、万が一漏洩しても削除すればすぐに無効化できます。
まとめ|メール送信自動化を使いこなそう
この章では、Pythonを使って Excelのリストからメールを自動送信する方法 を学びました。
ここで紹介したコードそのものは、シンプルに「Excelリストに従ってメールを一括送信する」仕組みです。
しかし、Pythonでメール送信を自動化する価値は拡張性にあります。
- Excelと連携して個別のメッセージを差し込む
- 添付ファイル(レポートや請求書)を自動生成して送信する
- 第4章で学ぶWebスクレイピングと組み合わせて「最新データを取得して自動通知する」
といった応用を行うことで、自分やチームの業務にぴったり合った オリジナルの業務効率化ツール を作り出せるのです。
この章をきっかけに、ぜひ自分のアイデアをPythonで形にしてみてください。


