Python: 単純・日本語メールを送信(smtplib)

概要

メール送信サンプル

使用環境や用途に応じて適宜変更してください。
完全なソースコードはgithubで公開しています。

GitHub

Contribute to nextdoorwith/archives development by creating …

プレーンテキスト

STARTTLS, SMTPS(SMTP over SSL/TLS)を使用したプレーンテキストを送信するサンプルです。
通信内容の例をこちらで紹介しています。

import smtplib
from email.message import Message

HOSTNAME = "smtp.gmail.com"
USERNAME = "sender@gmail.com"
PASSWORD = "aaaa bbbb cccc"
 
message = Message()
message["From"] = "sender@gmail.com"
message["To"] = "receiver1@gmail.com, receiver2@gmail.com"
message["Subject"] = "test_subject"
message.set_payload("test_body")

# STARTTLS
server = smtplib.SMTP(HOSTNAME, 587)
server.starttls()

server.login(USERNAME, PASSWORD)
server.send_message(message)
server.quit()
import smtplib
from email.message import Message

HOSTNAME = "smtp.gmail.com"
USERNAME = "sender@gmail.com"
PASSWORD = "aaaa bbbb cccc"
 
message = Message()
message["From"] = "sender@gmail.com"
message["To"] = "receiver1@gmail.com, receiver2@gmail.com"
message["Subject"] = "test_subject"
message.set_payload("test_body")

# SMTPS
server = smtplib.SMTP_SSL(HOSTNAME, 465)

server.login(USERNAME, PASSWORD)
server.send_message(message)
server.quit()
  • Messageを使用してメッセージを作成し、SMTP接続を表現するSMTPまたはSMTP_SSLを使ってメッセージを送信します。(SMTPとSMTP_SSLは同様に動作します。)
  • STARTTLSを使用する場合、smtplib.SMTP()オブジェクトを生成します。併せて、暗号化通信を開始するためにSMTP.starttls()を使用する必要があります。
  • SMTPSを使用する場合、smtplib.SMTP_SSL()オブジェクトを生成します。
  • 認証を行うために、SMTP.login()を使用します。
  • SMTPサーバとの通信内容を確認したい場合、SMTP.set_debuglevel()を使用します。出力例はこちらをご覧ください。
  • メッセージの送信は、SMTP.send_message()を使用します。同様のメソッドとして、SMTP.sendmail()がありますが、両者の違いはこちらをご覧ください。
  • なお、SMTPサーバやローカル側のリソース使用を最小限にするために、接続に依存しない処理は事前に行うことをお薦めします。(接続時間を可能な限り短くする。)

日本語プレーンテキスト

From, To, 件名, 本文に日本語(UTF-8)を使用したメールを送信するサンプルです。
通信内容の例をこちらで紹介しています。

import smtplib
from email.header import Header
from email.message import Message
from email.utils import formataddr

HOSTNAME = "smtp.gmail.com"
USERNAME = "sender@gmail.com"
PASSWORD = "aaaa bbbb cccc"

tolist = [
    ("試験宛先1", "receiver1@gmail.com"),
    ("試験宛先2", "receiver2@gmail.com")
]
message = Message()
message.set_type("text/plain"); message.set_charset("utf-8")
message["From"] = formataddr(("試験送信者", "sender@gmail.com"))
message["To"] = ", ".join([formataddr(e) for e in tolist])
message["Subject"] = "試験件名"
message.set_payload("試験本文".encode())

server = smtplib.SMTP(HOSTNAME, 587)
server.starttls()
server.login(USERNAME, PASSWORD)
server.send_message(message)
server.quit()
  • 表示名を付与したFromやToを指定する場合、email.utilsformataddr()を使用します。既定でUTF-8としてエンコードします。
  • 本文として、UTF-8エンコードしたデータを指定するためにstr.encode()を使用します。

参考

Googleアプリパスワードの発行方法

