面倒なメール配信の作業をPythonで自動化しよう|PythonでGmailを自動送信【Pythonで業務自動化シリーズ#07】

Python仕事自動化

この記事の執筆・監修

キノコード
キノコード

テクノロジーアンドデザインカンパニー合同会社のCEO。
日本最大級のプログラミング教育のYouTubeチャンネル「キノコード」や、プログラミング学習サービス「キノクエスト」を運営。
著書「あなたの仕事が一瞬で片付くPythonによる自動化仕事術」や、雑誌「日経ソフトウエア」や「シェルスクリプトマガジン」への寄稿など実績多数。

はじめに

例えば仕事をしているときに、何かの処理が終わったときに隣の席の人が知らせてくれたら便利だと思いませんか? また、メールの宛先によって宛名を変えたい場合、またその先ごとに本文の一部だけ変更したい場合、隣の人がやってくれたら便利じゃないですか? さらに、株取引をしているときに狙っている金額にまで行ったときに隣の人がやってくれたら便利じゃないですか? 今話した内容は、隣の人ではなく、PythonでGmailを使うと実現できます。

この動画では、あなたが発注担当者で、毎週、メールの本文には添付ファイルをつけて、担当者の名前、納期などを記載して送っているというケースで説明をしていきます。
このケースは、例えば、お客さんに毎週や毎日メーリングリストでおすすめ商品を紹介している場合などにも置き換えていただいてもよいでしょう。
これらのケースをExcelのリストを変更するだけで複数人に一斉送信をするコードを解説していきます。この動画の内容を習得すれば、メール送信の自動化ができます。
こういったメール配信は、MarketoやSalesForceなどのツールを導入することができると思います。しかし、導入費用と月額利用料を含めると100万円以上かかることもあります。
個人事業主や小規模事業を営んでいる方であれば難しい金額です。
そのコストをPythonで自作して浮かしてみましょう。
毎月100万円のコストを浮かすことができれば、数千万円の売上に相当します。
また、Gmailは、有料にはなりますが、会社のドメインを使ったビジネス用メールアドレスを使うことができます。
ここで学んだ内容はセキュリティ面は検討が必要なものの、まずは、テスト用のGoogleアカウントを用意してそのアカウントでGmailを配信してみましょう。
それがうまくいけば開発部、システム部の人と相談をして次のステップへ進めば良いと思います。
上司へのアピールの言葉も思い浮かべながら、学習を進めていってください。
それではパソコン画面に切り替えてレッスンを進めていきましょう。

レッスンで使ったファイルはこちら

キノクエストでアカウントの新規登録に進み、メール認証を完了します。

ログインした状態(プラン選択画面が表示されます)で下記のボタンをクリックいただくか、ファイルダウンロードページのURL:https://kinoquest.jp/main/file_download/を直接アドレスバーに入力ください。

モジュールのインポート

import datetime
import smtplib, ssl
from email.mime.text import MIMEText

まずモジュールなどのインポートをしていきましょう。
モジュールがどんなものなのかもあわせて説明していきます。
まず、datetimeのモジュールをインポートします。
datetimeは日付や時間を取得するモジュールです。
このモジュールを使うと今日の日付を取得したり、その日付に日数を足したり引いたりすることができます。
次に、smtplibのモジュールをインポート。
smtplibは、メールサーバを操作してメール送信することができるモジュールです。
ちなみに、SMTPとは、メールを送信するために使用する通信のルールです。 このSMTPは、メールを送信する時に使われるものです。

そして、sslというモジュールをインポートします。
sslは暗号化の仕組みを使うためのモジュールです。
最後に、email.mime(マイム).textというパッケージからMIMETextをインポートします。
MIMETextは、メールを日本語で送信できるようにするためのモジュールです。
ちなみに、MIMEとは、IT用語で「 Multipurpose Internet Mail Extensions」の略です。語弊を恐れずにいうと、色々な言語や添付ファイルをメールで送信するためのルールのようなものだと理解すれば良いと思います。
このMIMEは、アルファベット、数字、
実行します。

