メールを送る
Pythonでメールを送るのは、Webページ監視で使ったようなローカルのSMTPサーバで送る方法なら簡単だが、ここではiCloudのようなリモートのSMTPサーバにTLSで接続して送る方法を説明する。
Appleのほかのメールクライアント App 向けの iCloud メールサーバ設定という説明を読んで、まずはApp用パスワードを設定する。ユーザ名は、iCloudのメインの user@icloud.com の形式のメールアドレスである。
メールを組み立てるのは email モジュール、SMTPで送るのは smtplib モジュール、SSL/TLSは ssl モジュールを使う。いずれもPython標準ライブラリに含まれる。特にSSLの Security considerations のBest defaultsを参考にした。
from email.message import EmailMessage
import smtplib
import ssl
# メールを組み立てる
msg = EmailMessage()
msg['From'] = "差出人メアド"
msg['To'] = "宛先メアド"
msg['Subject'] = "件名"
msg.set_content("""本文1行目
本文2行目
""")
# メールを送る
with smtplib.SMTP("smtp.mail.me.com", 587) as smtp:
context = ssl.create_default_context()
smtp.starttls(context=context)
smtp.login("user@icloud.com", "password")
smtp.send_message(msg)
メールがどのように組み立てられたかは次のようにしてみればわかる。
print(msg.as_string())
smtp.starttls() がうまくいくと (220, b'2.0.0 Ready to start TLS') が返る。さらに smtp.login() がうまくいくと (235, b'2.7.0 Authentication successful') が返る。ユーザ名かパスワードが間違っていると SMTPAuthenticationError: (535, b'5.7.8 Error: authentication failed') が返る。メールを送り終わると (221, b'2.0.0 Bye') が返る。
ループで多人数に送る場合は次のようになりそうである。
from email.message import EmailMessage
import smtplib
import ssl
import time
# 1. 送信先リスト(実際はCSVやDBから読み込むのがよさそう)
# (名前, メールアドレス) のタプル形式
recipients = [
("山田 太郎", "yamada@example.com"),
("佐藤 花子", "sato@example.com"),
# ...
]
FROM_ADDRESS = "user@icloud.com"
PASSWORD = "password"
# 2. SSL/TLSのコンテキスト準備
context = ssl.create_default_context()
# 3. SMTP接続をループの外で確立
print("SMTPサーバーに接続中...")
with smtplib.SMTP("smtp.mail.me.com", 587) as smtp:
smtp.starttls(context=context)
smtp.login(FROM_ADDRESS, PASSWORD)
print("ログイン成功。配信を開始します。")
# 4. ループ処理で1人ずつ送信
for name, to_address in recipients:
try:
# メールの組み立て
msg = EmailMessage()
msg['From'] = FROM_ADDRESS
msg['To'] = to_address
msg['Subject'] = "【重要】大切なお知らせ"
# 本文に名前を差し込む
body = f"""{name} 様
いつも大変お世話になっております。
(ここにメールの本文を記述)
"""
msg.set_content(body)
# 送信
smtp.send_message(msg)
print(f"送信成功: {to_address}")
# 5. 送信間隔を空ける
time.sleep(2) # 2〜5秒
except Exception as e:
# エラーが発生しても止めず、ログに残して次へ進む
print(f"【エラー】送信失敗: {to_address} - 理由: {e}")
continue
print("すべての送信処理が完了しました。")
1日あたり1000人まで・1000通まで、1通あたり50人までが限度。それ以上は外部サービスを利用するのがよい。