目次
概要
- pythonの標準モジュールであるsmtplibを使って、プレーンテキストのメールを送信するサンプルを紹介します。
- Windows 10のPython 3.11.7(64bit)で動作検証しています。
- サンプルでは、SMTPS, STARTTLSに対応するgmailのSMTPサーバを使用しています。
- GoogleのSMTP仕様は次の情報をご覧ください。
- Googleアカウントのパスワードとは別にアプリパスワードを発行する必要があります。詳細はこちらをご覧ください。
メール送信サンプル
使用環境や用途に応じて適宜変更してください。
完全なソースコードはgithubで公開しています。
GitHub
Contribute to nextdoorwith/archives development by creating …
プレーンテキスト
STARTTLS, SMTPS(SMTP over SSL/TLS)を使用したプレーンテキストを送信するサンプルです。
通信内容の例をこちらで紹介しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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)を使用したメールを送信するサンプルです。
通信内容の例をこちらで紹介しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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.utilsのformataddr()を使用します。既定でUTF-8としてエンコードします。
- 本文として、UTF-8エンコードしたデータを指定するためにstr.encode()を使用します。
参考
Googleアプリパスワードの発行方法
Googleアカウントの、「セキュリティ」-「2段階認証プロセス」-「アプリパスワード」、からアプリパスワードを設定できます。
なお、アプリパスワードはGoogleパスワードとは異なるので、追加で設定する必要があります。また、アプリパスワードを設定するためには、2段階認証プロセスの有効化が必要です。
- Googleアカウントを開きます。
- 「セキュリティ」の「2段階認証プロセス」を開きます。
- 開いたページの下の方にある「アプリパスワード」を開きます。
- アプリ名に任意の名前を入力し、「作成」ボタンをクリックします。
- 生成されたパスワードが表示されます。
sendmail()とsend_message()の違い
- SMTP.sendmail()は、低レベルのメール送信メソッドです。次のサンプルのように、自身で生成したメールヘッダ・ボディを引数で指定する必要があります。なお、メールヘッダ・ボディ(文字列)は、Messageのas_string()から取得することもできます。
- SMTP.send_message()は、高レベルのメール送信メソッドです。引数で指定されたMessageやMIMEMessageオブジェクトから生成されたメールヘッダ・ボディが使用されます。
- 通常は、Message, MIMEMessageと併せてSMTP.send_message()を使用することになります。独自のメールヘッダ・ボディの使用等の低レベルの操作を行いたい場合は、SMTP.sendmail()を使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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' |
日本語メール
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 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' |