Password expiration notification in python

I've seen several scripts to notify users of impending AD password expiration, but nearly all of them are vbs. Here's a script to accomplish the same goal using python-ldap.

#!/usr/bin/env python
"""
    password_notify.py:
        provides notification of active directory password expiration via email

"""

import sys
import time
import smtplib
import ldap
import syslog

ldaphost = 'HOST'
ldapbase = 'SEARCHBASE'
ldapfilter = '(&(objectCategory=person)(objectClass=user)(!(pwdLastSet=0)))'
ldapuser = 'USER'
ldappass = 'PASS'
mailhost = 'MAILHOST'
from_address = 'donotreply@YOURDOMAIN.COM'
expiry_days = 90
notify_days = 5 # days before expiration to start notification



msg_template = """\
To: %s
From: %s
Subject: Password Expiration Notification

This message is to notify you that your directory password will expire
%s . Please change it before that time using one of the following methods: 

1.) Reboot or logoff/logon your PC and follow the password change prompts.

2.) If you're a Webmail user, you can change your password from within webmail by choosing 
'Options' from the menu on the left, then clicking the 'Change Password' button 
near the bottom of the page. In the popup window that appears, type 'DOMAIN' (no quotes) 
into the field labled 'Domain', and populate the rest of the fields with your username,
old password, and new password twice.

3.) If you're currently logged into your PC _as yourself_, you can change your password
by pressing Ctrl-Alt-Del, and clicking the 'Change Password...' button

[ password guidelines here ]

You'll continue to receive this message each day until your password expires,
or until you reset it using one of the procedures above.

Thanks,

The Helpdesk
"""
def exit_with_error(errorstr, errno=2):
    """Print error to screen and exit"""
    print errorstr
    sys.exit(2)

def wintime_to_epoch(wintime):
    """Convert windows time stamps to epoch seconds"""
    return (int(wintime)-116444736000000000)/10000000 

def epoch_to_wintime(epoch_secs):
    """Convert unix epoc seconds to windows time units"""
    return (int(epoch_secs)*10000000)+116444736000000000
    
cur_win_time = epoch_to_wintime(time.time())

# explicitly open a syslog connection
syslog.openlog("password_notify.py")

# open a connection to the mail server
smail = smtplib.SMTP(mailhost)

# attempt to establish a connection to the ldap server
try:
    conn = ldap.open(ldaphost)
    conn.simple_bind_s(ldapuser, ldappass)
except:
    syslog.syslog("Error opening connection to %s" % ldaphost)
    exit_with_error("Ldap connection error") 

# grab the list of "person" objects from AD
try:
    users = conn.search_st(ldapbase, ldap.SCOPE_SUBTREE, ldapfilter)
except: 
    syslog.syslog("Error retreiving userlist using filter: %s" % ldapfilter)
    exit_with_error("LDAP search error")
    

for user in users:
    try:
        name = user[1]['cn'][0]
        mail = user[1]['mail'][0]
        last_set = long(user[1]['pwdLastSet'][0])
        expires_win = last_set + expiry_days*24*60*60*10000000
        notify_win = expires_win - notify_days*24*60*60*10000000
    except:
        continue 
    if cur_win_time > notify_win and cur_win_time < expires_win:
        syslog.syslog("Sending notification to: %s" % mail)
        smail.sendmail(from_address,mail,msg_template % (mail, from_address,time.ctime(wintime_to_epoch(expires_win))))

sys.exit(0)

<-- Back