Googleアカウントの、「セキュリティ」-「2段階認証プロセス」-「アプリパスワード」、からアプリパスワードを設定できます。
なお、アプリパスワードはGoogleパスワードとは異なるので、追加で設定する必要があります。また、アプリパスワードを設定するためには、2段階認証プロセスの有効化が必要です。

  1. Googleアカウントを開きます。
  2. 「セキュリティ」の「2段階認証プロセス」を開きます。
  3. 開いたページの下の方にある「アプリパスワード」を開きます。
  4. アプリ名に任意の名前を入力し、「作成」ボタンをクリックします。
  5. 生成されたパスワードが表示されます。

sendmail()とsend_message()の違い

  • SMTP.sendmail()は、低レベルのメール送信メソッドです。次のサンプルのように、自身で生成したメールヘッダ・ボディを引数で指定する必要があります。なお、メールヘッダ・ボディ(文字列)は、Messageのas_string()から取得することもできます。
  • SMTP.send_message()は、高レベルのメール送信メソッドです。引数で指定されたMessageやMIMEMessageオブジェクトから生成されたメールヘッダ・ボディが使用されます。
  • 通常は、Message, MIMEMessageと併せてSMTP.send_message()を使用することになります。独自のメールヘッダ・ボディの使用等の低レベルの操作を行いたい場合は、SMTP.sendmail()を使用します。
import smtplib

HOSTNAME = "smtp.gmail.com"
USERNAME = "sender@gmail.com"
PASSWORD = "aaaa bbbb cccc"
 
from_addr = "sender@gmail.com"
to_addrs = "receiver1@gmail.com, receiver2@gmail.com"
raw_msg = (
    f"From: {from_addr}\r\n"
    f"To: {to_addrs}\r\n"
    f"Subject: test_subject\r\n"
    f"\r\n"
    f"test_body"
)
 
server = smtplib.SMTP(HOSTNAME, 587)
server.starttls()
server.login(USERNAME, PASSWORD)
server.sendmail(from_addr, to_addrs, raw_msg)
server.quit()

SMTP通信のダンプ例

  • 前述のサンプルを使用した際の通信例です。SMTP.set_debuglevel()を使用して出力した内容です。
  • 行頭の”send”はサンプルプログラム(クライアント)からの送信、”reply”はSMTPサーバの応答を表しています。一部は見やすいように適当に改行しています。

STARTTLS

send: 'ehlo [192.168.1.2]\r\n'
reply: b'250-smtp.gmail.com at your service, [x.x.x.x]\r\n'
reply: b'250-SIZE 35882577\r\n'
reply: b'250-8BITMIME\r\n'
reply: b'250-STARTTLS\r\n'
reply: b'250-ENHANCEDSTATUSCODES\r\n'
reply: b'250-PIPELINING\r\n'
reply: b'250-CHUNKING\r\n'
reply: b'250 SMTPUTF8\r\n'
reply: retcode (250); Msg: b'smtp.gmail.com at your service, [x.x.x.x]\n
       SIZE 35882577\n8BITMIME\nSTARTTLS\nENHANCEDSTATUSCODES\nPIPELINING\nCHUNKING\nSMTPUTF8'
send: 'STARTTLS\r\n'
reply: b'220 2.0.0 Ready to start TLS\r\n'
reply: retcode (220); Msg: b'2.0.0 Ready to start TLS'
send: 'ehlo [192.168.1.2]\r\n'
reply: b'250-smtp.gmail.com at your service, [x.x.x.x]\r\n'
reply: b'250-SIZE 35882577\r\n'
reply: b'250-8BITMIME\r\n'
reply: b'250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH\r\n'
reply: b'250-ENHANCEDSTATUSCODES\r\n'
reply: b'250-PIPELINING\r\n'
reply: b'250-CHUNKING\r\n'
reply: b'250 SMTPUTF8\r\n'
reply: retcode (250); Msg: b'smtp.gmail.com at your service, [x.x.x.x]\n
       SIZE 35882577\n8BITMIME\n
       AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH\n
       ENHANCEDSTATUSCODES\nPIPELINING\nCHUNKING\nSMTPUTF8'