import sys, codecs
sys.stdout = codecs.getwriter("utf-8")(sys.stdout)

次に、エンコードのエラーが発生することがあるので、このように記述してください。
これはエンコードを指定する方法です
実行します。

Googleアカウントの設定

それではGmailを送信するために、送信に利用するアカウントで設定を行います。


まず自分のGmailアカウントを開きます。
ご自身のアイコンをクリックします。

「Googleアカウントを管理」をクリック。

左のメニューの中のセキュリティをクリック。

このページの下の方へいきます

「安全性の低いアプリのアクセス」の「アクセスを有効にする(非推奨)」をクリックします。

「安全性の低いアプリの許可」を有効します。

これで設定の完了です。
こちらで送信の準備が整ったので送信の設定をしていきましょう。
なお、このセキュリティの設定変更は、セキュリティ上の危険もあります。
別途セキュリティについて検討するか、本番運用する場合は、Gmail APIを使って配信することも検討しましょう。
また、Googleアカウントはテスト用のアカウントを使うことをおすすめします。

添付ファイルなしのGmail送信

gmail_account = "test@example.com"
gmail_password = パスワード
mail_to = "test@example.com"
name = “キノコード”

メール送信の設定をしていきましょう。
まず、gmail_accountという変数にご自身のGmailのアカウントを代入します。
同じようにgmail_passwordという変数にご自身のパスワードを代入します。
次に送信先の設定をします。
先ほどと同様にmail_toという変数に送信先のメールアドレスを代入します。
さらに、nameと言う変数に送信先の宛名を代入します。

実行します。

today_date = datetime.date.today()
delivery_date = today_date + datetime.timedelta(days=7)
print(today_date,delivery_date)

今回は発注書を送るときの日付、納期も自動でメールに記載するようにしたいと思います。
datetimeモジュールを用いて今日の日付を生成し、それをtoday_dateという変数に代入します。
今日の日付を生成するには、datetime.date.today丸括弧です。
また納期をメールで記載するため、today_dateから7日後を納期として、delivery_dateという変数に代入をしましょう。
today_dateという変数に7を足して、それをdelivery_dateという変数に代入をしましょう。
日付は、datetimeモジュールの中のdatetimeの中にtimedeltaというオブジェクトがあるので、それを使いましょう。
timedeltaの丸括弧の中にdaysと書いて、7を渡しましょう。
ちなみに、daysのところをweeksに置き換えると週、時間だとhours、分だとminitesに置き換えて値を渡せばオッケーです。
それではtoday_dateとdelivery_dateに今日の日付と7日後の日付が代入されているかprint関数を使って確認しましょう。

実行してみましょう。
今日の日付と7日後の日付が表示されました。

subject = “{0}様、発注書の送付について”.format(name)
body = “{0}の発注書をお送りいたします。”.format(date)

それでは次に件名を設定していきます。
件名をsubjectという変数に代入します。
件名には先ほど送信先の宛名を代入したnameを使います。
formatメソッドというメソッドを使用すると、format丸括弧の中に記述した変数が{0}の部分に反映されます。
ちなみに、formatの丸括弧には変数ではなく、直接、値を記述することも可能です。
ただし、今回は、宛先によって宛名や納期を変更したいです。そこで、変数で可変になるようにformatの中は変数にしましょう。
そうすることにより、変数の中身を変えれば、それを使い回すことができるからです。
メールアドレスも変数にしたのはこれが理由です。
また、本文の文章も同様にformatメソッドを使って記述しましょう。本文の内容はbodyに代入します。
本文は改行させて表示したいので、送信形式に合わせて改行コードを入れます。ここでは、html形式で送信する予定なので、htmlタグの<br>を記述します。
先ほどの件名と同様にdelivery_dateの変数を使って波括弧ゼロのところに納期の日付を反映させましょう。
確認のために、subjectを表示させてみましょう。

print(subject)

うまく件名が作れています。

print(body)

