Last active
October 19, 2018 07:18
-
-
Save taketakeyyy/f5b80b1ae04bf24cbef1c076ee73ab09 to your computer and use it in GitHub Desktop.
imaplibによるラズパイ遠隔操作のサンプルプログラム
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import email | |
import ssl | |
import subprocess | |
import imaplib | |
from email.header import decode_header, make_header | |
# https://docs.python.jp/3/library/imaplib.html | |
# [参考]https://qiita.com/ekzemplaro/items/a35e15865d57372f1d2b | |
# https://docs.python.jp/3.6/library/email.message.html | |
# https://docs.python.org/ja/3.7/library/email.compat32-message.html#module-email.message | |
# https://docs.python.jp/3.6/library/email.parser.html | |
RASPI_MAIL_USERNAME = "username@gmail.com" | |
RASPI_MAIL_PASSWORD = "password" | |
def main(): | |
# メールサーバにラズパイ宛のメールが存在するか探す | |
result = search_command() | |
if result is False: | |
return | |
command, reply_address = result | |
# コマンドを実行する | |
out, err = execute_command(command) | |
# コマンドの実行結果を返信する | |
sendmail(command, out+err, reply_address) | |
def search_command(): | |
"""メールサーバにアクセスして、ラズパイ用のメールが存在するか探す""" | |
# IMAP4クライアントインスタンスを作成する | |
host = "imap.gmail.com" | |
port = 993 | |
context = ssl.create_default_context() | |
imapclient = imaplib.IMAP4_SSL(host, port, ssl_context=context) | |
#imapclient.debug = 5 # 各命令をトレースする | |
# IMAPサーバーにログインする | |
username = RASPI_MAIL_USERNAME | |
password = RASPI_MAIL_PASSWORD | |
imapclient.login(username, password) | |
imapclient.select() | |
typ, data = imapclient.search(None, "ALL") # data = [b"1 2 3 4 ..."] | |
#typ, data = imapclient.search(None, "UNSEEN") | |
#typ, data = imapclient.search(None, "NEW") | |
#typ, data = imapclient.search(None, "SENTSINCE \"01-Apr-2018\"") | |
datas = data[0].split() | |
N = 3 # 取得するメッセージの数 | |
auth_password = "qwerty" # 認証用の文字列 | |
for num in datas[len(datas)-N::]: | |
typ, data = imapclient.fetch(num, '(RFC822)') | |
msg = email.message_from_bytes(data[0][1]) | |
# Subjectが#raspiなら遠隔操作を受け付ける | |
subject = str(make_header(decode_header(msg["Subject"]))) | |
if subject.lower() != "#raspi": | |
continue | |
# Multipartに対応させる | |
# 各パートのいずれかで、一行目が認証用の文字列ならOKとする | |
for part in msg.walk(): | |
payload = part.get_payload(decode=True) | |
if payload is None: | |
continue | |
charset = part.get_content_charset() | |
if charset is not None: | |
payload = payload.decode(charset, "ignore") | |
lines = payload.splitlines() | |
# メールの1行目が認証用の文字列と一致するか確認する | |
if lines[0] != auth_password: | |
continue | |
# 認証をパスしたら、メールをサーバ上から削除した後、ログアウトする | |
imapclient.store(num, "+FLAGS", r"(\Deleted)") | |
imapclient.close() | |
imapclient.logout() | |
# 2行目の文字列と、返信先のメールアドレスを返して終了 | |
return lines[1], str(make_header(decode_header(msg["From"]))) | |
imapclient.close() | |
imapclient.logout() | |
return False | |
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") | |
def sendmail(command, result, reply_address): | |
import smtplib | |
from email.mime.text import MIMEText | |
from email.utils import formatdate | |
# MIMEメッセージを作成する | |
main_text = "{}\n".format(result) | |
charset = "utf-8" | |
msg = MIMEText(main_text, "plain", charset) | |
# MIMEメッセージに必要なヘッダを付ける | |
msg.replace_header("Content-Transfer-Encoding", "base64") | |
msg["Subject"] = "{}の実行結果".format(command) | |
msg["From"] = RASPI_MAIL_USERNAME | |
msg["To"] = reply_address | |
msg["Date"] = formatdate(None, True) | |
# SMTPクライアントインスタンスを作成する | |
host = "smtp.gmail.com" | |
port = 587 | |
smtpclient = smtplib.SMTP(host, port, timeout=10) | |
smtpclient.ehlo() | |
smtpclient.starttls() | |
smtpclient.ehlo() | |
# サーバにログインする | |
username = RASPI_MAIL_USERNAME | |
password = RASPI_MAIL_PASSWORD | |
smtpclient.login(username, password) | |
# メールを送信する | |
smtpclient.send_message(msg) | |
smtpclient.quit() | |
if __name__ == "__main__": | |
main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment