RaspberryPI - Externe IP via Email empfangen

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
ser_u
User
Beiträge: 2
Registriert: Sonntag 29. März 2015, 09:21

Hallo!

Bin neu hier im Forum und hoffe ich bin hier richtig mit meinem Anliegen!

Hab für mein Raspberry Pi (raspbian) ein Skript geschrieben, das mir via sendEmail die externe IP-Adresse des Raspberry Pi schickt, sobald diese sich ändert.

Da ich noch nicht so viel Erfahrung mit Linux und Python habe, würde ich gerne wissen ob sich am Code etwas verbessern lässt und ob es "sauber" programmiert ist.

Bin für Vorschläge offen! Danke schonmal!

Code: Alles auswählen

#!/usr/bin/python3
  
import os, time
    
def getIP():
        os.system('dig +short myip.opendns.com @resolver1.opendns.com > raspip.txt')
        with open('raspip.txt', 'r') as f:
                return f.readline().rstrip('\n')
    
def sendIP(currentIP):
        os.system('sendEmail '                            +  #sendEmail Applikation
                  '-o tls=yes '                           +  #use TLS
                  '-f \'***@outlook.com\' '               +  #Sender
                  '-t \'***@outlook.com\' '               +  #Empfänger
                  '-s \'smtp.live.com\' '                 +  #SMTP Server
                  '-xu \'***@outlook.com\' '              +  #user
                  '-xp \'**password**\' '                 +  #password
                  '-u \"raspberry via python\" '          +  #Betreff
                  '-m \"' + currentIP + '\"')                #Inhalt
    
def main():
        lastIP = None
        while (True):
                currentIP = getIP()
                if (lastIP != currentIP):
                        sendIP(currentIP)
                        lastIP = currentIP
                time.sleep(60)
    
    
if __name__ == "__main__":
         main()
Gruß, ser_u
BlackJack

@ser_u: `os.system()` sollte man nicht mehr verwenden, dafür gibt es das `subprocess`-Modul. Da kann man sich dann auch sparen die IP in eine Datei zu schreiben.

Bezüglich Einrückung und Namensschreibweisen könntest Du mal einen Blick in den Style Guide for Python Code werfen.

Literale Zeichenketten kann man in Python ja in ' oder in " setzen, mit dem netten Nebeneffekt das man die jeweils andere Variante *innerhalb* der Zeichenkette *nicht* durch \ schützen muss. Wobei das bei der Verwendung von `subprocess` sowieso weg fällt denn die ' oder " sind ja nur dazu da um Zeichen wie Leerzeichen vor der Shell zu schützen die bei `os.system()` zwischen den beiden Prozessen steht.

Werte in Zeichenketten einsetzen ist in Python eher etwas für die `format()`-Methode auf Zeichenketten und nicht für ``+``. Die ``+`` an den Zeilenenden in `sendIP() sind überflüssig denn literale Zeichenketten die nur durch „whitespace”-Zeichen getrennt sind, werden schon vom Compiler zu *einer* Zeichenkette zusammengesetzt.

Die Klammern um die Bedingungen bei ``while`` und ``if`` sind überflüssig.

Ich hätte das so nicht in Python geschrieben denn eigentlich ist es kein Python. Das besteht hauptsächlich aus externen Aufrufen und das bisschen Logik liesse sich als Shell-Skript genau so leicht ausdrücken.
ser_u
User
Beiträge: 2
Registriert: Sonntag 29. März 2015, 09:21

Danke für die Tipps!

Werd mich mal mit Shell Scripting befassen.
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Hallo ser_u,
ich hatte das vor einiger Zeit mal so gelöst.

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import json
import os
import smtplib
import socket
import sys

from argparse import ArgumentParser
from datetime import datetime
from email.mime.text import MIMEText
from tempfile import gettempdir
from urllib.request import urlopen


IP_FILE = os.path.join(gettempdir(), 'WAN-IP')
REALIP_URL = 'http://www.realip.info/api/p/realip.php'
DOMAIN = 'your.freedns.domain'
UPDATE_URL = ('http://freedns.afraid.org/dynamic/update.php?'
              'xxx-token-xxx')
MAIL_HOST = 'smtp.example.org'
MAIL_PORT = 465
MAIL_USER = 'sender@example.org'
MAIL_PASSWORD = 'xxx'
MAIL_TO = 'recipient@example.org'


def get_external_ip():
    try:
        with urlopen(REALIP_URL) as req:
            data = json.loads(req.read().decode('utf-8'))
        return data['IP'].strip()
    except:
        return ''


def get_registered_ip():
    ip = socket.gethostbyname(DOMAIN)
    return ip.strip()


def get_saved_ip():
    if os.path.isfile(IP_FILE):
        with open(IP_FILE) as fp:
            return fp.read().strip()


def save_ip(ip):
    with open(IP_FILE + '~', 'w') as fp:
        fp.write(ip)
    try:
        os.remove(IP_FILE)
    except OSError:
        pass
    os.rename(IP_FILE + '~', IP_FILE)


def update_dns():
    with urlopen(UPDATE_URL) as req:
        data = req.read()


def send_mail(ip):
    now = datetime.now()
    msg = MIMEText('Neue externe IP-Adresse: {}'.format(ip))
    msg['Subject'] = '[IP] RasPi2MM {:%d.%m.%Y %H:%M}'.format(now)
    msg['From'] = MAIL_USER
    msg['To'] = MAIL_TO
    smtp = smtplib.SMTP_SSL(MAIL_HOST, MAIL_PORT)
    smtp.login(MAIL_USER, MAIL_PASSWORD)
    smtp.sendmail(MAIL_USER, [MAIL_TO], msg.as_string())
    smtp.quit()


def main(send_update_mail, update_freedns, verbose):
    saved_ip = get_saved_ip()
    current_ip = get_external_ip()
    registered_ip = get_registered_ip()
    if verbose:
        print('Saved IP:', saved_ip)
        print('Registered IP:', registered_ip)
        print('Current IP:', current_ip)
    if (current_ip != registered_ip) and update_freedns:
        if verbose:
            print('Updating freedns entry')
        update_dns()
    if current_ip != saved_ip:
        if verbose:
            print('Saving current IP to', IP_FILE)
        save_ip(current_ip)
        if send_update_mail:
            if verbose:
                print('Sending mail to', MAIL_TO)
            send_mail(current_ip)


if __name__ == '__main__':
    p = ArgumentParser()
    p.add_argument('-u', '--update-dns', action='store_true', default=False,
                   dest='dns')
    p.add_argument('-m', '--send-mail', action='store_true', default=False,
                   dest='mail')
    p.add_argument('-v', '--verbose', action='store_true', default=False)
    args = p.parse_args()
    main(args.mail, args.dns, args.verbose)
Updated dann gleich noch meinen FreeDNS account. Das Skript lasse ich alle 10min per Systemd timer laufen (alternativ cron).

Gruß Whitie
Antworten