【Python】メールを自動送信する(失敗!)

このエントリーをはてなブックマークに追加
python
Python
ースポンサーリンクー

参考資料

フォルダ構成

(やりたい事)
複数のメールをまとめて送信する

f:id:Moriane:20220414064522p:plain
・メール本文にしようする文章はテキストファイルに保存
・顧客の名前やメールアドレスはExcelファイルから参照
・添付ファイルはフォルダに保存しておく
・該当する顧客にメール送信するプログラムを作成する!!

メール送信工程

①メール送付リストを作成フォルダーから請求書のPDFファイルを1つ取得する
(PDFファイルごとに繰り返す)顧客IDをPDFファイル名から把握する
該当する顧客データをファイル「顧客マスタ」から検索
メール送付リストに「顧客データ」と「PDFファイル」を登録
②メールを一斉送信SMTPサーバーに接続
(メール送付リストの顧客ごとに繰り返す)メッセージを準備
件名、メールアドレスを設定
メール本文を追加
添付ファイルにPDFファイルを追加
メッセージを送信
SMTPサーバーと接続を閉じる

メールを送信するには「メール送付リスト」に登録した顧客を1つずつ取り出して、顧客ごとにメッセージデータを作成する
メッセージデータには、まず件名とメールアドレスを設定し、本文を追加して。請求書のPDFファイルを添付ファイルとして加えて送信する

メール送付リストの作成

次のように[顧客データ、請求書PDFファイルのパス]を要素に持つリストにする
このようにリストを作成すれば、顧客データの中のメールアドレスに、PDFファイルを添付して、メール送信すれば良いので、一斉に送信する処理を作りやすくなる

mailing_list = [
[[顧客ID, 顧客名,部署名,担当者名,メールアドレス,・・・],
請求書PDFファイルパス],
[[顧客ID, 顧客名,部署名,担当者名,メールアドレス,・・・],
請求書PDFファイルパス],
・・・
]

・最初に必要なモジュールを全てインポートしておく

openpyxlExcelファイルの読み込み
Pathフォルダ内のファイル検索
smtplibSMTPサーバーと更新する
MIMEMultipartメッセージを作成する
MIMEText本文を作成する
MIMEApplication添付ファイルを作成する
sysプログラムを中止する
import sys
import openpyxl
from pathlib import Path
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication

# 顧客マスタの読み込み
wb_master = openpyxl.load_workbook("顧客マスタ.xlsx")
ws_master = wb_master["Sheet1"]

customer_list = []
for row in ws_master.iter_rows(min_row=2):
    if row[0].value is None:
        break
    value_list = []
    for c in row:
        value_list.append(c.value)
    customer_list.append(value_list)

# 請求書PDFのフォルダー
pdf_dir = "請求書PDF_202007"

# メーリングリスト
mailing_list = []

# フォルダーから請求書のPDFファイルを1つずつ取得する
for invoice in Path(pdf_dir).glob("*.pdf"):
    # 「顧客ID」 は、 PDFファイルの拡張子を除いた部分
    customer_id = invoice.stem
    # 該当する顧客データを「顧客マスタ」から検索
    for customer in customer_list:
        if customer_id == customer[0]:
            # メーリングリストに「顧客データ」と
            # 「PDFファイル」のパスを追加
            mailing_list.append([customer, invoice])
            # 顧客ID、顧客名、メールアドレス、
            # PDFファイルのパスを表示
            print(customer[0], customer[1], customer[4], invoice)

結果

(検索)
⇨PDFファイルが対象なので、glob()の括弧の中には「*.pdf」を指定して、拡張子でファイルを検索

(取得)
⇨取得したPDFを送信する顧客はファイル名が顧客IDとなっている。拡張子を除いた顧客IDの部分はstemで取得できる

(送信リストに追加)
検索した顧客データは送付する請求書のPDFファイルのパスと一緒にメール送信リストに追加。これから送付する顧客とPDFファイルが確認できるようprint()で表示
f:id:Moriane:20220414073651p:plain

メールを一斉に送信