send: 'AUTH PLAIN ABCxxxXYZ==\r\n'
reply: b'235 2.7.0 Accepted\r\n'
reply: retcode (235); Msg: b'2.7.0 Accepted'
send: 'mail FROM:<sender@gmail.com> size=96\r\n'
reply: b'250 2.1.0 OK d70-20020axxx176pga.27 - gsmtp\r\n'
reply: retcode (250); Msg: b'2.1.0 OK d70-20020axxx176pga.27 - gsmtp'
send: 'rcpt TO:<receiver@gmail.com>\r\n'
reply: b'250 2.1.5 OK d70-20020axxx176pga.27 - gsmtp\r\n'
reply: retcode (250); Msg: b'2.1.5 OK d70-20020axxx176pga.27 - gsmtp'
send: 'data\r\n'
reply: b'354  Go ahead d70-20020axxx176pga.27 - gsmtp\r\n'
reply: retcode (354); Msg: b'Go ahead d70-20020axxx176pga.27 - gsmtp'
data: (354, b'Go ahead d70-20020axxx176pga.27 - gsmtp')
send: b'From: sender@gmail.com\r\n
        To: receiver@gmail.com\r\n
        Subject: test_subject\r\n
        \r\n
        test_body\r\n
        .\r\n'
reply: b'250 2.0.0 OK  1707542678 d70-20020axxx176pga.27 - gsmtp\r\n'
reply: retcode (250); Msg: b'2.0.0 OK  1707542678 d70-20020axxx176pga.27 - gsmtp'
data: (250, b'2.0.0 OK  1707542678 d70-20020axxx176pga.27 - gsmtp')
send: 'quit\r\n'
reply: b'221 2.0.0 closing connection d70-20020axxx176pga.27 - gsmtp\r\n'
reply: retcode (221); Msg: b'2.0.0 closing connection d70-20020axxx176pga.27 - gsmtp'

SMTPS

send: 'ehlo [192.168.1.2]\r\n'
reply: b'250-smtp.gmail.com at your service, [x.x.x.x]\r\n'
reply: b'250-SIZE 35882577\r\n'
reply: b'250-8BITMIME\r\n'
reply: b'250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH\r\n'
reply: b'250-ENHANCEDSTATUSCODES\r\n'
reply: b'250-PIPELINING\r\n'
reply: b'250-CHUNKING\r\n'
reply: b'250 SMTPUTF8\r\n'
reply: retcode (250); Msg: b'smtp.gmail.com at your service, [x.x.x.x]\n
       SIZE 35882577\n8BITMIME\n
       AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH\n
       ENHANCEDSTATUSCODES\nPIPELINING\nCHUNKING\nSMTPUTF8'
send: 'AUTH PLAIN ABCxxxXYZ==\r\n'
reply: b'235 2.7.0 Accepted\r\n'
reply: retcode (235); Msg: b'2.7.0 Accepted'
send: 'mail FROM:<from@gmail.com> size=96\r\n'
reply: b'250 2.1.0 OK h3-20020axxx087pll.174 - gsmtp\r\n'
reply: retcode (250); Msg: b'2.1.0 OK h3-20020axxx087pll.174 - gsmtp'
send: 'rcpt TO:<receiver@gmail.com>\r\n'
reply: b'250 2.1.5 OK h3-20020axxx087pll.174 - gsmtp\r\n'
reply: retcode (250); Msg: b'2.1.5 OK h3-20020axxx087pll.174 - gsmtp'
send: 'data\r\n'
reply: b'354  Go ahead h3-20020axxx087pll.174 - gsmtp\r\n'
reply: retcode (354); Msg: b'Go ahead h3-20020axxx087pll.174 - gsmtp'
data: (354, b'Go ahead h3-20020axxx087pll.174 - gsmtp')
send: b'From: from@gmail.com\r\n
        To: receiver@gmail.com\r\n
        Subject: test_subject\r\n
        \r\n
        test_body\r\n
        .\r\n'
