Pythonでは様々な処理を実装できます。例えば、画像認識のプログラムで不審者を検知した場合、それを誰かに知らせる必要があります。その方法の1つがメール送信です。
今回は、Pythonでメールを送信する方法を紹介します。なるべくどんな手順で送信しているかについても触れていきたいと思っています。
サンプルコードを紹介しますが、今回はGmailでメール送信を行います。なので、ご自身のGmailアドレスに置き換えて試してみてください
メール送信の概要
メール送信にはSMTPというプロトコルを用います。SMTPは”Simple Mail Transfer Protocol”の略で、メール送信のためのプロトコルです。
クライアントがメールを送信するためには、まずSMTPサーバに接続する必要があります。接続には、SMTPサーバのホスト名、ポート番号、認証情報などが必要です。今回の場合はGmailで送信するので、Gmailのメールサーバ(SMTPサーバ)に接続します(図中のクライアント側メールサーバ)。
クライアントからメールを受け取ったSMTPサーバは、送信先の情報をもとに、メールをバトン式に次のSMTPサーバ(または終着点のPOP3サーバ)まで繋いでいきます。この転送にもSMTPが用いられます。
ちなみに、メールサーバ間の転送で送信先をどのように決めているかということですが、メールアドレスの@以下(Gmailなら@gmail.com)の部分をDNS参照することで決定しています。
Pythonで実装する
ざっくりとメール送信の仕組みに触れたところで、Pythonで実装していきます。
使用するモジュール
メール送信には以下のモジュールを利用します。
import smtplib
from email.mime.text import MIMEText
from email.utils import formatdate
いずれもPythonの標準ライブラリなので、特別インストールする必要はありません。
メールサーバと接続
まずはメールサーバと接続します。コードから紹介します。
#SMTPのオブジェクト作成。GmailのSMTPポートは587
smtpobj = smtplib.SMTP('smtp.gmail.com', 587)
#メールサーバに対する応答
smtpobj.ehlo()
#暗号化通信開始
smtpobj.starttls()
smtpobj.ehlo()
#ログイン
smtpobj.login("learn.nao.info@gmail.com", "xxxxxxxxxxxxx")
最初にSMTPのオブジェクトを作成します。今回はGmailなので、引数に”smtp.gmail.com”とポート番号の587を渡します。
elho()はメールサーバに対する応答です。このとき、クライアント側PCは自身のホスト名を名乗ります。メールサーバはこのホスト名をチェックし、接続の許可を判断します。
この時点ではまだ通信が暗号化されておらず、外部から丸見えです。なので、可能であればTLS通信で暗号化します。そのメソッドがstarttls()です。
starttls()では、直前の ehlo() の応答にSTARTTLSがあることを確認してからSTARTTLSコマンドをサーバに要求します。サーバがこのコマンドを受け入れることで、暗号化通信が始まります。
最後に認証情報を渡してログインします。 starttls() で暗号化通信を開始したあともう一度 ehlo() を実行すると、AUTH LOGINコマンドが出てきます。
ログインはlogin()メソッドで試みます。アドレス、パスワードを引数に渡します。これで認証が通れば、メールを送信できる状態になります。
Gmailの認証がうまくいかない場合
手順通りにやっているのにうまく接続できない場合は、安全性の低いアプリからのアクセスとして拒否されている可能性があります。
Googleはセキュリティの仕様上、よくわからないアプリからのアクセスを自動で拒否します。Pythonも漏れなく安全性の低いアプリ認定されているのです(まあ当然)。なので、以下URLから安全性の低いアプリの許可を「有効」にする必要があります。
https://support.google.com/accounts/answer/6010255
メール送信
SMTPサーバと接続したら、メール本文を作成して送信します。
#送信元、送信先
mail_from = "learn.nao.info@gmail.com"
mail_to = "learn.nao.info@gmail.com"
#本文
text = "これはテスト用のメールです"
#メッセージのオブジェクト
msg = MIMEText(text)
msg['Subject'] = "テスト送信"
msg['From'] = mail_from
msg['To'] = mail_to
msg['Date'] = formatdate(localtime=True)
#メール送信
smtpobj.sendmail(mail_from, mail_to, msg.as_string())
今回はテスト送信ということで、送信元と送信先を同じアドレスにしています。
メールの中身に関する情報は、MIMEText()オブジェクトに詰め込みます。本文、タイトル、送信元、送信先、日付を指定したら、sendmail()でメール送信を実行します。
ちゃんとメールが送られてきました。
コード全体
ここまでの一連のコードをまとめておきます。
import smtplib
from email.mime.text import MIMEText
from email.utils import formatdate
#SMTPのオブジェクト作成。GmailのSMTPポートは587
smtpobj = smtplib.SMTP('smtp.gmail.com', 587)
#メールサーバに対する応答
smtpobj.ehlo()
#暗号化通信開始
smtpobj.starttls()
smtpobj.ehlo()
#ログイン
smtpobj.login("learn.nao.info@gmail.com", "learning-nao")
#送信元、送信先
mail_from = "learn.nao.info@gmail.com"
mail_to = "learn.nao.info@gmail.com"
#本文
text = "これはテスト用のメールです"
#メッセージのオブジェクト
msg = MIMEText(text)
msg['Subject'] = "テスト送信"
msg['From'] = mail_from
msg['To'] = mail_to
msg['Date'] = formatdate(localtime=True)
#メール送信
smtpobj.sendmail(mail_from, mail_to, msg.as_string())
関数化したりすることでもっと便利に使えるようになると思います。
まとめ
Pythonからメールを送信する方法を紹介しました。手順も含めて解説したので、なんとなくどういうプロセスでメールが送られているのかもわかってもらえたのではないでしょうか。
原理を知っておくとコーディングの正確性も増します。もちろんGmail以外でも今回のプログラムは使えるので、是非試してみてください^^
ではでは👋