自動化の失敗をメールで知らせたいときは、本文を作る処理と、実際に送る処理を分けると確認しやすくなります。最初から業務の宛先へ送らず、送信しないプレビューで、差出人・宛先・件名を見ます。
送信前に決めること
送信に使うアカウント、認められた差出人、接続先、暗号化方式、認証方法を、メールサービスの正式な設定で確認します。ログインに使う名前と、自由に使える差出人が同じ範囲とは限りません。
パスワードをコードやCSVへ書かず、利用が認められた秘密の保管方法から読み取ります。通知に業務データを全文で載せる前に、処理名、時刻、確認先だけで足りないかを考えます。
メールを作って保存する
次のアドレスは説明用の例です。このコードはメールを送信せず、emlファイルへ保存します。
from email.message import EmailMessage
from email.policy import SMTP
message = EmailMessage()
message["From"] = "sender@example.com"
message["To"] = "recipient@example.net"
message["Subject"] = "CSV集計の確認依頼"
message.set_content("架空の通知です。集計ログを確認してください。")
with open("notification-preview.eml", "xb") as out:
out.write(message.as_bytes(policy=SMTP))
print(message["Subject"])
保存したファイルを、内容を読めるメールアプリなどで確認します。宛先を複数にする場合は、公開してよいアドレスかも確認します。emlを作れたことは、認証や配信の成功を示しません。
STARTTLSを使う送信関数の例
次はSTARTTLSを指定するサービス向けの構造例です。関数を定義するだけでは接続しません。実際の送信は行っていません。
import ssl
import smtplib
def send_after_review(message, host, port, user, password):
with smtplib.SMTP(host, port, timeout=20) as client:
client.ehlo()
client.starttls(context=ssl.create_default_context())
client.ehlo()
client.login(user, password)
return client.send_message(message)
最初から暗号化して接続するSMTP_SSLとは方式が違います。ポート番号だけを見て推測せず、利用するサービスの指定に合わせます。認証に別の方式が必要なら、その仕様に従います。
受付と受信を分ける
SMTPサーバーが受け付けても、最終的に相手の受信箱へ届いたことまでは分かりません。試験用の自分の宛先で、迷惑メール欄を含めた受信、差出人の表示、本文の文字化けを確認します。
タイムアウトしても、相手側の処理が終わっている可能性があります。すぐに同じ通知を再送せず、送信ログと受信の状態を照合します。処理ごとの通知IDや、同じ失敗を何度も知らせない条件も、運用へ入れる前に決めます。
ログへ残すのは時刻、処理、成否、確認用の識別子などに絞り、認証情報を出しません。通知メールの到着確認ができるまでは、ほかの確認経路も残してください。
関連する作業
通知の元になるログと、本文へ個人情報を載せる前の判断は次の記事が関連します。