続いて、bodyも表示させてみましょう。
本文はhtmlタグがそのまま表示されていますが、納期もうまく反映されています。

msg = MIMEText(body, “html”)

次に、MIMETextを使って、メールを作成していきましょう。
先ほど、MIMETextは、MIMETextは、メールを日本語で送信できるようにするためのモジュールだと説明しました。
本文が代入されたbodyをMIMETextオブジェクトでメールを送信できる状態に変更し、msgという変数に代入します。
記述方法は、MiMEtext丸括弧、第一引数にbodyを渡して、HTMLを指定しましょう。
htmlを指定しなくてもテキストメールの形でメールを送信することは可能です。
ただ今回は、本文がhtmlメールになるようにhtmlと指定しましょう。
ここで一度msgの中身を見てみましょう。実行します。

print(msg)

メールの形式や文字コードともにアルファベットと数字が出力されているのがわかるかと思います。
このアルファベットと数字がbodyに代入した本文のことです。
詳しく説明すると、この文字列はbase64という暗号化を用いて日本語で書いた本文を英語圏の文字に変更しています。
MIMETextのインポートの部分でも少し触れましたが、メールは基本的にアルファベットと数字以外では送れないのでこの処理を行う必要があります。
そのような事情から、base64は英語以外の言語や、0と1で出来た二進数のデータであるバイナリデータをメールで送信するためによく用いられます。
もう一度msgの中身を確認してみると、本文はあるものの、件名や送信先、自分のメールアドレスが設定されていません。
したがって、それらを追加していきましょう。

msg[“Subject”] = subject
msg[“To”] = mail_to
msg[“From”] = gmail_account
print(msg)

オブジェクトを代入したmsgのsubjectに件名、toに宛先のメールアドレス、fromにあなたのメールアドレスを代入すればよいです。
実行してmsgの中身を表示させてみましょう。
そうすると、今回は本文だけでなく、件名、宛先、送信元が追加されているはずです。実行してみましょう。

今度はSubjectやToやFromが設定されているのがわかります。これでメッセージを送る準備が出来たので、実際に送信していきましょう。

server = smtplib.SMTP_SSL(“smtp.gmail.com”, 465, context=ssl.create_default_context())
server.login(gmail_account, gmail_password)
server.send_message(msg)
print(‘送信完了’)

送信には、smtplibを使います。smtplibは、メールサーバを操作してメール送信することができるモジュールと説明しました。
このsmtplibモジュールのSMTP_SSLは、SSL接続でメールを送信するモジュールです。このモジュールに対して、メールサーバーであったり、ポート番号などを指定します。早速指定していきましょう。
第一引数には、メールサーバーを指定します。メールサーバーはGmailのSMTPサーバーであるsmtp.gmail.comを使用します。
次にポート番号です。
ポート番号は、GmailのSMTPサーバーの標準ポートである465番を指定します。
なお、ポート番号とは、サーバーなどとやりとりするための番号のことです。
最後にcontextの部分でssl.create_default_context()を指定しています。
ここでは、SSLという暗号化の仕組みを使います。
これををserverという変数に代入します。
次に、Gmailサーバーにログインします。
先ほどオブジェクトを代入したserverを使ってGmailサーバーにログインしていきます。
事前に設定したgmail_accountとgmail_passwordをserver.login()関数に渡すとGmailサーバーにログインできます。
Gmailサーバーにログインすればあとはメールを送信するだけです。
事前に準備しておいたmsgをserver.send_message()に渡せばメールを送ることができます。
最後に、送信がおわったか確認するために、print関数で送信完了と表示させましょう・。

これでPythonを使ってGmailを送信することができました。
それではメールが届いているか確認をしてみましょう。

メールが届いています。
メールを開いてみます。

配信日や納期、体裁なども問題ないようです。
これでひとまずPythonでGmailを送信できるようになりました。
おめでとうございます。ぱちぱち〜。
キノコードでは、Pythonを使ったGmail送信の動画の他に、Pythonを使ってExcel作業の自動化の動画や株のデータ分析の動画などをアップしています。
現在アップしている動画の他にも、仕事の役に立つ動画をアップしていきます。
新着通知がいくのでぜひチャンネル登録をお願いします。
それでは続きをどうぞ!