reply: b'250 2.0.0 OK  1707631472 h3-20020axxx087pll.174 - gsmtp\r\n'
reply: retcode (250); Msg: b'2.0.0 OK  1707631472 h3-20020axxx087pll.174 - gsmtp'
data: (250, b'2.0.0 OK  1707631472 h3-20020axxx087pll.174 - gsmtp')
send: 'quit\r\n'
reply: b'221 2.0.0 closing connection h3-20020axxx087pll.174 - gsmtp\r\n'
reply: retcode (221); Msg: b'2.0.0 closing connection h3-20020axxx087pll.174 - gsmtp'

日本語メール

send: 'ehlo [192.168.1.2]\r\n'
reply: b'250-smtp.gmail.com at your service, [x.x.x.x]\r\n'
reply: b'250-SIZE 35882577\r\n'
reply: b'250-8BITMIME\r\n'
reply: b'250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH\r\n'
reply: b'250-ENHANCEDSTATUSCODES\r\n'
reply: b'250-PIPELINING\r\n'
reply: b'250-CHUNKING\r\n'
reply: b'250 SMTPUTF8\r\n'
reply: retcode (250); Msg: b'smtp.gmail.com at your service, [x.x.x.x]\n
       SIZE 35882577\n8BITMIME\n
       AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH\n
       ENHANCEDSTATUSCODES\nPIPELINING\nCHUNKING\nSMTPUTF8'
send: 'AUTH PLAIN ABCxxxXYZ==\r\n'
reply: b'235 2.7.0 Accepted\r\n'
reply: retcode (235); Msg: b'2.7.0 Accepted'
send: 'mail FROM:<sender@gmail.com> size=346\r\n'
reply: b'250 2.1.0 OK n3-20020axxx119pfq.124 - gsmtp\r\n'
reply: retcode (250); Msg: b'2.1.0 OK n3-20020axxx119pfq.124 - gsmtp'
send: 'rcpt TO:<receiver1@gmail.com>\r\n'
reply: b'250 2.1.5 OK n3-20020axxx119pfq.124 - gsmtp\r\n'
reply: retcode (250); Msg: b'2.1.5 OK n3-20020axxx119pfq.124 - gsmtp'
send: 'rcpt TO:<receiver2@gmail.com>\r\n'
reply: b'250 2.1.5 OK n3-20020axxx119pfq.124 - gsmtp\r\n'
reply: retcode (250); Msg: b'2.1.5 OK n3-20020axxx119pfq.124 - gsmtp'
send: 'data\r\n'
reply: b'354  Go ahead n3-20020axxx119pfq.124 - gsmtp\r\n'
reply: retcode (354); Msg: b'Go ahead n3-20020axxx119pfq.124 - gsmtp'
data: (354, b'Go ahead n3-20020axxx119pfq.124 - gsmtp')
send: b'MIME-Version: 1.0\r\n
        Content-Type: text/plain; charset="utf-8"\r\n
        Content-Transfer-Encoding: base64\r\n
        From: =?utf-8?b?6Kmm6aiT6YCB5L+h6ICF?= <sender@gmail.com>\r\n
        To: =?utf-8?b?6Kmm6aiT5a6b5YWIMQ==?= <receiver1@gmail.com>,\r\n
            =?utf-8?b?6Kmm6aiT5a6b5YWIMg==?= <receiver2@gmail.com>\r\n
        Subject: =?utf-8?b?6Kmm6aiT5Lu25ZCN?=\r\n
        \r\n
        \xe8\xa9\xa6\xe9\xa8\x93\xe6\x9c\xac\xe6\x96\x87\r\n
        .\r\n'
reply: b'250 2.0.0 OK  1707632062 n3-20020axxx119pfq.124 - gsmtp\r\n'
reply: retcode (250); Msg: b'2.0.0 OK  1707632062 n3-20020axxx119pfq.124 - gsmtp'
data: (250, b'2.0.0 OK  1707632062 n3-20020axxx119pfq.124 - gsmtp')
send: 'quit\r\n'
reply: b'221 2.0.0 closing connection n3-20020axxx119pfq.124 - gsmtp\r\n'
reply: retcode (221); Msg: b'2.0.0 closing connection n3-20020axxx119pfq.124 - gsmtp'