やること
- pythonにてグローバルIPとローカルIPを調べて、変更があればGMailでその内容を送信するスクリプトを作る
- タスクスケジューラで定期的にスクリプトを実行する
経緯
ipad proを買ったので、開発環境として使うために自宅のWindowsマシンをRDTで使用したいなぁと考えました。
ところが、自宅のPR-500KIはVPN対応しているのですが、光電話を契約していないため、グローバルIP変更通知機能が使えませんでした。
そこでRDTで接続するマシンからグローバルIPの変更を通知できるようにしました。
(ついでにWindowsマシンはDHCPなんでローカルIPも通知しています)
GMailのアプリパスワードの発行
GMailでSMTPによるメール送信をするためには、アプリパスワードを発行しておく必要があります。
- Googleアカウントにログインする
- 「Googleへのログイン」を選択
- 「アプリパスワード」を選択
- ページ下部の「アプリ パスワードを生成するアプリと端末を選択してください。」で次のように設定
- アプリを選択→「メール」
- 端末を選択→「Windowsマシン」
そうするとパスワードが発行されるのでそのパスワードをメモっておく。
スクリプト
スクリプトを作成する際に必要な知識については下記のサイトを参考にしました。
- GMailメールの送信方法
- IPアドレスの取得方法
- グローバルIPの取得方法
- loggingの使い方
import requests
import json
import socket
import smtplib
from email.mime.text import MIMEText
from email.utils import formatdate
import logging
from logging import getLogger, StreamHandler,FileHandler, Formatter
LOGGER = getLogger('NCG')
LOGGER.setLevel(logging.DEBUG)
# 送信済みのIPの保存先
IPINFO_FILE = "./send_ipaddress.json"
# IP変更チェック実行ログ保存先
LOG_FILE = "notification_change_ipaddress.log"
# Gmailの設定
# https://qiita.com/okhrn/items/630a87ce1a44778bbeb1
FROM_ADDRESS = 'GMailのアドレス'
MY_PASSWORD = 'アプリパスワード'
TO_ADDRESS = '送信先のアドレス'
BCC = ''
SUBJECT = 'IPアドレス変更メール'
SMTP_ADDRESS = "smtp.gmail.com"
SMTP_PORT = 587
def create_message(from_addr, to_addr, bcc_addrs, subject, body):
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = from_addr
msg['To'] = to_addr
msg['Bcc'] = bcc_addrs
msg['Date'] = formatdate()
return msg
def send(from_addr, to_addrs, msg):
smtpobj = smtplib.SMTP(SMTP_ADDRESS, SMTP_PORT)
smtpobj.ehlo()
smtpobj.starttls()
smtpobj.ehlo()
smtpobj.login(FROM_ADDRESS, MY_PASSWORD)
smtpobj.sendmail(from_addr, to_addrs, msg.as_string())
smtpobj.close()
def send_ipinfo(ipinfo):
to_addr = TO_ADDRESS
subject = SUBJECT
body = json.dumps(ipinfo)
msg = create_message(FROM_ADDRESS, to_addr, BCC, subject, body)
send(FROM_ADDRESS, to_addr, msg)
def get_global_ip():
url="http://inet-ip.info/json"
headers = {"content-type": "application/json"}
result = requests.get(url,headers)
data = result.json()
return data["IP"]
def get_json_from_file(ipinfo_file):
'''
JSONファイルの読み込み
'''
df ={}
try:
with open(ipinfo_file,"r") as f:
df = json.load(f)
except FileNotFoundError:
LOGGER.debug("file not found :"+ ipinfo_file)
finally:
pass
return df
def set_json_to_file(ipinfo_file,ipinfo):
'''
JSONファイルの書き込み
'''
with open(ipinfo_file,"w") as f:
json.dump(ipinfo,f,indent=4,ensure_ascii=False)
# IPを保存するJSONのカラム名定義
GLOBALIP="globalip"
LOCALIP="localip"
def notification_change_ipaddress(ipinfo_file):
"""
IPを調べて、前回メール送信した時と変わっていたら、再度新しいIP
アドレスをメール送信する
"""
LOGGER.debug('Check for address change')
prev = get_json_from_file(ipinfo_file)
if not prev :
prev={
GLOBALIP:"",
LOCALIP:""
}
# global ip取得
globalip = get_global_ip()
# local ip取得
localip = socket.gethostbyname_ex(socket.gethostname())
# チェック
if prev[GLOBALIP] != globalip or prev[LOCALIP] != list(localip) :
LOGGER.debug(' IPAddress change detected')
prev[GLOBALIP] = globalip
prev[LOCALIP] = localip
# mail送信
send_ipinfo(prev)
# 送信した内容をローカルに保存
set_json_to_file(ipinfo_file,prev)
if __name__ == "__main__":
# loggerの使い方は下記のサイトを参照
# https://qiita.com/mimitaro/items/9fa7e054d60290d13bfc
# logging handlerの生成
file_handler = FileHandler(LOG_FILE, 'a')
# handlerのログレベル設定(ハンドラが出力するエラーメッセージのレベル)
file_handler.setLevel(logging.DEBUG)
# ログ出力フォーマット設定
handler_format = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(handler_format)
LOGGER.addHandler(file_handler)
# IPAddressチェック
notification_change_ipaddress(IPINFO_FILE)
batファイルの作成
windowsでスクリプトとして実行しますので、batファイルを作成します。
なお、python実行環境としてはvirtualenvにて仮想環境を作って動作させます。
あらかじめ環境は作成しておきましょう
virtualenv env
また、「requests」を使用しますのでpipでインストールしましょう
.\env\Scripts\activate.bat
pip install requests
ここまで準備ができたらバッチファイルは次のようにします。
@echo off
call .\env\Scripts\activate.bat
python notification_change_ipaddress.py
batファイルとpythonのスクリプトは同じディレクトリに配置しておきます。
タスクスケジューラの設定
コルタナに「タスクスケジューラ」と打てばデスクトップアプリが見つかります。
-
「操作」タブを選択し、下部にある「新規」ボタンを押下
-
「プログラム/スクリプト」にbatファイルのパスを指定し、「開始」の欄にbatファイルを格納しているフォルダのパスを指定します
-
「トリガー」タブを選択し、「新規」ボタンを押下
これで1時間ごとにIPアドレスを調べて、変更があればGmailが送信されます。
メールの送信内容
メールの本文は次のようになります
{"globalip": "xxx.xxx.xxx.xx","localip": [
"送信されたマシン名",[],["192.168.xxx.xxx",
"192.168.xxx.xxx","192.168.xxx.xxx",
"192.168.xxx.xxx"]]}