Notification when your dynamic IP changes


			Updated: November 23, 2010 04:09
A user has notified me that there is a small issue with the script in that it breaks if the user has not specified a mail [...]
Updated: November 23, 2010 04:09

A user has notified me that there is a small issue with the script in that it breaks if the user has not specified a mail server on the command line options. To fix this issue, please change the code as shown below:

        if server and from_address and to_address:
            password = getpass.getpass ("Password: ")
            mail (ip, server, from_address, to_address,
                  username, password)

I am sure I am not the only person out there who is running a website (or some kind of externally accessible server) on their home machine. I am also sure that I am not the only one doing the above with an Internet service that does not provide a static IP. As such, your IP can change at any point that the ISP’s servers deem necessary.

I know I have been in a situation where my assigned IP changes without me noticing and, all of a sudden, my website is not accessible anymore because the DNS servers point to the old IP address enough times that it was time for me to come up with some notification mechanism.

Below is a very short script that can be used to query one of the many online services that will return information about your connection, and email you the new IP address (if it has changed). Anyone with a Python installation on their server can download the script and create a cron job that will check the assigned IP periodically and send a notification when it changes.

#!/usr/bin/python
#
# Copyright (c) 2010 Mitko Haralanov. All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys
import httplib
import smtplib
import email.MIMEText as email
import getpass
import getopt
import socket
from os.path import basename

def get_old (filename):
    ip = None
    try:
        fd = open (filename, 'r')
        ip = fd.readline ().strip ()
        fd.close ()
    except IOError: pass
    return ip

def set_old (filename, ip):
    try:
        fd = open (filename, 'w')
        fd.write (ip.strip () + "\n")
        fd.close ()
    except IOError: pass

def mail (ip, mail_server, from_address, to_address,
          username=None, password=None):
    text = "External IP changed to: %s"%ip
    msg = email.MIMEText (text)
    msg["Subject"] = "IP Change"
    msg["To"] = to_address
    msg["From"] = from_address

    smtp = smtplib.SMTP (mail_server)
    if username and password:
        try: smtp.login (username, password)
        except (SMTPHeloError,
                SMTPAuthenticationError,
                SMTPException), e:
            print "Login error:",e
            smtp.quit ()
            return
    try:
        resp = smtp.sendmail (msg['From'], msg["To"],
                                msg.as_string ())
    except (smtplib.SMTPRecipientsRefused,
            smtplib.SMTPHeloError,
            smtplib.SMTPSenderRefused,
            smtplib.SMTPDataError), e:
        print "Sendmail Error:",e
    smtp.quit ()
    return

def usage (msg=None):
    _ = basename (sys.argv[0])
    if msg: print msg
    print _,"[-f <file>] [-s <smtp server>] [-o <from address>]"
    print " "*len (_),"[-e <to address>] [-u <username>] [-p <password>] [-h]"
    return

def main ():
    exip_file = ".exip"
    server = None
    from_address = None
    to_address = None
    username = None
    password = None

    try: opts, args = getopt.getopt (sys.argv[1:], "f:s:o:e:u:p:hdl:t:",
                                     [])
    except getopt.GetopError, e:
        usage (e)
        sys.exit (1)

    for opt, value in opts:
        if opt == '-f': exip_file = value
        if opt == '-s': server = value
        if opt == '-o': from_address = value
        if opt == '-e': to_address = value
        if opt == '-u': username = value
        if opt == '-p': password = value
        if opt == '-l': logfile = value
        if opt == '-h':
            usage ()
            sys.exit (0)

    old = get_old (exip_file)
    conn = httplib.HTTPConnection ("ifconfig.me")
    try: conn.request ("GET", "/all/json")
    except socket.error: return 1
    resp = conn.getresponse ()
    data = eval (resp.read ())
    ip = data.get ("ip_addr", None)
    if ip != old:
        password = getpass.getpass ("Password: ")
        mail (ip, server, from_address, to_address,
              username, password)
        set_old (exip_file, ip)
    return 0

if __name__ == "__main__":
    main ()

VN:F [1.9.13_1145]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.13_1145]
Rating: -1 (from 1 vote)