📫

🐍メールに画像を添付して送信する

4 min read

Pythonでメールを送信する方法

  • こんな感じのものができた
sender.py
import smtplib
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

# メールに関する設定
from config import config

...このあとで説明...

if __name__  = "__main__":
    # メールを作成する部分
    msg = compose()
    # メールを送信する部分
    send(msg)
  • 実行方法
メールを送信
$ python3 sender.py
  • 本文を作成する部分はemail(主にemail.mime.*)パッケージに任せた
  • メールを送信する部分はsmtplibパッケージに任せた

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

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

メールに関する設定(config.py)

  • メールに関する設定部分は非公開にしたい情報ばかり
  • config.pyという設定ファイルを用意して読み込むことにした
  • @dataclassを使ってみた(使ってみたかったから)
    • 😆 間違った値を代入したら教えてくれた
    • 😆 間違った変数を呼び出したら教えてくれた
config.py
from dataclasses import dataclass

@dataclass
class Config:
    charset: str
    subject: str
    me: str
    to: list[str]
    host: str
    port: int
    username: str
    password: str

# 読み込みたい設定をベタ書き
config  = Config(
    charset="UTF-8",
    subject="自動送信テスト",
    me="自分のメールアドレス",
    to=["宛先1", "宛先2"],
    host="SMTPサーバ",
    port=ポート番号,
    username="ユーザ名",
    password="パスワード",
)

自分だけで使うのでパスワードはベタ書きしているけど、ほんとうはもっと賢くやりたい

SMTPサーバの設定は、それぞれの環境で確認する

設定ファイルを読み込む

  • メール送信を実行するファイルの冒頭で読み込む
# 各ファイルでインポートする
from config import config

メール本文を作成する

要点

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

必要だったモジュール

sender.py
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

件名/差出人/宛先を設定する部分

  • 画像などを添付するためMIMEMultipartオブジェクトを作成した
  • オブジェクト名が長いので、このあとの説明ではMIMEオブジェクトと呼ぶことにする
sender.py
def add_header():
    msg = MIMEMultipart()
    msg["Subject"] = config.subject
    msg["From"] = config.me
    msg["To"] = ",".join(config.to)
    msg["Date] = formatdate(localtime=True)
    return msg

# MIMEオブジェクトを作成する
msg = add_header()

本文を追加する部分

  • MIMETextを使ってプレーンテキストを作成して、MIMEオブジェクトに.attachした
  • 文章を1文ずつ追加することを想定して、文末に改行コード(\n)をつけることにした
sender.py
def add_text(msg, text):
    _text = MIMEText(text+"\n", "plain", config.charset)
    msg.attach(_text)
    return msg

# 本文を追加
msg = add_text(msg, "自動送信のテスト中")

画像を添付する部分

  • MIMEImageを使って画像ファイルを作成し、MIMEオブジェクトに.attachした
  • 画像ファイルのパスはPathオブジェクトで作成した
  • 画像ファイルはバイナリ(rb)で開く
sender.py
def add_image(msg, fname):
    with open(fname, "rb") as f:
        img = f.read()
        image = MIMEImage(img, name=fname.name)
    msg.attach(image)
    return msg

# 画像ファイルを添付
fimg = Path("画像ファイルのパス")
msg = add_image(msg, fimg)

複数の画像ファイルを添付する

  • 上で定義したadd_imageを利用する
  • 画像ファイルを保存しているディレクトリからPNG画像の一覧を取得する
  • ファイル名の順番にならないことがあったのでsortedした
sender.py
def add_images(msg, fnames):
    for fname in fnames:
        msg = msg.add_image(msg, fname)
    return msg

# 複数の画像ファイルを添付する
fpath = Path("画像があるディレクトリ")
fimages = sorted(fpath.glob("*.png"))
msg = add_images(msg, fnames)

定型メールを作成する

  • これまでの手順をまとめて、定型メールを作成できるようにした
  • 定型メールなので本文は固定でよしとする
sender.py
def compose():
    msg = add_header()
    msg = msg.add_text(msg, "自動送信のテスト。テストだよ。")
    images = sorted(Path("images").glob("*.png"))
    msg - msg.add_images(msg, images)
    return msg

メールを送信する

要点

  1. SMTPサーバにTLSを使って接続する
  2. ユーザ名・パスワードを使って認証する
  3. SMTPの拡張機能を使うことを明示する

必要だったモジュール

sender.py
import smtplib

SMTPで送信する部分

  • 上で作成したMIMEオブジェクト(msg)を受け取る
  • SMTPを使ってメールを送信する
sender.py
def send(msg):
    smtp = smtplib.SMTP(config.host, config.port)
    smtp.starttls()
    smtp.ehlo()
    smtp.login(smtp.username, smtp.password)
    smtp.ehlo()
    smtp.send_message(msg)
    smtp.quit()

まとめ&感想

  1. email.mimeパッケージを使うことで、とても簡単にメール本文を作成することができた
  2. MIMEApplication、MIMEAudioなど、他のモジュールもあるので、添付したいファイルの形式に応じて使い分ければよさそう
  3. smtplibパッケージを使うことで、あっさりとメールを送信することができた
  4. crontab や watchdog と組み合わせて、定期実行できそう

Discussion

ログインするとコメントできます