SlideShare uma empresa Scribd logo
1 de 52
Hello!!
組み込み系(マイコン、Linux)
Python 歴 6年くらい
@takey
ラズパイを出先でも操作したい
調べたら色々出てくる
● SSH接続
● VPN接続
● TeamViewer
● AWS IoT
● etc...
メールを使う方法ってないな…
メールのすごいところ
● 環境を整備する必要なし
○ インフラ化している
● フリーメール
○ 無料
○ アカウント作りたい放題
○ SSL/TLSで暗号化できる
● スマホやPCなど端末を選ばず操作可能
システム概要
(1) メール送信
メールサーバ
自宅
(2) メール受信
(4) 実行結果をメール返信
(3) メール解析&
コマンド実行
(5) 返信受信
目次
1. メールの説明
2. Pythonでメールを送信する
3. Pythonでメールを受信する
4. メールを解析してコマンドを実行する
目次
1. メールの説明
2. Pythonでメールを送信する
3. Pythonでメールを受信する
4. メールを解析してコマンドを実行する
メールプロトコル
● SMTP
○ 送信用のプロトコル
● POP3
○ 受信用のプロトコル(ローカルにダウンロードして閲覧)
○ Thunderbird, Outlookなど
● IMAP4
○ 受信用のプロトコル(サーバで閲覧)
○ Gmail, Yahoo!メールなど
メールプロトコル
● SMTP
○ 送信用のプロトコル
● POP3
○ 受信用のプロトコル(ローカルにダウンロードして閲覧)
○ Thunderbird, Outlookなど
● IMAP4
○ 受信用のプロトコル(サーバで閲覧)
○ Gmail, Yahoo!メールなど
目次
1. メールの説明
2. Pythonでメールを送信する
3. Pythonでメールを受信する
4. メールを解析してコマンドを実行する
メールを送信してみよう
Gmail
ホスト名: smtp.gmail.com
通信方式:STARTTLS, SSL/TLS
※必ず暗号化必須
Yahoo!メール
ホスト名: smtp.mail.yahoo.co.jp
通信方式:暗号化なし, SSL/TLS
国内のフリーメール
Gmailを使うときの注意
https://myaccount.google.com/u/1/lesssecureapps?pageId=none
Gmailの設定で「セキュリティの低いアプリの許可」を有効にする必要あり
主なライブラリ
● smtplib (https://docs.python.jp/3/library/smtplib.html)
○ smtpプロトコル機能を提供するライブラリ(メール送信できるライブラリ)
● email.mime (https://docs.python.jp/3/library/email.mime.html)
○ MIMEメッセージを作成するライブラリ
MIMEメッセージとは、メールシステム上で扱えるようにした
データのこと
メールとは、MIMEメッセージのやりとりと言える
処理の流れ
1. MIMEメッセージを作成する
○ メール用のデータを作成!
2. MIMEメッセージに必要なヘッダ情報を付与する
○ FromとかToとか!
3. SMTPクライアントインスタンスを作成する
○ メール送信の準備!
4. SMTPサーバにログインする
○ 認証!
5. メール送信(MIMEメッセージを送信する)
import base64
import smtplib
import ssl
from email.mime.text import MIMEText
from email.utils import formatdate
# (1) MIMEメッセージを作成する
main_text = "これが本文です"
charset = “utf-8”
msg = MIMEText(main_text, "plain", charset)
メール送信サンプルコード(1/2)
# (2) MIMEメッセージに必要なヘッダを付ける
msg.replace_header("Content-Transfer-Encoding", "base64")
msg["Subject"] = "これが件名です"
msg["From"] = "from@gmail.com"
msg["To"] = "to@gmail.com"
msg["Cc"] = ""
msg["Bcc"] = ""
msg["Date"] = formatdate(None,True)
import base64
import smtplib
import ssl
from email.mime.text import MIMEText
from email.utils import formatdate
# (1) MIMEメッセージを作成する
main_text = "これが本文です"
charset = “utf-8”
msg = MIMEText(main_text, "plain", charset)
メール送信サンプルコード(1/2)
# (2) MIMEメッセージに必要なヘッダを付ける
msg.replace_header("Content-Transfer-Encoding", "base64")
msg["Subject"] = "これが件名です"
msg["From"] = "from@gmail.com"
msg["To"] = "to@gmail.com"
msg["Cc"] = ""
msg["Bcc"] = ""
msg["Date"] = formatdate(None,True)
import base64
import smtplib
import ssl
from email.mime.text import MIMEText
from email.utils import formatdate
# (1) MIMEメッセージを作成する
main_text = "これが本文です"
charset = “utf-8”
msg = MIMEText(main_text, "plain", charset)
メール送信サンプルコード(1/2)
# (2) MIMEメッセージに必要なヘッダを付ける
msg.replace_header("Content-Transfer-Encoding", "base64")
msg["Subject"] = "これが件名です"
msg["From"] = "from@gmail.com"
msg["To"] = "to@gmail.com"
msg["Cc"] = ""
msg["Bcc"] = ""
msg["Date"] = formatdate(None,True)
# (3) SMTPクライアントインスタンスを作成する
host = "smtp.gmail.com"
port = 587
smtpclient = smtplib.SMTP(host, port, timeout=10)
smtpclient.ehlo()
smtpclient.starttls()
smtpclient.ehlo()
メール送信サンプルコード(2/2)
# (4) SMTPサーバにログインする
user = "from@gmail.com"
password = "password"
smtpclient.login(user, password)
# (5) メールを送信する
smtpclient.send_message(msg)
smtpclient.quit()
# (3) SMTPクライアントインスタンスを作成する
host = "smtp.gmail.com"
port = 587
smtpclient = smtplib.SMTP(host, port, timeout=10)
smtpclient.ehlo()
smtpclient.starttls()
smtpclient.ehlo()
メール送信サンプルコード(2/2)
# (4) SMTPサーバにログインする
user = "from@gmail.com"
password = "password"
smtpclient.login(user, password)
# (5) メールを送信する
smtpclient.send_message(msg)
smtpclient.quit()
# (3) SMTPクライアントインスタンスを作成する
host = "smtp.gmail.com"
port = 587
smtpclient = smtplib.SMTP(host, port, timeout=10)
smtpclient.ehlo()
smtpclient.starttls()
smtpclient.ehlo()
メール送信サンプルコード(2/2)
# (4) SMTPサーバにログインする
user = "from@gmail.com"
password = "password"
smtpclient.login(user, password)
# (5) メールを送信する
smtpclient.send_message(msg)
smtpclient.quit()
# (3) SMTPクライアントインスタンスを作成する
host = "smtp.gmail.com"
port = 587
smtpclient = smtplib.SMTP(host, port, timeout=10)
smtpclient.ehlo()
smtpclient.starttls()
smtpclient.ehlo()
メール送信サンプルコード(2/2)
# (4) SMTPサーバにログインする
user = "from@gmail.com"
password = "password"
smtpclient.login(user, password)
# (5) メールを送信する
smtpclient.send_message(msg)
smtpclient.quit()
目次
1. メールの説明
2. Pythonでメールを送信する
3. Pythonでメールを受信する
4. メールを解析してコマンドを実行する
メールを受信してみよう
主なライブラリ
● imaplib (https://docs.python.jp/3/library/imaplib.html)
○ imap4プロトコル機能を提供するライブラリ(メール受信できるライブラリ)
● email.header (https://docs.python.jp/3/library/email.header.html)
○ MIMEメッセージのヘッダを解析するライブラリ
○ FromヘッダとかSubjectヘッダとかを取り出すのに便利
処理の流れ
1. IMAP4クライアントインスタンスを作成する
○ メール受信の準備!
2. IMAP4サーバにログインする
○ 認証!
3. メール受信(MIMEメッセージを受信する)
4. メール解析
○ 件名とか、本文とかをデコードする!
import email
import ssl
import imaplib
from email.header import decode_header, make_header
# (1) IMAP4クライアントインスタンスを作成する
host = "imap.gmail.com"
port = 993
context = ssl.create_default_context()
imapclient = imaplib.IMAP4_SSL(host, port, ssl_context=context)
# (2) IMAPサーバーにログインする
username = "username@gmail.com"
password = "password"
imapclient.login(username, password)
メール受信サンプルコード(1/1)
# (3) メール受信
imapclient.select()
typ, data = imapclient.search(None, "ALL")
datas = data[0].split() #datas = [b’1’, b’2’, ...]
fetch_num = 5 # 取得したいメッセージの数
msg_list = [] # 取得したMIMEメッセージを格納するリスト
for num in datas[len(datas)-fetch_num::]:
typ, data = imapclient.fetch(num, '(RFC822)')
msg = email.message_from_bytes(data[0][1])
msg_list.append(msg)
imapclient.close()
imapclient.logout()
# (4) メール解析(各ヘッダ情報や本文を取得する)
for msg in msg_list:
# ヘッダ情報は、ディクショナリのようにアクセスできる
# str(make_header(decode_header(msg["From"])))
payload = msg.get_payload(decode=True)
charset = msg.get_content_charset()
if charset is not None:
payload = payload.decode(charset,
"ignore")
print(payload) # 本文表示
import email
import ssl
import imaplib
from email.header import decode_header, make_header
# (1) IMAP4クライアントインスタンスを作成する
host = "imap.gmail.com"
port = 993
context = ssl.create_default_context()
imapclient = imaplib.IMAP4_SSL(host, port, ssl_context=context)
# (2) IMAPサーバーにログインする
username = "username@gmail.com"
password = "password"
imapclient.login(username, password)
メール受信サンプルコード(1/1)
# (3) メール受信
imapclient.select()
typ, data = imapclient.search(None, "ALL")
datas = data[0].split() #datas = [b’1’, b’2’, ...]
fetch_num = 5 # 取得したいメッセージの数
msg_list = [] # 取得したMIMEメッセージを格納するリスト
for num in datas[len(datas)-fetch_num::]:
typ, data = imapclient.fetch(num, '(RFC822)')
msg = email.message_from_bytes(data[0][1])
msg_list.append(msg)
imapclient.close()
imapclient.logout()
# (4) メール解析(各ヘッダ情報や本文を取得する)
for msg in msg_list:
# ヘッダ情報は、ディクショナリのようにアクセスできる
# str(make_header(decode_header(msg["From"])))
payload = msg.get_payload(decode=True)
charset = msg.get_content_charset()
if charset is not None:
payload = payload.decode(charset,
"ignore")
print(payload) # 本文表示
import email
import ssl
import imaplib
from email.header import decode_header, make_header
# (1) IMAP4クライアントインスタンスを作成する
host = "imap.gmail.com"
port = 993
context = ssl.create_default_context()
imapclient = imaplib.IMAP4_SSL(host, port, ssl_context=context)
# (2) IMAPサーバーにログインする
username = "username@gmail.com"
password = "password"
imapclient.login(username, password)
メール受信サンプルコード(1/1)
# (3) メール受信
imapclient.select()
typ, data = imapclient.search(None, "ALL")
datas = data[0].split() #datas = [b’1’, b’2’, ...]
fetch_num = 5 # 取得したいメッセージの数
msg_list = [] # 取得したMIMEメッセージを格納するリスト
for num in datas[len(datas)-fetch_num::]:
typ, data = imapclient.fetch(num, '(RFC822)')
msg = email.message_from_bytes(data[0][1])
msg_list.append(msg)
imapclient.close()
imapclient.logout()
# (4) メール解析(各ヘッダ情報や本文を取得する)
for msg in msg_list:
# ヘッダ情報は、ディクショナリのようにアクセスできる
# str(make_header(decode_header(msg["From"])))
payload = msg.get_payload(decode=True)
charset = msg.get_content_charset()
if charset is not None:
payload = payload.decode(charset,
"ignore")
print(payload) # 本文表示
import email
import ssl
import imaplib
from email.header import decode_header, make_header
# (1) IMAP4クライアントインスタンスを作成する
host = "imap.gmail.com"
port = 993
context = ssl.create_default_context()
imapclient = imaplib.IMAP4_SSL(host, port, ssl_context=context)
# (2) IMAPサーバーにログインする
username = "username@gmail.com"
password = "password"
imapclient.login(username, password)
メール受信サンプルコード(1/1)
# (3) メール受信
imapclient.select()
typ, data = imapclient.search(None, "ALL")
datas = data[0].split() #datas = [b’1’, b’2’, ...]
fetch_num = 5 # 取得したいメッセージの数
msg_list = [] # 取得したMIMEメッセージを格納するリスト
for num in datas[len(datas)-fetch_num::]:
typ, data = imapclient.fetch(num, '(RFC822)')
msg = email.message_from_bytes(data[0][1])
msg_list.append(msg)
imapclient.close()
imapclient.logout()
# (4) メール解析(各ヘッダ情報や本文を取得する)
for msg in msg_list:
# ヘッダ情報は、ディクショナリのようにアクセスできる
# str(make_header(decode_header(msg["From"])))
payload = msg.get_payload(decode=True)
charset = msg.get_content_charset()
if charset is not None:
payload = payload.decode(charset,
"ignore")
print(payload) # 本文表示
import email
import ssl
import imaplib
from email.header import decode_header, make_header
# (1) IMAP4クライアントインスタンスを作成する
host = "imap.gmail.com"
port = 993
context = ssl.create_default_context()
imapclient = imaplib.IMAP4_SSL(host, port, ssl_context=context)
# (2) IMAPサーバーにログインする
username = "username@gmail.com"
password = "password"
imapclient.login(username, password)
メール受信サンプルコード(1/1)
# (3) メール受信
imapclient.select()
typ, data = imapclient.search(None, "ALL")
datas = data[0].split() #datas = [b’1’, b’2’, ...]
fetch_num = 5 # 取得したいメッセージの数
msg_list = [] # 取得したMIMEメッセージを格納するリスト
for num in datas[len(datas)-fetch_num::]:
typ, data = imapclient.fetch(num, '(RFC822)')
msg = email.message_from_bytes(data[0][1])
msg_list.append(msg)
imapclient.close()
imapclient.logout()
# (4) メール解析(各ヘッダ情報や本文を取得する)
for msg in msg_list:
# ヘッダ情報は、ディクショナリのようにアクセスできる
# str(make_header(decode_header(msg["From"])))
payload = msg.get_payload(decode=True)
charset = msg.get_content_charset()
if charset is not None:
payload = payload.decode(charset,
"ignore")
print(payload) # 本文表示
目次
1. メールの説明
2. Pythonでメールを送信する
3. Pythonでメールを受信する
4. メールを解析してコマンドを実行する
システム概要(おさらい)
(1) メール送信
メールサーバ
自宅
(2) メール受信
(4) 実行結果をメール返信
(3) メール解析&
コマンド実行
(5) 返信受信
ラズパイ宛に送るメール仕様
件名が#raspiのメールはラズパイ宛のメール
と判定させる
本文1行目は認証用の文字列とする
(誤って勝手に実行されるのを防ぐ)
本文2行目に、ラズパイに実行させたいコマンドを書く
ラズパイは定期的にメールサーバにアクセスし、この仕様のメールが存在するか確認し続ける
(存在したらコマンドを実行して、実行結果を返信する)
作る
作った
def main():
# (1) メールサーバにラズパイ宛のメールが存在するか探す
result = search_command()
if result is False:
return
command, reply_address = result
# (2) コマンドを実行する
out, err = execute_command(command)
# (3) コマンドの実行結果を返信する
sendmail(command, out+err, reply_address)
if __name__ == "__main__":
import time
while True:
main()
time.sleep(5*60)
詳細はGitHubGistに…
https://gist.github.com/taketakeyyy/f5b80b1ae04bf24cbef1c076ee73ab09
def main():
# (1) メールサーバにラズパイ宛のメールが存在するか探す
result = search_command()
if result is False:
return
command, reply_address = result
# (2) コマンドを実行する
out, err = execute_command(command)
# (3) コマンドの実行結果を返信する
sendmail(command, out+err, reply_address)
if __name__ == "__main__":
import time
while True:
main()
time.sleep(5*60)
search_command()
search_command()
(1) IMAP4サーバにアクセスする
(2) 適当個数メールをフェッチする(3個程度)
(3) フェッチしたメールの中にラズパイ宛のメールが存在するか確認する
(a) Subjectヘッダが#raspiか?
(b) payload部の1行目が認証用文字列と一致するか?
(4) ラズパイ宛のメールが存在するならば、
(a) payload部の2行目を返す(実行するコマンド)
(b) 返信先用に、Fromヘッダのメールアドレスも返す
(c) サーバ上からこのメールを削除する(次回実行時同じことをしないように)
(5) ラズパイ宛のメールが存在しないならば、
(a) Falseを返して終了
execute_command()
def main():
# (1) メールサーバにラズパイ宛のメールが存在するか探す
result = search_command()
if result is False:
return
command, reply_address = result
# (2) コマンドを実行する
out, err = execute_command(command)
# (3) コマンドの実行結果を返信する
sendmail(command, out+err, reply_address)
if __name__ == "__main__":
import time
while True:
main()
time.sleep(5*60)
import subprocess
def execute_command(command):
""" コマンドを実行する"""
p = subprocess.run(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env={'LANG':'C'},
shell=True
)
return p.stdout.decode("utf-8", "ignore"), p.stderr.decode("utf-8", "ignore")
subprocess.run()はシェルコマンドを実行するモジュール
実行結果と実行時のエラーを返している
execute_command()
sendmail(command, out+err, reply_address)
def main():
# (1) メールサーバにラズパイ宛のメールが存在するか探す
result = search_command()
if result is False:
return
command, reply_address = result
# (2) コマンドを実行する
out, err = execute_command(command)
# (3) コマンドの実行結果を返信する
sendmail(command, out+err, reply_address)
if __name__ == "__main__":
import time
while True:
main()
time.sleep(5*60)
(1) commandは実行したコマンド
○ 件名が「commandの実行結果」になるようにする
(2) out+errは実行結果または実行時エラーメッセージ
○ 本文に実行結果を記載する
(3) reply_addressは返信先アドレス
○ ラズパイはreply_address宛にメールを送信する
sendmail(command, out+err, reply_address)
デモ動画なくてごめんなさい
実行例
ラズパイへ送ったメール ラズパイからの返信メール
systemctl status
takey@gmail.com
ラズパイへ送ったメール ラズパイからの返信メール
ifconfig
takey@gmail.com
ラズパイへ送ったメール ラズパイからの返信メール
gpio readall
takey@gmail.com
できた…
メリット
● 無料
● かんたん
デメリット
● 即応性がない
○ 5分間隔でサーバにアクセス
→応答に最大5分かかる
● コマンド一回一回打つのしんどい
○ あらかじめバッチ処理を用意しとけばある
程度使い物になる予感
メリット/デメリット
Thanks!!

Mais conteúdo relacionado

Semelhante a Hannari python10 20181019

MailFluteでメール送信を楽しもう!
MailFluteでメール送信を楽しもう!MailFluteでメール送信を楽しもう!
MailFluteでメール送信を楽しもう!p1us2er0
 
Enable Skype to favorite the messages
Enable Skype to favorite the messagesEnable Skype to favorite the messages
Enable Skype to favorite the messagesdaipanchi
 
10080分でPythonからIP Messeneger
10080分でPythonからIP Messeneger10080分でPythonからIP Messeneger
10080分でPythonからIP MessenegerSatoshi Yamada
 
#logstudy 01 rsyslog入門
#logstudy 01 rsyslog入門#logstudy 01 rsyslog入門
#logstudy 01 rsyslog入門Takashi Takizawa
 
#mailerstudy 01 LT POP/IMAP入門
#mailerstudy 01 LT POP/IMAP入門#mailerstudy 01 LT POP/IMAP入門
#mailerstudy 01 LT POP/IMAP入門Takashi Takizawa
 
STNSサーバーを書いてみた
STNSサーバーを書いてみたSTNSサーバーを書いてみた
STNSサーバーを書いてみたYoshinori Teraoka
 
AWS Simple Email Service詳細 -ほぼ週刊AWSマイスターシリーズ第11回-
AWS Simple Email Service詳細 -ほぼ週刊AWSマイスターシリーズ第11回-AWS Simple Email Service詳細 -ほぼ週刊AWSマイスターシリーズ第11回-
AWS Simple Email Service詳細 -ほぼ週刊AWSマイスターシリーズ第11回-SORACOM, INC
 
Thunderbird 3のご紹介と企業に求められるカスタマイズ
Thunderbird 3のご紹介と企業に求められるカスタマイズThunderbird 3のご紹介と企業に求められるカスタマイズ
Thunderbird 3のご紹介と企業に求められるカスタマイズMakoto Kato
 
SESとLambdaでメールをSlackに通知してみよう
SESとLambdaでメールをSlackに通知してみようSESとLambdaでメールをSlackに通知してみよう
SESとLambdaでメールをSlackに通知してみようKen'ichirou Kimura
 
Html5 Web Applications
Html5  Web ApplicationsHtml5  Web Applications
Html5 Web Applicationstotty jp
 
2012/06/28 #ssmjp
2012/06/28 #ssmjp2012/06/28 #ssmjp
2012/06/28 #ssmjpth0x0472
 
資料2:メールシステム移行ご説明資料 0.7c版 メール設定
資料2:メールシステム移行ご説明資料 0.7c版 メール設定資料2:メールシステム移行ご説明資料 0.7c版 メール設定
資料2:メールシステム移行ご説明資料 0.7c版 メール設定Kousaku Okubo
 
【19-C-L】Web開発者ならおさえておきたい「常時SSL/TLS化の実装ポイント」
【19-C-L】Web開発者ならおさえておきたい「常時SSL/TLS化の実装ポイント」【19-C-L】Web開発者ならおさえておきたい「常時SSL/TLS化の実装ポイント」
【19-C-L】Web開発者ならおさえておきたい「常時SSL/TLS化の実装ポイント」Developers Summit
 
Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyotoGo言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyotoShoot Morii
 
高トランザクションシステムとしてのメールシステム
高トランザクションシステムとしてのメールシステム高トランザクションシステムとしてのメールシステム
高トランザクションシステムとしてのメールシステムIIJ
 

Semelhante a Hannari python10 20181019 (20)

MailFluteでメール送信を楽しもう!
MailFluteでメール送信を楽しもう!MailFluteでメール送信を楽しもう!
MailFluteでメール送信を楽しもう!
 
Enable Skype to favorite the messages
Enable Skype to favorite the messagesEnable Skype to favorite the messages
Enable Skype to favorite the messages
 
10080分でPythonからIP Messeneger
10080分でPythonからIP Messeneger10080分でPythonからIP Messeneger
10080分でPythonからIP Messeneger
 
#logstudy 01 rsyslog入門
#logstudy 01 rsyslog入門#logstudy 01 rsyslog入門
#logstudy 01 rsyslog入門
 
#mailerstudy 01 LT POP/IMAP入門
#mailerstudy 01 LT POP/IMAP入門#mailerstudy 01 LT POP/IMAP入門
#mailerstudy 01 LT POP/IMAP入門
 
STNSサーバーを書いてみた
STNSサーバーを書いてみたSTNSサーバーを書いてみた
STNSサーバーを書いてみた
 
AWS Simple Email Service詳細 -ほぼ週刊AWSマイスターシリーズ第11回-
AWS Simple Email Service詳細 -ほぼ週刊AWSマイスターシリーズ第11回-AWS Simple Email Service詳細 -ほぼ週刊AWSマイスターシリーズ第11回-
AWS Simple Email Service詳細 -ほぼ週刊AWSマイスターシリーズ第11回-
 
AWS Black Belt Techシリーズ Amazon SES
AWS Black Belt Techシリーズ  Amazon SESAWS Black Belt Techシリーズ  Amazon SES
AWS Black Belt Techシリーズ Amazon SES
 
20111207 11 aws-meister-ses-public
20111207 11 aws-meister-ses-public20111207 11 aws-meister-ses-public
20111207 11 aws-meister-ses-public
 
Thunderbird 3のご紹介と企業に求められるカスタマイズ
Thunderbird 3のご紹介と企業に求められるカスタマイズThunderbird 3のご紹介と企業に求められるカスタマイズ
Thunderbird 3のご紹介と企業に求められるカスタマイズ
 
SESとLambdaでメールをSlackに通知してみよう
SESとLambdaでメールをSlackに通知してみようSESとLambdaでメールをSlackに通知してみよう
SESとLambdaでメールをSlackに通知してみよう
 
BBBBB
BBBBBBBBBB
BBBBB
 
1MB
1MB1MB
1MB
 
Html5 Web Applications
Html5  Web ApplicationsHtml5  Web Applications
Html5 Web Applications
 
2012/06/28 #ssmjp
2012/06/28 #ssmjp2012/06/28 #ssmjp
2012/06/28 #ssmjp
 
資料2:メールシステム移行ご説明資料 0.7c版 メール設定
資料2:メールシステム移行ご説明資料 0.7c版 メール設定資料2:メールシステム移行ご説明資料 0.7c版 メール設定
資料2:メールシステム移行ご説明資料 0.7c版 メール設定
 
【19-C-L】Web開発者ならおさえておきたい「常時SSL/TLS化の実装ポイント」
【19-C-L】Web開発者ならおさえておきたい「常時SSL/TLS化の実装ポイント」【19-C-L】Web開発者ならおさえておきたい「常時SSL/TLS化の実装ポイント」
【19-C-L】Web開発者ならおさえておきたい「常時SSL/TLS化の実装ポイント」
 
Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyotoGo言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
 
高トランザクションシステムとしてのメールシステム
高トランザクションシステムとしてのメールシステム高トランザクションシステムとしてのメールシステム
高トランザクションシステムとしてのメールシステム
 
01 php7
01   php701   php7
01 php7
 

Hannari python10 20181019

  • 1.
  • 6. メールのすごいところ ● 環境を整備する必要なし ○ インフラ化している ● フリーメール ○ 無料 ○ アカウント作りたい放題 ○ SSL/TLSで暗号化できる ● スマホやPCなど端末を選ばず操作可能
  • 7. システム概要 (1) メール送信 メールサーバ 自宅 (2) メール受信 (4) 実行結果をメール返信 (3) メール解析& コマンド実行 (5) 返信受信
  • 8. 目次 1. メールの説明 2. Pythonでメールを送信する 3. Pythonでメールを受信する 4. メールを解析してコマンドを実行する
  • 9. 目次 1. メールの説明 2. Pythonでメールを送信する 3. Pythonでメールを受信する 4. メールを解析してコマンドを実行する
  • 10. メールプロトコル ● SMTP ○ 送信用のプロトコル ● POP3 ○ 受信用のプロトコル(ローカルにダウンロードして閲覧) ○ Thunderbird, Outlookなど ● IMAP4 ○ 受信用のプロトコル(サーバで閲覧) ○ Gmail, Yahoo!メールなど
  • 11. メールプロトコル ● SMTP ○ 送信用のプロトコル ● POP3 ○ 受信用のプロトコル(ローカルにダウンロードして閲覧) ○ Thunderbird, Outlookなど ● IMAP4 ○ 受信用のプロトコル(サーバで閲覧) ○ Gmail, Yahoo!メールなど
  • 12.
  • 13. 目次 1. メールの説明 2. Pythonでメールを送信する 3. Pythonでメールを受信する 4. メールを解析してコマンドを実行する
  • 15. Gmail ホスト名: smtp.gmail.com 通信方式:STARTTLS, SSL/TLS ※必ず暗号化必須 Yahoo!メール ホスト名: smtp.mail.yahoo.co.jp 通信方式:暗号化なし, SSL/TLS 国内のフリーメール
  • 17. 主なライブラリ ● smtplib (https://docs.python.jp/3/library/smtplib.html) ○ smtpプロトコル機能を提供するライブラリ(メール送信できるライブラリ) ● email.mime (https://docs.python.jp/3/library/email.mime.html) ○ MIMEメッセージを作成するライブラリ MIMEメッセージとは、メールシステム上で扱えるようにした データのこと メールとは、MIMEメッセージのやりとりと言える
  • 18. 処理の流れ 1. MIMEメッセージを作成する ○ メール用のデータを作成! 2. MIMEメッセージに必要なヘッダ情報を付与する ○ FromとかToとか! 3. SMTPクライアントインスタンスを作成する ○ メール送信の準備! 4. SMTPサーバにログインする ○ 認証! 5. メール送信(MIMEメッセージを送信する)
  • 19. import base64 import smtplib import ssl from email.mime.text import MIMEText from email.utils import formatdate # (1) MIMEメッセージを作成する main_text = "これが本文です" charset = “utf-8” msg = MIMEText(main_text, "plain", charset) メール送信サンプルコード(1/2) # (2) MIMEメッセージに必要なヘッダを付ける msg.replace_header("Content-Transfer-Encoding", "base64") msg["Subject"] = "これが件名です" msg["From"] = "from@gmail.com" msg["To"] = "to@gmail.com" msg["Cc"] = "" msg["Bcc"] = "" msg["Date"] = formatdate(None,True)
  • 20. import base64 import smtplib import ssl from email.mime.text import MIMEText from email.utils import formatdate # (1) MIMEメッセージを作成する main_text = "これが本文です" charset = “utf-8” msg = MIMEText(main_text, "plain", charset) メール送信サンプルコード(1/2) # (2) MIMEメッセージに必要なヘッダを付ける msg.replace_header("Content-Transfer-Encoding", "base64") msg["Subject"] = "これが件名です" msg["From"] = "from@gmail.com" msg["To"] = "to@gmail.com" msg["Cc"] = "" msg["Bcc"] = "" msg["Date"] = formatdate(None,True)
  • 21. import base64 import smtplib import ssl from email.mime.text import MIMEText from email.utils import formatdate # (1) MIMEメッセージを作成する main_text = "これが本文です" charset = “utf-8” msg = MIMEText(main_text, "plain", charset) メール送信サンプルコード(1/2) # (2) MIMEメッセージに必要なヘッダを付ける msg.replace_header("Content-Transfer-Encoding", "base64") msg["Subject"] = "これが件名です" msg["From"] = "from@gmail.com" msg["To"] = "to@gmail.com" msg["Cc"] = "" msg["Bcc"] = "" msg["Date"] = formatdate(None,True)
  • 22. # (3) SMTPクライアントインスタンスを作成する host = "smtp.gmail.com" port = 587 smtpclient = smtplib.SMTP(host, port, timeout=10) smtpclient.ehlo() smtpclient.starttls() smtpclient.ehlo() メール送信サンプルコード(2/2) # (4) SMTPサーバにログインする user = "from@gmail.com" password = "password" smtpclient.login(user, password) # (5) メールを送信する smtpclient.send_message(msg) smtpclient.quit()
  • 23. # (3) SMTPクライアントインスタンスを作成する host = "smtp.gmail.com" port = 587 smtpclient = smtplib.SMTP(host, port, timeout=10) smtpclient.ehlo() smtpclient.starttls() smtpclient.ehlo() メール送信サンプルコード(2/2) # (4) SMTPサーバにログインする user = "from@gmail.com" password = "password" smtpclient.login(user, password) # (5) メールを送信する smtpclient.send_message(msg) smtpclient.quit()
  • 24. # (3) SMTPクライアントインスタンスを作成する host = "smtp.gmail.com" port = 587 smtpclient = smtplib.SMTP(host, port, timeout=10) smtpclient.ehlo() smtpclient.starttls() smtpclient.ehlo() メール送信サンプルコード(2/2) # (4) SMTPサーバにログインする user = "from@gmail.com" password = "password" smtpclient.login(user, password) # (5) メールを送信する smtpclient.send_message(msg) smtpclient.quit()
  • 25. # (3) SMTPクライアントインスタンスを作成する host = "smtp.gmail.com" port = 587 smtpclient = smtplib.SMTP(host, port, timeout=10) smtpclient.ehlo() smtpclient.starttls() smtpclient.ehlo() メール送信サンプルコード(2/2) # (4) SMTPサーバにログインする user = "from@gmail.com" password = "password" smtpclient.login(user, password) # (5) メールを送信する smtpclient.send_message(msg) smtpclient.quit()
  • 26. 目次 1. メールの説明 2. Pythonでメールを送信する 3. Pythonでメールを受信する 4. メールを解析してコマンドを実行する
  • 28. 主なライブラリ ● imaplib (https://docs.python.jp/3/library/imaplib.html) ○ imap4プロトコル機能を提供するライブラリ(メール受信できるライブラリ) ● email.header (https://docs.python.jp/3/library/email.header.html) ○ MIMEメッセージのヘッダを解析するライブラリ ○ FromヘッダとかSubjectヘッダとかを取り出すのに便利
  • 29. 処理の流れ 1. IMAP4クライアントインスタンスを作成する ○ メール受信の準備! 2. IMAP4サーバにログインする ○ 認証! 3. メール受信(MIMEメッセージを受信する) 4. メール解析 ○ 件名とか、本文とかをデコードする!
  • 30. import email import ssl import imaplib from email.header import decode_header, make_header # (1) IMAP4クライアントインスタンスを作成する host = "imap.gmail.com" port = 993 context = ssl.create_default_context() imapclient = imaplib.IMAP4_SSL(host, port, ssl_context=context) # (2) IMAPサーバーにログインする username = "username@gmail.com" password = "password" imapclient.login(username, password) メール受信サンプルコード(1/1) # (3) メール受信 imapclient.select() typ, data = imapclient.search(None, "ALL") datas = data[0].split() #datas = [b’1’, b’2’, ...] fetch_num = 5 # 取得したいメッセージの数 msg_list = [] # 取得したMIMEメッセージを格納するリスト for num in datas[len(datas)-fetch_num::]: typ, data = imapclient.fetch(num, '(RFC822)') msg = email.message_from_bytes(data[0][1]) msg_list.append(msg) imapclient.close() imapclient.logout() # (4) メール解析(各ヘッダ情報や本文を取得する) for msg in msg_list: # ヘッダ情報は、ディクショナリのようにアクセスできる # str(make_header(decode_header(msg["From"]))) payload = msg.get_payload(decode=True) charset = msg.get_content_charset() if charset is not None: payload = payload.decode(charset, "ignore") print(payload) # 本文表示
  • 31. import email import ssl import imaplib from email.header import decode_header, make_header # (1) IMAP4クライアントインスタンスを作成する host = "imap.gmail.com" port = 993 context = ssl.create_default_context() imapclient = imaplib.IMAP4_SSL(host, port, ssl_context=context) # (2) IMAPサーバーにログインする username = "username@gmail.com" password = "password" imapclient.login(username, password) メール受信サンプルコード(1/1) # (3) メール受信 imapclient.select() typ, data = imapclient.search(None, "ALL") datas = data[0].split() #datas = [b’1’, b’2’, ...] fetch_num = 5 # 取得したいメッセージの数 msg_list = [] # 取得したMIMEメッセージを格納するリスト for num in datas[len(datas)-fetch_num::]: typ, data = imapclient.fetch(num, '(RFC822)') msg = email.message_from_bytes(data[0][1]) msg_list.append(msg) imapclient.close() imapclient.logout() # (4) メール解析(各ヘッダ情報や本文を取得する) for msg in msg_list: # ヘッダ情報は、ディクショナリのようにアクセスできる # str(make_header(decode_header(msg["From"]))) payload = msg.get_payload(decode=True) charset = msg.get_content_charset() if charset is not None: payload = payload.decode(charset, "ignore") print(payload) # 本文表示
  • 32. import email import ssl import imaplib from email.header import decode_header, make_header # (1) IMAP4クライアントインスタンスを作成する host = "imap.gmail.com" port = 993 context = ssl.create_default_context() imapclient = imaplib.IMAP4_SSL(host, port, ssl_context=context) # (2) IMAPサーバーにログインする username = "username@gmail.com" password = "password" imapclient.login(username, password) メール受信サンプルコード(1/1) # (3) メール受信 imapclient.select() typ, data = imapclient.search(None, "ALL") datas = data[0].split() #datas = [b’1’, b’2’, ...] fetch_num = 5 # 取得したいメッセージの数 msg_list = [] # 取得したMIMEメッセージを格納するリスト for num in datas[len(datas)-fetch_num::]: typ, data = imapclient.fetch(num, '(RFC822)') msg = email.message_from_bytes(data[0][1]) msg_list.append(msg) imapclient.close() imapclient.logout() # (4) メール解析(各ヘッダ情報や本文を取得する) for msg in msg_list: # ヘッダ情報は、ディクショナリのようにアクセスできる # str(make_header(decode_header(msg["From"]))) payload = msg.get_payload(decode=True) charset = msg.get_content_charset() if charset is not None: payload = payload.decode(charset, "ignore") print(payload) # 本文表示
  • 33. import email import ssl import imaplib from email.header import decode_header, make_header # (1) IMAP4クライアントインスタンスを作成する host = "imap.gmail.com" port = 993 context = ssl.create_default_context() imapclient = imaplib.IMAP4_SSL(host, port, ssl_context=context) # (2) IMAPサーバーにログインする username = "username@gmail.com" password = "password" imapclient.login(username, password) メール受信サンプルコード(1/1) # (3) メール受信 imapclient.select() typ, data = imapclient.search(None, "ALL") datas = data[0].split() #datas = [b’1’, b’2’, ...] fetch_num = 5 # 取得したいメッセージの数 msg_list = [] # 取得したMIMEメッセージを格納するリスト for num in datas[len(datas)-fetch_num::]: typ, data = imapclient.fetch(num, '(RFC822)') msg = email.message_from_bytes(data[0][1]) msg_list.append(msg) imapclient.close() imapclient.logout() # (4) メール解析(各ヘッダ情報や本文を取得する) for msg in msg_list: # ヘッダ情報は、ディクショナリのようにアクセスできる # str(make_header(decode_header(msg["From"]))) payload = msg.get_payload(decode=True) charset = msg.get_content_charset() if charset is not None: payload = payload.decode(charset, "ignore") print(payload) # 本文表示
  • 34. import email import ssl import imaplib from email.header import decode_header, make_header # (1) IMAP4クライアントインスタンスを作成する host = "imap.gmail.com" port = 993 context = ssl.create_default_context() imapclient = imaplib.IMAP4_SSL(host, port, ssl_context=context) # (2) IMAPサーバーにログインする username = "username@gmail.com" password = "password" imapclient.login(username, password) メール受信サンプルコード(1/1) # (3) メール受信 imapclient.select() typ, data = imapclient.search(None, "ALL") datas = data[0].split() #datas = [b’1’, b’2’, ...] fetch_num = 5 # 取得したいメッセージの数 msg_list = [] # 取得したMIMEメッセージを格納するリスト for num in datas[len(datas)-fetch_num::]: typ, data = imapclient.fetch(num, '(RFC822)') msg = email.message_from_bytes(data[0][1]) msg_list.append(msg) imapclient.close() imapclient.logout() # (4) メール解析(各ヘッダ情報や本文を取得する) for msg in msg_list: # ヘッダ情報は、ディクショナリのようにアクセスできる # str(make_header(decode_header(msg["From"]))) payload = msg.get_payload(decode=True) charset = msg.get_content_charset() if charset is not None: payload = payload.decode(charset, "ignore") print(payload) # 本文表示
  • 35. 目次 1. メールの説明 2. Pythonでメールを送信する 3. Pythonでメールを受信する 4. メールを解析してコマンドを実行する
  • 36. システム概要(おさらい) (1) メール送信 メールサーバ 自宅 (2) メール受信 (4) 実行結果をメール返信 (3) メール解析& コマンド実行 (5) 返信受信
  • 39. 作った def main(): # (1) メールサーバにラズパイ宛のメールが存在するか探す result = search_command() if result is False: return command, reply_address = result # (2) コマンドを実行する out, err = execute_command(command) # (3) コマンドの実行結果を返信する sendmail(command, out+err, reply_address) if __name__ == "__main__": import time while True: main() time.sleep(5*60) 詳細はGitHubGistに… https://gist.github.com/taketakeyyy/f5b80b1ae04bf24cbef1c076ee73ab09
  • 40. def main(): # (1) メールサーバにラズパイ宛のメールが存在するか探す result = search_command() if result is False: return command, reply_address = result # (2) コマンドを実行する out, err = execute_command(command) # (3) コマンドの実行結果を返信する sendmail(command, out+err, reply_address) if __name__ == "__main__": import time while True: main() time.sleep(5*60) search_command()
  • 41. search_command() (1) IMAP4サーバにアクセスする (2) 適当個数メールをフェッチする(3個程度) (3) フェッチしたメールの中にラズパイ宛のメールが存在するか確認する (a) Subjectヘッダが#raspiか? (b) payload部の1行目が認証用文字列と一致するか? (4) ラズパイ宛のメールが存在するならば、 (a) payload部の2行目を返す(実行するコマンド) (b) 返信先用に、Fromヘッダのメールアドレスも返す (c) サーバ上からこのメールを削除する(次回実行時同じことをしないように) (5) ラズパイ宛のメールが存在しないならば、 (a) Falseを返して終了
  • 42. execute_command() def main(): # (1) メールサーバにラズパイ宛のメールが存在するか探す result = search_command() if result is False: return command, reply_address = result # (2) コマンドを実行する out, err = execute_command(command) # (3) コマンドの実行結果を返信する sendmail(command, out+err, reply_address) if __name__ == "__main__": import time while True: main() time.sleep(5*60)
  • 43. import subprocess def execute_command(command): """ コマンドを実行する""" p = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env={'LANG':'C'}, shell=True ) return p.stdout.decode("utf-8", "ignore"), p.stderr.decode("utf-8", "ignore") subprocess.run()はシェルコマンドを実行するモジュール 実行結果と実行時のエラーを返している execute_command()
  • 44. sendmail(command, out+err, reply_address) def main(): # (1) メールサーバにラズパイ宛のメールが存在するか探す result = search_command() if result is False: return command, reply_address = result # (2) コマンドを実行する out, err = execute_command(command) # (3) コマンドの実行結果を返信する sendmail(command, out+err, reply_address) if __name__ == "__main__": import time while True: main() time.sleep(5*60)
  • 45. (1) commandは実行したコマンド ○ 件名が「commandの実行結果」になるようにする (2) out+errは実行結果または実行時エラーメッセージ ○ 本文に実行結果を記載する (3) reply_addressは返信先アドレス ○ ラズパイはreply_address宛にメールを送信する sendmail(command, out+err, reply_address)
  • 51. メリット ● 無料 ● かんたん デメリット ● 即応性がない ○ 5分間隔でサーバにアクセス →応答に最大5分かかる ● コマンド一回一回打つのしんどい ○ あらかじめバッチ処理を用意しとけばある 程度使い物になる予感 メリット/デメリット