📫

email.mimeで画像を添付して送りたい

に公開
2026/10/11
python3 sender.py

画像(プロット)を関係者にもメールでお知らせしたいので、Pythonでメールを作成して送信してみました。
メールは定期的に自動送信したいので、スクリプトにしておきます。

メッセージの作成はemail.mimeパッケージに、メールの送信はsmtplibパッケージに任せます。

メッセージを作成したい(email.mime)

https://docs.python.org/ja/3/library/email.mime.html

メッセージ用オブジェクトの作成
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.utils import formatdate
from pathlib import Path

# メールに関する設定
me = "送信元のメールアドレス"
you = "Toアドレス1,Toアドレス2,..."
them = "Bccアドレス1,Bccアドレス2,..."
text = MIMEText("これは本文です\n", "plain", "utf-8")

# メッセージ用オブジェクト
msg = MIMEMultipart()

# ヘッダーセクションを追加
msg["From"] = me
msg["Date"] = formatdate(localtime=True)
msg["To"] = you
msg["Bcc"] = them
msg["Subject"] = "MIMEMultipartを使ってみる"

# 本文を追加
msg.attach(text)

# 画像を添付
fnames = sorted(Path("images/").glob("*.png"))
for fname in fnames:
    with open(fname, "rb") as f:
        img = f.read()
        image = MIMEImage(img, name=fname.name)
        msg.attach(image)

email.mimeパッケージには、次のようなモジュールがあります。

  1. MIMEMultipart:画像などを添付できるメッセージ用オブジェクトを作成する
  2. MIMEText:メールの本文オブジェクトを作成する
  3. MIMEImage:メールに添付する画像オブジェクトを作成する

メッセージ用オブジェクトを作成したい(MIMEMultipart)

msg = MIMEMultipart()

画像などを添付するため、MIMEMultipartオブジェクトを作成します。
このオブジェクトに対して、本文や画像をattachで追加します。

ヘッダーを追加したい(msg["From"]など)

msg["From"] = me
msg["Date"] = formatdate(localtime=True)

メッセージ用オブジェクトは、msg["From"] = meのように、辞書型と同じように扱えます。

日付は、RFC2822に準拠した形式にする必要があります。
formatdate(localtime=True)を使うのが、一番簡単だと思います。

本文を追加したい(MIMEText)

text = MIMEText("これは本文です\n", "plain", "utf-8")
msg.attach(text)

MIMETextで、プレーンテキストの本文を作成します。
文末には改行コード(\n)をつけておきます。
作成した本文は、メッセージ用オブジェクトに.attachします。

画像を添付したい(MIMEImage)

fnames = sorted(Path("images/").glob("*.png"))
for fname in fnames:
    with open(fname, "rb") as f:
        img = f.read()
        image = MIMEImage(img, name=fname.name)
        msg.attach(image)

MIMEImageで、画像オブジェクトを作成します。
画像ファイルのパスはPathオブジェクトで作成し、バイナリ(rb)で開きます。
作成した画像は、メッセージ用オブジェクトに.attachします。

複数の画像を添付するときは、画像ファイルを保存しているディレクトリから、PNG画像の一覧を取得します。
ファイル名の順番にならないことがあったので、sortedしています。

内容を確認したい(print)

メッセージ用オブジェクトの内容
msg.items()

[('Content-Type', 'multipart/mixed'),
 ('MIME-Version', '1.0'),
 ('From', 'Fromアドレス'),
 ('Date', 'Wed, 05 Jan 2022 13:29:06 +0900'),
 ('To', 'Toアドレス1,Toアドレス2,Toアドレス3,...'),
 ('Bcc', 'Bccアドレス1,Bccアドレス2,Bccアドレス3...'),
 ('Subject', 'MIMEMultipartを使ってみる')]

msg.items()で、ヘッダーの内容を確認できます。
printすると、メッセージ全体を確認できます。