間違えて送信しないようにテストをする
プログラムにテストモードを追加する
変数test_modeがTrieの場合は自分のアドレス宛てに送信するようにする
※テストモードではtest、本番モードではrealと入力してもらうようにするが、本番モードのreal以外が入力された場合はテストモードにする

また、テストモードの切り替えはinput()を用いて、画面から行うようにする
次に送信を開始する前に、どちらのモードが設定されているかを明示して送信しても大丈夫かを確認する
input()を用いて、続行して送信する場合はyes、中止する場合はnoを入力してもらい、入力した値がyes以外の場合は、sys.exit()でプログラムを中止する
プログラムを続行する場合は、メッセージの送信に備えて、メール本文をmail_body.txtから読み込んでおく

# モード選択
print()  # 1行空ける
mode = input("モード選択(テスト=test、本番=real):")
# 本番以外はテスト
if mode != "real":
    test_mode = True
else:
    test_mode = False

# 送信確認
if test_mode:
    result = input("テストモードで自分宛てに送信します(続行=yes、中止=no):")
else:
    result = input("本番モードで送信します(続行=yes、中止=no):")

# 続行以外は中止
if result != "yes":
    print("プログラムを中止します")
    sys.exit()

# メール本文をファイルから読み込んでおく
text = open("mail_body.txt", encoding="utf-8")
body_temp = text.read()
text.close()

▼結果
プログラムを実行すると次のように画面モードを選択できる。
ここでは、送信するかどうかの確認でNoを入力して、プログラムを中止している
・SMTPサーバに接続したら、メール送信リストの顧客への送信を始める。メール送付リストの1件文のデータは[顧客データ, 請求書PDFファイルのパス]のようなリストになっている。
⇨そこでメール送信リストをリープして一つの要素を変数dataに代入してインデックスを用いてdata[0]で顧客データ、data[1]で請求書PDFファイルのパスを取得する
⇨この顧客データから顧客メールアドレスを取得して、件名や自分のアドレスと一緒にメッセージ設定する。
さらに、会社名や担当者名も取得して、メール本文にformat()で埋め込む。
・添付ファイルのデータは請求書PDFファイルのパスにあるPDFファイルからバイナリで読み取る
※ここでヘッダーにふあするファイル名には、パスに.nameをつけて「フォルダーを除いたファイル名」を指定する
・メール本文と添付ファイルの追加が終わったら、メッセージをsend_message()で送信する。
・送信中は進捗がわかるように、print()で送信している顧客IDと会社名を表示
・リストの全ての顧客に送信を完了したら、最後にSMTPサーバーとの接続を閉じる

▼全てのコード(mail_invice_sender.py)

# モード選択
print()  # 1行空ける
mode = input("モード選択(テスト=test、本番=real):")
# 本番以外はテスト
if mode != "real":
    test_mode = True
else:
    test_mode = False

# 送信確認
if test_mode:
    result = input("テストモードで自分宛てに送信します(続行=yes、中止=no):")
else:
    result = input("本番モードで送信します(続行=yes、中止=no):")

# 続行以外は中止
if result != "yes":
    print("プログラムを中止します")
    sys.exit()

# メール本文をファイルから読み込んでおく
text = open("mail_body.txt", encoding="utf-8")
body_temp = text.read()
text.close()

▼結果(失敗!)
なぜ!ここまできて😭
Emailポリシーに引っかかったらしいです💦

解決できなかったので、ここまでにしましょうw
f:id:Moriane:20220415073107p:plain

Pythonで自動送信するときに気をつけること

メール送信を自動化するときには「送信ミス」と「迷惑メールに間違われること」に特に気をつけないといけない。
まずはテストモードを実装して、自分のアドレス宛てにテストで送信して、本文と添付ファイルの内容を確認できるようにする
また、本当に一斉送信を開始しても大丈夫か、一時停止して確認するステップも実装する
さらに、送信中は進捗がわかるように、送信している相手をprint()で随時表示し、送信中にミスに気がついた場合は、キー「Ctrl+C」を押すことで強制終了できる。

今回はここまで🌸

suno
suno

それではまた!

sunoでした

コメント

タイトルとURLをコピーしました