添付ファイル付きGmailの送信

from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

次に、ファイルを添付してメールを送信してみましょう。
添付ファイルのメールを送信するには、3つのオブジェクトをインポートします。
一つ目は、MIMEMultipartというメール本文以外に添付ファイルを送信できるようにするモジュールです。
二つ目は、MIMEBaseという添付ファイルの形式を指定するモジュールです。
三つ目は、encodersという添付ファイルをメールで送ることができるように変換するモジュールです。
先ほどと同じように、件名と本文をそれぞれの変数に代入します。
今回添付するファイルはPDF形式を想定して進めていきましょう。

msg = MIMEMultipart()
msg[‘Subject’] = subject
msg[‘To’] = mail_to
msg[‘From’] = gmail_account
body = MIMEText(body, “html”)
msg.attach(body)

さて、添付ファイルをつけたメールを作成していきます。
MIMEMultipartで、メール本文以外に添付ファイルを送信できるオブジェクトを生成して、msgにオブジェクトを代入します。
そのオブジェクトに、件名、宛先、送信元に追加していきます。
次に、MIMETextを使って本文を追加をしましょう。
ただし、先ほどとは違い、MIMETextで生成した内容はbodyに再度代入をします。
最後に、オブジェクトに対して、attachメソッドを使用してmsgにbodyを追加します。

filename = “order_a.pdf”
file = open(filename, “rb”)
attachment_file = MIMEBase(‘application’, ‘pdf’)
attachment_file.set_payload((file).read())
file.close()
encoders.encode_base64(attachment_file)
attachment_file.add_header(‘Content-Disposition’, “attachment”, filename=filename)
msg.attach(attachment_file)

次にPDFファイルを添付する準備をします。
今回はorder_aというPDFを添付しましょう。ファイル名をfilnameという変数に代入。
次にPDFファイルを読み込みます。
openメソッドを使用して送信したいファイルを読み込みます。
この時にrbを指定するとファイルの読み込みのモードになるので、rbを指定しましょう。
続いて、MINEBaseを使用して添付ファイルの形式を指定しましょう。
第一引数はmaintypeというものを指定するのでここをapplicationを指定、第二引数にはsubtypeというものを指定するのでここをPDFとします。
これをattachment_fileという変数に代入をします。
ちなみに、attachmentとは添付という意味で、attachment_fileで添付ファイルという意味で私は変数を命名しました。
次に、set_payloadメソッドでattachment_fileの変数にPDFファイルを追加します。
この時、read()メソッドでファイルを読み込ませる必要があります。
次に、openで読み込んだファイルを閉じておきましょう。
続いて、インポートしたencodersのモジュールの中からencode_base64を使用して、添付ファイルをメールで送ることができるように変換します。
そして、メールヘッダーというメールの情報が書き込まれている部分に、添付ファイルの情報を追加します。
その時に、第一引数にContent-Disposition、第二引数に添付という意味のattachmentを指定し、その後ファイル名を指定します。ファイル名を指定する部分は、先ほど変数に代入をしたfilenameを使用します。
最後にattachメソッドを使用してmsgにPDFファイルを追加します。

実行します。
難しい理屈が続きましたがこれで添付ファイルをつけたメールが完成しました。
細かい理屈については、ご興味がある方、説明する必要がある方は、個別に探求してみてください。
私自身も誤って理解している部分があるかもしれませんので!

server = smtplib.SMTP_SSL(“smtp.gmail.com”, 465, context=ssl.create_default_context())
server.login(gmail_account, gmail_password)
server.send_message(msg)

あとは添付ファイルなしのGmailを送信した時と同様にSMTPサーバー経由でメールを送信します。

実行します。
これで添付ファイル付きGmailの送信をすることができたと思います。
メールを確認してみましょう。