メッセージ用オブジェクトの内容
print(msg)
出力結果
Content-Type: multipart/mixed; boundary="===============3710731288596159002=="
MIME-Version: 1.0
From: =?utf-8?b?RnJvbeOCouODieODrOOCuQ==?=
Date: Wed, 05 Jan 2022 13:29:06 +0900
To: =?utf-8?b?VG/jgqLjg4njg6zjgrkxLFRv44Ki44OJ44Os44K5MixUb+OCouODieODrOOCuTMsLi4u?=
Bcc: =?utf-8?b?QmNj44Ki44OJ44Os44K5MSxCY2PjgqLjg4njg6zjgrkyLEJjY+OCouODieODrOOCuTMuLi4=?=
Subject: =?utf-8?b?TUlNRU11bHRpcGFydOOCkuS9v+OBo+OBpuOBv+OCiw==?=

--===============3710731288596159002==
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64

CuOBk+OCjOOBr+acrOaWh+OBp+OBme+8iDHooYznm67vvIkK44GT44KM44Gv5pys5paH44Gn44GZ
77yIMuihjOebru+8iQrjgZPjgozjga/mnKzmlofjgafjgZnvvIgz6KGM55uu77yJCgo=

--===============3710731288596159002==
Content-Type: image/png; name="age_address.png"
MIME-Version: 1.0
Content-Transfer-Encoding: base64

iVBORw0KGgoAAAANSUhEUgAAAowAAAJ7CAYAAABppMB3AAAgAElEQVR4XuydB5RU1fL1S3nkoCCI
...(画像データの部分はとても長いので省略)...
Tw/BIYAAAggggAACrhcgYXT9HBABAggggAACCCBgtcD/ADLCLHirTzJQAAAAAElFTkSuQmCC

--===============3710731288596159002==
Content-Type: image/png; name="age_gender.png"
MIME-Version: 1.0
Content-Transfer-Encoding: base64

iVBORw0KGgoAAAANSUhEUgAAAowAAAJ7CAYAAABppMB3AAAgAElEQVR4XuydC3gV1dW/V0K4RQgX
...(画像データの部分はとても長いので省略)...
LSABEiABEiABEiABpwn8P1SdUGsvHrDXAAAAAElFTkSuQmCC

--===============3710731288596159002==
Content-Type: image/png; name="age_repeat.png"
MIME-Version: 1.0
Content-Transfer-Encoding: base64

iVBORw0KGgoAAAANSUhEUgAAArgAAAJ7CAYAAAAIvOI1AAAgAElEQVR4XuydCXQVRfb/b8IedpR9
...(画像データの部分はとても長いので省略)...
BAAAAABJRU5ErkJggg==

--===============3710731288596159002==--

出力結果から、次のことを確認できました。

  • メッセージがmultipart/mixed形式で作成できている
  • 本文がtext/plain形式で追加できている
  • 画像3枚をimage/pngで追加できている

ヘッダーセクションに日本語を使ったため、文字がエンコードされています。この点は、さらに確認が必要です。


メールを送信したい(smtplib)

https://docs.python.org/ja/3/library/smtplib.html

sender.py
import smtplib

# SMTPサーバの設定
host = "SMTPサーバのアドレス"
port = ポート番号
user = "SMTPサーバのログイン名"
password = "ログインパスワード"

mailer = smtplib.SMTP(host, port)
mailer.set_debuglevel(2)
mailer.starttls()
mailer.ehlo()
mailer.login(user, password)
mailer.send_message(msg)
mailer.quit()

smtplibで、作成したメッセージ用オブジェクト(msg)をメールとして送信します。
処理の流れは、次の通りです。

  1. starttls:SMTPサーバーにTLSを使って接続する
  2. ehlo:SMTPの拡張機能を使うことを明示する
  3. login:ユーザー名とパスワードで認証する
  4. send_message:作成したメッセージ用オブジェクト(msg)を受け取って、メールを送信する
  5. quit:接続を終了する

実行したい(sender.py)

メールを送信
$ python3 sender.py

メッセージを作成する部分と、メールを送信する部分を、1つのファイル(sender.py)にまとめて実行します。

まとめ

email.mimeパッケージを使うことで、とても簡単にメール本文を作成できました。
smtplibパッケージを使うことで、あっさりとメールを送信できました。

MIMEApplicationやMIMEAudioなど、他のモジュールもあるので、添付したいファイルの形式に応じて使い分ければよさそうです。
crontabやwatchdogと組み合わせれば、定期的に実行することもできそうです。

リファレンス

https://docs.python.org/ja/3/library/email.mime.html

https://docs.python.org/ja/3/library/smtplib.html

Discussion