To help me keep track of my friend’s birthdays I’ve written a Confluence wiki page with their dates and a Python script that parses the page and sends an email.
The script looks for all confluence pages that have the label ‘notifier’, and parses a table with a format like this:
Name
Date
user1@mydomain.com
user2@mydomain.com
Friend 1
1978-01-01
x
Friend 2
1975-01-01
x
The table could contain many receiving email addresses, and a ‘x’ marks where to send the email. The Python script is installed in crontab and runs every night.
notifier.py
#!/usr/bin/env python
# -*- coding: latin1 -*-
import MySQLdb
import datetime
import time
import smtplib
import quopri
class ParseError ( Exception ):
pass
def parsetable ( text ):
"""Parses a text in confluence table format and returns a dictionary
with header and content elements"""
table_text = [ line for line in text . split ( ' \n ' ) if line . startswith ( '|' )]
header = [ item . strip ( ' \ ' ) for item in table_text [ 0 ] . split ( '||' )[ 1 : - 1 ]]
if len ( header ) < 3 :
raise ParseError , 'header'
content = []
for line in table_text [ 1 :]:
row = [ item . strip ( ' \ ' ) for item in line . split ( '|' )[ 1 : - 1 ]]
if len ( row ) != len ( header ):
raise ParseError , 'content'
if len ( row [ 0 ]) > 0 :
content . append ( row )
return { 'header' : header , 'content' : content }
def checknotify ( table ):
"""Iterates over a table (in the format that parsetable returns,
and calls notify() if the date in the second row is near todays date"""
today = datetime . date . today ()
for row in table [ 'content' ]:
subject = ''
try :
date = datetime . date ( * time . strptime ( row [ 1 ], " % Y- % m- % d" )[: 3 ])
except ValueError :
continue
diff = datetime . date ( today . year , date . month , date . day ) - today
name = quopri . encodestring ( row [ 0 ])
if diff . days == 5 :
subject = " % s soon % s years" % ( name , today . year - date . year )
text = "In five days % s will be % s =E5r. \n\n The date was % s. \n " % (
name , today . year - date . year , date )
elif diff . days == 0 :
subject = " % s % s years today" % ( name , today . year - date . year )
text = "Today % s will be % s =E5r. \n\n The date was % s. \n " % (
name , today . year - date . year , date )
if subject != '' :
dest = []
for i in range ( 2 , len ( row )):
if row [ i ] != '' :
dest . append ( table [ 'header' ][ i ])
if len ( dest ) > 0 :
notify ( subject , text , dest )
def notify ( subject , text , destination ):
"""Sends an email to destination"""
sender = "noreply@localhost"
message = "From: % s \r\n " % sender + \
"To: % s \r\n " % ', ' . join ( destination ) + \
"Subject: Reminder: % s?= \r\n " % subject + \
"Content-Transfer-Encoding: quoted-printable \r\n\r\n " + \
text
mailserver = smtplib . SMTP ( 'localhost' )
mailserver . sendmail ( sender , destination , message )
mailserver . quit ()
def main ():
"""Connects to confluence and selects all pages that are marked with the
label 'notifier', and sends email when a reminder is needed"""
db = MySQLdb . connect ( db = "confluence" , user = "confluence" , passwd = "xxx" )
c = db . cursor ()
c . execute ( "select BODY from BODYCONTENT where CONTENTID
in (select CONTENTID from CONTENT_LABEL, LABEL where
CONTENT_LABEL.LABELID = LABEL.LABELID and LABEL.NAME =
'notifier')" )
for page in c . fetchall ():
try :
table = parsetable ( page [ 0 ])
checknotify ( table )
except ParseError , detail :
print "parse failed:" , detail
c . close ()
if __name__ == "__main__" :
main ()