添付ファイルがついているメールが届いているようです。

これで添付ファイルつきのメール送信できるようになりました。おめでとうございます。

複数の宛先に一斉送信

最後に複数の宛先に一斉送信をする方法についてみていきましょう。
複数の宛先に送信をするにはPandasとExcelを使います。

今回の場合は、このExcelファイルのように宛先名、メールアドレス、添付ファイルの3つのデータを記載します。
そのExcelファイルをPandasのread_excel関数を使って読み込み、データフレームにします。
Pandasをpdという名前でインポートした後に、read_excel関数を使ってエクセルを読み取りDataFrameにして、そのデータフレーム表示させてみます。
ちなみに、read_excel関数については、Pandas入門コースのレッスン6で説明しているのでわからない方はそちらをご覧ください。それでは3つのセルを実行します。

今回は、このDataFrameのそれぞれの宛先名、メールアドレス、添付ファイルを使って一斉送信をしていきます。
具体的には、DataFrameの1行ずつを取り出して、それぞれのカラム、つまり、宛名、メールアドレス、添付ファイルの値を取得。
そして、先ほど説明した添付ファイルつきのメール送信のコードを関数化して、その関数に取得したデータ渡してメール送信をするということをやっていきます。
まず、1行ずつ、それぞれのカラムの値を同時に取り出すことからやっていきます。
1行ずつ、それぞれのカラムの値を同時に取り出すには、for文とPythonのzip関数を組み合わせればできます。
forと書いて、ここは名前はなんでもよいですが、あとでこの変数を関数に渡すのでsend_name、mail_to、filenameとしましょう。
そして、inと描いてzip。zipの丸括弧の中にデータフレームのカラム名を記述しましょう。
そうすると、zip内に記述されたカラムの値をデータフレームの1行ずつ取り出して、send_name、mail_to、filenameに代入されていきます。
では、for文内にprint関数を書いて表示させてみましょう。
実行します。

このような感じで1行ずつ、それぞれのカラムのデータを取り出すことができます。
このデータを関数に渡して、メール送信をしていきましょう。
その前に、まず添付つきメール送信のコードを関数化します。

それでは関数を定義します。
関数名はgmail_sendにしましょう。関数の定義の方法はdefを使いましたね。関数については、Python超入門コースのレッスン12で説明をしています。わからない方はそちらをご覧ください。
それでは、今まで書いてきたコードをコピペをします。
件名と本文を変数に代入をした記述もここに持ってきます。
変更点は2点のみです。
1点目はコードを見やすくするために、bodyへ代入する記述ところをトリプルクオテーションに変更しました。
そうすると、改行して記述することが可能です。
2点目はfilenameのところです。前回は、ここを直接ファイル名を記述して変数に代入をしていましたが、関数に渡した引数filenameを使います

それでは、実行します。
ちなみに、この関数については綺麗に書いていません。ご自身の業務の状況にあわせて書き換えたり、保守性をあげる書き方に変更することも検討してみてください。
それではこの関数と先ほどみたzipのfor文を使って配信をしていきます。
printだった部分をgmail_sendに書き換えればよいです。
実行します。
一斉送信が完了したようです。
それではメールを確認してみましょう

エクセルの表の通り、キノコード様になっていて、添付ファイルにorder_a.pdfがついています。
問題なさそうです。

次のメールアカウントにはユーチューズ様になっていて、添付ファイルはorder_b.pdfになっています。


最後のメールアカウントにはパイソン様になっていて、添付ファイルはorder_c.pdfになっています。
問題なく一斉送信ができたようです。

動画はいかがでしたでしょうか?
理解はできましたでしょうか?
キノコードでは株のデータ分析の動画も作っています。
特定の条件に当てはまったら、このレッスンでやったGmail送信の関数を呼び出して、メールで送信をするということもできます。
ご興味ある方は、ぜひトライしてみてください。
キノコードでもそれの開設動画をつくりますので、チャンネル登録をしてお待ちいただければと思います。
それでは、次回のレッスンでお会いしましょう。